0

I needed to make a default global scope for a model using the newQuery() method.

The Laravel docs say that it's possible in Eloquent to use an anonymous function to group WHERE conditions:

DB::table('users')
        ->where('name', '=', 'John')
        ->orWhere(function($query)
        {
            $query->where('votes', '>', 100)
                  ->where('title', '<>', 'Admin');
        })
        ->get();

But I'm running into something strange when trying that in an overloaded newQuery() method. For example, let's say I want to do this:

class User extends Eloquent implements UserInterface, RemindableInterface {

    use UserTrait, RemindableTrait;

    public function newQuery()
    {
        return parent::newQuery()->where(function($query) {
            $query->where('foreign_id', MyClass::$id)->orWhere('role', 'admin');
        });
    }

I get a 502 Bad Gateway error! The only way I could figure out how to do a compound WHERE in that method is by doing a raw query:

class User extends Eloquent implements UserInterface, RemindableInterface {

    use UserTrait, RemindableTrait;

    public function newQuery()
    {
        return parent::newQuery()
            ->whereRaw('(foreign_id = ? or role = ?)')
            ->setBindings( array( MyClass::$id, 'admin' ) );
    }

Does anyone know why that could be happening with Eloquent? It looks like someone else had a slightly different issue with Eloquent in that same method, but there was no definitive answer.

Community
  • 1
  • 1
groovenectar
  • 2,828
  • 3
  • 22
  • 26
  • Is it older version of the framework that you need to do it this way? Global scopes are meant for this, not `newQuery`. – Jarek Tkaczyk Aug 13 '14 at 20:20
  • @JarekTkaczyk_deczo_ thanks for the info! I think at the time I was searching for how to do it properly, I didn't know the term "global scope" in regards to filtering regards by default. Going to check this out. – groovenectar Aug 14 '14 at 15:43
  • 1
    Let's have it as an answer – Jarek Tkaczyk Aug 14 '14 at 15:59

1 Answers1

1

You need global scope for this.

Here's a basic example (for more info browser SoftDeletingScope and SoftDeletingTrait that come with the framework):

// Model
class PopularUser extends User {

    protected $table = 'users';

    public static function boot()
    {
        parent::boot();

        static::addGlobalScope(new PopularUserScope);
    }
}

// Scope
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\ScopeInterface;

class PopularUserScope implements ScopeInterface {

    public function apply(Builder $builder)
    {
        $builder->where('votes', '>', 100)
                ->where('title', '<>', 'Admin');
    }

    public function remove(Builder $builder) { // you don't need this in your case }
}
Jarek Tkaczyk
  • 78,987
  • 25
  • 159
  • 157