Cómo unir tres mesas por modelo elocuente de laravel


85

Tengo tres mesas

Tabla de artículos

 id
 title
 body
 categories_id
 user_id

Tabla de categorías

  id
  category_name

Tabla de usuarios

 id
 user_name
 user_type

Quiero mostrar artículos con su nombre de categoría en lugar de category_id y user_name en lugar de user_id. Intento como esta consulta. ¡Es un trabajo!

$articles =DB::table('articles')
                ->join('categories', 'articles.id', '=', 'categories.id')
                ->join('users', 'users.id', '=', 'articles.user_id')
                ->select('articles.id','articles.title','articles.body','users.username', 'category.name')
                ->get();

Pero quiero hacerlo de manera elocuente. Por favor, ¿cómo puedo hacer?


1
¿Qué tal si creas una vista que se una a esas tablas y luego creas el modelo Eloquent que simplemente lee de él? Reducción de la complejidad del código, beneficios, sin trabajo duro.
NB

1
Todos los demás modelos y funciones relacionados funcionan junto con Eloquent Model. Entonces necesito usar Eloquent Way.
No

1
¿Estás equivocado aquí ->join('categories', 'articles.id', '=', 'categories.id'):? En lugar de articles.iddebería serlo articles.categories_id. ¿O me equivoco?
FreeLightman

Respuestas:


140

Con Eloquent es muy fácil recuperar datos relacionales. Consulte el siguiente ejemplo con su escenario en Laravel 5.

Tenemos tres modelos:

1) Artículo (pertenece al usuario y categoría)

2) Categoría (tiene muchos artículos)

3) Usuario (tiene muchos artículos)


1) Article.php

<?php

namespace App\Models;
 use Eloquent;

class Article extends Eloquent{

    protected $table = 'articles';

    public function user()
    {
        return $this->belongsTo('App\Models\User');
    }

    public function category()
    {
        return $this->belongsTo('App\Models\Category');
    }

}

2) Category.php

<?php

namespace App\Models;

use Eloquent;

class Category extends Eloquent
{
    protected $table = "categories";

    public function articles()
    {
        return $this->hasMany('App\Models\Article');
    }

}

3) User.php

<?php

namespace App\Models;
use Eloquent;

class User extends Eloquent
{
    protected $table = 'users';

    public function articles()
    {
        return $this->hasMany('App\Models\Article');
    }

}

Debe comprender la relación de su base de datos y la configuración en modelos. El usuario tiene muchos artículos. La categoría tiene muchos artículos. Los artículos pertenecen a usuario y categoría. Una vez que configure las relaciones en Laravel, será fácil recuperar la información relacionada.

Por ejemplo, si desea recuperar un artículo utilizando el usuario y la categoría, deberá escribir:

$article = \App\Models\Article::with(['user','category'])->first();

y puedes usar esto así:

//retrieve user name 
$article->user->user_name  

//retrieve category name 
$article->category->category_name

En otro caso, es posible que deba recuperar todos los artículos dentro de una categoría, o recuperar todos los artículos de un usuario específico. Puedes escribirlo así:

$categories = \App\Models\Category::with('articles')->get();

$users = \App\Models\Category::with('users')->get();

Puede obtener más información en http://laravel.com/docs/5.0/eloquent


Gracias por su respuesta, pero uso laravel 4 y quiero devolver los datos en formato json. Como estos, return Response::json( array( 'total_count' => $count, 'incomplete_results' => false, 'items'=> $articles->toArray() ));¿cómo podría hacerlo para el formato json?
No

no importa que todo el código funcione en Laravel 4, solo necesita eliminar el espacio de nombres, y $ artículos-> toArray () funciona igual, intente
Anand Patel

Gracias hermano es trabajo y me salvas la vida :). Perdón por la respuesta tardía porque no estoy cerca de la computadora ayer.
No

4
No estoy seguro, pero parece que de esta manera (usando elocuente) genera 3 consultas. Mientras que la consulta con los personalizados joinserá única. Entonces, la respuesta de @NayZawOo a continuación es más aceptable.
FreeLightman

¿Qué pasa si no quiero acceder a él como $ artículo-> categoría-> nombre de categoría, pero uso algún alias como $ artículo-> nombre de categoría, cómo escribo una consulta elocuente en ese caso?
Herokiller

23

Tratar:

$articles = DB::table('articles')
            ->select('articles.id as articles_id', ..... )
            ->join('categories', 'articles.categories_id', '=', 'categories.id')
            ->join('users', 'articles.user_id', '=', 'user.id')

            ->get();

Quiero que el formato de objeto json regrese. Porque necesito probar $ artículos-> count () y $ artículos-> offset ($ offset); $ artículos-> get (array ('id', 'título', 'cuerpo')); Pero Tu manera no puede aplicar esas funciones de objeto. Gracias tu apoyo
No

1
return Respuesta: json ($ artículos);
Nay Zaw Oo

Aunque esta no es la forma elocuente de hacerlo, es la única forma si está ordenando por campos en tablas externas. (que no recomendaría, pero ocasionalmente es necesario). Por eso, creo que esta sigue siendo una respuesta muy válida. (la pregunta era cómo unir tablas, la forma elocuente en realidad nunca las une en la consulta original).
Skeets


"Aunque esta no es la forma elocuente de hacerlo, es la única forma si está ordenando por campos en tablas extranjeras". Skeets, cuando dice que es la única forma, ¿está diciendo que los documentos de laravel omiten esta información importante?
Glen

3
$articles =DB::table('articles')
                ->join('categories','articles.id', '=', 'categories.id')
                ->join('user', 'articles.user_id', '=', 'user.id')
                ->select('articles.id','articles.title','articles.body','user.user_name', 'categories.category_name')
                ->get();
return view('myarticlesview',['articles'=>$articles]);

La consulta anterior tiene un error de violación de restricción de integridad que se resolvió en esta respuesta
Akshay Kashyap
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.