ホームページ  >  記事  >  データベース  >  PDO 拡張機能を介して MySQL データベースと対話し、追加、削除、変更、クエリの実装とデータベース トランザクションを実装します。

PDO 拡張機能を介して MySQL データベースと対話し、追加、削除、変更、クエリの実装とデータベース トランザクションを実装します。

coldplay.xixi
coldplay.xixi転載
2020-09-09 16:29:093217ブラウズ

PDO 拡張機能を介して MySQL データベースと対話し、追加、削除、変更、クエリの実装とデータベース トランザクションを実装します。

#関連する学習の推奨事項:

mysql チュートリアル

前処理ステートメントによる追加、削除、変更、およびクエリ

プリペアド ステートメントを使用する理由

前のチュートリアルでプリペアド ステートメントを簡単に紹介しました。それらをビュー テンプレートと比較できます。いわゆるプリペアド ステートメントは事前定義された SQL ステートメント テンプレートです。特定のパラメーター値は次のとおりです。プレースホルダーで置き換えられます:

INSERT INTO REGISTRY (name, value) VALUES (?, ?)
INSERT INTO REGISTRY (name, value) VALUES (:name, :value)
その後、後続の SQL ステートメントが実際に実行される前に、特定のパラメーター値が特定の API メソッドを通じて対応するプレースホルダーにバインドされ、マッピングされます。定義されたビュー テンプレートと同様に、変数を特定のプレースホルダーに置き換えてから、実際のレンダリング中に変数値を渡して入力し、レンダリングします。

なぜこんな苦労をするのでしょうか?前に示した

query メソッドを直接使用して、追加、削除、変更、クエリ操作を実行できたら便利だと思いませんか?さて、プリペアド ステートメントの利点について、またはデータベース インタラクションにプリペアド ステートメントを使用する理由について話しましょう。メリットは 2 つあります:

    まず、プリペアド ステートメントを使用して SQL を事前に定義します。解析は一度だけですが、異なるパラメータ値を渡すことで複数回実行できるため、テンプレート内の同じ SQL ステートメントの繰り返しの分析、コンパイル、最適化が回避され、データベース操作の実行速度が向上します。処理ステートメントは基礎となるドライバーによって処理されるため、SQL インジェクション攻撃を効果的に回避できます。
  • 要約すると、パフォーマンスとセキュリティの観点から、データベースの追加、削除、変更、クエリ操作を処理するには準備済みステートメントを使用することをお勧めします。
追加、削除、変更、およびクエリのサンプル コード

次に、PDO が提供するプリペアド ステートメント API に基づいて、MySQL データベースの追加、削除、変更、およびクエリの操作を実装します。これをオブジェクト指向の方法で実装します。

<?php class Post
{
    public $id;
    public $title;
    public $content;
    public $created_at;

    /**
     * @var PDO
     */
    protected $pdo;

    public function __construct(PDO $pdo = null)
    {
        if ($pdo != null) {
            $this->pdo = $pdo;
        }
    }

    public function insert($title, $content)
    {
        $sql = 'INSERT INTO `post` (title, content, created_at) VALUES (:title, :content, :created_at)';
        try {
            // 准备预处理语句
            $stmt = $this->pdo->prepare($sql);
            // 获取当前时间对应的格式化字符串:2020-05-28 13:00:00
            $datetime = date('Y-m-d H:i:s', time());
            // 绑定参数值
            $stmt->bindParam(':title', $title, PDO::PARAM_STR);
            $stmt->bindParam(':content', $content, PDO::PARAM_STR);
            $stmt->bindParam(':created_at', $datetime, PDO::PARAM_STR);
            // 执行语句
            $stmt->execute();
            return $this->pdo->lastInsertId();  // 返回插入记录对应ID
        } catch (PDOException $e) {
            printf("数据库插入失败: %s\n", $e->getMessage());
        }
    }

    public function select($id)
    {
        $sql = 'SELECT * FROM `post` WHERE id = ?';
        try {
            // 准备预处理语句
            $stmt = $this->pdo->prepare($sql);
            // 绑定参数值
            $stmt->bindValue(1, $id, PDO::PARAM_INT);
            // 执行语句
            $stmt->execute();
            return $stmt->fetchObject(self::class);  // 以对象方式返回结果集
        } catch (PDOException $e) {
            printf("数据库查询失败: %s\n", $e->getMessage());
        }
    }

    public function selectAll()
    {
        $sql = 'SELECT * FROM `post` ORDER BY id DESC';
        try {
            // 准备预处理语句
            $stmt = $this->pdo->prepare($sql);
            // 执行语句
            $stmt->execute();
            return $stmt->fetchAll();  // 返回所有结果集
        } catch (PDOException $e) {
            printf("数据库查询失败: %s\n", $e->getMessage());
        }
    }

    public function update($id)
    {
        $sql = 'UPDATE `post` SET created_at = :created_at WHERE id = :id';
        try {
            // 准备预处理语句
            $stmt = $this->pdo->prepare($sql);
            $datetime = date('Y-m-d H:i:s', time());
            // 绑定参数值
            $stmt->bindParam(':created_at', $datetime, PDO::PARAM_STR);
            $stmt->bindValue(':id', $id, PDO::PARAM_INT);
            // 执行语句
            $stmt->execute();
            return $stmt->rowCount();
        } catch (PDOException $e) {
            printf("数据库更新失败: %s\n", $e->getMessage());
        }
    }

    public function delete($id)
    {
        $sql = 'DELETE FROM `post` WHERE id = ?';
        try {
            // 准备预处理语句
            $stmt = $this->pdo->prepare($sql);
            // 绑定参数值
            $stmt->bindValue(1, $id, PDO::PARAM_INT);
            // 执行语句
            $stmt->execute();
            return $stmt->rowCount();
        } catch (PDOException $e) {
            printf("数据库删除失败: %s\n", $e->getMessage());
        }
    }
}

