2017-02-05 17 views
0

私はmini-DBALをコーディングしました。PHP PDO - 動的SQL準備文がハードコーディングのように機能しない

private function setWhere($conditions) { 
    if (count($conditions)>0) { 
     $where = '1=1'; 
     $params = []; 

     $ret = $this->iterateWhere($where, $conditions, $params, 'AND', '='); 
     return [ 
        'where' => 'WHERE '.str_replace('1=1 OR ', '', str_replace('1=1 AND ', '', $ret['where'])), 
        'params' => $ret['params'], 
       ]; 
    } else 
     return [ 
        'where' => '', 
        'params' => [], 
       ]; 
} 

private function iterateWhere($where, $conditions, $params, $logic, $op) { 
    //go through given set of conditions 
    foreach ($conditions as $condition=>$value) { 
     //check for lowest condition 
     if (is_array($value)) { 
      //check for logic or operator condition 
      if (in_array($value[0], ['AND', 'OR', 'and', 'or'])) { 
       //logic 
       $where .= ' '.$logic.' (1=1'; 
       $ret = $this->iterateWhere($where, $value, $params, $value[0], $op); 
       $where = $ret['where']; 
       $params = $ret['params']; 
       $where .= ')'; 
      } else { 
       //operator 
       foreach($value as $k=>$v) { 
        if ($k != '0') { 
         $where .= ' '.$logic.' ('.$k.$value[0].':'.count($params).')'; 
         $params[] = $v; 
         break; 
        } 
       } 
      } 
     } else { 
      if ($condition != '0') { 
       $where .= ' '.$logic.' ('.$condition.$op.':'.count($params).')'; 
       $params[] = $value; 
      } else { 
       if (in_array($value, ['AND', 'OR', 'and', 'or'])) 
        $logic = strtoupper($value); 
       else 
        $op = strtoupper($value); 
      } 
     } 
    } 

    return [ 
       'where' => $where, 
       'params' => $params, 
      ]; 
} 

public function getTableCol($table, $column, $conditions) { 
    try { 
     $condition_part = $this->setWhere($conditions); 
     $stmt = $this->pdo->prepare('SELECT '.$column.' FROM '.$table.' '.$condition_part['where']); 

     foreach ($condition_part['params'] as $param=>$pVal) { 
      switch (strtolower(gettype($pVal))) { 
       case 'string': 
        $stmt->bindParam(':'.$param, $pVal, \PDO::PARAM_STR); 
        break; 

       case 'integer': 
        $stmt->bindParam(':'.$param, $pVal, \PDO::PARAM_INT); 
        break; 

       case 'float': 
       case 'double': 
        $stmt->bindParam(':'.$param, $pVal); 
        break; 

       case 'boolean': 
        $stmt->bindParam(':'.$param, $pVal, \PDO::PARAM_BOOL); 
        break; 

       case 'null': 
        $stmt->bindParam(':'.$param, $pVal, \PDO::PARAM_NULL); 
        break; 

       default: 
        die('Unhandled param type for \''.$pVal.'\''); 
        break; 
      } 
     } 

     $stmt->execute(); 
     $ret = $stmt->fetchAll(\PDO::FETCH_COLUMN, 0); 

     return [ 
        'rows' => count($ret), 
        'result' => $ret, 
       ]; 
    } catch (\PDOException $e) { 
     return [ 
        'rows' => 0, 
        'result' => $e->getMessage(), 
       ]; 
    } 
} 

私はそうのように私の関数を呼び出す:

$client_list = $db->getTableCol("cs_client", "client_id", ["domain" => "PB", "name" => "My Client"]); 

私は自分のコードが正しくSQLやパラメータを移入見つけるが、私は複数のWHERE条件を渡すとき、それはすべての行を返しません。私が手動で動的に準備されたステートメントをハードコードすると、それは動作します。なぜ私は理解できません。 (準備に渡さ

SQL):ここ

は、エコー及びますprint_rからいくつかの出力でのparamsの

SELECT client_id FROM cs_client WHERE (domain=:0) AND (name=:1) 

配列出力:

Array 
(
    [0] => PB 
    [1] => My Client 
) 

シーケンスPARAMを結合するループのために:

0 => PB 
1 => My Client 

再作成するには、プリペアドステートメントを手動で '$ stmt = $ this-> pdo-> prepare( "")'にコピーしてから出力値を使用してバインド:0と:1にした場合、その表の行。

私は条件を1つだけ渡すか、条件を渡さないと、行を返しますが、2つの条件を満たす場合は条件を正しく入力しません。

あまり重要ではないはずですが、私は私は私はあまりしようとしていたと思いますMS SQL Serverの2014

答えて

0

を使用しています。 count()を使って名前付きのパラメータを0,1,2,3のようにインクリメントするのではなく、単に '?'そしてそのように実行するステートメントにパラメータのリストを渡さ:私は偶然にのリストを反復処理するループを必要としなかったので、

$stmt->execute($condition_part['params']); 

は、小さなコードになります。

関連する問題