spatie/eloquent-sortable

为Eloquent模型提供排序行为

4.4.0 2024-06-04 11:09 UTC

README

Latest Version GitHub Workflow Status Software License Total Downloads

此包提供了一个特性,可以将排序行为添加到Eloquent模型。

新记录模型的排序列的值由该模型所有记录的排序列的最大值加1确定。

该包还提供了一个查询作用域,用于按正确顺序获取所有记录。

Spatie是位于比利时安特卫普的一家网络设计公司。您可以在我们的网站上找到我们所有开源项目的概述 在此

支持我们

通过观看我们的付费视频课程,了解如何创建此类包

Laravel Package training

我们投入了大量资源来创建 最佳开源包。您可以通过 购买我们的付费产品之一 来支持我们。

我们非常感谢您从您所在城市寄给我们一张明信片,说明您正在使用我们的哪个包。您可以在我们的 联系我们页面 上找到我们的地址。我们将所有收到的明信片发布在我们的 虚拟明信片墙上

安装

对于Laravel 6.x或PHP 7.x,请使用此包的3.x版本。

此包可以通过Composer安装。

composer require spatie/eloquent-sortable

在Laravel 5.5及更高版本中,服务提供程序将自动注册。在框架的旧版本中,只需在config/app.php文件中添加服务提供程序即可。

'providers' => [
    ...
    Spatie\EloquentSortable\EloquentSortableServiceProvider::class,
];

可选地,您可以使用以下命令发布配置文件:

php artisan vendor:publish --tag=eloquent-sortable-config

这是将在config/eloquent-sortable.php中发布的文件内容

return [
  /*
   * The name of the column that will be used to sort models.
   */
  'order_column_name' => 'order_column',

  /*
   * Define if the models should sort when creating. When true, the package
   * will automatically assign the highest order number to a new model
   */
  'sort_when_creating' => true,

  /*
   * Define if the timestamps should be ignored when sorting.
   * When true, updated_at will not be updated when using setNewOrder
   */
  'ignore_timestamps' => false,
];

使用方法

要将排序行为添加到您的模型,您必须

  1. 实现Spatie\EloquentSortable\Sortable接口。
  2. 使用特性Spatie\EloquentSortable\SortableTrait
  3. 可选地指定将用作排序列的列。默认为order_column

示例

use Spatie\EloquentSortable\Sortable;
use Spatie\EloquentSortable\SortableTrait;

class MyModel extends Model implements Sortable
{
    use SortableTrait;

    public $sortable = [
        'order_column_name' => 'order_column',
        'sort_when_creating' => true,
    ];

    // ...
}

如果您未设置值$sortable['order_column_name'],则包会假设您的排序列名称为order_column

如果您未设置值$sortable['sort_when_creating'],则包将自动将最高的排序号分配给新模型;

假设MyModel的数据库表为空

$myModel = new MyModel();
$myModel->save(); // order_column for this record will be set to 1

$myModel = new MyModel();
$myModel->save(); // order_column for this record will be set to 2

$myModel = new MyModel();
$myModel->save(); // order_column for this record will be set to 3


//the trait also provides the ordered query scope
$orderedRecords = MyModel::ordered()->get();

您可以使用setNewOrder方法设置所有记录的新顺序

/**
 * the record for model id 3 will have order_column value 1
 * the record for model id 1 will have order_column value 2
 * the record for model id 2 will have order_column value 3
 */
MyModel::setNewOrder([3,1,2]);

可选地,您可以将起始顺序号作为第二个参数传递。

/**
 * the record for model id 3 will have order_column value 11
 * the record for model id 1 will have order_column value 12
 * the record for model id 2 will have order_column value 13
 */
MyModel::setNewOrder([3,1,2], 10);

您可以通过传递闭包作为第四个参数来修改将执行的查询。

/**
 * the record for model id 3 will have order_column value 11
 * the record for model id 1 will have order_column value 12
 * the record for model id 2 will have order_column value 13
 */
MyModel::setNewOrder([3,1,2], 10, null, function($query) {
    $query->withoutGlobalScope(new ActiveScope);
});

要使用除主键之外的列进行排序,请使用setNewOrderByCustomColumn方法。

/**
 * the record for model uuid '7a051131-d387-4276-bfda-e7c376099715' will have order_column value 1
 * the record for model uuid '40324562-c7ca-4c69-8018-aff81bff8c95' will have order_column value 2
 * the record for model uuid '5dc4d0f4-0c88-43a4-b293-7c7902a3cfd1' will have order_column value 3
 */
MyModel::setNewOrderByCustomColumn('uuid', [
   '7a051131-d387-4276-bfda-e7c376099715',
   '40324562-c7ca-4c69-8018-aff81bff8c95',
   '5dc4d0f4-0c88-43a4-b293-7c7902a3cfd1'
]);

setNewOrder一样,setNewOrderByCustomColumn也将接受可选的起始顺序参数。

/**
 * the record for model uuid '7a051131-d387-4276-bfda-e7c376099715' will have order_column value 10
 * the record for model uuid '40324562-c7ca-4c69-8018-aff81bff8c95' will have order_column value 11
 * the record for model uuid '5dc4d0f4-0c88-43a4-b293-7c7902a3cfd1' will have order_column value 12
 */
MyModel::setNewOrderByCustomColumn('uuid', [
   '7a051131-d387-4276-bfda-e7c376099715',
   '40324562-c7ca-4c69-8018-aff81bff8c95',
   '5dc4d0f4-0c88-43a4-b293-7c7902a3cfd1'
], 10);

您还可以使用这些方法上移或下移模型

$myModel->moveOrderDown();
$myModel->moveOrderUp();

您还可以使用这些方法将模型移动到第一个或最后一个位置

$myModel->moveToStart();
$myModel->moveToEnd();

您可以确定一个元素是第一还是最后一个

$myModel->isFirstInOrder();
$myModel->isLastInOrder();

您可以交换两个模型的顺序

MyModel::swapOrder($myModel, $anotherModel);

分组

如果您的模型/表有一个分组字段(通常是一个外键):id, user_id, title, order_column并且您希望上述方法考虑它,您可以在您的模型中创建一个buildSortQuery方法

// MyModel.php

public function buildSortQuery()
{
    return static::query()->where('user_id', $this->user_id);
}

这将限制计算仅适用于模型实例的字段值。

已派发的事件

一旦完成排序,就会派发一个事件(Spatie\EloquentSortable\EloquentModelSortedEvent),您可以监听它。这可以用于运行排序后的逻辑,如清除缓存或其他排序后需要采取的操作。

事件有一个isFor辅助函数,它允许您方便地检查已排序的Eloquent类。

下面是如何监听此事件的示例

use Spatie\EloquentSortable\EloquentModelSortedEvent as SortEvent;

class SortingListener
{
    public function handle(SortEvent $event): void {
        if ($event->isFor(MyClass::class)) {
            // ToDo: flush our cache
        }
    }
}

测试

该包包含一些与Orchestra集成的/烟雾测试,通过phpunit运行。

vendor/bin/phpunit

变更日志

请参阅变更日志以获取有关最近更改的更多信息。

贡献

请参阅贡献指南以获取详细信息。

安全漏洞

请审查我们的安全策略了解如何报告安全漏洞。

鸣谢

替代方案

许可证

MIT许可证(MIT)。请参阅许可证文件以获取更多信息。