0

私はこのバラバラになったコードを修正しようとしています - ご想像のとおり、バインド パラメータの構文を修正しています。実際、私がやろうとしていることさえ可能かどうかさえわかりません。これがクラスメソッドです...

/***
*
* @select values from table
*
* @access public
*
* @param string $table The name of the table
*
* @param array $fieldlist Fields to return in results, defaults null
*
* @param array $criteria Search criteria by keyed by fieldname
*
* @param int $limit Limit of records to return, defaults 10
*
* @return Array on success or throw PDOException on failure
*
*/
public function dbSearch($table, $fieldList = null, $criteria = null, $limit = 10)
{
    // setup $this->db to point to a PDO instance
    $this->conn();

    // build fieldlist
    if( is_null($fieldList) OR !is_array($fieldList) OR count($fieldList) == 0) {
        $returnFields = '*';
    } else {
        $returnFields = "'".implode("', '", $fieldList)."'";
    }

    // build criteria
    if( is_null($criteria) OR !is_array($criteria) OR count($criteria) == 0) {
        $whereClause = '';
    } else {
        $whereClause = array();
        foreach ($criteria as $key => $value){
           $bind_name    = 'bind_'.$key; //generate a name for bind1, bind2, bind3...
           $$bind_name   = $value; //create a variable with this name with value in it
           $bind_names[] = & $$bind_name; //put a link to this variable in array
           $whereClause[] = "'$key' = :$bind_name";
        }
        $whereClause = count($whereClause) > 0 ? ' WHERE '.implode( ' AND ' , $whereClause ) : '';
    }

    $sql = "SELECT $returnFields FROM '$table' $whereClause LIMIT $limit"; 

    $stmt = $this->db->prepare($sql);

    if( $whereClause != '') {
        call_user_func_array(array(&$stmt, 'bindParam'), $bind_names);
    }

    $stmt->execute();
    return $stmt->fetchAll(PDO::FETCH_ASSOC);
}

...ある時点で、これらの行に沿って何かを使用して呼び出したい...

// look for users in database...
$user_recs = $crud->dbSearch('user', array('user_name'), array('user_name'=> $_POST['username']));
$users = $user_recs->fetchAll(PDO::FETCH_ASSOC);

これはどのようにばかげていますか?出来ますか?どういうわけか、パラメーターの型も渡す必要がありますか? どんな助けもありがたく受け取った!

4

3 に答える 3

4

実際、問題は、バインドされた値ではなく、バインドされたパラメーターを使用することでした...おお!

連想配列内の SQL ステートメントといくつかの値が与えられた場合、たとえば

$sql = "SELECT * FROM event
        WHERE eventdate >= :from 
        AND eventdate <= :until 
        AND ( user_name LIKE :st OR site_name LIKE :st )
        ORDER BY eventdate, start_time LIMIT 100";

$values = array( 'st'    => '%'.$searchterm.'%',
                 'from'  => $fromdate,
                 'until' => $untildate, );

次に、このクラスメソッド(ただし、単純な関数で簡単に実行できます)はトリックを行いました:

    public function dbBoundQuery($sql, $values, $types = false) {
        $this->conn();

        $stmt = $this->db->prepare($sql);

        foreach($values as $key => $value) {
            if($types) {
                $stmt->bindValue(":$key",$value,$types[$key]);
            } else {
                if(is_int($value))        { $param = PDO::PARAM_INT; }
                elseif(is_bool($value))   { $param = PDO::PARAM_BOOL; }
                elseif(is_null($value))   { $param = PDO::PARAM_NULL; }
                elseif(is_string($value)) { $param = PDO::PARAM_STR; }
                else { $param = FALSE;}

                if($param) $stmt->bindValue(":$key",$value,$param);
            }
        }

        $stmt->execute();
        return $stmt->fetchAll(PDO::FETCH_ASSOC);
    }

これが他の誰かに役立つことを願っています。

于 2013-09-04T15:12:56.727 に答える
1

この機能が従来より優れている点がよくわかりません

$stmt = $db->prepare("SELECT user_name FROM user WHERE user_name = ?");
$stmt->execute($_POST['username']);
$users = $stmt->fetchAll();

気をつけて、

  • クエリの柔軟性を維持します。LIMIT ?,?可能です
  • クエリを読みやすくします。SQL のほぼ自然な英語がそのまま使用されます。脳にダメージを与える言語を学ぶ必要なく、クエリが何をするかを知ることができます副作用として、他の開発者もこのコードを理解できます。
于 2013-08-28T15:24:17.523 に答える
0

さて、コードでうまくいかないことがかなりあります。

一度だけ、句の間にAND/が表示されません。これがおそらく機能しない理由です。ORWHERE

次に、SQL 関数を使用できません。次のようなクエリを書く必要があるとしましょう。

SELECT * FROM `table` WHERE UNIX_TIMESTAMP(date_added) < ...;

あなたはアイデアを得る。

既存の ORM ( DoctrinePropelなど) を使用するか、PDO を使用することをお勧めします。

User クラスに PDO を使用する方法の例を次に示します。

class User
{

 protected $data;
 public function __get($key) {
      return $this->data[$key];
 }
 public function __set($key, $value) {
     $this->data[$key] = $value;
 }
/**
 * @param $value
 * @param $field
 * @return $this
 */
public function loadBy($value, $field)
{
    $db = DbFactory::getInstance();
    $query = "SELECT * FROM users WHERE $field = :$field LIMIT 1";
    $stmt = $db->prepare($query);
    $stmt->execute(array(":$field" => $value));
    $result = $stmt->fetch();

    foreach ($result as $key => $value) {
        $this->$key = $value;
    }

    return $this;
}
}

エンティティに対してそのような関数を作成できます。これにより、特殊化され、機能が効率的で、テストが容易な関数が得られます。

PS:data :) という名前のフィールドがある場合に表示される問題は無視してください。

于 2013-08-28T15:29:47.080 に答える