s-damian/larasort

Laravel 列表排序

v1.0.13 2024-08-17 08:32 UTC

This package is auto-updated.

Last update: 2024-09-17 08:38:19 UTC


README

Laravel 列表排序 - 可排序 - 按排序

Tests Static analysis Total Downloads Latest Stable Version License

Larasort : Laravel 列表排序 - 轻松排序

简介 - Larasort 包

此包允许您自动化 SQL 查询的 ORDER BY,同时还能自动化生成可排序链接。

此开源库允许您使用 Laravel 自动化方式制作 可排序列

您有一个包,但有两个功能:Larasort(用于与 Eloquent ORM 进行排序)和 LarasortManual(用于不使用 Eloquent ORM 进行排序)。

自动化的方式轻松排序 🚀

使用 Larasort 的简单示例

  • 模型示例
private array $sortables = [ // The attributes that are sortable.
    'email',
    'first_name',
    'created_at',
];
  • 控制器示例
$customers = Customer::whereNotNull('confirmed_at')
    ->autosort() // Automate ORDER BY and its direction.
    ->paginate();
  • 视图示例(blade 模板中)
@sortableLink('email', 'Email')

表格中链接的示例渲染

Larasort

作者

此包由 Stephen Damian 开发

要求

  • PHP 8.0 || 8.1 || 8.2 || 8.3
  • Laravel 8 || 9 || 10 || 11

摘要

安装

通过 Composer 安装

composer require s-damian/larasort

使用 "vendor:publish" 进行自定义

自定义配置和语言以及 CSS

安装包后,您必须运行 vendor:publish 命令

php artisan vendor:publish --provider="SDamian\Larasort\LarasortServiceProvider"

vendor:publish 命令将生成以下文件

  • config/larasort.php

  • public/vendor/larasort/css/larasort.css您必须在网站中包含此 CSS

  • public/vendor/larasort/images/order.webp

您当然可以自定义这些文件。

使用 "--tag" 参数的 "vendor:publish"

仅发布 config 文件

php artisan vendor:publish --provider="SDamian\Larasort\LarasortServiceProvider" --tag=config

仅发布 CSS 文件

php artisan vendor:publish --provider="SDamian\Larasort\LarasortServiceProvider" --tag=css

仅发布 images 文件

php artisan vendor:publish --provider="SDamian\Larasort\LarasortServiceProvider" --tag=images

Larasort - 用于 Eloquent ORM

Larasort 在使用 Eloquent ORM 时非常有用。

基本用法

首先,您的模型必须使用 AutoSortable 特性。

然后,在您的模型中声明 $sortables。此属性用于定义允许在 ORDER BY 中排序的列(数据库表中的列)。

PS:数组 $sortables 的第一列将用作 SQL ORDER BY 的默认列。

示例

<?php

use SDamian\Larasort\AutoSortable;

class Customer extends Model
{
    use AutoSortable;
    
    /**
     * The attributes that are sortable.
     */
    private array $sortables = [
        'id', // "id" column will be the default column for the ORDER BY.
        'first_name', 
        'email',
        'created_at',
    ];
}

您可以使用此静态方法覆盖用于 ORDER BY 的默认列

PS:使用 setDefaultSortable 方法的优点是,即使 URL 中没有 ?orderby={column}&order={direction},默认列的链接中也会出现相同的图标。

<?php

use SDamian\Larasort\Larasort;

Larasort::setDefaultSortable('email') // "email" column will be the default column for the ORDER BY.

如果默认情况下(当 URL 中没有 ?orderby={column} 时),您不希望在 SQL 查询中添加 ORDER BY

<?php

use SDamian\Larasort\AutoSortable;

class Customer extends Model
{
    use AutoSortable;
    
    /**
     * The attributes that are sortable.
     */
    private array $sortables = [
        null, // Will be null by default (by default there will be no ORDER BY).
        'id',
        'first_name', 
        'email',
        'created_at',
    ];
}

