Jak dołączyć do trzech stolików według elokwentnego modelu Laravel

85

Mam trzy stoliki

Tabela artykułów

 id
 title
 body
 categories_id
 user_id

Tabela kategorii

  id
  category_name

Tabela użytkowników

 id
 user_name
 user_type

Chcę wyświetlać artykuły z nazwą kategorii zamiast category_id i user_name zamiast user_id. Próbuję odpowiedzieć na to zapytanie. To działa!

$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();

Ale chcę to zrobić elokwentnie. Proszę, jak mogłem zrobić?

Nie
źródło
1
Co powiesz na utworzenie widoku łączącego te tabele, a następnie utworzenie modelu Eloquent, który po prostu z niego odczytuje? Zmniejszona złożoność kodu, zysk, bez ciężkiej pracy.
Uwaga:
1
Wszystkie inne powiązane modele i funkcje działają razem z Eloquent Model. Więc muszę użyć Eloquent Way.
Nie
1
Czy pomylić tutaj: ->join('categories', 'articles.id', '=', 'categories.id')? Zamiast articles.idtego powinno być articles.categories_id. A może się mylę?
FreeLightman

Odpowiedzi:

140

Dzięki Eloquent bardzo łatwo jest odzyskać dane relacyjne. Sprawdź następujący przykład ze swoim scenariuszem w Laravel 5.

Mamy trzy modele:

1) Artykuł (należy do użytkownika i kategorii)

2) Kategoria (zawiera wiele artykułów)

3) Użytkownik (zawiera wiele artykułów)


1) Artykuł.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');
    }

}

Musisz zrozumieć relacje z bazą danych i konfigurację modeli. Użytkownik ma wiele artykułów. Kategoria zawiera wiele artykułów. Artykuły należą do użytkownika i kategorii. Po skonfigurowaniu relacji w Laravel łatwo będzie odzyskać powiązane informacje.

Na przykład, jeśli chcesz pobrać artykuł za pomocą użytkownika i kategorii, musisz napisać:

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

i możesz użyć tego w ten sposób:

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

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

W innym przypadku może zajść potrzeba pobrania wszystkich artykułów w kategorii lub wszystkich artykułów określonego użytkownika. Możesz to napisać tak:

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

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

Możesz dowiedzieć się więcej na http://laravel.com/docs/5.0/eloquent

Anand Patel
źródło
Dzięki za odpowiedź Ale używam laravel 4 i chcę zwracać dane w formacie json. Podobnie jak te return Response::json( array( 'total_count' => $count, 'incomplete_results' => false, 'items'=> $articles->toArray() ));Jak mogę zrobić dla formatu json?
Nie
Bez względu na wszelkie prace kodu w laravel 4 prostu trzeba usunąć nazw i $ ArtykuĹ,y> toArray () działa tak samo, spróbuj
Anand Patel
Dzięki tobie bracie to praca i ratujesz mi życie :). Przepraszam za spóźnioną odpowiedź, ponieważ wczoraj nie było mnie w pobliżu komputera.
Nay
4
Nie jestem pewien, ale wydaje się, że w ten sposób (elokwentnie) generuje 3 zapytania. Podczas gdy zapytanie z niestandardowymi joinbędzie pojedyncze. Więc odpowiedź @NayZawOo poniżej jest bardziej akceptowalna.
FreeLightman
co jeśli nie chcę uzyskać do niego dostępu, takiego jak $ article-> category-> category_name, ale używam aliasu, takiego jak $ article-> categoryName, jak w takim przypadku napisać wymowne zapytanie?
Herokiller,
23

Próbować:

$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();
Nay Zaw Oo
źródło
Chcę, aby powrócił format obiektu JSON. Ponieważ muszę wypróbować $ artykuly-> count () i $ artykuly-> offset ($ offset); $ artykuły-> get (tablica ('id', 'tytuł', 'treść')); Ale Twój sposób nie może zastosować tych funkcji obiektów. Dziękuję za wsparcie.
Nay
1
odpowiedź zwrotna: json ($ artykuły);
Nie Zaw Oo
Chociaż nie jest to wymowny sposób, aby to zrobić, jest to jedyny sposób, jeśli sortujesz według pól w obcych tabelach. (czego nie polecam, ale czasami jest to konieczne). Z tego powodu uważam, że jest to nadal bardzo ważna odpowiedź. (pytanie zadane, jak dołączyć do stołów, wymowny sposób w rzeczywistości nigdy nie łączy ich w pierwotnym zapytaniu.)
Skeets
ten pakiet cal ci pomoże github.com/fico7489/laravel-eloquent-join
fico7489
„Chociaż nie jest to wymowny sposób, aby to zrobić, jest to jedyny sposób, jeśli sortujesz według pól w obcych tabelach.” Skeets, kiedy mówisz jedyny sposób, czy twierdzisz, że laravel docs pomijają tę ważną informację?
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]);
Akshay Kashyap
źródło
Powyższe zapytanie zawiera błąd naruszenia ograniczenia integralności, który został rozwiązany w tej odpowiedzi
Akshay Kashyap,