目次
Connector.php
ホームページ データベース mysql チュートリアル 独自のデータベース パッケージを作成する方法 (2)

独自のデータベース パッケージを作成する方法 (2)

Apr 04, 2017 pm 02:23 PM
データベースのカプセル化


Connector.php

  • データベースとの通信、追加、削除、変更、読み取り(CRUD)を担当します

まず、Connectorクラスを作成し、属性を設定します

<?php
class Connector {
    // 数据库地址前缀,常见的有mysql,slqlsrv,odbc等等等
    private $driver = &#39;mysql&#39;;
    // 数据库地址
    private $host = &#39;localhost&#39;;
    // 数据库默认名称, 设置为静态是因为有切换数据库的需求
    private static $db = &#39;sakila&#39;;
    // 数据库用户名
    private $username = &#39;root&#39;;
    // 数据库密码
    private $password = &#39;&#39;;
    // 当前数据库连接
    protected $connection;
    // 数据库连接箱,切换已存在的数据库连接不需要重新通信,从这里取即可
    protected static $container = [];

    // PDO默认属性配置,具体请自行查看文档
    protected $options = [
        PDO::ATTR_CASE => PDO::CASE_NATURAL,
        PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
        PDO::ATTR_ORACLE_NULLS => PDO::NULL_NATURAL,
        PDO::ATTR_STRINGIFY_FETCHES => false,
    ];
}
ログイン後にコピー

上記のコードコメントを見れば理解できるはずです したがって、これ以上の説明はせずに、関数に直接アクセスしてください

  • buildConnectString - DSN接続文字列を生成するためのもので、非常に簡単です

      protected function buildConnectString() {
          return "$this->driver:host=$this->host;dbname=".self::$db;
      }
          // "mysql:host=localhost;dbname=sakila;"
    ログイン後にコピー
  • connect - データベースに接続します

      public function connect() {
          try {
              // 连接数据库,生成pdo实例, 将之赋予$connection,并存入$container之中
              self::$container[self::$db] = $this->connection = new PDO($this->buildConnectString(), $this->username, $this->password, $this->options);
              // 返回数据库连接
              return $this->connection;
          } catch (Exception $e) {
              // 若是失败, 返回原因
              // 还记得dd()吗?这个辅助函数还会一直用上
              dd($e->getMessage());
          }
      }
    ログイン後にコピー
  • setDatabase - データベースを切り替えます

      public function setDatabase($db) {
          self::$db = $db;
          return $this;
      }
    ログイン後にコピー
  • _construct - インスタンスを生成した後の最初のステップは何ですか?

      function construct() {
          // 如果从未连接过该数据库, 那就新建连接
          if(empty(self::$container[self::$db])) $this->connect();
          // 反之, 从$container中提取, 无需再次通信
          $this->connection = self::$container[self::$db];
      }
    ログイン後にコピー

次の 2 つの関数式は一緒に使用されているので、見て混乱するかもしれません。この例を使用して段階的にデバッグします

$a = new Connector();

$bindValues = [
    'PENELOPE',
    'GUINESS'
];

dd($a->read('select * from actor where first_name = ? and last_name = ?', $bindValues));
ログイン後にコピー
戻り値

array (size=1)
  0 => 
    object(stdClass)[4]
      public 'actor_id' => string '1' (length=1)
      public 'first_name' => string 'PENELOPE' (length=8)
      public 'last_name' => string 'GUINESS' (length=7)
      public 'last_update' => string '2006-02-15 04:34:33' (length=19)
