Laravel否定本地范围

eld*_*blz 6 php laravel eloquent laravel-5

我在我的项目中使用laravel 5.2我刚刚实现了一个本地范围(为简单起见,使用laravel docs示例-https://laravel.com/docs/master/eloquent#local-scopes )

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class User extends Model
{
    /**
     * Scope a query to only include popular users.
     *
     * @return \Illuminate\Database\Eloquent\Builder
     */
    public function scopePopular($query)
    {
        return $query->where('votes', '>', 100);
    }

}
Run Code Online (Sandbox Code Playgroud)

我打电话:

$users = App\User::popular()->get();
Run Code Online (Sandbox Code Playgroud)

它就像一个魅力

可以否定范围吗?

$users = App\User::Notpopular()->get();
Run Code Online (Sandbox Code Playgroud)

还是我必须手动实现上述范围的否定?如果是这样,有更好的方法吗?

先感谢您!

Kys*_*lik 9

我正在使用这段代码来“否定”范围。

public function scopePublished($query, $negate = false) {
    return ($negate ? $query->where('published', false) : $query->where('published', true));
}
Run Code Online (Sandbox Code Playgroud)

现在,如果我只是想要我调用的已发布记录,我想要我调用的$post->published()...所有非发布记录$post->published(true)...


我可能会切换到以下,因为它更容易理解:

public function scopePublished($query, $override = true) {
    return $query->where('published', $override);
}
Run Code Online (Sandbox Code Playgroud)

已发表记录:$post->published()...
未发表记录:$post->published(false)...


jed*_*ylo 2

在不实现另一个作用域方法的情况下创建一个否定另一个局部作用域的局部作用域是不可能的(从技术上来说是这样,但它需要更多的代码)。然而,可以在另一个范围中重用一个范围的否定标准。

下面的代码应该可以解决这个问题:

public function scopeNotPopular($query) {
  $query->whereNotIn($this->getKeyName(), function($q) {
    $q->select($this->getKeyName())->from($this->getTable());
    $this->scopePopular($q);
  });
}
Run Code Online (Sandbox Code Playgroud)

此代码使用whereNotIn约束从另一个范围应用否定约束。它将允许您重用约束逻辑,而不是在两个不同的地方实现原始版本和否定版本。虽然对于文档中的示例范围来说,如此数量的代码似乎是相当大的开销,但对于更复杂的约束来说,它更有意义。

请记住,虽然它允许代码重用,但从性能角度来看,将应用的 SQL 查询可能不是最佳的。它使用子选择来标识应从结果集中排除的行。