利用 AI 幫我們寫了許多程式,今天來介紹一下 PHP 8 引入的 attribute,以及在 Laravel 內怎麼使用。
PHP attribute,或者翻譯成屬性/注解,是 PHP 8 引入的新語法,讓開發者可以在 PHP 程式內,不管是類別、方法、屬性、參數或者常數等元素,加上額外的描述資訊(metadata)。
在其他的程式語言內,對應 Java 的 Annotation 或 C# 的 Attribute。
#[Attribute]
class Service {
public function __construct(
#[Attribute] public string $path
) {}
}
利用這個特性,過去一些必須要透過程式標記才能達成的效果,可以很直觀的在對應的位置加上 attribute 就能達成。
我們來看幾個例子。
當我們使用 Eloquent ORM,取出的資料超過一筆時,通常會取出一個 Illuminate\Database\Eloquent\Collection
物件
use App\Models\User;
$users = User::where('active', 1)->get();
foreach ($users as $user) {
echo $user->name;
}
如果我們想要自定義 Collection,來加上我們自己的邏輯,可以這樣做
use Illuminate\Database\Eloquent\Collection;
class OrderCollection extends Collection
{
public function unpaid()
{
return $this->filter(fn ($order) => !$order->isPaid());
}
public function totalRevenue()
{
return $this->sum(fn ($order) => $order->amount);
}
}
要將自定義的 Collection 和 Model 綁定,我們可以在 Model 內宣告一段程式
或者更簡單的,直接加上 CollectedBy
這個屬性
namespace App\Models;
use App\Support\OrderCollection;
use Illuminate\Database\Eloquent\Attributes\CollectedBy;
use Illuminate\Database\Eloquent\Model;
#[CollectedBy(OrderCollection::class)]
class Order extends Model
{
// ...
}
有時候我們會希望在 Model 改變時同步一些行為,比方說一旦某用戶被刪除了,我們就在後台新增一筆用戶刪除資料。
這類行為可以使用 Observer 達成
<?php
namespace App\Observers;
use App\Models\User;
use Illuminate\Support\Facades\Log;
class UserObserver
{
/**
* Handle the User "deleted" event.
*/
public function deleted(User $user): void
{
Log::info("User deleted: {$user->id}");
}
}
要將 Observer 和 Model 綁定,我們可以在 Service Provider 內註冊,或者使用更直觀的 ObservedBy
use App\Observers\UserObserver;
use Illuminate\Database\Eloquent\Attributes\ObservedBy;
#[ObservedBy([UserObserver::class])]
class User extends Authenticatable
{
// ...
}
這樣,當我們未來在除錯時,就不需要從 Service Provider 內找哪邊產生這個更動的邏輯,只要從 ORM 上面的 attribute 就可以找到了。
當然 Laravel 內使用到 attribute 的地方還有很多,這邊只是簡單的介紹兩種,希望未來大家對這個寫法更加熟悉,未來遇到相似邏輯時可以想到或許存在這樣的寫法。
今天的部分就到這邊,我們明天見!