ログイン後にコピー
  • read - データを読み取ります

      public function read($sql, $bindings) {
          // 将sql语句放入预处理函数
          // $sql = select * from actor where first_name = ? and last_name = ?
          $statement = $this->connection->prepare($sql);
          // 将附带参数带入pdo实例
          // $bindings = ['PENELOPE', 'GUINESS']
          $this->bindValues($statement, $bindings);
          // 执行
          $statement->execute();
          // 返回所有合法数据, 以Object对象为数据类型
          return $statement->fetchAll(PDO::FETCH_OBJ);
      }
    ログイン後にコピー
  • bindValues - 添付されたパラメータを PDO インスタンスに取り込みます

          // 从例子中可以看出, 我用在预处理的变量为?, 这是因为pdo的局限性, 有兴趣可以在评论区讨论这个问题
      public function bindValues($statement, $bindings) {
          // $bindings = ['PENELOPE', 'GUINESS']
          // 依次循环每一个参数
          foreach ($bindings as $key => $value) {
              // $key = 0/1
              // $value = 'PENELOPE'/'GUINESS'
              $statement->bindValue(
                  // 如果是字符串类型, 那就直接使用, 反之是数字, 将其+1
                  // 这里是数值, 因此返回1/2
                  is_string($key) ? $key : $key + 1,
                  // 直接放入值
                  // 'PENELOPE'/'GUINESS'
                  $value,
                  // 这里直白不多说
                  // PDO::PARAM_STR/PDO::PARAM_STR
                  is_int($value) ? PDO::PARAM_INT : PDO::PARAM_STR
              );
          }
      }
    ログイン後にコピー

    _( :3 ∠)

  • update - データを書き換える

      // 与read不同的地方在于, read返回数据, update返回boolean(true/false)
      public function update($sql, $bindings) {
          $statement = $this->connection->prepare($sql);
          $this->bindValues($statement, $bindings);
          return $statement->execute();
      }
    ログイン後にコピー
  • delete - 削除data

    // 与update一样, 分开是因为方便日后维护制定
      public function delete($sql, $bindings) {
          $statement = $this->connection->prepare($sql);
          $this->bindValues($statement, $bindings);
          return $statement->execute();
      }
    ログイン後にコピー
  • create - データを追加する

    // 返回最新的自增ID, 如果有
      public function create($sql, $bindings) {
          $statement = $this->connection->prepare($sql);
          $this->bindValues($statement, $bindings);
          $statement->execute();
          return $this->lastInsertId();
      }
    ログイン後にコピー
  • lastInsertId -

    Addを返すID、

      // pdo自带,只是稍微封装
      public function lastInsertId() {
          $id = $this->connection->lastInsertId();
          return empty($id) ? null : $id;
      }
    ログイン後にコピー
がある場合は高度すぎて複雑です SQLステートメントがカプセル化されていない可能性があるため、RAWクエリを使用してデータベースと直接通信できる2つの関数を用意しました

  • - 追加、削除、変更

      public function exec($sql) {
          return $this->connection->exec($sql);
      }
    ログイン後にコピー
  • クエリ - 読み取りに適しています

      public function query($sql) {
          $q = $this->connection->query($sql);
          return $q->fetchAll(PDO::FETCH_OBJ);
      }
    ログイン後にコピー
データベーストランザクション関連の関数を直接カプセル化しているのでコメントはありません

        public function beginTransaction() {
        $this->connection->beginTransaction();
        return $this;
    }

    public function rollBack() {
        $this->connection->rollBack();
        return $this;
    }

    public function commit() {
        $this->connection->commit();
        return $this;
    }

    public function inTransaction() {
        return $this->connection->inTransaction();
    }
ログイン後にコピー
全コード

<?php
class Connector {
    // 数据库地址前缀,常见的有mysql,slqlsrv,odbc等等等
    private $driver = &#39;mysql&#39;;
    // 数据库地址
    private $host = &#39;localhost&#39;;
    // 数据库默认名称, 设置为静态是因为有切换数据库的需求
    private static $db = &#39;sakila&#39;;
    // 数据库用户名
    private $username = &#39;root&#39;;
    // 数据库密码
    private $password = &#39;&#39;;
    // 当前数据库连接
    protected $connection;
    // 数据库连接箱,切换已存在的数据库连接不需要重新通信,从这里取即可
    protected static $container = [];

    // PDO默认属性配置,具体请自行查看文档
    protected $options = [
        PDO::ATTR_CASE => PDO::CASE_NATURAL,
        PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
        PDO::ATTR_ORACLE_NULLS => PDO::NULL_NATURAL,
        PDO::ATTR_STRINGIFY_FETCHES => false,
    ];

    function construct() {
        // 如果从未连接过该数据库, 那就新建连接
        if(empty(self::$container[self::$db])) $this->connect();
        // 反之, 从$container中提取, 无需再次通信
        $this->connection = self::$container[self::$db];
    }

    // 生成DSN连接串
    protected function buildConnectString() {
        return "$this->driver:host=$this->host;dbname=".self::$db;
    }