然后,您可以使用 Eloquent 的 ->autosort() 魔法方法

<?php

use App\Models\Customer;

class CustomerController extends Controller
{
    public function index()
    {
        $customers = Customer::whereNotNull('confirmed_at')
            ->autosort() // Automate ORDER BY and its direction.
            ->paginate();

        return view('customer.index', [
            'customers' => $customers,
        ]);
    }
}

在视图中,您可以在tablethead部分执行此操作,例如。

PS:您必须在包含blade指令的HTML标签(例如tablethead标签)上放置CSS类with-larasort

<thead class="with-larasort">
    <tr>
        <th>
            @sortableLink('first_name', 'First name')
        </th>
        <th>
            @sortableLink('email', 'Email')
        </th>
        <th>
            @sortableLink('created_at', 'Register on')
        </th>
    </tr>
</thead>

PS:第一个参数是数据库中的column,第二个参数是titlelabel)。第二个参数是可选的。如果您没有指定,将自动根据列名生成标签。

如果您需要在th内部保持更多控制,作为等效方案,可以将@sortableLink替换为@sortableHref@sortableIcon。示例

<th>
    <a @sortableHref('email')>
        Email
        @sortableIcon('email')
    </a>
</th>

别名

对于某些列,如果您不想指定以表前缀,则必须使用$sortablesAs属性。

在具体情况下,别名在执行带有连接的SQL查询时特别有用。

使用 ->join() 的示例

  • 在客户模型中的示例
<?php

use SDamian\Larasort\AutoSortable;

class Customer extends Model
{
    use AutoSortable;
    
    /**
     * The attributes that are sortable.
     */
    private array $sortables = [
        'id',
        'first_name', 
        'email',
        'created_at',
    ];

    /**
     * The attributes that are sortable without table in prefix.
     */
    private array $sortablesAs = [
        'article_title', // Here.
    ];
}
  • 在客户控制器中的示例
<?php

class CustomerController extends Controller
{
    public function index()
    {
        $customers = Customer::select([
                'customers.*',
                'articles.title AS article_title', // Here.
            ])
            ->join(
                'articles',
                'customers.id', '=', 'articles.customer_id'
            )
            ->autosort() // Automate ORDER BY and its direction.
            ->paginate();

        return view('customer.index', [
            'customers' => $customers,
        ]);
    }
}
  • 视图示例(blade 模板中)
@sortableLink('article_title', 'Article Title')

关系

使用Larasort,您可以自动为您的关系One To One和One To Many设置ORDER BY

为此,您可以使用autosortWith方法。

一对一

在这个例子中,一个user创建了一个article,一个article由一个user创建。

这因此建立了usersarticles之间的One To One关系。

  • 在用户模型中的示例
<?php

/**
 * The attributes of its sortable relations.
 */
private array $sortablesRelated = [
    // Convention: {relationship name}{separator}{column in this relationship table}.
    'article.title',
];

public function article()
{
    return $this->hasOne(Article::class, 'user_id_created_at', 'id');
}
  • 在用户控制器中的示例
<?php

$users = User::autosortWith('article', [
        'join_type' => 'join', // Optional - "leftJoin" by default.
        'columns' => ['id', 'username', 'email', 'role'], // Optional - "*" by default.
        'related_columns' => ['title AS article_title', 'h1'], // Optional - "*" by default.
    ])
    ->paginate();
  • 视图示例(blade 模板中)
@sortableLink('article.title', 'Article Title')

PS:对于@sortableLink的第一个参数,使用与模型$sortablesRelated属性中的相同约定。

一对多

在这个例子中,一个user创建了许多articles,一个article由一个user创建。

这因此建立了usersarticles之间的One To Many关系(每个用户有多个文章,每个文章只有一个用户)。

  • 在用户模型中的示例
<?php

/**
 * The attributes of its sortable relations.
 */
