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
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号