programing

WordPress가 IN() 조건으로 준비한 문

topblog 2023. 2. 27. 23:20
반응형

WordPress가 IN() 조건으로 준비한 문

다음과 같은 문자열에는 다음 세 가지 값이 있습니다.

$villes = '"paris","fes","rabat"';

이렇게 준비된 문장에 입력해 보면:

$sql    = 'SELECT distinct telecopie FROM `comptage_fax` WHERE `ville` IN(%s)';
$query  = $wpdb->prepare($sql, $villes);

echo $query;다음에 나타냅니다.

SELECT distinct telecopie FROM `comptage_fax` WHERE `ville` IN('\"CHAPELLE VIVIERS \",\"LE MANS \",\"QUEND\"')

이 문자열은 세 개의 개별 값으로 작성되지 않습니다.큰따옴표가 이스케이프된 하나의 문자열일 뿐입니다.

여러 값을 사용하여 WordPress에서 준비된 문장을 올바르게 구현하려면 어떻게 해야 합니까?

다음 코드를 사용해 보십시오.

// Create an array of the values to use in the list
$villes = array("paris", "fes", "rabat");    

// Generate the SQL statement.
// The number of %s items is based on the length of the $villes array
$sql = "
  SELECT DISTINCT telecopie
  FROM `comptage_fax`
  WHERE `ville` IN(".implode(', ', array_fill(0, count($villes), '%s')).")
";

// Call $wpdb->prepare passing the values of the array as separate arguments
$query = call_user_func_array(array($wpdb, 'prepare'), array_merge(array($sql), $villes));

echo $query;

WordPress에는 이 목적을 위한 함수가 이미 있습니다. esc_sql()을 참조하십시오.이 함수의 정의는 다음과 같습니다.

MySQL 쿼리에서 사용하기 위해 데이터를 이스케이프합니다.보통 wpdb::prepare()를 사용하여 쿼리를 준비해야 합니다.스폿 이스케이프가 필요하거나 유용할 수 있습니다.예를 들어 IN 절에서 사용할 배열을 준비하는 경우가 있습니다.

다음과 같이 사용할 수 있습니다.

$villes = ["paris", "fes", "rabat"];
$villes = array_map(function($v) {
    return "'" . esc_sql($v) . "'";
}, $villes);
$villes = implode(',', $villes);
$query = "SELECT distinct telecopie FROM `comptage_fax` WHERE `ville` IN (" . $villes . ")"

기능:

function escape_array($arr){
    global $wpdb;
    $escaped = array();
    foreach($arr as $k => $v){
        if(is_numeric($v))
            $escaped[] = $wpdb->prepare('%d', $v);
        else
            $escaped[] = $wpdb->prepare('%s', $v);
    }
    return implode(',', $escaped);
}

용도:

$arr = array('foo', 'bar', 1, 2, 'foo"bar', "bar'foo");

$query = "SELECT values
FROM table
WHERE column NOT IN (" . escape_array($arr) . ")";

echo $query;

결과:

SELECT values
FROM table
WHERE column NOT IN ('foo','bar',1,2,'foo\"bar','bar\'foo')

더 효율적일 수도 있고 그렇지 않을 수도 있지만 재사용할 수 있습니다.

여기 소독을 위한 저의 접근법이 있습니다.IN (...)에 대한 가치관$wpdb.

  1. 목록의 각 값을 전달하는 도우미 기능을 사용합니다.$wpdb->prepare()제대로 빠져나갈 수 있도록 하기 위해서요.
  2. 준비된 값 목록은 를 통해 SQL 쿼리에 삽입됩니다.sprintf().

도우미 기능:

// Helper function that returns a fully sanitized value list.
function _prepare_in ( $values ) {
    return implode( ',', array_map( function ( $value ) {
        global $wpdb;

        // Use the official prepare() function to sanitize the value.
        return $wpdb->prepare( '%s', $value );
    }, $values ) );
};

사용 예:

// Sample 1 - note that we use "sprintf()" to build the SQL query!
$status_cond = sprintf(
    'post_status IN (%s)',
    _prepare_in( $status )
);
$posts = $wpdb->get_col( "SELECT ID FROM $wpdb->posts WHERE $status_cond;" );


// Sample 2:
$posts = $wpdb->get_col( sprintf( "
    SELECT ID
    FROM $wpdb->posts
    WHERE post_status IN (%s) AND post_type IN (%s)
    ;",
    _prepare_in( $status ),
    _prepare_in( $post_types )
) );

