Як об’єднати три таблиці за допомогою красномовної моделі laravel


85

У мене три столи

Таблиця статей

 id
 title
 body
 categories_id
 user_id

Таблиця категорій

  id
  category_name

Таблиця користувачів

 id
 user_name
 user_type

Я хочу показувати статті з їхніми назвами категорій замість ідентифікатора категорії та імені користувача замість імені користувача. Я намагаюся сподобатися цим запитам. Це робота!

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

Але я хочу зробити це красномовним способом. Будь ласка, як я міг це зробити?


1
Як щодо створення подання, яке об’єднує ці таблиці, тоді ви створюєте модель Eloquent, яка просто читає з неї? Складність коду зменшується, ви отримуєте прибуток, не вимагаючи жодної важкої роботи.
НБ

1
Усі інші пов’язані моделі та функції працюють разом з Eloquent Model. Тож мені потрібно використовувати Красномовний шлях.
Ні

1
Ви помиляєтесь тут ->join('categories', 'articles.id', '=', 'categories.id'):? Замість articles.idцього повинно бути articles.categories_id. Або я помиляюся?
FreeLightman

Відповіді:


140

За допомогою Eloquent дуже легко отримувати реляційні дані. Перевірте наступний приклад із вашим сценарієм у Laravel 5.

У нас є три моделі:

1) Стаття (належить користувачеві та категорії)

2) Категорія (має багато статей)

3) Користувач (має багато статей)


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');
    }

}

Ви повинні розуміти взаємозв'язок та налаштування бази даних у моделях. Користувач має багато статей. Категорія має багато статей. Статті належать користувачеві та категорії. Після налаштування взаємозв’язків у Laravel стає легко отримати відповідну інформацію.

Наприклад, якщо ви хочете отримати статтю за допомогою користувача та категорії, вам потрібно буде написати:

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

і ви можете використовувати це так:

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

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

В іншому випадку вам може знадобитися отримати всі статті в межах категорії або всі статті конкретного користувача. Ви можете написати це так:

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

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

Ви можете дізнатись більше на http://laravel.com/docs/5.0/eloquent


Дякуємо за відповідь, але я використовую laravel 4 і хочу повернути дані у форматі json. Подібно до них return Response::json( array( 'total_count' => $count, 'incomplete_results' => false, 'items'=> $articles->toArray() ));Як я можу зробити для формату json?
Ні

незважаючи на те, що весь код працює в Laravel 4, вам просто потрібно видалити простір імен, а $ articles-> toArray () працює однаково, спробуйте
Ананд Пател

Дякую, брате, це робота, і Ти врятуєш мені життя :). Вибачте за пізню відповідь, тому що вчора я не біля комп'ютера.
Ні,

4
Я не впевнений, але, схоже, таким чином (за допомогою красномовства) генерується 3 запити. Хоча запит із користувацькими joinбуде єдиним. Тож відповідь @NayZawOo нижче є більш прийнятною.
FreeLightman

що, якщо я не хочу отримати до нього доступ, як $ article-> category-> category_name, але використовую деякі псевдоніми, такі як $ article-> categoryName, як мені написати красномовний запит у такому випадку?
Герокілер

23

Спробуйте:

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

Я хочу повернути формат об'єкта json. Тому що мені потрібно спробувати $ articles-> count () і $ articles-> offset ($ offset); $ статей-> get (масив ('id', 'title', 'body')); Але Ваш спосіб не може застосувати ці об’єктні функції. Дякую за підтримку.
Не,

1
return Response: json ($ статей);
Nay Zaw Oo

Хоча це не красномовний спосіб зробити це, це єдиний спосіб, якщо ви сортуєте за полями в іноземних таблицях. (що я б не рекомендував, але іноді є необхідним). Через це, я думаю, це все ще дуже слушна відповідь. (Питання , який задають , як приєднатися до таблиць, красномовний спосіб на насправді ніколи не приєднується до них у вихідному запиті.)
Skeets

цей пакет допоможе вам github.com/fico7489/laravel-eloquent-join
fico7489

"Хоча це не красномовний спосіб зробити це, це єдиний спосіб, якщо ви сортуєте за полями в зарубіжних таблицях." Skeets, Коли ви говорите єдиним способом, ви говорите, що документи laravel опускають цю важливу інформацію?
Глен

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]);

Над запитом є помилка порушення обмеження цілісності, яка була вирішена у цій відповіді
Акшай Кашьяп
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.