문제

다음은 내 코드의 스냅 샷입니다.

$fetchPictures = $PDO->prepare("SELECT * 
    FROM pictures 
    WHERE album = :albumId 
    ORDER BY id ASC 
    LIMIT :skip, :max");

$fetchPictures->bindValue(':albumId', $_GET['albumid'], PDO::PARAM_INT);

if(isset($_GET['skip'])) {
    $fetchPictures->bindValue(':skip', trim($_GET['skip']), PDO::PARAM_INT);    
} else {
    $fetchPictures->bindValue(':skip', 0, PDO::PARAM_INT);  
}

$fetchPictures->bindValue(':max', $max, PDO::PARAM_INT);
$fetchPictures->execute() or die(print_r($fetchPictures->errorInfo()));
$pictures = $fetchPictures->fetchAll(PDO::FETCH_ASSOC);

나는 얻다

SQL 구문에 오류가 있습니다. 오른쪽 구문이``15 ', 15'에서 사용하려면 MySQL 서버 버전에 해당하는 설명서를 확인하십시오.

PDO는 SQL 코드의 한계 부분에서 내 변수에 단일 따옴표를 추가하는 것 같습니다. 나는 그것을 찾았다. 나는 내가 생각하는이 버그를 발견했다.http://bugs.php.net/bug.php?id=44639

그게 내가보고있는 것입니까? 이 버그는 2008 년 4 월부터 열렸습니다! 그 동안 우리는 무엇을해야합니까?

페이지 매김을 구축해야하며 SQL 명령문을 보내기 전에 데이터가 깨끗하고 SQL 주입 세이프인지 확인해야합니다.

도움이 되었습니까?

해결책

나는 전에이 문제를 겪은 것을 기억합니다. 바인드 함수에 전달하기 전에 정수에 값을 캐스트하십시오. 나는 이것이 그것을 해결한다고 생각한다.

$fetchPictures->bindValue(':skip', (int) trim($_GET['skip']), PDO::PARAM_INT);

다른 팁

가장 간단한 솔루션은 다음과 같습니다 에뮬레이션 모드를 끄십시오. 연결 옵션으로 또는 간단히 다음 줄을 추가하여 수행 할 수 있습니다.

$PDO->setAttribute( PDO::ATTR_EMULATE_PREPARES, false );

그것은 bind param으로 문제를 해결할뿐만 아니라 execute ()에서 값을 보낼 수있게 해주므로 코드가 훨씬 더 어리 석습니다.

$skip = $_GET['skip'] ?: 0;
$sql  = "SELECT * FROM pictures WHERE album = ? ORDER BY id LIMIT ?, ?";
$PDO->setAttribute( PDO::ATTR_EMULATE_PREPARES, false );
$stmt  = $PDO->prepare($sql);
$stmt->execute([$_GET['albumid'], $skip, $max]);
$pictures = $stmt->fetchAll(PDO::FETCH_ASSOC);

버그 보고서를 살펴보면 다음이 효과가있을 수 있습니다.

$fetchPictures->bindValue(':albumId', (int)$_GET['albumid'], PDO::PARAM_INT);

$fetchPictures->bindValue(':skip', (int)trim($_GET['skip']), PDO::PARAM_INT);  

그러나 들어오는 데이터가 정확합니까? 오류 메시지에서 하나 숫자 후 인용문 (인용문으로 둘러싸인 정수와 반대). 이것은 또한 들어오는 데이터에 오류가 될 수 있습니다. 당신은 할 수 있습니까? print_r($_GET); 알아 보려면?

이것은 요약대로.
한계/오프셋 값을 매개 변수화하는 네 가지 옵션이 있습니다.

  1. 장애를 입히다 PDO::ATTR_EMULATE_PREPARES 말한 바와 같이 ~ 위에.

    이 값이 전달 된 값을 방지합니다 ->execute([...]) 항상 끈으로 나타납니다.

  2. 수동으로 전환하십시오 ->bindValue(..., ..., PDO::PARAM_INT) 매개 변수 모집단.

    그러나 이것은 -> 실행 목록 []보다 덜 편리합니다.

  3. 여기서 예외를 만들고 SQL 쿼리를 준비 할 때 일반 정수를 보간하십시오.

     $limit = intval($limit);
     $s = $pdo->prepare("SELECT * FROM tbl LIMIT {$limit}");
    

    캐스팅이 중요합니다. 더 일반적으로 당신이 볼 수 있습니다 ->prepare(sprintf("SELECT ... LIMIT %d", $num)) 그러한 목적으로 사용됩니다.

  4. MySQL을 사용하지 않고 SQLITE 또는 Postgres를 사용하는 경우; SQL에서 바운드 매개 변수를 직접 캐스트 할 수도 있습니다.

     SELECT * FROM tbl LIMIT (1 * :limit)
    

    다시, MySQL/Mariadb는 한계 조항에서 표현을 지원하지 않습니다. 아직 아님.

~을 위한 LIMIT :init, :end

당신은 그런 식으로 묶어야합니다. 당신이 같은 것을 가지고 있다면 $req->execute(Array()); 캐스팅대로 작동하지 않습니다 PDO::PARAM_STR 배열의 모든 var에 LIMIT 당신은 절대적으로 정수가 필요합니다. 원하는대로 BindValue 또는 BindParam.

$fetchPictures->bindValue(':albumId', (int)$_GET['albumid'], PDO::PARAM_INT);

왜 이런 일이 일어나고 있는지 설명하지 않았기 때문에 답을 추가하고 있습니다. 이것이 행동하는 이유는 당신이 사용하기 때문입니다. trim(). PHP 매뉴얼을 보면 trim, 반환 유형은입니다 string. 그런 다음 이것을 통과하려고합니다 PDO::PARAM_INT. 이 문제를 해결하는 몇 가지 방법은 다음과 같습니다.

  1. 사용 filter_var($integer, FILTER_VALIDATE_NUMBER_INT) 정수를 통과하고 있는지 확인합니다.
  2. 다른 사람들이 말했듯이, 사용 intval()
  3. 캐스팅 (int)
  4. 정수인지 확인합니다 is_int()

더 많은 방법이 있지만 이것은 기본적으로 근본 원인입니다.

pdo :: param_int를 사용하여 BindValue 오프셋 및 제한하면 작동합니다.

// 이전 (현재 오류) $ query = ".... Limit : P1, 30;"; ... $ stmt-> bindparam ( ': p1', $ limiteinferior);

// 후 (오류 수정) $ query = ".... Limit : P1, 30;"; ... $ limiteInferior = (int) $ limiteInferior; $ stmt-> bindparam ( ': p1', $ limiteinferior, pdo :: param_int);

PDO::ATTR_EMULATE_PREPARES 나에게 주었다

드라이버는이 기능을 지원하지 않습니다.이 드라이버는 속성 설정 오류를 지원하지 않습니다.

내 해결 방법은 a를 설정하는 것이 었습니다 $limit string으로 변수를 한 다음 다음 예제에서와 같이 준비 문에 결합하십시오.

$limit = ' LIMIT ' . $from . ', ' . $max_results;
$stmt = $pdo->prepare( 'SELECT * FROM users WHERE company_id = :cid ORDER BY name ASC' . $limit . ';' );
try {
    $stmt->execute( array( ':cid' => $company_id ) );
    ...
}
catch ( Exception $e ) {
    ...
}
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top