PHP代码复用特殊类Trait的简要说明和相关举例

Posted 小雨青年

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了PHP代码复用特殊类Trait的简要说明和相关举例相关的知识,希望对你有一定的参考价值。

一、什么是Trait

php 实现了一种代码复用的方法,称为 trait。

Trait 是为类似 PHP 的单继承语言而准备的一种代码复用机制。Trait 为了减少单继承语言的限制,使开发人员能够自由地在不同层次结构内独立的类中复用 method。Trait 和 Class 组合的语义定义了一种减少复杂性的方式,避免传统多继承和 Mixin 类相关典型问题。

Trait 和 Class 相似,但仅仅旨在用细粒度和一致的方式来组合功能。 无法通过 trait 自身来实例化。它为传统继承增加了水平特性的组合;也就是说,应用的几个 Class 之间不需要继承。

代码实例如下:

trait cat

    private $name = '糖果';

    public function age()
    
        return 2;
    


二、Trait解决的问题

Trait解决的是PHP的类只能单继承没有多继承的问题。

看一个Trait的实际用法

<?php

trait catOne 

    private $name = "糖果";

    static $color = '黑色';

    protected $color2 = '灰色';

    public function demo() 
        echo 'trait,猫'.$this->name."是".self::$color."的并且带一点".$this->color2."____";
    

class CatTwo 
    use catOne;
    public function demo1() 
        echo "我是一个父类____";
    

class CatTwoTwo extends CatTwo 
    public function demo1() 
        echo "我是一个子类____";
    

$body = new CatTwoTwo();
$body->demo1();
$body->demo1();
$body->demo();

输出内容为

我是一个子类____我是一个子类____trait,猫糖果是黑色的并且带一点灰色____

三、注意事项

  • Trait是一个特殊类,只能嵌入到宿主类中使用

  • 通过在类中使用use关键字,声明要组合的Trait名称,trait里面可以使用:静态成员,抽象成员,普通成员.不能使用常量

  • Trait内的属性会和调用它的类内的同名的属性冲突,优先顺序:当前类成员 > trait类成员 > 基类成员

  • 一个类可以组合多个Trait,通过逗号相隔,trait不能在接口中使用

  • 自 PHP 8.1.0 起,弃用直接在 trait 上调用静态方法或者访问静态属性。 静态方法和属性应该仅在使用了 trait 的 class 中访问。

四、Laravel中 Trait 的使用

我们常用的Model类,位置在src/Illuminate/Database/Eloquent/Model.php,部分代码如下:

use Exception;
use ArrayAccess;
use JsonSerializable;
use Illuminate\\Support\\Arr;
use Illuminate\\Support\\Str;
use Illuminate\\Contracts\\Support\\Jsonable;
use Illuminate\\Contracts\\Support\\Arrayable;
use Illuminate\\Support\\Traits\\ForwardsCalls;
use Illuminate\\Contracts\\Routing\\UrlRoutable;
use Illuminate\\Contracts\\Queue\\QueueableEntity;
use Illuminate\\Database\\Eloquent\\Relations\\Pivot;
use Illuminate\\Contracts\\Queue\\QueueableCollection;
use Illuminate\\Support\\Collection as BaseCollection;
use Illuminate\\Database\\ConnectionResolverInterface as Resolver;

abstract class Model implements ArrayAccess, Arrayable, Jsonable, JsonSerializable, QueueableEntity, UrlRoutable

    use Concerns\\HasAttributes,
        Concerns\\HasEvents,
        Concerns\\HasGlobalScopes,
        Concerns\\HasRelationships,
        Concerns\\HasTimestamps,
        Concerns\\HidesAttributes,
        Concerns\\GuardsAttributes,
        ForwardsCalls;

Model类是一个抽象类,调用了多个 Trait 类,实现了Model类的多个功能。比如第一个Concerns\\HasAttributes,查看源码如下,截取部分代码可以看出实现了 Model 中的方法。

    /**
     * Add the casted attributes to the attributes array.
     *
     * @param  array  $attributes
     * @param  array  $mutatedAttributes
     * @return array
     */
    protected function addCastAttributesToArray(array $attributes, array $mutatedAttributes)
    
        foreach ($this->getCasts() as $key => $value) 
            if (! array_key_exists($key, $attributes) || in_array($key, $mutatedAttributes)) 
                continue;
            

            // Here we will cast the attribute. Then, if the cast is a date or datetime cast
            // then we will serialize the date for the array. This will convert the dates
            // to strings based on the date format specified for these Eloquent models.
            $attributes[$key] = $this->castAttribute(
                $key, $attributes[$key]
            );

            // If the attribute cast was a date or a datetime, we will serialize the date as
            // a string. This allows the developers to customize how dates are serialized
            // into an array without affecting how they are persisted into the storage.
            if ($attributes[$key] &&
                ($value === 'date' || $value === 'datetime')) 
                $attributes[$key] = $this->serializeDate($attributes[$key]);
            

            if ($attributes[$key] && $this->isCustomDateTimeCast($value)) 
                $attributes[$key] = $attributes[$key]->format(explode(':', $value, 2)[1]);
            
        

        return $attributes;
    

对应到实际应用中,我们自己的Model继承了Model类,可以直接调用。

        $model = new Book();
        $model->addCastAttributesToArray($attributes, $mutatedAttributes);

五、总结

理解Trait并掌握使用方法,可以帮助我们理解框架的写法,并指导自己更好地复用代码。

以上是关于PHP代码复用特殊类Trait的简要说明和相关举例的主要内容,如果未能解决你的问题,请参考以下文章

php中trait

PHP之Trait特性

PHP之Trait详解

PHP 中的关于 trait 的简单

php实现多继承-trait语法

什么是 Trait