六月婷婷综合激情-六月婷婷综合-六月婷婷在线观看-六月婷婷在线-亚洲黄色在线网站-亚洲黄色在线观看网站

明輝手游網中心:是一個免費提供流行視頻軟件教程、在線學習分享的學習平臺!

如何寫一個屬于自己的數據庫封裝(2)

[摘要]Connector.php負責與數據庫通信,增刪改讀(CRUD)首先, 建一個Connector類, 并且設置屬性<?phpclass Connector {// 數據庫地址前綴,常見的有mysql,slqlsrv,odbc等等等private $driver = mysql;// 數據庫地...

Connector.php

  • 負責與數據庫通信,增刪改讀(CRUD)

首先, 建一個Connector類, 并且設置屬性

<?php
class Connector {
    // 數據庫地址前綴,常見的有mysql,slqlsrv,odbc等等等
    private $driver = 'mysql';
    // 數據庫地址
    private $host = 'localhost';
    // 數據庫默認名稱, 設置為靜態是因為有切換數據庫的需求
    private static $db = 'sakila';
    // 數據庫用戶名
    private $username = 'root';
    // 數據庫密碼
    private $password = '';
    // 當前數據庫連接
    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];
      }

接下來兩個函數式配合著用的,單看可能會懵逼, 配合例子單步調試

$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 - 刪除數據

    // 與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 - 返回新增id, 如果有

      // pdo自帶,只是稍微封裝
      public function lastInsertId() {
          $id = $this->connection->lastInsertId();
          return empty($id) ? null : $id;
      }

過于高級復雜的SQL語句可能無法封裝, 因此準備了可直接用RAW query通信數據庫的兩個函數

  • exec - 適用于增刪改

      public function exec($sql) {
          return $this->connection->exec($sql);
      }
  • query - 適用于讀

      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 = 'mysql';
    // 數據庫地址
    private $host = 'localhost';
    // 數據庫默認名稱, 設置為靜態是因為有切換數據庫的需求
    private static $db = 'sakila';
    // 數據庫用戶名
    private $username = 'root';
    // 數據庫密碼
    private $password = '';
    // 當前數據庫連接
    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斷開連接, 不知這樣是不是一種 bad practice?
2.) 增加和改寫數據的兩個函數并不支持多組數據一次性加入,只能單次增該, 原因是我之前寫了嫌太繁瑣所以刪了, 有心的童鞋可以提供方案

以上就是如何寫一個屬于自己的數據庫封裝(2)的詳細內容,更多請關注php中文網其它相關文章!


學習教程快速掌握從入門到精通的SQL知識。




主站蜘蛛池模板: 四虎影院免费看 | 亚洲男人天堂影院 | 欧美伊人久久久久久久久影院 | 欧美亚洲一区二区三区四 | 午夜精品久久久久久影视riav | 七月丁香八月婷婷综合激情 | 中文字幕日韩精品一区口 | 亚洲国产成人va在线观看网址 | 色综合久久天天影视网 | 亚洲va久久久噜噜噜久久狠狠 | 青青草免费观看视频 | 亚洲自偷精品视频自拍 | 亚洲成av人影片在线观看 | 欧美伊人影院 | 伊人网影院 | 中文字幕一区在线观看视频 | 四月激情网| 日韩在线视频网址 | 天天玩天天操 | 手机国产乱子伦精品视频 | 伊人精品在线 | 伊人三级 | 日韩深夜视频 | 日韩视频在线播放 | 亚洲网在线| 亚洲国产天堂久久综合226 | 欧美性大战久久久久久久 | 图片区小说区欧洲区 | 亚洲91| 武则天一级淫片免费看 | 色黄网站在线观看 | 日韩一区二区久久久久久 | 欧美无人区码卡二三卡四卡 | 一级毛片一级毛片一级毛片aaav | 四虎最新网址 | 四虎黄色网址 | 中日韩美中文字幕 | 天天看片天天爽_免费播放 天天看片天天爽 | 青娱乐手机免费视频 | 全部免费毛片在线 | 香蕉大成网人站在线 |