private array $sortablesRelated = [
    // Convention: {relationship name}{separator}{column in this relationship table}.
    'articles.title',
];

public function articles()
{
    return $this->hasMany(Article::class, 'user_id_created_at', 'id');
}
  • 在用户控制器中的示例
<?php

$users = User::autosortWith('articles', [
        'join_type' => 'join', // Optional - "leftJoin" by default.
        'columns' => ['id', 'username', 'email', 'role'], // Optional - "*" by default.
        'related_columns' => ['title AS article_title', 'h1'], // Optional - "*" by default.
    ])
    ->paginate();
  • 视图示例(blade 模板中)
@sortableLink('articles.title', 'Article Title')

PS:对于@sortableLink的第一个参数,使用与模型$sortablesRelated属性中的相同约定。

属于

对于One To OneOne To Many关系,您必须在文章模型中放置belongsTo方法。

  • 在文章模型中的示例
<?php

private array $sortablesRelated = [
    // Convention: {relationship name}{separator}{column in this relationship table}.
    'user.email',
];

public function user()
{
    return $this->belongsTo(User::class, 'user_id_created_at', 'id');
}
  • 在文章控制器中的示例
<?php

$articles = Article::autosortWith('user', [
        'join_type' => 'join', // Optional - "leftJoin" by default.
        'columns' => ['id', 'slug', 'h1', 'updated_at'], // Optional - "*" by default.
        'related_columns' => ['email AS user_email', 'first_name'], // Optional - "*" by default.
    ])
    ->paginate();
  • 视图示例(blade 模板中)
@sortableLink('user.email', 'User Email')

PS:对于@sortableLink的第一个参数,使用与模型$sortablesRelated属性中的相同约定。

关系 - 规范

模型$sortablesRelated属性

对于放置在$sortablesRelated属性中的列,约定是:{关系名称}{分隔符}{此关系表中的列}

Larasort将使用{关系名称}对其表进行ORDER BY

默认情况下,分隔符是点。如果您愿意,可以在配置中将其更改为relation_column_separator

->autosortWith()方法选项

要执行连接,您必须在->autosortWith()的第一个参数中指定关系的名称。

内部,您必须传递您的关系名称(您在模型中放置的关系方法名称)。Larasort将使用此名称进行join

选项

PS:如果将->autosortWith()的第一个参数放置在不同于属性$sortablesRelated{关系名称}的关系名称中,则关系上不会发生ORDER BY

  • "join_type"(可选)

要执行除了默认连接(配置中指定的)之外的其他连接,可以指定join_type选项。

  • "columns"(可选)

如果您想指定要为您的模型SELECT的列,可以指定columns选项。

您可以使用数组或字符串。数组示例:['id', 'email', 'username'] 字符串示例:'id, email, username'

默认情况下,将选择所有列。

  • "related_columns"(可选)

如果您想指定为您的模型的关系SELECT哪些列,可以指定related_columns选项。

您可以使用数组或字符串。数组示例:['title AS article_title', 'content'] 字符串示例:'title AS article_title, content'

默认情况下,将选择所有列。

对于一列,指定其表

使用Larasort,您可以针对列指定它们的表(这在执行带有连接的SQL查询时很有用)。

默认情况下,Larasort将会在包含AutoSortable特质的表上执行ORDER BY

让我们举一个例子,在一个SQL查询中,你想要检索文章(来自articles表)和分类(来自categories表),并且对于这两个表,你想要检索id列。但你想要在categories表上而不是在articles表上执行ORDER BY id

你可以通过以下两种解决方案来解决这个问题

解决方案 1 - 使用$sortablesToTables属性

你可以选择在模型中设置$sortablesToTables属性

<?php

use SDamian\Larasort\AutoSortable;

class Article extends Model
{
    use AutoSortable;
    
    /**
     * The attributes that are sortable.
     */
    private array $sortables = [
        'id',
        'title',
        'updated_at',
    ];

