#laravel #eloquent
#laravel #eloquent
Вопрос:
Я хочу написать запрос на основе необязательного условия, который будет извлекать данные из разных таблиц. Моя схема выглядит так
Таблица myboxes
id,
type_id --> foreign key to box_type table
postal_code
po_box
created_at
updated_at
таблица mybox_access
id
mybox_id -> foreign key to myboxes table
email
box_type таблица
id
type_name
И вот мои модели
MyBox.php
class MyBox extends Model {
public function type() {
return this->hasOne(BoxType::class, 'id', 'type_id');
}
public function access() id
return this->hasOne(MyBoxAccess::class, 'mybox_id', 'type_id');
}
}
MyBoxType.php имеет следующие отношения корабль
public function mybox() {
return this->hasOne(MyBox::class, 'id', 'type_id');
}
И MyBoxAccess.php имеет следующие отношения
public function vbox() {
return $this->belongsTo(MyBox::class, 'id', 'mybox_id');
}
Теперь я хочу получить на основе следующего условия
У меня есть email в качестве требуемого параметра, а postal_code и po_box — в качестве необязательных параметров (но один из них будет обязательным, и оба также могут присутствовать).
Итак, я хочу получить данные всех my_boxes, которые имеют type_id 3, ИЛИ всех myboxes, идентификатор которых соответствует электронной почте в таблице mybox_access, А postal_code или po_box соответствуют параметрам в таблице myboxes
Для простого сопоставления параметров почтовый индекс и po_box я могу написать что-то вроде
$result = new MyBox();
if(!empty($request['postal_code'])) {
$result->where('postal_code', like, '%'.$request['postal_code']);
}
if(!empty($request['po_box'])) {
$result->where('po_box', like, '%'.$request['po_box']);
}
$result = $result->get();
Но я не знаю, как получить данные для вышеупомянутого условия. Когда я пытаюсь сделать, используя with()
like
MyBox::with(['access' => function(Builder $query) use ($request){
$query->where('mybox_id',$request['id']);
}])->get();
Я получаю
`Argument 1 Passed to {closure} () must be an instance of IlluminatDatabaseQueryBuilder, instance of IlluminateDatabaaseEloquentRelationHasOne given`
Может ли какое-либо тело сообщить мне, как я могу получить данные на основе вышеупомянутого условия
Ответ №1:
$query
это отношение, а не экземпляр builder .
Так что это не должно вызывать никаких исключений.
MyBox::with(['access' => function ($query) {
$query->where('mybox_id', $request['id']);
}])->get();
Но я не думаю, что это решило бы вашу проблему, потому что ваше отношение Box <=> Access неверно. Это должно быть много.
// MyBox.php
public function type()
{
return $this->hasOne(BoxType::class, 'id', 'type_id');
}
public function access()
{
return $this->hasMany(MyBoxAccess::class, 'mybox_id', 'id');
}
Затем в вашем контроллере вы могли бы это сделать.
// $results where type_id is 3
$results = MyBox::where('type_id', 3)->get();
// List of boxes accessible by email
$results = MyBox::whereHas('access', function ($query) {
$query->where('email', request()->input('email'));
})->get();
// Results where postal_code and po_box matches the request
$results = MyBox::with('access')->where(function ($query) {
if (request()->has('postal_code')) {
$query->where('postal_code', 'like', '%' . request()->input('postal_code'));
}
if (request()->has('po_box')) {
$query->where('po_box', 'like', '%' . request()->input('po_box'));
}
})->get();
И если вы хотите объединить все условия:
$results = MyBox::where(function ($query) {
if (request()->has('type_id')) {
$query->where('type_id', request()->input('type_id'));
}
if (request()->has('email')) {
$query->whereHas('access', function ($query) {
$query->where('email', request()->input('email'));
});
}
if (request()->has('postal_code')) {
$query->where('postal_code', 'like', '%' . request()->input('postal_code'));
}
if (request()->has('po_box')) {
$query->where('po_box', 'like', '%' . request()->input('po_box'));
}
})->get();
Я всегда использую request()
фасад при использовании в замыканиях, он кажется мне более чистым.
Комментарии:
1. Буду ли я использовать
->get()
три раза?2. Ну, это зависит. Вы запросили 3 разных вида результатов (на основе type_id ИЛИ email ИЛИ postal_code / po_box). Вы, конечно, могли бы использовать только 1
->get()
.3. @SimponDepelchin ну, как я могу объединить их в одно
->get()
, например, каждый раз, когда будет обязательное условие типа id и emaill и одно из post_code или po_box? например, где (type_id = 3 или email = myemail) и (post_code = 12 или po_box = 12)?4. @AwaisQarni Я отредактировал свой пост, добавил пример объединения всех условий. Не стесняйтесь изменять условия (if/elseif/else) по мере необходимости.
Ответ №2:
Попробуйте выполнить этот запрос:
MyBox::with('access')->get();
Комментарии:
1. И это решит все мои вопросы, которые я задал в quesiton?