Trait 的使用

什么是 Traits

自 PHP 5.4.0 起,PHP 实现了一种代码复用的方法,称为 trait。

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

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

Hello World 的例子

<?php

Trait Hello {
    public function sayHello() {
        echo 'Hello ';
    }
}

Trait World {
    public function sayWorld() {
        echo 'World';
    }
}

class MyHelloWorld {
    use Hello, World;
    public function sayExclamationMark() {
        echo '!';
    }
}

$o = new MyHelloWorld();
$o->sayHello();
$o->sayWorld();
$o->sayExclamationMark();
?>

这将输出:

Hello World!

Laravel 模型关系使用 Trait :

很多个模型中都有如下代码:

public function user(){
    return $this->belongsTo(User::class,'user_id');
}

如何能够在其他模型中复用这个代码呢?当然,您可以直接复制粘贴这段代码到新模型中,但长期这样做可能会造成一些麻烦,特别是我们希望增加更多复用代码的时候。

例如下面 3 个迁移,分别为:用户、员工、客户。

Schema::create('users', function (Blueprint $table) {
    $table->increments('id');
    $table->string('name');
    $table->string('email')->unique();
    $table->string('password');
    $table->rememberToken();
    $table->timestamps();
});
Schema::create('employees', function (Blueprint $table) {
    $table->increments('id');
    $table->integer('user_id');
    $table->string('employee_code');
    $table->string('phone');
    $table->timestamps();
});
Schema::create('clients', function (Blueprint $table) {
    $table->increments('id');
    $table->integer('user_id');
    $table->string('company_name');
    $table->string('phone');
    $table->timestamps();
});

其中,员工和客户都关联了 users 表,都具有 user_id 字段。

下面我们将创建一个 Trait 来存放用户关系相关的代码。

新建一个文件 app\Support\Traits\BelongsToUser.php

它的代码看起来是这样的:

<?php

namespace App\Support\Traits;

trait BelongsToUser{

    public function user(){
        return $this->belongsTo(\App\User::class,'user_id');
    }

}

在 客户 模型中使用 BelongsToUser 这个 Trait

<?php

namespace App;

use App\Support\Traits\BelongsToUser;
use Illuminate\Database\Eloquent\Model;

class Client extends Model
{
    use BelongsToUser;
}

在 员工 模型中使用 BelongsToUser 这个 Trait

<?php

namespace App;

use App\Support\Traits\BelongsToUser;
use Illuminate\Database\Eloquent\Model;

class Employee extends Model
{

    use BelongsToUser;

}

现在您可以非常方便地使用 $employee->user$client->user 了。

UUID 中使用 Trait

什么是 UUID ?

通用唯一识别码(英语:Universally Unique Identifier,UUID),是用于计算机体系中以识别信息数目的一个128位标识符,还有相关的术语:全局唯一标识符(GUID)。

根据标准方法生成,不依赖中央机构的注册和分配,UUID具有唯一性,这与其他大多数编号方案不同。重复UUID码概率接近零,可以忽略不计。

UUID 长这个样 ceb580c4-8b8d-4c9c-85c9-5d3c39b6ed9c

如果我们不想向公众公开我们的 ID,这时候使用 UUID 是非常好的主意!例如,假设我们在构建论坛系统,我不希望用户能够查看到地址中的 /users/1 ,表示这是本论坛的第一个用户。

使用 UUID

第一步:

使用 ramsey/uuid 包

$ composer require ramsey/uuid

第二步:

新建一个文件 app\Support\Traits\UuidTrait.php

它的代码如下:

<?php

namespace App\Support\Traits;

use Ramsey\Uuid\Uuid;

trait UuidTrait
{

}

这个 Trait 应该做些什么呢。首先我们需要将设置的 字段 定义为 UUID。然后,我们需要在模型创建的时候,自动为这个模型生成 UUID。
最后我们需要提供一个 boot() 方法,重写模型自身的 boot() 方法。

<?php

namespace App\Support\Traits;

use Ramsey\Uuid\Uuid;

trait UuidTrait
{
    /**
     * 在模型创建时,生成 UUID v4 。
     */
    protected static function boot()
    {
        parent::boot();

        self::uuid();
    }

    /**
     * 设置 UUID 对应的模型的字段。
     * @return string
     */
    protected static function uuidField()
    {
        return 'uuid';
    }

    /**
     * 重写模型的 boot()。
     */
    protected static function uuid()
    {
        static::creating(function ($model) {
            $model->{self::uuidField()} = Uuid::uuid4()->toString();
        });
    }
}

User.php 模型中使用:

<?php

namespace App;

use App\Support\Traits\UuidTrait;
use Illuminate\Notifications\Notifiable;
use Illuminate\Foundation\Auth\User as Authenticatable;

class User extends Authenticatable
{
    use Notifiable, UuidTrait;

    ...
}

Users 表的迁移文件:

<?php

use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;

class CreateUsersTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('users', function (Blueprint $table) {
            $table->increments('id');
            $table->string('name');
            $table->string('email')->unique();
            $table->string('password');
            $table->uuid('uuid');
            $table->rememberToken();
            $table->timestamps();
        });
    }

    ...
}

完。

本作品采用《CC 协议》,转载必须注明作者和本文链接
本帖由系统于 4年前 自动加精
《L05 电商实战》
从零开发一个电商项目,功能包括电商后台、商品 & SKU 管理、购物车、订单管理、支付宝支付、微信支付、订单退款流程、优惠券等
《G01 Go 实战入门》
从零开始带你一步步开发一个 Go 博客项目,让你在最短的时间内学会使用 Go 进行编码。项目结构很大程度上参考了 Laravel。
讨论数量: 5

感谢 +1

5年前 评论

你这个uuid的使用也是用model的Observer,那直接写个UserObserver就是了。trait更多的是为了方便代码复用

4年前 评论

感谢,看完了后知道Trait是干嘛的了.

4年前 评论

观察器 saving就能处理了 访问器或修改器也可以

4年前 评论

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!