<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                合規國際互聯網加速 OSASE為企業客戶提供高速穩定SD-WAN國際加速解決方案。 廣告
                # :-: 一、接口中的常量 * 接口常量的作用: 當作配置常量來使用 ```php namespace admin; if (!interface_exists(__NAMESPACE__.'\iDbParam')) { interface iDbParam{ const TYPE = 'mysql'; const HOST = 'localhost'; const USER_NAME = 'root'; const PASSWORD = 'root'; const DBNAME = 'php'; public static function connection (); } } class Connection implements namespace\iDbParam{ // 初始化連接參數 private static $type = iDbParam::TYPE; private static $host = iDbParam::HOST; private static $userName = iDbParam::USER_NAME; private static $password = iDbParam::PASSWORD; private static $dbname = iDbParam::DBNAME; // 實現接口中的抽象方法: connection public static function connection(){ $dsn = self::$type.':host='.self::$host.';dbname='.self::$dbname; $user = self::$userName; $password = self::$password; $pdo = new \PDO($dsn,$user,$password); return $pdo; } } // 以后連接數據庫只需要這個靜態方法即可, 注意命名空間 $link = Connection::connection(); // 執行一個查詢進行測試 $stmt = $link->prepare('SELECT * FROM `user` LIMIT :limit'); $stmt->bindValue('limit', 5, \PDO::PARAM_INT); $stmt->execute(); //die($stmt->debugDumpParams()); $users = $stmt->fetchAll(\PDO::FETCH_ASSOC); // 遍歷結果集 foreach ($users as $user) { // date(時間格式,時間戳): 將時間戳轉為指定格式的日期時間字符串 $last_time = date('Y/m/d',$user['last_time']); echo "<li>{$user['uid']}-{$user['name']}-{$user['phone']}-{$last_time}</li>"; } ``` >[info] 以后只要數據庫發生了變化, 我們只需要改一下連接接口參數就可以, 項目代碼不必做任何改動 ***** # :-: 二、后期靜態綁定 * 后期靜態綁定,也叫"延遲靜態綁定" * 這個技術應用在靜態繼承的上下文環境中,用于動態調用被重寫的方法 * 調用被重寫的靜態方法使用關鍵字: `static` 加上"范圍解析符"`::` * `::` 范圍解析符的使用場景 * 1. 訪問類方法與類常量 * 2. 訪問被重寫的對象或類方法 ```php # 為了簡化代碼,直接引用php官網上的例子: # http://cn2.php.net/manual/zh/language.oop5.late-static-bindings.php class A { public static function who() { echo __CLASS__; } public static function test() { // self::who(); // 那么如何在這種靜態繼承的上下文環境中, 靜態調用類中方法的時候,正確識別調用者呢? // 可以將self 關鍵字改為: static , // 注意: static 除了可以用在靜態方法中, 也可以用在普通對象方法中 static::who(); } } class B extends A { // 在子類中重寫了父類A中的靜態方法who() public static function who() { echo __CLASS__; } } B::test(); echo '<hr>'; ``` >[info] 總結: static關鍵字用來調用重寫方法的時候,可以動態的綁定當前調用的類 * 這種綁定是在運行階段發生, 而不是代碼編寫的詞法分析階段(靜態的代碼文本),所以要后期延遲靜態綁定 * 這種延遲綁定,有什么卵用呢? 用處非常大,特別是在現代的PHP框架開中, 隨處可見 * 下面舉一個簡單的小案例,來看一下它的使用場景 ```php // 以最簡單的數據庫連接,來演示延遲靜態綁定的應用 class Connect{ public static function connect(){ // self::調用是當前Connec類中的config方法,而并非在子類被重寫的config方法 // 因為用戶在子類中重新定義了連接參數, 所以查詢會失敗 // return self::config(); // 使用static:: 根據調用者,動態的調用被重寫的方法,這樣就可以調用到被重寫的方法了 return static::config(); } public static function config(){ return new \PDO('mysql:dbname=ouyangke','root', '123456'); } } class Link extends Connect{ public static function config(){ return new \PDO('mysql:dbname=php','root', 'root'); } } $pdo = Link::connect(); //var_dump($pdo instanceof PDO); $users = $pdo->query('select * from user limit 5'); foreach ($users as $user) { print_r($user); echo '<br>'; } ``` >[info] 總結: user::, 可以在靜態繼承的上下文環境中, 調用被子類重寫的靜態方法(大家可以試試能否調用被重寫的普通方法) ***** # :-: 三、命名空間的層級關系 * 命名空間是可以分層管理的,也叫子命名空間 * __NAMESPACE__: 雙下劃線開頭的魔術常量, 所謂魔術是指,盡管是常量,但它的值可以隨作用域發生變化 ```php namespace admin; echo '當前命名空間是: ' . __NAMESPACE__ . '<br>'; class Dog {} echo Dog::class . '<hr>'; namespace admin\one; echo '當前命名空間是: ' . __NAMESPACE__ . '<br>'; class Dog {} echo Dog::class . '<br>'; // 關鍵字: namespace: 可以顯示的訪問當前空間或子空間中的元素 echo namespace\Dog::class, '<br>'; // 如果我想訪問空間:admin\one\two類 // 可以將當前空間看成當前目錄,用關鍵字namespace來引用當前空間 // 當前命名空間是: admin\one\, 所以從two開始就可以找到指定的類 echo namespace\two\Dog::class . '<hr>'; namespace admin\one\two; echo '當前命名空間是: ' . __NAMESPACE__ . '<br>'; class Dog {} echo Dog::class . '<hr>'; ``` * "\\"是命名空間分隔符, 將空間分層有什么卵用呢? * 作用非常大, 現代PHP編程中的類的自動加載技術就靠它撐著呢,框架沒有它, 難以想像 * 多層級的命名空間,非常像多層級的目錄結構,如果類名稱中的空間部分與類文件的絕對路徑一致,就可以實現 * 類文件的全自動加載,并且不會千萬命名沖突,因為類名本身仍是帶有命名空間的 ***** # :-: 四、使用空間別名簡化命名空間 ```php namespace admin; # 允許通過別名引用或導入外部的完全限定名稱 # 當類帶有空間或子空間時, 類名稱有可能會變得很長,可以使用空間別名導入來簡化類名 // 例如, 當前腳本需要加載'demo4.php'中的: admin\one\two\Dog類 include __DIR__ . '/Test.php'; # 檢測 Dog類是否導入成功 $className = namespace\one\two\three\Test::class; # 如果類存在,則調用類中的靜態方法demo() echo class_exists($className) ? $className::demo().' 類存在' : '類不存在'; // 大家應該注意到了, 這個類名非常的長, 不僅書寫起來非常的不方便, 而且引用時候, 也容易出錯,代碼也臃腫 // 特別是當前腳本,如果需要在多處引用這個類的時候, 不得不每次都寫一遍這么長的類名, 太麻煩了 // 解決方案: 給當前類起一個簡短的別名, 起別名使用的關鍵字是: use // 下面使用別名: "T" 代替之前冗長的類名稱 // use 默認是從全局空間開始查找類,不得使用當前空間的引用關鍵字namespace // 可以在use 的第一個空間名稱前加上全局空間標識符: \, 盡管你根本不需要這樣去做 use admin\one\two\three\Test as T; // 允許用 Test 代替 完整的Test1類名 // 現在起, 在當前腳本中, 我就可以直接用Test1 來取代之前的: admin\one\two\three\Test echo class_exists(T::class) ? T::demo().' 類存在' : '類不存在'; // 別名允許與原始類名相同 //use admin\one\two\three\Test as Test; // 如果類的別名, 與原始類名相同, 例如本例, 都是 Test, 允許省略后面的 as 部分 use admin\one\two\three\Test; echo class_exists(Test::class) ? Test::demo().' 類存在' : '類不存在'; // 那么什么時候使用 as 來定義 別名呢? // 當前腳本中導入的空間別名沖突的時候使用 use o\p\q\Demo; use x\y\z\Demo as Hell; ``` > Tast.php文件 ```php namespace admin\one\two\three; class Test{ public static function demo(){ return __METHOD__; } } class Test2{ public static function demo(){ return __METHOD__; } } ``` ***** # :-: 五、命名空間的實戰小案例 ```php // 命名空間實戰 namespace admin; // 導入全局空間中的PDO類 use PDO; // 連接數據庫: 目前在空間中寫代碼, PDO類中全局中, 建議加上"\",或者在前面用use導入類的別名 // 將連接參數放在接口常量中 interface iDbParams{ const DSN = 'mysql:host=localhost;dbname=ouyangke'; const URSE = 'root'; const PASS = 'root'; } $pdo = new PDO(iDbParams::DSN,iDbParams::URSE,iDbParams::PASS); //查詢點數據展示出來,以測試數據庫操作正確 // :num, :offset, 這里必須是整數類型, 而SQL語句默認都是字符串, 需要進行類型限定 $sql = 'SELECT `uid`,`name`,`phone` FROM `user` LIMIT :num OFFSET :offset'; $stmt = $pdo->prepare($sql); $stmt->bindValue('num',5, PDO::PARAM_INT); $stmt->bindValue('offset',0, PDO::PARAM_INT); $stmt->execute(); // 遍歷結果集 foreach ($stmt->fetchAll() as $user) { echo "<p>{$user['uid']} -- {$user['name']} -- {$user['phone']}</p>"; } exit; ``` ***** # :-: 六、Trait 技術 * 為什么要用 Trait? * php是單繼承的語言, 即一個類只允許從一個父類中繼承成員 * trait是一個與"類"類似的數據結構,內部可以聲明一些方法或屬性,供調用者使用 * Trait 解析了什么問題? * 解決php只能從一個類中繼承成員的問題 * 最大程度的實現了代碼復用 * 對一些無法用類進行封裝的功能,使用Trait封裝更加的方便,實用 * trait 的創建語句與class類是完全一樣的 * trait 使用 trait 關鍵字來聲明, 同樣, 也不允許實例化,只能是調用類調用 ```php namespace admin; use PDO; trait Db{ // 連接數據庫 public function connect($dsn, $username, $password){ return new \PDO($dsn, $username, $password); } } trait Query{ // 查詢滿足條件的第一條記錄 public function get($pdo, $where = ''){ // 處理查詢條件 $where = empty($where) ? '' : ' WHERE '.$where; // 拼裝SQL語句, 創建預處理對象PDOStatment $stmt = $pdo->prepare('SELECT * FROM `user` ' . $where . ' LIMIT 1'); $stmt->execute(); // 生成的SQL語句: SELECT * FROM `user` WHERE age < 30 LIMIT 1 // die($stmt->debugDumpParams()); // 將獲取的結果集以一維數組的形式返回給調用者 return $stmt->fetch(PDO::FETCH_ASSOC); } // 其它方法,例如 insert, update, delete, select , 大家可自行擴展 } // 客戶端調用類 class Client{ // 在宿主類中引入上面聲明的二個Trait方法庫 use Db; use Query; // 也可以寫到一行引入, 推薦分行引入, 便于寫注釋和代碼調試 // use Db, Query; // 調用類會有多個方法要用到數據庫連接對象,所以應該將它聲明一個獨立于方法的共享屬性 public $pdo = null; // 調用類實例化, 應該實現自動連接數據庫的功能, 這里調用的Trait類中的connect() // 當前Trait類Db已經導入了, 所以它里面聲明的connect()方法, 就像是Client類自己的方法一樣,直接用$this調用 public function __construct($dsn, $username, $password){ $this->pdo = $this->connect($dsn, $username, $password); } // 調用類的find()方法, 實現查詢滿足條件的第一條記錄的功能 // find()方法是調用 Trait類Query中的get()方法實現 public function find($where){ return $this->get($this->pdo, $where); } } // 客戶端通過客戶類的實例化,來調用Trait中的方法 // 設置數據庫連接參數 $dsn = 'mysql:host=localhost;dbname=ouyangke'; $username = 'root'; $password = 'root'; // 實例化并連接數據庫, 底層是調用 Trait類Db::connect() $client = new Client($dsn, $username, $password); // 獲取滿足條件的第一條記錄, 底層是調用 Trait類Query::get() echo '<pre>'.print_r($client->find('age < 30'), true); ```
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看