    // 连接数据库
    public function connect() {
        try {
            // 连接数据库,生成pdo实例, 将之赋予$connection,并存入$container之中
            self::$container[self::$db] = $this->connection = new PDO($this->buildConnectString(), $this->username, $this->password, $this->options);

            // 返回数据库连接
            return $this->connection;
        } catch (Exception $e) {
            // 若是失败, 返回原因
            dd($e->getMessage());
        }
    }

    // 切换数据库
    public function setDatabase($db) {
        self::$db = $db;
        return $this;
    }

    // 读取数据
    public function read($sql, $bindings) {
        // 将sql语句放入预处理函数
        $statement = $this->connection->prepare($sql);
        // 将附带参数带入pdo实例
        $this->bindValues($statement, $bindings);
        // 执行
        $statement->execute();
        // 返回所有合法数据, 以Object对象为数据类型
        return $statement->fetchAll(PDO::FETCH_OBJ);
    }

    // 将附带参数带入pdo实例
    public function bindValues($statement, $bindings) {
        // 依次循环每一个参数
        foreach ($bindings as $key => $value) {
            $statement->bindValue(
                // 如果是字符串类型, 那就直接使用, 反之是数字, 将其+1
                is_string($key) ? $key : $key + 1,
                // 直接放入值
                $value,
                // 这里直白不多说
                is_int($value) ? PDO::PARAM_INT : PDO::PARAM_STR
            );
        }
    }

    // 改写数据
    public function update($sql, $bindings) {
        // 与read不同的地方在于, read返回数据, update返回boolean(true/false)
        $statement = $this->connection->prepare($sql);
        $this->bindValues($statement, $bindings);
        return $statement->execute();
    }

    // 删除数据
    public function delete($sql, $bindings) {
        $statement = $this->connection->prepare($sql);
        $this->bindValues($statement, $bindings);
        return $statement->execute();
    }

    // 增加数据
    public function create($sql, $bindings) {
        $statement = $this->connection->prepare($sql);
        $this->bindValues($statement, $bindings);
        $statement->execute();
        return $this->lastInsertId();
    }

    // 返回新增id, 如果有
    public function lastInsertId() {
        $id = $this->connection->lastInsertId();
        return empty($id) ? null : $id;
    }

    // 适用于增删改
    public function exec($sql) {
        return $this->connection->exec($sql);
    }

    // 适用于读
    public function query($sql) {
        $q = $this->connection->query($sql);
        return $q->fetchAll(PDO::FETCH_OBJ);
    }

    public function beginTransaction() {
        $this->connection->beginTransaction();
        return $this;
    }

    public function rollBack() {
        $this->connection->rollBack();
        return $this;
    }

    public function commit() {
        $this->connection->commit();
        return $this;
    }

    public function inTransaction() {
        return $this->connection->inTransaction();
    }
}
ログイン後にコピー

この問題に関する質問

1.) PHP 自体、デフォルトではすべてのコード クラスは実行後に自動的に破棄され、PDO は自動的に切断されるため、disconnect() を使用せずに PDO を切断させます。これは悪い習慣なのでしょうか?

2.) 2 つの関数データの追加と書き換えは一度に複数のデータの追加をサポートしておらず、一度にのみデータを追加できます。その理由は、複雑すぎると思う前に書いたので、いくつかの思慮深い子供たちのために削除しました。靴は解決策を提供します


以上が独自のデータベース パッケージを作成する方法 (2)の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。

ホットAIツール

Undresser.AI Undress

Undresser.AI Undress

リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover

AI Clothes Remover

写真から衣服を削除するオンライン AI ツール。

Undress AI Tool

Undress AI Tool

脱衣画像を無料で

Clothoff.io

Clothoff.io

AI衣類リムーバー

AI Hentai Generator

AI Hentai Generator

AIヘンタイを無料で生成します。

ホットツール

メモ帳++7.3.1

メモ帳++7.3.1

使いやすく無料のコードエディター

SublimeText3 中国語版

SublimeText3 中国語版

中国語版、とても使いやすい

ゼンドスタジオ 13.0.1

ゼンドスタジオ 13.0.1

強力な PHP 統合開発環境

ドリームウィーバー CS6

ドリームウィーバー CS6

ビジュアル Web 開発ツール

SublimeText3 Mac版

SublimeText3 Mac版

神レベルのコード編集ソフト(SublimeText3)

INNODBフルテキスト検索機能を説明します。 INNODBフルテキスト検索機能を説明します。 Apr 02, 2025 pm 06:09 PM