Post

クラスを構築し、(から渡された) コンストラクターで

$pdo インスタンスを初期化しました。チェック操作は、準備されたステートメントに基づいて追加、削除、および変更され、対応するクラス メソッドに分解されます。全体的なロジックは非常に単純です。例として insert を取り上げます。まず、SQL テンプレートが PDO オブジェクトの prepare メソッドを通じて渡され、準備されたステートメントが構築されます。このメソッドは PDOStatement オブジェクトを返します。次に、オブジェクトのbindParamメソッドが呼び出されます。特定のパラメータ値を決定します。このメソッドの最初のパラメータはプレースホルダ、2番目のパラメータはパラメータ値、3番目のパラメータは値の型です(対応する定数はPDOでクエリできます)その後、PDOStatement オブジェクトのexecuteメソッドを呼び出して、準備されたステートメントを実行できます。 挿入操作の場合は、PDO オブジェクトの lastInsertId メソッドを使用して、挿入されたレコードの主キー ID を返すことができます。更新および削除メソッドの場合は、PDOStatement オブジェクトの rowCount メソッドを使用して、操作が成功したかどうかを示す、影響を受けた行の数。クエリ操作の場合、PDOStatement オブジェクトの fetch メソッドを通じて 1 つのレコードを返すか、fetchObject メソッドを通じて指定されたクラスにマップされたオブジェクト インスタンス (これも 1 つのレコード) を返すことができます。複数の結果の場合は、それを返すことができます。 fetchAll メソッドを通じて。

プリペアド ステートメントを宣言するときは、

?

プレースホルダーまたは

:name を使用でき、どちらの方が読みやすいことに注意してください。その後、パラメーターをバインドするときにも使用できます。では、bindValue メソッドまたは bindingParam メソッドを渡すことができます。両方に渡されるパラメータは同じですが、? プレースホルダの場合は、数値シーケンス番号を通じて SQL テンプレートとの関係を確立する必要があります。 (1から開始)。 上記のコードと PHP 公式ドキュメントを組み合わせれば、理解することは難しくありません。次に、テスト コードを書きましょう:

// 初始化 PDO 连接实例
$dsn = 'mysql:host=127.0.0.1;port=3306;dbname=test;charset=utf8mb4';
$user = 'root';
$pass = 'root';
try {
    $pdo = new PDO($dsn, $user, $pass);
} catch (PDOException $e) {
    printf("数据库连接失败: %s\n", $e->getMessage());
}

// 测试代码
$post = new Post($pdo);
// insert
$title = '这是一篇测试文章';
$content = '测试内容: 今天天气不错';
$id = $post->insert($title, $content);
echo '文章插入成功: ' . $id . '<br>';
// select
$item = $post->select($id);
echo '<pre class="brush:php;toolbar:false">';
print_r($item);
// update
$affected = $post->update($id);
echo '受影响的行数: ' . $affected . '<br>';
// delete
$affected = $post->delete($id);
echo '受影响的行数: ' . $affected . '<br>';
// selectAll
$items = $post->selectAll();
print_r($items);
PDO オブジェクト インスタンスを初期化して、それを渡します

