【问题标题】:Dynamic model filter in Laravel's EloquentLaravel Eloquent 中的动态模型过滤器
【发布时间】:2018-01-20 23:53:21
【问题描述】:

我正在寻找一种在 Laravel 中制作动态和全局模型过滤器的方法。 我在我的 User.php 模型中想象一个类似以下的函数:

public function filter() {
    return ($someVariable === true);
}

每当我使用 Eloquent 的查询构建器进行查询时,我只希望用户在上面的过滤器返回 true 时出现在集合中。我会认为存在这样的功能,但快速查看文档表明并非如此。还是我错过了?

【问题讨论】:

  • 用返回用户集合展示你的函数
  • @IlyaYaremchuk 我有数百个。不过,他们几乎都使用 Eloquent 的查询构建器(所以类似于User::with(...)->where(...)........->groupBy(...)->get())。同样对于User::find(...),我想在过滤器未通过时返回null。我可以手动执行的原始查询是关于查询生成器的结果。谢谢。
  • 可能是if($someVariable === false){return null;}else{return User::find(...);} :)
  • @IlyaYaremchuk 我正在寻找一个全球解决方案,我有一个包含许多控制器和模型的项目。我不想在访问此模型的任何地方都使用 if 语句。
  • $someVariable 来自哪里?

标签: php mysql laravel eloquent


【解决方案1】:

我相信您正在寻找的是查询范围。

它们是可以在全局或本地上下文中定义的方法,可以改变给定模型的当前查询。

https://laravel.com/docs/5.5/eloquent#query-scopes

例如:

假设我有一个名为“Teams”的数据库表,其中有一列名为“Wins”。如果我想检索在 A 和 B 之间有多个 Wins 的所有团队,我可以在团队模型上编写以下本地范围方法:

public function scopeWinsBetween($query, int $min, int $max)
{
    return $query->whereBetween('wins', $min, $max);
}

它可以这样调用:

$teams = Teams::winsBetween(50, 100)->get();

【讨论】:

  • 嗨@Endl,谢谢。我遇到了这个功能,但遗憾的是这仅适用于查询约束。这不允许我检查 PHP 范围内的变量。所以在我的例子中 $someVariable 不是我表中的列,它是一个本地 PHP 变量。
  • 啊,对不起,我误解了你的问题。您是否考虑过将所有 Eloquent 调用封装在另一个对象中,并让它过滤查询结果?
  • 不用担心,感谢您的尝试 :-) 这将是最后的手段,但我真的想在我的模型中实现它,因为它使我的代码更清晰。
【解决方案2】:

我认为您可以使用 Collection 宏,但您需要将所有雄辩的 get(); 后缀添加到 get()->userDynamicFilter();

Collection::macro('userDynamicFilter', function () {
    //$expected = ...
    return $this->filter(function ($value) use($expected) {
        return $value == $expected;
    });
});

【讨论】:

  • 哈,还不知道宏,这很酷,当然是一个选择。仍在寻找一种在我的模型中执行此操作的方法,并且在我的代码中没有额外的混乱。让我们看看是否有人提出了真正的解决方案。谢谢!
【解决方案3】:

谢谢。现在我只是使用以下代码为模型添加了一个后过滤器选项:

// Apply a post filter on the model collection
$data = $data->filter(function($modelObject) {
    return (method_exists($modelObject, 'postFilter')) ? $modelObject->postFilter($modelObject) : true;
});

Illuminate/Database/Eloquent/Builder.php 的get() 函数中,在创建集合之后。这允许我在我的模型中添加一个函数 postFilter($model),它返回 true 或 false。

可能不是最干净的解决方案,但目前是可行的解决方案。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-09-18
    • 1970-01-01
    相关资源
    最近更新 更多