    /**
     * The sortable attributes to which their table is specified.
     */
    private array $sortablesToTables = [
        'id' => 'categories.id', // Here.
    ];
}

解决方案 2 - 使用Larasort::setSortablesToTables(array $sortablesToTables)

可以在使用->autosort()的SQL查询之前(例如在控制器或模型中)选择性地设置Larasort::setSortablesToTables(array $sortablesToTables)方法。

在ArticleController中的示例

<?php

use SDamian\Larasort\Larasort;

class ArticleController extends Controller
{
    public function index()
    {
        Larasort::setSortablesToTables(['id' => 'categories.id']); // Here.

        // Here your SQL query with ->autosort()
        // Then the rest of the code...
    }
}

如果同时使用$sortablesToTables属性和Larasort::setSortablesToTables(array $sortablesToTables)方法对同一列进行操作,则Larasort::setSortablesToTables(array $sortablesToTables)方法将覆盖$sortablesToTables属性。

使用这两种解决方案,SQL查询的结果将是:ORDER BY `categories`.`id` ASC而不是ORDER BY `articles`.`id` ASC

对于某些列,默认使用 "desc" 或 "asc"

对于某些列,可能希望默认顺序(或在其链接的第一次点击上)为desc而不是asc

可以在使用->autosort()的SQL查询之前选择性地进行设置(例如在控制器或模型中)。

在InvoiceController中的示例

<?php

use SDamian\Larasort\Larasort;

class InvoiceController extends Controller
{
    public function index()
    {
        Larasort::setSortablesDefaultOrder([
            'desc' => ['id', 'created_at', 'price_with_vat'], // Here.
        ]);

        // Here your SQL query with ->autosort()
        // Then the rest of the code...
    }
}

如果你更改“default_order”在“config/larasort.php”文件中 - 为某些列设置默认的“asc”

config/larasort.php配置文件中,你可以更改default_order的值(默认为asc)。

如果你这样做,则某些列的顺序可能希望为asc而不是desc

在InvoiceController中的示例

<?php

use SDamian\Larasort\Larasort;

class InvoiceController extends Controller
{
    public function index()
    {
        Larasort::setSortablesDefaultOrder([
            'asc' => ['customer_email', 'customer_first_name'], // Here.
        ]);

        // Here your SQL query with ->autosort()
        // Then the rest of the code...
    }
}

清除 Larasort 静态方法

如果需要,你可以清除(重置)Larasort的静态方法

<?php

Larasort::clearDefaultSortable();

Larasort::clearSortablesToTables();

Larasort::clearSortablesDefaultOrder();

Larasort - API 文档

模型属性

Larasort 类

对于SDamian\Larasort\Larasort

AutoSortable 特性

对于SDamian\Larasort\AutoSortable特质

Blade 指令

LarasortManual - 用于不使用 Eloquent ORM

Larasort在未使用Eloquent ORM时非常有用。

如果你想要进行手动SQL查询(或如果你想要进行文件列表),存在一个替代方案:LarasortManual

LarasortManual - 基本用法

使用LarasortManualsetSortables(array $sortables)方法可以用来定义允许在ORDER BY中排序的列。简单示例

<?php

use SDamian\Larasort\Manual\LarasortManual;