Post

コンストラクターを呼び出し、Post オブジェクトの add、delete、modify、query メソッドを順番に呼び出します。ブラウザでアクセスすると、出力される結果は次のとおりです。

PDO 拡張機能を介して MySQL データベースと対話し、追加、削除、変更、クエリの実装とデータベース トランザクションを実装します。fetchAll

メソッドによって返される結果セット配列には、デフォルトで両方が含まれていることがわかります。インデックス マッピングと含まれるフィールド名のマッピングは、取得モードを設定することで解決できます。たとえば、

Post オブジェクト配列を返したい場合は、次のように実行できます:

return $stmt->fetchAll(PDO::FETCH_CLASS, self::class);
Inこの場合、返される結果は次のようになります。

モード設定の詳細については、公式ドキュメントの fetchAll メソッドの概要と例を参照してください。 PDO 拡張機能を介して MySQL データベースと対話し、追加、削除、変更、クエリの実装とデータベース トランザクションを実装します。

データベース トランザクション

最後に、PDO 拡張機能を使用してデータベース トランザクションの送信とロールバックを実装する方法を見てみましょう。単一の SQL ステートメントに対して、トランザクションの送信とロールバックが次のように行われることはすでにわかっています。自動的に完了します。一連の SQL ステートメント (複数の SQL ステートメント) の場合は、明示的にトランザクションを開始してトランザクションを送信する必要があります。PDO オブジェクトは、これに対応する API メソッドも提供します。非常に簡単です。たとえば、

Post

クラスにバッチ挿入メソッドを追加します。

batchInsert メソッド:

public function batchInsert(array $items)
{
    $sql = 'INSERT INTO `post` (title, content, created_at) VALUES (:title, :content, :created_at)';
    try {
        // 开启事务
        $this->pdo->beginTransaction();
        // 准备预处理语句
        $stmt = $this->pdo->prepare($sql);
        foreach ($items as $item) {
            // 绑定参数值
            $datetime = date('Y-m-d H:i:s', time());
            $stmt->bindParam(':title', $item->title, PDO::PARAM_STR);
            $stmt->bindParam(':content', $item->content, PDO::PARAM_STR);
            $stmt->bindParam(':created_at', $datetime, PDO::PARAM_STR);
            // 执行语句
            $stmt->execute();
        }
        $this->pdo->commit(); // 提交事务
        return $stmt->rowCount();  // 返回受影响的行数
    } catch (PDOException $e) {
        $this->pdo->rollBack(); // 回滚事务
        printf("数据库批量插入失败: %s\n", $e->getMessage());
    }
}

我们只需要在执行 SQL 序列之前调用 PDO 对象的 beginTransaction 方法开启事务,然后在所有 SQL 语句执行完成后调用 commit 方法提交事务,如果 SQL 执行过程中出错,则在异常处理代码中通过 PDO 对象的 rollBack 方法回滚事务。

为上述方法编写测试代码:

$post = new Post($pdo);
$items = [
    [
        'title' => '这是一篇测试文章111',
        'content' => '测试内容'
    ],
    [
        'title' => '这是一篇测试文章222',
        'content' => '测试内容'
    ],
    [
        'title' => '这是一篇测试文章333',
        'content' => '测试内容'
    ],
];
$post->batchInsert($items);
$items = $post->selectAll();
print_r($items);

执行这段代码,打印结果中包含新插入的文章数据,则表明事务提交成功:

PDO 拡張機能を介して MySQL データベースと対話し、追加、削除、変更、クエリの実装とデータベース トランザクションを実装します。

小结

关于通过 PDO 扩展与 MySQL 数据库交互,我们就简单介绍到这里,更多细节可以阅读官方文档,相信通过这几个课程的学习,你已经对 MySQL 数据库的基本使用以及如何在 PHP 中连接数据库并进行增删改查有了初步的认知,从下篇教程开始,我们将结合具体实战项目来开发一个现代的 PHP 项目,将之前的学习到的知识点应用到实战中,并且引入一些现代的 PHP 理念对项目进行管理。

想了解更多相关文章,敬请关注php mysql栏目!

以上がPDO 拡張機能を介して MySQL データベースと対話し、追加、削除、変更、クエリの実装とデータベース トランザクションを実装します。の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事はxueyuanjun.comで複製されています。侵害がある場合は、admin@php.cn までご連絡ください。