1. 分级命名空间
php 中命名空间是可以定义成类似目录路径的形式,如( Mi\You\Him )
当我们在一个命名空间下需要访问另一空间下的成员时,比如说类,便需要在 类前加上对应的命名空间,这就会形成比较繁琐的代码书写。
因此,可以使用 use 关键字来简化类名。
先声明几个名空间:space.php
<?php namespace day1010\One; class Test1 { public static function demo() { return __METHOD__; } } namespace day1010\One\Two; class Test1 { public static function demo() { return __METHOD__; } }
使用 use 来引用需要的类:
<?php namespace day1010; include __DIR__.'/spaces.php'; // use // 默认从全局开始, 可以省略掉: \ // as 给当前的空间名称起一个别名 // 防止当前空间名称命名冲突 use day1010\One\Test1; // // 如果省略as ,那么当前类的别名就是当前类的去掉空间名称的类名 use day1010\One\Two\Test1 as T; echo Test1::demo(); // day1010\One\Test1::demo echo '<hr>'; echo T::demo(); // day1010\One\Two\Test1::demo echo '<hr>'; echo namespace\One\Test1::demo();
PS: namespace 关键字 和 __NAMESPACE__常量区别
1. 常量__NAMESPACE__的值是包含当前命名空间名称的字符串,这个应该很好理解。
2. 关键字 namespace 可用来显式访问当前命名空间或子命名空间中的元素。它等价于类中的 self 操作符。
可以将 namespace看成是当前命名空间的一个引用,在使用一个类时,我们可以这样写。
2. trait
php 只能实现单继承,无法同时从两个基类中继承属性和方法,为了解决这个问题,php实现了一种代码复用的方法,称为 trait。
trait 可以实现让一个类从 多个 trait类中进行继承,实现类似多继承的机制。
1. trait是一种代码复用的手段
2. trait 使用的是类的语法,不过它不是类,不能被实例化
<?php namespace day1010; use PDO; trait DB { public function connect($dsn, $username, $password) { return new PDO($dsn, $username, $password); } public function test() { return '这是 DB 中的 test()'; } } // 查询父类 class Query { public function get(PDO $pdo, $where = '') { $where = empty($where) ? '' : ' WHERE ' . $where; $sql = 'SELECT * FROM `staff`' . $where . ' LIMIT 5'; $stmt = $pdo->prepare($sql); $stmt->execute(); return $stmt->fetchAll(PDO::FETCH_ASSOC); } public function test() { return '这是 Query 中的 test()'; } } // 定义一个 trait类 trait Query_user { // 这里也定义一个 查询方法,不过改为默认查询 1条 public function get(PDO $pdo, $where = '') { $where = empty($where) ? '' : ' WHERE ' . $where; $sql = 'SELECT * FROM `staff`' . $where . ' LIMIT 1'; $stmt = $pdo->prepare($sql); $stmt->execute(); return $stmt->fetchAll(PDO::FETCH_ASSOC); } public function test() { return '这是 Query_user 中的 test()'; } } class Client extends Query { 当引用 不同trait时出现重名方法时,可以这样来区分 use DB, Query_user { DB::test insteadof Query_user; // 这里表示用 DB 中的 test方法代替 Query_user中的 Query_user::test as q_test; // 可以将 Query_user 中 test 改名来进行使用 } public $pdo = null; public function __construct($dsn, $username, $password) { // 这里就可以访问 DB 中的 connect方法 $this->pdo = $this->connect($dsn, $username, $password); } public function select($where) { // 这里是 访问的 父类中的 get(),还是 trait中的get()呢? return $this->get($this->pdo, $where); } // public function getClassName() { // return $this->test(); // return $this->q_test(); // } } $client = new Client('mysql:dbname=zmx', 'root', 'root'); // 结果显示,调用的是 trait中的方法,因此,可以得知 trait 是夹在父类与子类之间的,trait会覆盖父类方法 echo '<pre>' . print_r($client->select('staff_id >3'), true); echo $client->q_test();
总结:
1. trait 优先级比父类高,会覆盖父类中的成员方法
2. 一个类中可以继承多个 trait