데이터베이스 작업에 PHP의 MySQLI 확장을 사용할 때는 종종 준비된 진술을 사용하여 보안 및 성능을 향상시킵니다. 동시에 개발자는 종종 실행 중에 SQL 구문 오류와 같은 가능한 오류를 정확하게 캡처하려고합니다. 그러나 당신은 그런 혼란스러운 문제를 겪을 수 있습니다.
그래서 무슨 일이 일어나고 있습니까? 이 기사는이 문제에 대한 심층 분석을 수행하고 실용적인 해결책을 제공합니다.
다음 샘플 코드를 참조하십시오.
$mysqli = new mysqli("localhost", "user", "password", "testdb");
// 구문 오류:누락 된 것 FROM
$sql = "SELECT id name users WHERE id = ?";
$stmt = $mysqli->prepare($sql);
if (!$stmt) {
echo "Prepare failed: " . $mysqli->error; // 올바른 방법
} else {
$stmt->bind_param("i", $id);
$id = 1;
$stmt->execute();
if ($stmt->error) {
echo "Execute error: " . $stmt->error; // 不会捕捉到구문 오류
}
$stmt->close();
}
$mysqli->close();
Prepare failed: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version...
보시다시피, SQL 구문 오류는 $ stmt-> 오류를 전혀 입력하지 않지만 repary () 단계에서 $ mysqli-> 오류 에 의해 잡혔습니다.
PHP에서 MySQLI 와 MySQLI_STMT 사이의 노동 분업을 이해해야합니다.
mysqli :: repay ()는 데이터베이스 연결 객체에서 호출되는 메소드입니다. SQL에 구문 오류가 있으면 STMT 객체가 전혀 생성되지 않으므로 $ stmt는 false 입니다.
MySQLI_STMT :: $ 오류는 명령문이 성공적으로 준비되고 런타임 오류가 발생한 후에 만 값 만 가지고 있습니다 (예 : 실행 중에 바인딩 변수 유형이 일치하지 않으면 외래 키 제약 조건이 실패하는 것).
따라서 SQL 구문 오류는 STMT 객체를 생성하지 않기 때문에 $ stmt-> 오류 로 잡을 수 없으며 잡을 수 없습니다 .
다시 말해서:
SQL 구문 오류는 ready () 단계에서 발생하며 $ stmt-> execute () 를 기다리지 않고 $ mysqli-> error 또는 mysqli :: repay () 의 반환 값으로 판단해야합니다.
위의 코드를 다시 작성하고보다 안전한 오류 처리 로직을 채택하십시오.
$mysqli = new mysqli("localhost", "user", "password", "testdb");
$sql = "SELECT id, name FROM users WHERE id = ?"; // 올바른 구문
$stmt = $mysqli->prepare($sql);
if (!$stmt) {
// 检查구문 오류
die("SQL prepare failed: " . $mysqli->error);
}
$stmt->bind_param("i", $id);
$id = 1;
if (!$stmt->execute()) {
// 런타임 오류를 확인하십시오
die("Execute failed: " . $stmt->error);
}
$result = $stmt->get_result();
$data = $result->fetch_assoc();
echo "User: " . $data['name'];
$stmt->close();
$mysqli->close();
AJAX 인터페이스를 사용하여 다음과 같은 주소에 액세스하는 것과 같은 SQL 매개 변수를 제출하는 경우
https://gitbox.net/api/get_user.php?id=1
그런 다음 사용자 입력을 SQL (Dangerous!)로 연결합니다.
$id = $_GET['id'];
$sql = "SELECT * FROM users WHERE id = $id"; // 잠재적인 SQL 주사 위험
이 글쓰기 방법은 스 플라이 싱 중에 SQL을 잘못 작성하기 쉽고 준비 () 가 사용되지 않으며 오류를 찾기가 더 어렵습니다. 따라서 다음과 같은 글쓰기 방법이 권장됩니다.
$sql = "SELECT * FROM users WHERE id = ?";
$stmt = $mysqli->prepare($sql);
$stmt->bind_param("i", $_GET['id']);
이는 SQL 주입을 피할뿐만 아니라 명확하고 중앙 집중식을 확인하는 오류를 만듭니다.
SQL 구문 오류는 Prepar () 단계에서만 찾을 수 있으며 $ stmt-> 오류를 통해 얻을 수 없습니다.
repary () 의 반환 값을 확인하고 $ mysqli-> 오류를 사용하여 오류 메시지를 출력하십시오.
사전 처리 문을 사용하여 주입을 방지하는 것이 좋습니다. 오류를 디버깅하고 포착하는 것이 더 쉽습니다.
MySQLI 와 MySQLI_STMT 간의 책임 부서를 이해 함으로써만 더 강력하고 안전한 데이터베이스 상호 작용 코드를 작성할 수 있습니다.