class CustomerController extends Controller
{
    public function index()
    {
        $larasortMan = new LarasortManual();
        $larasortMan->setSortables(['id', 'first_name', 'email', 'created_at']); // Here.
        $resultLarasortMan = $larasortMan->get();

        $customers = DB::select('
            SELECT *
            FROM customers
            ORDER BY '.$resultLarasortMan['order_by'].' '.$resultLarasortMan['order'].'
        ');

        return view('customer.index', [
            'customers' => $customers,
            'larasortManAttrs' => $resultLarasortMan['attrs'],
        ]);
    }
}

在视图中的theadtable中可以这样做,例如

<thead class="with-larasort">
    <tr>
        <th>
            <a {!! $larasortManAttrs['first_name']['href'] !!}>
                First name
                {!! $larasortManAttrs['first_name']['icon'] !!}
            </a>
        </th>
        <th>
            <a {!! $larasortManAttrs['email']['href'] !!}>
                Email
                {!! $larasortManAttrs['email']['icon'] !!}
            </a>
        </th>
        <th>
            <a {!! $larasortManAttrs['created_at']['href'] !!}>
                Register on
                {!! $larasortManAttrs['created_at']['icon'] !!}
            </a>
        </th>
        <th>Actions</th>
    </tr>
</thead>

PS:如果你希望,你也可以访问$larasortManAttrs['column_name']['url']

LarasortManual - 对于一列,指定其表

使用LarasortManual也可以为列指定它们的表(这在执行带有join的SQL查询时很有用)。

与默认情况下在包含AutoSortable特质的表上执行SQL查询的Larasort不同,LarasortManual默认将执行不指定前缀表的ORDER BY column

因此,当你连接多个表时,如果你在多个表上SELECT相同的列名,你可能会遇到类似“完整性约束违反:1052 列 '{colomn}' 在顺序子句中是模糊的”的错误。

让我们举一个例子,在一个SQL查询中,你想要检索文章(来自articles表)和分类(来自categories表),并且对于这两个表,你想要检索id列。并且你想要在categories表上执行ORDER BY id

你可以使用$larasortMan->setSortablesToTables(array $sortablesToTables)方法来做这件事。示例

<?php

use SDamian\Larasort\Manual\LarasortManual;

class ArticleController extends Controller
{
    public function index()
    {
        $larasortMan = new LarasortManual();
        $larasortMan->setSortables(['id', 'title', 'created_at']);
        $larasortMan->setSortablesToTables(['id' => 'categories.id']); // Here.
        $resultLarasortMan = $larasortMan->get();

        // Here your SQL query with $resultLarasortMan['order_by'] and $resultLarasortMan['order']
        // Then the rest of the code...
    }
}

$resultLarasortMan['order_by']将生成SQL查询ORDER BY `categories`.`id` ASC而不是ORDER BY `id` ASC

LarasortManual - 对于某些列,默认使用 "desc" 或 "asc"

使用 LarasortManual,您也可以对某些列进行排序(即 ORDER BY 的方向),默认(或在首次点击其链接时)为 desc 而不是 asc

您可以通过 $larasortMan->setSortablesDefaultOrder(array $sortablesDefaultOrder) 方法来实现这一点。示例

<?php

use SDamian\Larasort\Manual\LarasortManual;

class InvoiceController extends Controller
{
    public function index()
    {
        $larasortMan = new LarasortManual();
        $larasortMan->setSortables(['id', 'ref', 'customer_email', 'created_at', 'price_with_vat']);
        $larasortMan->setSortablesDefaultOrder([
            'desc' => ['id', 'created_at', 'price_with_vat'], // Here.
        ]);
        $resultLarasortMan = $larasortMan->get();

        // Here your SQL query with $resultLarasortMan['order_by'] and $resultLarasortMan['order']
        // Then the rest of the code...
    }
}

如果你更改“default_order”在“config/larasort.php”文件中 - 为某些列设置默认的“asc”

您可以通过与 Larasort 完全相同的方式进行操作。例如这样做

<?php

$larasortMan->setSortablesDefaultOrder([
    'asc' => ['customer_email', 'customer_first_name'], // Here.
]);

LarasortManual - API 文档

LarasortManual 类

对于 SDamian\Larasort\Manual\LarasortManual

支持

错误和安全漏洞

如果您发现错误或安全漏洞,请给 Stephen 发送消息。谢谢。

所有错误和所有安全漏洞都将得到及时解决。

许可证

此项目是一个 MIT 许可下的开源软件包。有关详细信息,请参阅 LICENSE 文件。