Trait 的使用

lcbp發表於2019-01-22

什麼是 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 協議》,轉載必須註明作者和本文連結

相關文章