【问题标题】:Laravel: how to sort by related model with pagination & filterLaravel:如何通过分页和过滤器按相关模型排序
【发布时间】:2020-01-19 00:33:49
【问题描述】:

我的配置被阻止已经三天了。我无法按报告的模型排序,我尝试了很多方法但没有任何结论,例如 sortBy / sortByDesc,连接表但没有解决方案

我想执行分页、排序和服务器端过滤器。过滤器可以是多个。除了按相关模型排序外,一切正常 我得到网址: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);
        }
    }

这是user belongsTo group 的示例:

return response()->json([
    'items' => Utils::pagination($request, new User(), [
        'group',
    ], 'user')->paginate($limit)->toArray()
]);

如何在此配置中引入按相关模型排序?

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

谢谢

【问题讨论】:

    标签: javascript laravel sorting


    【解决方案1】:

    这在 Laravel 中看起来并不容易。有人建议在 Laravel here 中执行此操作的语法,但 Taylor 关闭了该问题。

    在所有其他资源上,我可以找到 suggest using joins 的人,但这不太适合您更通用的方法。

    Laravel 最近还引入了“子查询增强”,其中包括按子查询值排序(在 this page 上搜索“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 不支持绑定列名。因此,您永远不应该允许用户输入来指示查询引用的列名,包括“排序依据”列等。如果您必须允许用户选择某些列进行查询,请始终根据白色验证列名-允许的列列表。

    【讨论】:

      猜你喜欢
      • 2013-02-19
      • 2019-02-03
      • 2019-09-16
      • 2019-02-17
      • 2014-05-17
      • 1970-01-01
      • 1970-01-01
      • 2021-09-18
      • 1970-01-01
      相关资源
      最近更新 更多