2017-02-16 19 views
0

Я использую Laravel 5.3 и пытаюсь вернуть данные из нескольких таблиц с помощью соединения.Как сгруппировать одно из многих отношений с присоединением в Laravel

Я использую 3 модели/таблицы, с клиентами, бизнес и сайт, которые связаны следующим образом:

В Customer.php:

<?php 

namespace App; 

use Illuminate\Database\Eloquent\Model; 

class Customer extends Model 
{ 
    public function businesses() 
    { 
    return $this->hasMany('App\Business'); 
    } 
} 

В Business.php:

<?php 

namespace App; 

use Illuminate\Database\Eloquent\Model; 

class Business extends Model 
{ 
    public function customer() 
    { 
    return $this->belongsTo('App\Customer'); 
    } 

    public function websites() 
    { 
    return $this->hasMany('App\Website'); 
    } 
} 

И в Website.php:

<?php 

namespace App; 

use Illuminate\Database\Eloquent\Model; 

class Website extends Model 
{ 
    public function business() { 
    return $this->belongsTo('App\Business'); 
    } 
} 

Таким образом, Customer может иметь много Businesses, которые могут иметь много Websites. Теперь я пытаюсь использовать оператор объединения, чтобы возвращать список клиентов и связанные с ними сведения о бизнесе и веб-сайте. Я использую следующий код, чтобы вернуть эту информацию:

$customers = \DB::table('customers') 
       ->join('businesses', 'customers.id', '=', 'businesses.customer_id') 
       ->join('websites', 'businesses.id', '=', 'websites.business_id') 
       ->select('customers.x', 'businesses.y', 'websites.z') 
       ->get(); 

И я хотел бы, чтобы данные быть возвращение в массиве ассоциативных массивов клиентов с данными бизнес и веб-сайтов, вложенных в ассоциативном массиве, как так:

[ 
    0 => { 
    $customer1Data, 
    $customer1BusinessData, 
    $customer1WebsiteData 
    } 
    1 => { 
    $customer2Data, 
    $customer2BusinessData, 
    $customer2WebsiteData 
    } 
    ... 
] 

Это прекрасно работает, если клиент имеет один бизнес, который имеет один сайт, но предположим $customer1 имеет два предприятия, то выше соединение возвращает что-то в этом формате:

[ 
    0 => { 
    $customer1Data, 
    $customer1BusinessData1, 
    $customer1WebsiteData 
    } 
    1 => { 
    $customer1Data, 
    $customer1BusinessData2, 
    $customer1WebsiteData 
    } 
    ... 
] 

Есть ли способ, что я могу изменить джойн заявления, чтобы вернуться, что сценарий в этом формате:

[ 
    0 => { 
    $customer1Data, 
    businesses => { 
     $customer1BusinessData1, 
     $customer1BusinessData2 
    } 
    ... 
    } 
] 

Есть ли способ, я могу добиться этого с присоединиться заявлением? Или я должен подойти к этому по-другому? Любая помощь будет очень признательна, большое спасибо.

+0

Вы еще не использовали красноречивого. вы можете просто использовать '$ customer = Customer :: with ('business', 'business.websites') -> all()' Это загрузит всех клиентов, их бизнес и его веб-сайты. поэтому вы можете просто использовать '$ customer-> business', чтобы получить все бизнес и вложенный цикл для получения веб-сайтов предприятий. –

ответ

0

В соответствии с замечанием @Rooshan Akthar, вы можете сделать один следующий используя красноречивым из-за отношений вы создали:

// Loading with relationships (i.e single query) 
Customer::with('businesses.websites'); 

// Lazy loading (i.e. multiple queries) 
Customer::find($id)->load('businesses.websites'); 

Вы также можете просто идти $customer->businesses->websites; без заехав либо из вышеперечисленного и laravel получит эти отношения для вас.

0

Прежде чем я углубится в объяснение красноречивых отношений модели, прочтите следующее: https://laravel.com/docs/5.4/eloquent. Это прояснит ситуацию.

В отношении модели вы можете указать, какие имена полей базы данных связаны с этими двумя таблицами. Это даже работает со сводными таблицами. Для базовой документации прочтите это: https://laravel.com/docs/5.4/eloquent-relationships#defining-relationships.

Например, в модели клиента:

public function businesses() 
{ 
    return $this->hasMany(Business::class, 'id', 'customer_id'); 
} 

public function websites() 
{ 
    //Argument order: final class, pivot class, pivot foreign key, foreign key final model, primary key start model (customer) 
    return $this->hasManyThrough(Website::class, Business::class, 'customer_id', 'id', id); 
} 

Если эта последняя часть была немного трудно понять, прочитайте документацию: https://laravel.com/docs/5.4/eloquent-relationships#has-many-through

А для бизнес-модели:

public function website() 
{ 
    return $this->hasMany(Website::class, 'id', 'business_id'); 
} 

И теперь вы можете получать данные с помощью красноречия.

//This will retrieve all customers with all of their website information. 
Customer::with('websites')->get(); 

//This will retrieve all customers with their business information. 
Customer::with('businesses')->get(); 

//This will retrieve all customers with business and website information 
//Retrieves: [ 
// customer: [ 
//  customerDetails: [] 
//  businesses: [ b1, b2], 
//  websites: [w1, w2] 
// ] 
//] 
Customer::with('businesses', 'websites')->get(); 

//This will retrieve all customers with business information and the website information for each business 
//Retrieves: [ 
// customer: [ 
//  customerDetails: [] 
//  businesses: [ 
//   b1: [ websites: [w1] ], 
//   b2: [ websites: [w2] ] 
//  ], 
// ] 
//] 
Customer::with('businesses.websites')->get(); 

Надеюсь, это поможет!

+0

Если вы поместите массив значений ключей в -> get(), вы можете указать столбцы, которые хотите получить. Не забывайте названия таблиц! –