yassinedabbous/laravel-dynamic-fields

v1.0.0 2024-06-09 18:25 UTC

This package is auto-updated.

Last update: 2024-09-14 23:12:39 UTC


README

简化你的API & 通过仅选择所需内容来减少SQL查询的整体大小。

✨ 特点

作为API用户(前端开发者),无需了解哪些字段是列、追加或模型关系,这个包可以帮助他处理以下操作:

  • 选择列
  • 追加属性
  • 加载关系
  • 应用聚合

通过单个URL参数 _fields 自动完成

🔻 安装

composer require yassinedabbous/laravel-dynamic-fields

🧑‍💻 设置

HasDynamicFields 特性添加到你的模型类中并定义你的列

use YassineDabbous\DynamicFields\HasDynamicFields;

class User extends Model
{
    use HasDynamicFields;
    

    /** Allowed table columns */
    public function dynamicColumns(): array
    {
        return ['id', 'name', 'avatar', 'birthday', 'created_at'];
    }

    public function dynamicRelations(){
        return ['posts', 'recent_comments'];
    }

	/** Appends and their dependencies */
    public function dynamicAppendsDepsColumns() { 
        return [
            'age' => 'birthday',
        ];
	}

    /** aggregates closures */
    public function dynamicAggregates(){
        return [
            'posts_count' => fn($q) => $q->withCount('posts'),
            'points' => fn($q) => $q->withSum('matches', 'score'),
        ];
    }



    // Model attributes & relations ...

    public function age(): Attribute
    {
        return Attribute::get(fn() => Carbon::parse($this->birthdate)->age);
    }
    
    public function comments()
    {
        return $this->hasMany(Comment::class);
    }

}

动态选择不会自动应用,你需要调用 dynamicSelect()dynamicAppend()

class UserController
{
    public function index()
    {
        $collection = User::dynamicSelect()->paginate();
        $collection->dynamicAppend();
        return $collection;
    }
}

🧑‍💻 使用

• API调用

GET /users?fields=id,name,age,points,recent_comments

• 数据库查询

// select only "id", "name"
SELECT "id", "name" FROM "users"

// aggregates
SELECT SUM("score") FROM "matches" where ...

// relation loaded
SELECT * FROM "comments" where "date" > ...

• 响应:("年龄", "积分", "最近的评论" 自动追加)

{
    "id": 1,
    "name": "Someone",
    "age": 99,
    "points": 1048,
    "recent_comments": {...}
}