2

わかりましたので、バインディングは初めてです。これが機能するコードです。この形式はチュートリアルから学びましたが、もっと効率的な方法があると思います。私の例では 4 つの名前がありますが、実際には 20 ほどのフィールドを持つプロジェクトで多くの挿入と更新を行うことになります。私はこのアプローチが明快であることを気に入っていますが、明らかに 20 以上のフィールドを扱う場合、かなりのスペースが必要です。最初に私のコードを見てみましょう。

使用する関数は次のとおりです。

// prepare the statement
public function query($query){
    $this->stmt = $this->dbh->prepare($query);
}

public function bind($param, $value, $type = null){
    if (is_null($type)) {
        switch (true) {
            case is_int($value):
                $type = PDO::PARAM_INT;
                break;
            case is_bool($value):
                $type = PDO::PARAM_BOOL;
                break;
            case is_null($value):
                $type = PDO::PARAM_NULL;
                break;
            default:
                $type = PDO::PARAM_STR;
        }
    }
// run the binding process
$this->stmt->bindValue($param, $value, $type);
}

// execute the prepared statement
public function execute(){
    return $this->stmt->execute();
}

そして今、実際のコード

$database->query("
    INSERT INTO users(
        user_name,
        user_password_hash,
        user_email,
        user_activation_hash
)

    VALUES(
        :user_name,
        :user_password_hash,
        :user_email,
        :user_activation_hash
    )
");

// bind the values
$database->bind(":user_name", "$this->user_name");
$database->bind(":user_password_hash", "$this->user_password_hash");
$database->bind(":user_email", "$this->user_email");
$database->bind(":user_activation_hash", "$this->user_activation_hash");

// execute the statement and insert the values into the database
$database->execute();

特に私は投稿フィールド、入力フィールド、変数、プレースホルダーを同じ名前で呼ぶ習慣があるので、それが良いことなのか悪いことなのかはわかりませんが、対処するときに役立つと思います私がなる大きな形。

いずれにせよ、私は次のようなことができます:

$placeholder_array = array(
    "user_name"               => "\$this->user_name",
    "user_password_hash"      => "\$this->user_password_hash",
    "user_email"              => "\$this->user_email",
    "user_activation_hash"    => "\$this->user_activation_hash"
);

// well use this copy to edit the array keys and keep original for the binding
$placeholder_copy = $placeholder_array;


// turn the array into a string i.e user_name, user_password_hash....
$fields = implode (", ", array_keys($placeholder_array));

// foreach to add : placeholder prefix for binding
foreach ($placeholder_copy as $key => $value){
$placeholder_copy [':'.$key] = $value;
unset($placeholder_copy[$key]);
}

// turn the copy array which has prefix :user_name into a string 
$placeholders = implode (", ", array_keys($placeholder_copy));

$database->query("
    INSERT INTO users($fields)
    VALUES($placeholders) 
");

// bind the values
foreach ($placeholder_copy as $bind_values => $value){
    echo '$database->bind("'.$bind_values.'", "'.$value.'");' . "<br />";
}

// execute the statement and insert the values into the database
$database->execute();

次に、これを連想配列とテーブル名を渡すためのパラメーターを持つ関数に変換して、メイン コードをよりクリーンに保つことができます。

私が取り組んでいるプロジェクトには、ユーザーにデータを送信する大量の大きなフォームが含まれているため、これらをいくらでも実行すると想像してください。私はPDOを初めて使用し、それを把握しようとしているので、これらのタイプのクエリを構造化するより簡単な方法があるかもしれません.Googleとstackflowを見ましたが、彼らが何をしているのか本当にわからなかったので、自分でやると思いました.人々は私に何が起こっているのかをよりよく説明してくれます。後で戻ってすべてを変更するよりも、プロジェクトを開始して正しく理解することをお勧めします。それで、より良いアプローチがありますか、それともこれは大丈夫ですか?

フィードバックに本当に感謝しています。ここで人々のアドバイスを受けて、PDO に移行したことをうれしく思います。

4

2 に答える 2

2

いいえ、残念ながら、PDO は問題を解決する助けにはなりません。
しかし、あなた自身のアプローチも私には効率的なものではないようです。

まず第一に、あなたの一連の関数がまったく役に立たないことを示しましょう。API関数のそのような直接の書き換えは理解していません。PDO はすでにこれらすべてのことを行っています。

生の PDO を使用すると、さらに簡潔なコードを作成できます。

$stm  = $pdo->prepare("INSERT INTO users VALUES(NULL,?,?,?,?)");
$data = array($this->user_name, 
              $this->user_password_hash, 
              $this->user_email, 
              $this->user_activation_hash
);
$stm->execute($data);

動的クエリの構築に関しては、肥大化しすぎているにもかかわらず、まだ安全ではありません。いくつかの欠陥は

  • ":named" プレースホルダーは人間が読めるはずですが、人間がここで読むことは想定されていないため、気にする意味はありません。言うまでもなく、PDO はそれらを ?s に変換してから mysql に送信します。
  • 名前付きプレースホルダーに対する別の反論 - Mysql (および HTTP) ではフィールド名にスペースを入れることができますが、スペースを含むプレースホルダーはクエリをクラッシュさせるだけです。
  • このコードには、同じ名前のアプローチからの実際の利点はありません.1ダースずつ手動で書く必要があります.
  • しかし、それが使用される場合、フィールド リストをチェックするためのホワイト リストがなく、重大なセキュリティ違反となる可能性があります。
  • コードが多すぎる
  • 非常に便利なUPDATEクエリもサポートされていません(mysqlを使用している場合)
  • このコードを関数に入れると、2 つの単語を節約できる可能性に誘惑されて、他の人と同じ悪い根拠に陥るでしょう。

この問題に対する私の以前のアプローチは次のとおりです。

$allowed = array(
    "user_name", "user_password_hash", "user_email", "user_activation_hash"
);
$sql = "INSERT INTO users SET ".pdoSet($allowed, $values);
$stmt = $dbh->prepare($sql);
$stmt->execute($values);

そして、これが私の現在のアプローチであり、配列データのカスタムプレースホルダーを使用して、ベストオブザベスト(PDOではなくmysqliを使用して実装されています)です:

$placeholder_array = array(
    "user_name"               => $this->user_name,
    "user_password_hash"      => $this->user_password_hash,
    "user_email"              => $this->user_email,
    "user_activation_hash"    => $this->user_activation_hash
);
$db->query("INSERT INTO users SET ?u", $placeholder_array);

または、フォーム フィールドと SQL 列の間の直接接続の場合

$allowed = array(
    "user_name", "user_password_hash", "user_email", "user_activation_hash"
);
$insert = $db->filterArray($_POST,$allowed);
$db->query("INSERT INTO users SET ?u", $insert);

このようにしてINSERT IGNOREINSERT DELAYED, INSERT.. ON DUPLICATE UPDATE, UPDATE,UPDATEを join とともに使用したり、その他の無数のオプションを使用したりして、完全なSQL 言語をサポートすることができます。

于 2013-08-20T07:23:38.200 に答える