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. Потому что отношения сделаны для использования данных базы данных как реляционных объектов.