INNODBのフルテキスト検索機能は非常に強力であり、データベースクエリの効率と大量のテキストデータを処理する能力を大幅に改善できます。 1)INNODBは、倒立インデックスを介してフルテキスト検索を実装し、基本的および高度な検索クエリをサポートします。 2)一致を使用してキーワードを使用して、ブールモードとフレーズ検索を検索、サポートします。 3)最適化方法には、単語セグメンテーションテクノロジーの使用、インデックスの定期的な再構築、およびパフォーマンスと精度を改善するためのキャッシュサイズの調整が含まれます。

Alter Tableステートメントを使用してMySQLのテーブルをどのように変更しますか? Alter Tableステートメントを使用してMySQLのテーブルをどのように変更しますか? Mar 19, 2025 pm 03:51 PM

この記事では、MySQLのAlter Tableステートメントを使用して、列の追加/ドロップ、テーブル/列の名前の変更、列データ型の変更など、テーブルを変更することについて説明します。

MySQLでインデックスを使用するよりも、フルテーブルスキャンがいつ速くなるのでしょうか? MySQLでインデックスを使用するよりも、フルテーブルスキャンがいつ速くなるのでしょうか? Apr 09, 2025 am 12:05 AM

完全なテーブルスキャンは、MySQLでインデックスを使用するよりも速い場合があります。特定のケースには以下が含まれます。1)データボリュームは小さい。 2)クエリが大量のデータを返すとき。 3)インデックス列が高度に選択的でない場合。 4)複雑なクエリの場合。クエリプランを分析し、インデックスを最適化し、オーバーインデックスを回避し、テーブルを定期的にメンテナンスすることにより、実際のアプリケーションで最良の選択をすることができます。

Windows 7にMySQLをインストールできますか? Windows 7にMySQLをインストールできますか? Apr 08, 2025 pm 03:21 PM

はい、MySQLはWindows 7にインストールできます。MicrosoftはWindows 7のサポートを停止しましたが、MySQLは引き続き互換性があります。ただし、インストールプロセス中に次のポイントに注意する必要があります。WindowsのMySQLインストーラーをダウンロードしてください。 MySQL(コミュニティまたはエンタープライズ)の適切なバージョンを選択します。インストールプロセス中に適切なインストールディレクトリと文字セットを選択します。ルートユーザーパスワードを設定し、適切に保ちます。テストのためにデータベースに接続します。 Windows 7の互換性とセキュリティの問題に注意してください。サポートされているオペレーティングシステムにアップグレードすることをお勧めします。

MySQL接続用のSSL/TLS暗号化を構成するにはどうすればよいですか? MySQL接続用のSSL/TLS暗号化を構成するにはどうすればよいですか? Mar 18, 2025 pm 12:01 PM

記事では、証明書の生成と検証を含むMySQL用のSSL/TLS暗号化の構成について説明します。主な問題は、セルフ署名証明書のセキュリティへの影響を使用することです。[文字カウント:159]

人気のあるMySQL GUIツール(MySQL Workbench、PhpMyAdminなど)は何ですか? 人気のあるMySQL GUIツール(MySQL Workbench、PhpMyAdminなど)は何ですか? Mar 21, 2025 pm 06:28 PM

記事では、MySQLワークベンチやPHPMyAdminなどの人気のあるMySQL GUIツールについて説明し、初心者と上級ユーザーの機能と適合性を比較します。[159文字]

INNODBのクラスターインデックスと非クラスターインデックス(セカンダリインデックス)の違い。 INNODBのクラスターインデックスと非クラスターインデックス(セカンダリインデックス)の違い。 Apr 02, 2025 pm 06:25 PM

クラスター化されたインデックスと非クラスター化されたインデックスの違いは次のとおりです。1。クラスター化されたインデックスは、インデックス構造にデータを保存します。これは、プライマリキーと範囲でクエリするのに適しています。 2.非クラスター化されたインデックスストアは、インデックスキー値とデータの行へのポインターであり、非プリマリーキー列クエリに適しています。

MySQLの大きなデータセットをどのように処理しますか? MySQLの大きなデータセットをどのように処理しますか? Mar 21, 2025 pm 12:15 PM

記事では、MySQLで大規模なデータセットを処理するための戦略について説明します。これには、パーティション化、シャード、インデックス作成、クエリ最適化などがあります。

See all articles