2015-01-20 8 views
3

У меня есть две таблицы базы данных: пользователи и студенты. Студент является пользователем, но имеет дополнительные данные (адрес). У меня есть отношение toTo ('User') в моей модели Student.Laravel 5 leftJoin on принадлежит отношение

Если я теперь запросить модель Student как это:

$this->student 
    ->with('user') 
    ->first(); 

Я получаю этот результат:

{ 
    "id": 1, 
    "user_id": 12, 
    "street": "Petershof", 
    "house_number": "3787", 
    "postal_code": "8161 NM", 
    "city": "Tienhoven", 
    "user": { 
     "id": 12, 
     "email": "[email protected]", 
     "first_name": "Nathan", 
     "last_name": "van Dijk", 
     "name": "Nathan van Dijk" 
    } 
} 

Однако я хочу, чтобы сгладить результат, так что пользовательские поля находятся в родительский (Student) объект. Как это:

{ 
    "id": 1, 
    "user_id": 12, 
    "street": "Petershof", 
    "house_number": "3787", 
    "postal_code": "8161 NM", 
    "city": "Tienhoven", 
    "email": "[email protected]", // = user field 
    "first_name": "Nathan",  // = user field 
    "last_name": "van Dijk",  // = user field 
    "name": "Nathan van Dijk"  // = user field 
} 

Я пытался использовать LeftJoin ('пользователей', 'user_id', '=', 'users.id') вместо того, чтобы с(), но тогда я потеряю виртуальный атрибут имя» '(определенный в модели пользователя), а также больше не может запрашивать отношения пользователя.

Как я могу достичь этого чистым способом?

ответ

0
$this->student 
    ->leftJoin('users', 'users.id', '=', 'students.user_id') 
    ->select(
    'students.*', 
    'users.email', 
    'users.first_name', 
    'users.last_name', 
    DB::raw("concat(users.first_name, ' ', users.last_name) as name"), 
)->first(); 

В этом случае вы можете отбросить таблицу, выбрав users.email.

отношения будут работать так же, я полагаю, что проблема была только с наиважнейшей students ид с users идентификатором, если вы не указали select и просто схватил все поля.

+1

Спасибо за ваш ответ. Это хороший способ сделать это сейчас, но мне не очень нравится то, что вы пропускаете модель User. Поэтому, если я хочу изменить поле виртуального имени, я должен изменить его в разных местах. –

+0

Что вы подразумеваете под * skip user model *? Если единственное, чего вы хотите достичь, это выходное представление, в форме JSON, я полагаю, тогда вы должны были это сказать. –

+1

Я имею в виду, что с помощью leftJoin() я должен переписать «поле виртуального имени» как sql concat, в то время как я уже определил его в модели User, так что это двойной код, а не DRY. В идеале было бы сделать что-то вроде этого: $ this-> student-> with (user, 'left join') -> first(). Есть ли способ достичь этого? –

0

Старый вопрос, но здесь идет.

Чтение вашего комментария кажется, что вы хотите сделать api для этого. Если только один конечный пункт форматирует результат «на лету», это не должно быть проблемой, однако для большего количества конечных точек я бы предложил шаблон трансформатора.

Это будет работать, если отдельный класс возвращает массив на основе данных вашего db. Затем вы берете этот массив и используете его в своем response().

Итак, в вашем контроллере вместо того, чтобы делать что-то вроде return response(Student::all());, вы могли бы сделать что-то вроде return response(StudentTransformer::transform(Student::all())).

Преимущество здесь в том, что у вас есть только одна папка (ваш Transformers), чтобы проверить формат данных ответа. Недостатком является то, что при изменении вашей базы данных вам также необходимо обновить свои трансформаторы.

Смежные вопросы