Laravel:如何在分页和筛选功能中按关联模型排序

3

我已经被我的配置问题困扰了三天。我无法按报告的模型进行排序,尝试了许多方法但没有什么结果,例如sortBy / sortByDesc、join table等等。

我想要执行分页、排序和服务器端过滤。过滤器可以是多个。除了相关模型的排序外,其他都可以正常工作。

我得到的URL是:http://127.0.0.1:8000/api/user/list?page=1&limit=30&sort=user__created_at&direction=desc&search__user__name=James&search__group__name=Client

查询search__model__col允许我在多个模型或列上链接多个搜索。

以下是我的代码:

    public static function pagination(Request $request, $model, $relation, $modelStringify)
    {
        $modelSortBy = explode('__', $request->query('sort'))[0]; // user
        $tableSortBy = explode('__', $request->query('sort'))[1]; // created_at
        $query       = $request->query(); // ['page' => 1, 'limit' => 30...]
        $direction   = $request->query('direction'); // desc
        try {

            $model = $model->with($relation);

            //TODO : orderBy relationship
            if ($modelSortBy === $modelStringify): // modelStringify = 'user'
                $model->orderBy($tableSortBy, $direction);
            else:
                 // sort server side here 
            endif;

            foreach (array_keys($query) as $q) {
                if (strpos($q, 'search__') === 0) {
                    $modelSearchBy = explode('__', $q)[1]; // ['user', 'group']
                    $tableSearchBy = explode('__', $q)[2]; // ['name', 'name']
                    $valueSearchBy = $query[$q];
                    if ($modelSearchBy === $modelStringify):
                        $model->where($tableSearchBy, 'like', $valueSearchBy . '%');
                    else:
                        $model->whereHas($modelSearchBy, function (Builder $q) use ($valueSearchBy, $tableSearchBy) {
                            $q->where($tableSearchBy, 'like', $valueSearchBy . '%'); // $valueSearchBy = ['James', 'Client']
                        });
                    endif;
                }
            }
            return $model;
        } catch (Exception $e) {
            return response()->json(['message' => $e], 400);
        }
    }

这是一个关于 用户 属于 的示例:
return response()->json([
    'items' => Utils::pagination($request, new User(), [
        'group',
    ], 'user')->paginate($limit)->toArray()
]);

我该如何在这个配置中引入按相关模型排序的功能?

例如,按组名排序,我得到的URL为&sort=group__name

谢谢

1个回答

1

看起来在Laravel中很难做到这一点。有人建议在Laravel中使用一种语法(此处),但Taylor关闭了该问题。

在我找到的所有其他资源中,人们建议 使用 连接, 但这与您更通用的方法不太匹配。

Laravel最近还推出了“子查询增强功能”,包括按子查询值排序(在此页面上搜索“Eloquent Subquery Enhancements”),但我无法弄清如何使用它使通过Eloquent关系值排序更容易。

我认为最好的选择是使用第三方包,比如从 Github 问题中链接的 fico7489/laravel-eloquent-join。安装后,您可以简单地创建一个新的基础模型类,该类使用 use Fico7489\Laravel\EloquentJoin\Traits\EloquentJoin; 特性,然后从您的模型继承该类。
use Fico7489\Laravel\EloquentJoin\Traits\EloquentJoin;
use Illuminate\Database\Eloquent\Model;

abstract class BaseModel extends Model
{
    use EloquentJoin;

class ExampleModel extends BaseModel

然后,您将能够使用orderByJoin函数按关系排序:

$model->orderByJoin('<relationship>.<column>', $direction);

relationship的值是你在模型上定义的关系名称。

请注意,orderByJoin函数仅支持BelongsToHasOne关系。

还要记住的是,无论是Laravel还是laravel-eloquent-join包都不能保护您免受列名(或orderByJoin函数中的方向值)的SQL注入攻击。 Laravel docs建议您使用白名单来验证列名:

PDO不支持绑定列名。 因此,您永远不应该允许用户输入决定查询引用的列名,包括“order by”列等。 如果必须允许用户选择某些要查询的列,请始终将列名与允许的列的白名单进行验证。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接