Laravel 5.1 загружает данные отношения в выбранную строку
В моей базе данных есть таблица timesheet
и таблица user
. В модели timesheet
установлено следующее соотношение.
/**
* The user that owns the timesheet.
*
* @return Object
*/
public function user()
{
return $this->belongsTo('App\Models\User\User');
}
Вышеупомянутое означает, что я могу получить пользовательские данные, когда я выбираю расписания из базы данных, используя что-то вроде:
$this->timesheet->whereStatus('Approved')->with('user');
Это приведет к загрузке объекта пользователя в результат, и если преобразование в массив будет выглядеть так:
0 => array:13 [▼
"id" => 1
"user_id" => 2
"week" => 1
"year" => 2016
"week_ending" => "Sunday 10th January 2016"
"total_hours" => "45.00"
"token" => "0e6796a2dc68066c8d36ff828c519af00657db02b733309b8a4ac0f7b5d6a385"
"status" => "Approved"
"supervisor_id" => 1
"approved_by" => 1
"created_at" => "2016-01-13 15:42:49"
"updated_at" => "2016-01-14 14:52:07"
"user" => array:7 [▼
"id" => 2
"first_name" => "Bill"
"last_name" => "Andrews"
"email" => "[email protected]"
"status" => 1
"created_at" => "2016-01-13 15:38:18"
"updated_at" => "2016-01-14 14:50:03"
]
]
Однако мне нужно только first_name
и last_name
из таблицы пользователя. Есть способ слияния/сглаживания массива user
с timesheet
, чтобы он выглядел следующим образом:
0 => array:14 [▼
"id" => 1
"user_id" => 2
"week" => 1
"year" => 2016
"week_ending" => "Sunday 10th January 2016"
"total_hours" => "45.00"
"token" => "0e6796a2dc68066c8d36ff828c519af00657db02b733309b8a4ac0f7b5d6a385"
"status" => "Approved"
"supervisor_id" => 1
"approved_by" => 1
"created_at" => "2016-01-13 15:42:49"
"updated_at" => "2016-01-14 14:52:07"
"first_name" => "Bill"
"last_name" => "Andrews"
]
Я попытался использовать такую загружаемую загрузку,
$this->timesheet->with(['user' => function ($query) {
$query->select('first_name', 'last_name');
}])->get()->toArray();
Однако это приводит к следующему результату:
array:126 [▼
0 => array:13 [▼
"id" => 1
"user_id" => 2
"week" => 1
"year" => 2016
"week_ending" => "Sunday 10th January 2016"
"total_hours" => "45.00"
"token" => "0e6796a2dc68066c8d36ff828c519af00657db02b733309b8a4ac0f7b5d6a385"
"status" => "Approved"
"supervisor_id" => 1
"approved_by" => 1
"created_at" => "2016-01-13 15:42:49"
"updated_at" => "2016-01-14 14:52:07"
"user" => null
]
Ответы
Ответ 1
Причина, по которой отношение пользователя является нулевым во втором примере, заключается в том, что для того, чтобы отношения Eloquent работали, ему нужны ключи, которые связывают отношения. Другими словами...
- Получить
timesheet
.
- Получить
user
только с first_name
и last_name
.
- Строить отношения.
- Поскольку вы не выбрали идентификатор пользователя,
user id
и timesheet user_id
не совпадают, поэтому связь не может быть построена.
Чтобы ваш запрос работал, вам необходимо настроить его следующим образом:
$this->timesheet->with(['user' => function ($query) {
$query->select('id', 'first_name', 'last_name');
}])->get()->toArray();
С учетом этого, если вы хотите сгладить результат, я считаю, что лучше использовать joins
, а не загружать загрузку из-за природы нетерпеливой загрузки.
$this->timesheet
->join('users', 'timesheets.user_id', '=', 'users.id')
->select('timesheets.*', 'users.first_name', 'users.last_name')
->get()->toArray();
Предполагается, что ваши имена таблиц users
и timesheets
.
Ответ 2
Вы пытались получить список
->lists('first_name', 'last_name');
или если вы хотите выполнить выбор
->select('first_name', 'last_name')->get()
Обновление
Вы также можете выполнять загружаемую нагрузку на объекты, связанные с нагрузкой. Вот пример
$users = App\User::with(['posts' => function ($query) {
$query->select('first_name', 'last_name');
}])->get();
Пожалуйста, дайте мне знать, если это поможет.
Ответ 3
Модели Laravel имеют способ модифицировать данные до получения/установки атрибута. Фактически вы можете добавлять атрибуты к модели, определяя функцию геттера. Это позволит вам ссылаться на имена пользователей так же, как и на user_id
или status
. Эти функции также отлично подходят для изменения форматов даты для представления или дезинфекции ввода формы.
/**
* Get the first name of the user.
*
* @return string
*/
public function getFirstNameAttribute()
{
return $this->user->first_name;
}
/**
* Get the last name of the user.
*
* @return string
*/
public function getLastNameAttribute()
{
return $this->user->last_name;
}
Ответ 4
То, что делает join
.
Из документации
Конструктор запросов также может использоваться для записи операторов соединения. к выполнить базовое SQL "внутреннее соединение", вы можете использовать метод объединения на экземпляр построителя запросов. Первый аргумент, переданный методу объединения это имя таблицы, к которой нужно присоединиться, в то время как остальные аргументы указывают ограничения столбца для соединения.
$this->timesheet
->leftjoin('user', 'user.id', '=','timesheet.user_id')
->get()
->toArray();
Если вы хотите быть более избирательным в своих полях, вы можете выбрать, что вы select
;
$this->timesheet
->leftjoin('user', 'user.id', '=','timesheet.user_id')
->select('timesheet.*', 'user.first_name', 'user.last_name')
->get()
->toArray();
Как и другие, возможно, лучше использовать построитель запросов БД, например
this->timesheet = DB::table('timesheet')
->where('timesheet.status', 'Approved')
->leftjoin('user', 'user.id', '=','timesheet.user_id')
->select('timesheet.*', 'user.first_name', 'user.last_name')
->get()
->toArray();
Ответ 5
В этом случае лучше использовать Raw SQL или Query builder.
Потому что отношения сделаны для использования данных базы данных как реляционных объектов.