배열에서 준비된 문장의 자리 표시자를 생성하는 작은 함수를 만들었습니다. 예를 들어 다음과 같습니다.(%s,%d,%f)어레이의 각 항목에 따라 사용하는 플레이스 홀더를 정확하게 파악할 수 있습니다.

function generate_wpdb_prepare_placeholders_from_array( $array ) {
    $placeholders = array_map( function ( $item ) {
        return is_string( $item ) ? '%s' : ( is_float( $item ) ? '%f' : ( is_int( $item ) ? '%d' : '' ) );
    }, $array );
    return '(' . join( ',', $placeholders ) . ')';
}

질문의 예를 참고하여 먼저 값을 배열로 변환해야 합니다.

$villes = array( "paris", "fes", "rabat" );   
$in_str = generate_wpdb_prepare_placeholders_from_array( $villes );
$sql    = "SELECT distinct telecopie FROM `comptage_fax` WHERE `ville` IN {$in_str}";
$query  = $wpdb->prepare( $sql, $villes );

첫 번째는 배열에 알 수 없는 수의 값이 포함된 mysqli 준비된 문을 사용하는 최신 비 WordPress 기술 세트입니다.두 번째 스니펫은 WordPress와 동등한 것입니다.

인덱스된 입력 데이터 배열이 신뢰할 수 없으며 다음 위치에서 액세스할 수 있다고 가정합니다.$_GET['villes']준비된 스테이트먼트는 최신 표준으로 프로 개발자들이 오래된/신뢰할 수 없는 이스케이프 기술보다 선호합니다.다음에 이어지는 스니펫은 다음 중 하나가 있는 행을 반환합니다.ville값을 지정합니다.어레이가 선언되지 않았거나 비어 있으면 데이터베이스 테이블의 모든 행을 반환합니다.

기본 PHP 기술:

$sql = "SELECT DISTINCT telecopie FROM comptage_fax";
if (!empty($_GET['villes'])) {
    $count = count($_GET['villes']);
    $commaDelimitedPlaceholders = implode(',', array_fill(0, $count, '?'));
    $stmt = $conn->prepare("$sql WHERE ville IN ($commaDelimitedPlaceholders)");
    $stmt->bind_param(str_repeat('s', $count), ...$_GET['villes']);
    $stmt->execute();
    $result = $stmt->get_result();
} else {
    $result = $conn->query($sql);
}

이 시점에서, 다른 행에 액세스 할 수 있습니다.telecopie단순한 관련 배열의 인덱스 배열을 반복하는 것과 같은 값(기술적으로는 반복 가능한 결과 집합 객체)foreach().

foreach ($result as $row) {
    echo $row['telecopie'];
}

WordPress의 도우미 메서드를 사용하면 변수 바인딩 및 쿼리 실행이 다음과 같이 처리되므로 구문이 더 단순해집니다.get_results():

$sql = "SELECT DISTINCT telecopie FROM comptage_fax";
if (!empty($_GET['ville']) {
    $commaDelimitedPlaceholders = implode(',', array_fill(0, count($_GET['ville']), '%s'));
    $sql = $wpdb->prepare("$sql WHERE ville IN ($commaDelimitedPlaceholders)", $_GET['ville']);
}
$result = $wpdb->get_results($sql, ARRAY_A);

시점부터, 「 」는$result의 인덱스 으로는 '어소시에이션 배열'이 입니다.★★★★★★★★★★★★★★★★★★,ARRAY_A$result첫 번째 네이티브 php 스니펫과 같은 결과 집합 개체가 아닙니다., 풀 인 루핑 언어 생성자를 모두 할 수 .array_데이터상에서 기능합니다.

유용한 참고 자료:

이 함수는 또한array두 번째 파라미터로 지정합니다.

해 보세요.$villes음음음같 뭇매하다

현재의

<?php
$villes = '"paris","fes","rabat"';
?

로 변경하다

<?php
$villes = array("paris","fes","rabat");
?>

그럼 이번에는 ㅇㅇ, ㅇㅇㅇㅇ를 .$villes펑크를 준비해서 동작하는지 확인합니다.도움이 됐으면 좋겠다.

언급URL : https://stackoverflow.com/questions/10634058/wordpress-prepared-statement-with-in-condition

반응형