flyhjaelp / laravel-eloquent-orderable
通过在模型上使用可排序特性,使Eloquent模型可排序。当当前模型的排序更新或新模型插入或删除时,它将自动更新其组内所有其他模型的排序。
Requires (Dev)
- orchestra/testbench: ^3.8
- phpunit/phpunit: ^8.1
This package is auto-updated.
Last update: 2024-09-30 01:18:49 UTC
README
Laravel Eloquent Orderable 是一个帮助您使Eloquent模型可排序的包,无论是在组内还是在同一类的所有其他模型内。
安装
通过composer安装
composer require flyhjaelp/laravel-eloquent-orderable
数据库设置
如果要在模型上使用可排序功能,它必须有一个数据库列可以按其排序。默认情况下,该包将寻找名为 "order" 的列,但此名称可以重写。排序列应是无符号整数,可以是空值。示例
Schema::create('orderable_test_models', function (Blueprint $table) { $table->unsignedInteger('order')->nullable(); });
默认用法
<?php use Flyhjaelp\LaravelEloquentOrderable\Interfaces\OrderableInterface; use Flyhjaelp\LaravelEloquentOrderable\Traits\Orderable; use Illuminate\Database\Eloquent\Model; class Foobar extends Model implements OrderableInterface { //implement the orderable interface use Orderable; //use the orderable trait }
创建一个没有指定排序的新模型
新实例将自动添加一个排序,默认情况下它们被添加为最后一个排序。
$foobarA = (new Foobar())->save(); $foobarB = (new Foobar())->save(); $foobarC = (new Foobar())->save(); Foobar::all()->pluck('order','id'); // will output [1 => 1, 2 => 2, 3 => 3]
创建一个具有指定排序的新模型
如果创建时指定了排序,则该排序将相应地更新已存在的排序。
$foobarD = new Foobar(); $foobarD->order = 2; $foobarD->save(); Foobar::all()->pluck('order','id'); // will output [1 => 1, 4 => 2, 2 => 3, 3 => 4]
更新模型的排序
当更新模型的排序时,其他模型将自动相应地更新它们的排序。
$foobarC->order = 2;` $foobarC->save(); Foobar::all()->pluck('order','id'); // will output [1 => 1, 3 => 2, 4 => 3, 2 => 3]
删除模型
当删除模型时,所有其他具有更高排序的模型的排序将减少一个。
$foobarA->delete(); Foobar::all()->pluck('order','id'); // will output [3 => 1, 4 => 2, 2 => 3]
分组使用
您可以在模型中创建一个组,排序只适用于该组。例如,您可能有一个名为MenuItem的模型,它应该按menu_id分组,排序应只适用于其组。要将组添加到模型中,您必须包含orderableWithinGroup特性并实现以下函数
- scopeOrdered(Builder $query)
- scopeWithinOrderGroup(Builder $query, OrderableInterface $orderableModel)
- columnsAffectingOrderGroup()
<?php use Flyhjaelp\LaravelEloquentOrderable\Interfaces\OrderableInterface; use Flyhjaelp\LaravelEloquentOrderable\Traits\OrderableWithinGroup; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Builder; use Illuminate\Support\Collection; class MenuItem extends Model implements OrderableInterface { //implement the orderable interface use OrderableWithinGroup; //use the orderableWithinGroup trait public function scopeOrdered(Builder $query): void{ $query->orderBy('menu_id')->orderBy('order'); } public function scopeWithinOrderGroup(Builder $query, OrderableInterface $orderableModel): void{ $query->where('menu_id',$orderableModel->menu_id); } public function columnsAffectingOrderGroup(): Collection{ return collect(['menu_id']); } }
模型现在在其组内排序
新实例将自动添加一个排序,默认情况下它们被添加为组内的最后一个排序。
<?php $foobarA = new Foobar(); $foobarA->menu_id = 1; $foobarA->save(); $foobarB= new Foobar(); $foobarB->menu_id = 1; $foobarB->save(); $foobarC = new Foobar(); $foobarC->menu_id = 2; $foobarC->save(); Foobar::all()->pluck('order','id'); // will output [1 => 1, 2 => 2, 3 => 1]
在关联模型中的使用
如果您希望能够在检索时对多对多关系进行排序,则可以创建可排序的关联模型。排序只能单向工作,这意味着如果您例如有一个包含多个检查点的旅程,则可以在检索旅程时使检查点按照正确的顺序显示,但不能反过来。
设置关联模型排序
为了使关联模型可排序,您必须在模型上使用PivotOrderable特性。还需要在关联关系表中有自增主键(通常是一个 "id")。此外,您必须实现以下提到的OrderableWithinGroup方法
<?php use Flyhjaelp\LaravelEloquentOrderable\Interfaces\OrderableInterface; use Flyhjaelp\LaravelEloquentOrderable\Traits\PivotOrderable; use Illuminate\Database\Eloquent\Relations\Pivot; use Illuminate\Database\Eloquent\Builder; class JourneyCheckpointsRelationship extends Pivot implements OrderableInterface{ use PivotOrderable; public $incrementing = true; public function scopeWithinOrderGroup($query, OrderableInterface $orderableModel) { return $query->where('journey_id', $orderableModel->journey_id); } public function scopeOrdered(Builder $query): void { $query->orderBy('journey_id')->orderBy($this->getOrderableColumn()); } public function columnsAffectingOrderGroup(): Collection { return collect(['journey_id']); } }
当从模型调用关系时,您必须在模型上定义关系时,在belongsToMany调用上链式使用using方法。此外,如果您希望在检索时对关系进行排序,还必须添加orderBy方法调用。
<?php use Illuminate\Database\Eloquent\Model; class Journey extends Model{ public function checkpoints() { return $this ->belongsToMany(Checkpoint::class) ->using(JourneyCheckpointsRelationship::class) ->withPivot('order') ->orderBy('pivot_order'); } }
重写默认值
您必须更改用于存储排序的默认列以及默认排序作用域。
重写默认排序列
public function getOrderableColumn(): string { return 'non_default_order_column'; }
重写全局排序作用域
public function scopeOrdered(Builder $query): void{ $query->orderBy('menu_id')->orderBy('order'); }
贡献
欢迎提交拉取请求。对于主要更改,请首先打开一个问题以讨论您想要更改的内容。
请确保根据需要更新测试。