PDO bind array to Where IN

后端 未结 4 1616
执念已碎
执念已碎 2021-01-23 18:29

I want to bind a array of Strings to the WHERE IN part of a SQL command, which I want to run afterwards on a SQL Server. The problem is probably that I try to bind

4条回答
  •  清酒与你
    2021-01-23 18:45

    You can use a wrapper method that parses the sql string for you:

    so when i do the query i always write it like this :

    $sql="SELECT * from TableA where account=:account_id and categories in(:categories_list)"
    

    Then, i send this to the PDO class as:

    PDO::getAll($sql, array("account_id"=>$_GET["account] , "categories_list"=>explode(",","1,2,3") );

    If you notice, the account_id is a direct variable, but the categories_list will be an array, so the wrapper will need to parse that and check if that values is array or not.

    Then what the wrapper does it parse the array and create the binbing elements. Because as you can see i feed the array with no ":account_id" etc.. that will be automatically assign that symbol, for the pdo binding to work.

    I have many different methods depending if i want all the results of mysql or just a row or just a cell, but in this case i use my made getAll method is which this:

    public static function getAll($query,$array=array()){
    $me=self::getInstance();
    if(self::execute($query,$array)){ $resultset = $me->statement->fetchALL(PDO::FETCH_ASSOC); }else{$resultset=false;}
    return $resultset;
    }
    

    so when you call this, it will call the execute method which is like this:

    private static function execute($query,$array){
    $me=self::getInstance();
    
    $query_array=$array;
    $multibind_array=array();
    
    foreach ($query_array as $key => $value) { 
        if(strpos($query, ":".$key)){
            $query_array[":".$key] = $query_array[$key]; 
    
        if(is_array($query_array[$key]) ){ 
    
        $multibind_array[":".$key]="";
        foreach($query_array[$key] as $bindKey=>$multibind){
            $bind_id=(":__".$key).$bindKey;
            $multibind_array[":".$key][]=$bind_id;
            $query_array[$bind_id]=$multibind;
        }
    
    $query = str_replace(":".$key, implode(",",$multibind_array[":".$key]) ,$query ); unset($query_array[":".$key]);
    
        }  
        } unset($query_array[$key]); 
         } //auto prepair array for PDO
    
    $me->dbh->exec("set names utf8");
    $me->statement = @$me->dbh->prepare($query); //Verify if this token really match those fieds
    
    try{$me->result=$me->statement->execute($query_array);}
    catch(Exception $e){
        $me->result=false;
        echo "PDO error ";
        print_r($me->statement->errorInfo()) ;
    }
    
    $me->lastError=$me->statement->errorInfo()[2];
    return $me->result;
    }
    

    As you can see, the array will append the ":" symbol by its own, and when is an array, it will assign the same placeholder but append an id, and then string replace the original query with those ids, that will later match the array i feed.

    In the end we save alot of time, because you can write SQL code directly almost, and benefit of PDO.

    in the PDO::getAll($sql, array("account_id"=>$_GET["account] ,"categories_list"=>explode(",","1,2,3") ); part i can feed even values that i end up not using in the sql, the wrapper will find those and exclude it. SO we can directly from a single update object do many different mysql actions with the same data.

    $update_obj=array("id"=>1, "name"=>"test", "account"=>"10");
    
    PDO::doQuery("UPDATE ... name=:name" , $update_obj ); 
    

    This mysql will update just the name. In a normal situation, PDO would tell you error because bind value "account" or "id" do not match the same tokens found on the query.

提交回复
热议问题