国产三级农村妇女在线,国产精品毛片a∨一区二区三区,国产乱子伦视频大全,国产精品色拉拉,国产欧美日韩一区二区三区,

首頁 > 技術(shù) > IOS開發(fā)

PHP如何初始化PDO及原始SQL語句操作

IOS開發(fā) 2023-02-16 22:19:21
目錄
  • PDO 實例
    • dns 參數(shù)
  • PDO 對象屬性
    • 查詢語句
      • 普通查詢及遍歷
      • 查詢結(jié)果集(數(shù)組、對象)
      • 查詢結(jié)果集(類)
      • 查詢結(jié)果集(指定字段)
    • 增、刪、改操作
      • 增加操作
      • 修改操作
      • 刪除操作
    • 總結(jié)

      PDO 實例

      首先來看看一個 PDO 實例是如何初始化的。

      $dns = 'mysql:host=localhost;dbname=blog_test;port=3306;charset=utf8';
      $pdo = new PDO($dns, 'root', '');

      普通情況下,我們直接實例化的時候傳遞構(gòu)造參數(shù)就可以獲得一個 PDO 對象。這樣,我們就和數(shù)據(jù)庫建立了連接。如果連接失敗,也就是參數(shù)寫得有問題的時候,在實例化時直接就會報異常。

      PDO 對象的參數(shù)包括 DNS 信息、用戶名、密碼,另外還有一個參數(shù)就是可以設(shè)置 PDO 連接的一些屬性,我們將在后面看到它的使用。

      dns 參數(shù)

      PDO 構(gòu)造參數(shù)的第一個參數(shù)是一個 DNS 字符串。在這個字符串中使用分號 ; 分隔不同的參數(shù)內(nèi)容。它里面可以定義的內(nèi)容包括:

      • DSN prefix,也就是我們要連接的數(shù)據(jù)庫類型,MySQL 數(shù)據(jù)庫一般都是直接使用 mysql: 這樣來定義即可。
      • host,連接的地址,在這里我們連接的是本地數(shù)據(jù)庫 localhost
      • port,端口號,MySQL 默認為 3306 ,可以不寫
      • dbname,要連接的數(shù)據(jù)庫名稱
      • unix_socket,可以指定 MySQL 的 Unix Socket 文件
      • charset,連接的字符集

      我們可以通過一個函數(shù)來查看當前 PHP 環(huán)境中所支持的數(shù)據(jù)庫擴展都有哪些:

      print_r(PDO::getAvailableDrivers());exit;
      // Array
      // (
      //     [0] => dblib
      //     [1] => mysql
      //     [2] => odbc
      //     [3] => pgsql
      //     [4] => sqlite
      // )

      PDO 對象屬性

      PDO 構(gòu)造參數(shù)的最后一個參數(shù)可以設(shè)置連接的一些屬性,如:

      $pdo = new PDO($dns, 'root', '', [PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION]);
      showPdoAttribute($pdo);
      // ……
      // PDO::ATTR_ERRMODE: 2
      // ……

      showPdoAttribute() 方法是我們自己封裝的一個展示所有連接屬性的函數(shù)。

      // 顯示pdo連接屬性
      function showPdoAttribute($pdo){
          $attributes = array(
              "DRIVER_NAME", "AUTOCOMMIT", "ERRMODE", "CASE", "CLIENT_VERSION", "CONNECTION_STATUS",
              "ORACLE_NULLS", "PERSISTENT", "SERVER_INFO", "SERVER_VERSION"
          );
          
          foreach ($attributes as $val) {
              echo "PDO::ATTR_$val: ";
              echo $pdo->getAttribute(constant("PDO::ATTR_$val")) . "n";
          }
      }

      在這個函數(shù)中,我們使用 PDO 實例的 getAttribute() 方法來獲取相應(yīng)的屬性值。在沒有設(shè)置 PDO::ATTR_ERRMODE 時,它的默認值為 0 ,也就是 PDO::ERRMODE_SILENT 常量所對應(yīng)的值。在上述代碼中,我們將它設(shè)置為了 PDO::ERRMODE_EXCEPTION ,查看屬性輸出的結(jié)果就變成了 2 。

      除了在構(gòu)造函數(shù)的參數(shù)中設(shè)置屬性外,我們也可以使用 PDO 實例的 setAttribute() 方法來設(shè)置 PDO 的屬性值。

      pdo2 = new PDO($dns, 'root', '', [PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION]);
      
      echo $pdo2->getAttribute(PDO::ATTR_DEFAULT_FETCH_MODE), PHP_EOL;
      // 4
      
      // 設(shè)置屬性
      $pdo2->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC);
      echo $pdo2->getAttribute(PDO::ATTR_DEFAULT_FETCH_MODE), PHP_EOL;
      // 2

      在這段代碼中,我們設(shè)置 PDO::ATTR_DEFAULT_FETCH_MODE 為 PDO::FETCH_ASSOC 。這樣,在使用這個 $pdo2 的連接進行查詢時,輸出的結(jié)果都會是以數(shù)組鍵值對形式返回的內(nèi)容。我們馬上就進入查詢方面相關(guān)函數(shù)的學(xué)習(xí)。

      查詢語句

      大多數(shù)情況下,使用 PDO 我們都會用它的預(yù)處理能力來編寫 SQL 語句,一來是性能更好,二來是更加安全。不過我們今天先不講預(yù)處理方面的問題,還是以最原始的直接操作 SQL 語句的方式學(xué)習(xí)相關(guān)的一些函數(shù)。

      普通查詢及遍歷

      // 普通查詢 - 遍歷1
      $stmt = $pdo->query('select * from zyblog_test_user limit 5');
      foreach ($stmt as $row) {
          var_dump($row);
      }
      
      // array(8) {
      //     ["id"]=>
      //     string(3) "204"
      //     [0]=>
      //     string(3) "204"
      //     ["username"]=>
      //     string(5) "three"
      //     [1]=>
      //     string(5) "three"
      //     ["password"]=>
      //     string(6) "123123"
      //     [2]=>
      //     string(6) "123123"
      //     ["salt"]=>
      //     string(3) "ccc"
      //     [3]=>
      //     string(3) "ccc"
      //   }
      //   ……
      
      // 普通查詢 - 遍歷2
      $stmt = $pdo->query('select * from zyblog_test_user limit 5');
      
      while ($row = $stmt->fetch()) {
          var_dump($row);
      }
      
      // array(8) {
      //     ["id"]=>
      //     string(3) "204"
      //     [0]=>
      //     string(3) "204"
      //     ["username"]=>
      //     string(5) "three"
      //     [1]=>
      //     string(5) "three"
      //     ["password"]=>
      //     string(6) "123123"
      //     [2]=>
      //     string(6) "123123"
      //     ["salt"]=>
      //     string(3) "ccc"
      //     [3]=>
      //     string(3) "ccc"
      //   }
      //   ……

      PDO 實例的 query() 方法就是執(zhí)行一條查詢語句,并返回一個 PDOStatement 對象。通過遍歷這個對象,就可以獲得查詢出來的數(shù)據(jù)結(jié)果集。

      在代碼中,我們使用了兩種方式來遍歷,其實它們的效果都是一樣的。在這里,我們要關(guān)注的是返回的數(shù)據(jù)格式。可以看出,數(shù)據(jù)是以數(shù)組格式返回的,并且是以兩種形式,一個是數(shù)據(jù)庫定義的鍵名,一個是以下標形式。

      查詢結(jié)果集(數(shù)組、對象)

      其實大部分情況下,我們只需要數(shù)據(jù)庫鍵名的那種鍵值對形式的數(shù)據(jù)就可以了。這個有兩種方式,一是直接使用上文中我們定義好默認 PDO::ATTR_DEFAULT_FETCH_MODE 屬性的 $pdo2 連接,另一個就是在查詢的時候為 query() 方法指定屬性。

      $stmt = $pdo2->query('select * from zyblog_test_user limit 5');
      foreach ($stmt as $row) {
          var_dump($row);
      }
      // array(4) {
      //     ["id"]=>
      //     string(1) "5"
      //     ["username"]=>
      //     string(3) "two"
      //     ["password"]=>
      //     string(6) "123123"
      //     ["salt"]=>
      //     string(3) "bbb"
      //   }
      //   ……
      
      $stmt = $pdo->query('select * from zyblog_test_user limit 5', PDO::FETCH_ASSOC);
      foreach ($stmt as $row) {
          var_dump($row);
      }
      // array(4) {
      //     ["id"]=>
      //     string(1) "5"
      //     ["username"]=>
      //     string(3) "two"
      //     ["password"]=>
      //     string(6) "123123"
      //     ["salt"]=>
      //     string(3) "bbb"
      //   }
      //   ……

      當然,我們也可以直接讓數(shù)據(jù)返回成對象的格式,同樣的也是使用預(yù)定義的常量來指定 query() 或者 PDO 實例連接的屬性就可以了。

      $stmt = $pdo->query('select * from zyblog_test_user limit 5', PDO::FETCH_OBJ);
      foreach ($stmt as $row) {
          var_dump($row);
      }
      // object(stdClass)#4 (4) {
      //     ["id"]=>
      //     string(1) "5"
      //     ["username"]=>
      //     string(3) "two"
      //     ["password"]=>
      //     string(6) "123123"
      //     ["salt"]=>
      //     string(3) "bbb"
      //   }
      //   ……

      查詢結(jié)果集(類)

      上面返回對象形式的結(jié)果集中的對象是 stdClass 類型,也就是 PHP 的默認類類型。那么我們是否可以自己定義一個類,然后在查詢完成后直接生成它的結(jié)果集呢?就是像是 ORM 框架一樣,完成數(shù)據(jù)到對象的映射。既然這么說了,那當然是可以的啦,直接看代碼。

      class user
      {
          public $id;
          public $username;
          public $password;
          public $salt;
      
          public function __construct()
          {
              echo 'func_num_args: ' . func_num_args(), PHP_EOL;
              echo 'func_get_args: ';
              var_dump(func_get_args());
          }
      }
      
      class user2
      {
      
      }
      // 返回指定對象
      $u = new user;
      $stmt = $pdo->query('select * from zyblog_test_user limit 5', PDO::FETCH_INTO, $u);
      foreach ($stmt as $row) {
          var_dump($row);
      }
      // object(user)#3 (4) {
      //     ["id"]=>
      //     string(1) "5"
      //     ["username"]=>
      //     string(3) "two"
      //     ["password"]=>
      //     string(6) "123123"
      //     ["salt"]=>
      //     string(3) "bbb"
      //   }
      //   ……
      
      // 空類測試
      $u = new user2;
      $stmt = $pdo->query('select * from zyblog_test_user limit 5', PDO::FETCH_INTO, $u);
      foreach ($stmt as $row) {
          var_dump($row);
      }
      
      // object(user2)#2 (4) {
      //     ["id"]=>
      //     string(1) "5"
      //     ["username"]=>
      //     string(3) "two"
      //     ["password"]=>
      //     string(6) "123123"
      //     ["salt"]=>
      //     string(3) "bbb"
      //   }
      //   ……

      在這段代碼中,我們定義了兩個類,user 類有完整的和數(shù)據(jù)庫字段對應(yīng)的屬性,還定義了一個構(gòu)造方法(后面會用到)。而 user2 類則是一個空的類。通過測試結(jié)果來看,類的屬性對于 PDO 來說并不重要。它會默認創(chuàng)建數(shù)據(jù)庫查詢到的字段屬性,并將它賦值給對象。那么假如我們定義了一個 const 常量屬性并給予相同的字段名稱呢?大家可以自己嘗試一下。

      對于 user 和 user2 來說,我們將它實例化了并傳遞給了 query() ,并且指定了結(jié)果集格式為 PDO::FETCH_INTO ,這樣就實現(xiàn)了獲取對象結(jié)果集的能力。但是 PDO 遠比你想象的強大,我們還可以直接用類模板來獲取查詢結(jié)果集。

      // 根據(jù)類返回指定對象
      $stmt = $pdo->query('select * from zyblog_test_user limit 5', PDO::FETCH_CLASS, 'user', ['x1', 'x2']);
      foreach ($stmt as $row) {
          var_dump($row);
      }
      // func_num_args: 2
      // func_get_args: array(2) {
      //   [0]=>
      //   string(2) "x1"
      //   [1]=>
      //   string(2) "x2"
      // }
      // object(user)#4 (4) {
      //   ["id"]=>
      //   string(1) "5"
      //   ["username"]=>
      //   string(3) "two"
      //   ["password"]=>
      //   string(6) "123123"
      //   ["salt"]=>
      //   string(3) "bbb"
      // }
      // ……

      query() 方法直接使用查詢結(jié)果集模式為 PDO::FETCH_CLASS ,并傳遞一個類模板的名稱,PDO 就會在當前代碼中查找有沒有對應(yīng)的類模板,獲得的每個結(jié)果都會實例化一次。在這里,我們又多了一個參數(shù),最后一個參數(shù)是一個數(shù)組,并且給了兩個元素。估計有不少小伙伴已經(jīng)看出來了,這個參數(shù)是傳遞給類的構(gòu)造方法的。記住,使用這個模式,每個元素都會實例化一次,結(jié)果集中的每個元素都是新創(chuàng)建的類(object(user2)#3,#號后面的數(shù)字是不同的對象句柄id),而 PDO::FETCH_INTO 則是以引用的形式為每個元素賦值(object(user2)#3,#號后面的數(shù)字是相同的對象句柄id)。也就是說,我們使用 PDO::FETCH_INTO 模式的時候,修改一個元素的值,其它的元素也會跟著改變,如果使用一個數(shù)組去記錄遍歷的元素值,最后數(shù)組的結(jié)果也會是相同的最后一個元素的內(nèi)容。

      $stmt = $pdo->query('select * from zyblog_test_user limit 5', PDO::FETCH_INTO, $u);
      $resArr = [];
      foreach ($stmt as $row) {
          var_dump($row);
          $resArr[] = $row;
      }
      $resArr[0]->id = 55555;
      print_r($resArr);
      // Array
      // (
      //     [0] => user2 Object
      //         (
      //             [id] => 55555
      //             [username] => two
      //             [password] => 123123
      //             [salt] => bbb
      //         )
      
      //     [1] => user2 Object
      //         (
      //             [id] => 55555
      //             [username] => two
      //             [password] => 123123
      //             [salt] => bbb
      //         )
      
      //     [2] => user2 Object
      //         (
      //             [id] => 55555
      //             [username] => two
      //             [password] => 123123
      //             [salt] => bbb
      //         )
      
      //     [3] => user2 Object
      //         (
      //             [id] => 55555
      //             [username] => two
      //             [password] => 123123
      //             [salt] => bbb
      //         )
      
      //     [4] => user2 Object
      //         (
      //             [id] => 55555
      //             [username] => two
      //             [password] => 123123
      //             [salt] => bbb
      //         )
      
      // )

      如何解決這個問題呢?最簡單的方式就是在數(shù)組賦值的時候加個 clone 關(guān)鍵字唄!

      查詢結(jié)果集(指定字段)

      最后輕松一點,我們看下 query() 方法還可以指定查詢的某一個字段。

      // 只返回第幾個字段
      $stmt = $pdo->query('select * from zyblog_test_user limit 5', PDO::FETCH_COLUMN, 2);
      foreach ($stmt as $row) {
          var_dump($row);
      }
      // string(32) "bbff8283d0f90625015256b742b0e694"
      // string(6) "123123"
      // string(6) "123123"
      // string(6) "123123"
      // string(6) "123123"

      增、刪、改操作

      除了查詢之外的操作,我們也可以使用 exec() 方法來執(zhí)行其他一些相應(yīng)的 SQL 語句。

      增加操作

      $count = $pdo->exec("insert into zyblog_test_user(`username`, `password`, `salt`) value('akk', 'bkk', 'ckk')");
      $id = $pdo->lastInsertId();
      
      var_dump($count); // int(1)
      var_dump($id); // string(3) "205"

      exec() 返回的是影響的行數(shù),如果我們執(zhí)行這一條 SQL ,返回的就是成功添加了一行數(shù)據(jù)。如果要獲得新增加數(shù)據(jù)的 id ,就要使用 lastInserId() 方法來獲取。

      $count = $pdo->exec("insert into zyblog_test_user(`username`, `password`, `salt`) value('akk', 'bkk', 'ckk', 'dkk')");
      // Fatal error: Uncaught PDOException: SQLSTATE[21S01]: Insert value list does not match column list: 1136 Column count doesn't match value count at row 1

      執(zhí)行錯誤的 SQL 語句,就像根據(jù) PDO::ATTR_ERRMODE 屬性的設(shè)置來返回錯誤信息。我們在最上面的實例化 PDO 代碼中指定了錯誤形式是異常處理模式,所以這里直接就會報 PDOException 異常。

      修改操作

      // 正常更新
      $count = $pdo->exec("update zyblog_test_user set `username`='aakk' where id='{$id}'");
      
      var_dump($count); // int(1)
      
      // 數(shù)據(jù)不變更新
      $count = $pdo->exec("update zyblog_test_user set `username`='aakk' where id='{$id}'");
      var_dump($count); // int(0)
      
      // 條件錯誤更新
      $count = $pdo->exec("update zyblog_test_user set `username`='aakk' where id='123123123123'");
      var_dump($count); // int(0)
      echo '===============', PHP_EOL;

      同樣的,在執(zhí)行更新操作的時候,exec() 返回的也是受影響的行數(shù)。很多小伙伴會以這個進行判斷是否更新成功,但如果數(shù)據(jù)沒有修改,那么它返回的將是 0 ,SQL 語句的執(zhí)行是沒有問題的,邏輯上其實也沒有問題。比如我們在后臺打開了某條數(shù)據(jù)查看,然后并不想更新任何內(nèi)容就直接點了提交,這時候不應(yīng)該出現(xiàn)更新失敗的提示。也就是說,在前端判斷更新操作的時候,需要判斷字段是否都有改變,如果沒有改變的話那么不應(yīng)該提示更新失敗。這一點是業(yè)務(wù)邏輯上的考慮問題,如果你認為這樣也是更新失敗的話,那么這么報錯也沒有問題,一切以業(yè)務(wù)形式為主。

      刪除操作

      $count = $pdo->exec("delete from zyblog_test_user where id = '{$id}'");
      var_dump($count); // int(1)
      
      // 條件錯誤刪除
      $count = $pdo->exec("delete from zyblog_test_user where id = '5555555555'");
      var_dump($count); // int(0)

      刪除操作需要注意的問題和更新操作是一樣的,那就是同樣的 exec() 只是返回影響行數(shù)的問題,不過相對于更新操作來說,沒有受影響的行數(shù)那肯定是刪除失敗的,沒有數(shù)據(jù)被刪除。同樣的,這個失敗的提示也請根據(jù)業(yè)務(wù)情況來具體分析。

      總結(jié)

      不學(xué)不知道,一學(xué)嚇一跳吧,簡簡單的一個 PDO 的創(chuàng)建和語句執(zhí)行竟然有這么多的內(nèi)容。對于我們的日常開發(fā)來說,掌握這些原理能夠避免很多莫名其妙的問題,比如上面 exec() 只是返回影響行數(shù)在業(yè)務(wù)開發(fā)中如何判斷操作是否成功的問題就很典型。好了,這只是第一篇,后面的學(xué)習(xí)不要落下了哦!

      測試代碼

      以上就是PHP如何初始化PDO及原始SQL語句操作的詳細內(nèi)容,更多關(guān)于PHP 初始化PDO及原始SQL語句操作的資料請關(guān)注腳本之家其它相關(guān)文章!

      TAg

      加載中~

      本網(wǎng)站LOGO受版權(quán)及商標保護,版權(quán)登記號:國作登字-2022-F-10126915,未經(jīng)湖南木星科技官方許可,嚴禁使用。
      Copyright ? 2012-2022 湖南木星科技有限公司(木星網(wǎng))版權(quán)所有
      轉(zhuǎn)載內(nèi)容版權(quán)歸作者及來源網(wǎng)站所有,本站原創(chuàng)內(nèi)容轉(zhuǎn)載請注明來源,商業(yè)媒體及紙媒請先聯(lián)系:aishangyiwan@126.com

      工信部備案號:湘ICP備19012813號-5