Как вы заключите области запросов Laravel Eloquent ORM в круглые скобки при связывании?

В Eloquent я хотел бы сгенерировать такой запрос:

SELECT * FROM table WHERE a=1 AND ( b=2 OR c=3 );

Но вместо этого я, кажется, генерирую этот запрос:

SELECT * FROM table WHERE a=1 AND b=2 OR c=3;

Вот моя реализация и код:

$result = Model::aIsOne()->bIsTwoOrCIsThree()->get();

Model содержит:

function scopeAIsOne($query) {
    return $query->where('a', 1);
}

function scopeBIsTwoOrCIsThree($query) {
    return $query->where('b', 2)->orWhere('c', 3);
}

Спасибо за любую помощь. Я просмотрел документы, включая Advanced Wheres, но безрезультатно.


person crowsfan85    schedule 03.01.2014    source источник


Ответы (5)


Вы тестировали whereRaw ()?

поэтому ваша функция должна выглядеть так:

function scopeIsFeaturedOrIsBlogPost($query) {
    return $query->whereRaw('( isFeatured = "true" OR type = "blogPost" )');
}

пс. это не проверено

person raymond.idema    schedule 03.01.2014
comment
Хороший звонок. Я попробую это сделать, хотя надеюсь, что будет более элегантный способ сделать это. Я склонен думать, что каждая связанная область видимости должна автоматически заключаться в круглые скобки. (ps. жаль, что у меня не было представителя, чтобы проголосовать за вас) - person crowsfan85; 04.01.2014
comment
Хотя это решает проблему, мы не используем Eloquent. И пс. это не проверено ... спасибо за честность, но не делайте этого. - person Luciano Bargmann; 16.06.2019

Вы можете создать круглые скобки, передав функцию обратного вызова where().

Model::where('a',1)->where(function($query) {
    $query->where('b', 2)->orWhere('c',3);
})->get();
person Martins Balodis    schedule 07.10.2015

ПОСМОТРЕТЬ ИЗМЕНИТЬ, ЧТОБЫ ОТВЕТИТЬ

Лучше сырого используйте или Где с закрытием:

$model = Model::whereAIsOne()->orWhere(function($query) {
    $query->where('b', 1)->where('c', 1);
})->get();

По-настоящему досадная вещь (и то, как я попал в этот пост), заключается в том, что второй запрос $, используемый в закрытии, является экземпляром \ Illuminate \ Database \ Query \ Builder, а не \ Illuminate \ Database \ Eloquent \ Builder - это означает что вы не можете использовать области модели в этом закрытии, потому что экземпляры Query \ Builder не имеют ссылки на модель.

Тем не менее, я все еще думаю, что это больше похоже на ORM и как разработчик полезно.

ИЗМЕНИТЬ

Потребовалось время, чтобы разобраться, но это сработает, если вы также захотите использовать свои прицелы:

$model = Model::whereAIsOne()->orWhere(function($query) {
    $this->newEloquentBuilder($query)->setModel($this)->whereBIsOneAndCIsOne();
})->get();

Фактически я создаю в своем коде четвертую область видимости, которая охватывает все это, поэтому $this может не работать в этом контексте - однако я считаю, что определение области видимости для моих моделей является одной из самых важных частей построения хорошей системы.

Это определенно должно быть встроено в Eloquent - двигатель хорошо запускается, но так много функций отсутствует.

person Tim    schedule 19.02.2014

Я немного опаздываю на вечеринку, но разве не самым логичным способом было бы завершить where в Closure?

    Model::where('a', '=', 1)
            ->where(function($query) {
                    $query->where('b', '=', 2)
                    ->orWhere('c', '>', 3);
    })
    ->get();
person S16    schedule 17.12.2015
comment
для тех, кому нужно передать переменную в гнездо, не забудьте USE, например: ->where(function($query) use ($options) { $query... - person STWilson; 15.11.2016

Чтобы обернуть запросы, вы можете сделать что-то вроде этого:

$builder->where(function ($query) {
    $query->where('gender', 'Male')
        ->where('age', '>=', 18);
})->orWhere(function($query) {
    $query->where('gender', 'Female')
        ->where('age', '>=', 65);   
})

Будет выведен следующий запрос:

WHERE (gender = 'Male' and age >= 18) or (gender = 'Female' and age >= 65)
person M0hsen    schedule 07.12.2020