Kebetulan di group Laravel Indonesia ada pertanyaan Eloquent mengenai has many through relationship.

Apa itu has many through relationship? Seperti biasa, untuk mengerti sesuatu kita sebaiknya mengerti dulu artinya. Karena istilah itu biasanya tidak sembarangan dibuat. Biasanya mirip dengan dunia nyata. Kata “through” berdasarkan Google Translate artinya “melalui”. Sedangkan relationship adalah hubungan. Hubungan apa? Jangan dibahas -_-”

Contoh kasus paling mudah itu adalah negara, provinsi, dan kota. Misalnya kita punya tiga table, yaitu countries, provinces dan cities. Berikut field yang ada di masing-masing table yang saya ilustrasikan dalam format YAML:

---
countries:
    - id          : int
    - name        : string

provinces:
    - id          : int
    - name        : string
    - country_id  : int

cities:
    - id          : int
    - name        : string
    - province_id : int    # tidak ada country_id disini

Karena tidak ada country_id pada cities, bagaimana caranya untuk bisa mendapatkan data cities dari countries? Solusinya adalah has many through. Ingat kata “melalui”? Jadi untuk mendapatkan data cities dari countries harus “melalui” provinces.

Bagaimana penggunaannya di Eloquent?

Saya asumsikan anda sudah familiar dengan relationship antar table seperti 1-1, 1-n, dan juga sudah familiar menggunakan hasOne, hasMany dan belongsTo di Eloquent.

Sebagai contoh kita buat tiga class turunan Eloquent. Kita buat dari City dulu, baru lanjut ke Province dan Country.

<?php 

# app/City.php

use Illuminate\Database\Eloquent\Model;

class City extends Model
{
	/**
	  * Kota dimiliki oleh satu provinsi
	  */
	public function province()
	{
		return $this->belongsTo('Province');
	}
}
<?php

# app/Province.php

use Illuminate\Database\Eloquent\Model;

class Province extends Model
{
	/**
	  * Provinsi dimiliki oleh satu negara
	  */
	public function country()
	{
		return $this->belongsTo('Country');
	}
	
	/**
	  * Provinsi memiliki banyak kota
	  */
	public function cities()
	{
		return $this->hasMany('City');
	}
}
<?php

# app/Country.php

use Illuminate\Database\Eloquent\Model;

class Country extends Model
{
	/**
	  * Negara memiliki banyak provinsi
	  */ 
	public function provinces()
	{
		return $this->hasMany('Province');
	}
}

Oke, jika kita lihat file yang terakhir, belum ada method dengan nama cities disana. Karena jika kita tambahkan hasMany('City') tentu saja tidak bisa. Karena seperti yang disebutkan sebelumnya, tidak ada field dengan nama country_id pada cities.

Solusinya kita tambahkan method ini:

	public function cities()
	{
		return $this->hasManyThrough('City', 'Province');
	}

Penjelasannya gini

eloquent-hasmanythrough

Sehingga untuk mengambil data cities dari Country cukup menggunakan

App\Country::with('cities')->get();

// Hanya dari negara Indonesia
App\Country::with('cities')->where('name', 'Indonesia')->get();

Tutup dulu

Informasi lebih detail mengenai hal ini bisa dilihat pada dokumentasi Laravel http://laravel.com/docs/master/eloquent#has-many-through

Jika ada pertanyaan atau error, silahkan sampaikan di kolom komentar. Karena code ini sebenarnya belum dicoba. 😐

Iklan

14 pemikiran pada “Laravel Eloquent Has Many Through

  1. terima kasih om Mulia, sangat bermanfaat bagi kami yang baru belajar laravel, isinya singkat dan jelas

    1. Cara loopingnya biasa aja seperti nggak tau kalau itu ada has many through :/

      Supaya gampang, liat aja menggunakan ->toArray();

      Misalnya

      $countries = App\Country::with('cities')->get();
      
      var_dump($countries->toArray());
      
      // Jadi looping biasa aja
      
      foreach ($countries as $country)
      {
          var_dump($country->cities);
      }
      
      // Kalau mau pakai collection bisa juga, sama aja
      
      $countries->each(function($country)
      {
          var_dump($country->cities);
      }
      
  2. tapi di eloquentnya, dimana sisi penjelasan “where city.province_id = province.id” nya ya? apakah dari sisi Table nya sudah dibuat FK (“city.province_id” ke “province.id”) terlebih dahulu?

    1. Tidak harus ada foreign key (bukan tidak perlu).
      Eloquent bisa menghubungkannya berdasarkan convention.

      Misalnya convention untuk nama table plural: users
      Maka convention name-nya adalah nama table singular user ditambah dengan _id, sehingga menjadi user_id. Hanya dengan itu sudah bisa terhubung.

      Kalau mau eksplisit atau nama field berbeda, bisa tambahkan di paremeter kedua dan ketiga. Misalnya:

      
      return $this->belongsTo('users', 'id_nama_lain');
      

      Detailnya bisa dibaca di dokumentasi http://laravel.com/docs/master/eloquent-relationships#has-many-through

  3. Mas, saya punya contoh kasus dengan tabel2 seperti ini:

    # Countries
    id | country_name
    
    # Places
    id | place_name | country_id
    
    # Merchant
    id | merchant_name | place_id

    Pada App\Models\Merchants saya buat method seperti ini:

    public function country()
    {
        return $this->hasManyThrough('App\Models\Countries', 'App\Models\Places');
    }

    Lalu di controller saya gunakan seperti ini:

    $merchants = $this->merchantsRepository->with(['country'])->paginate();

    tapi kenapa error 500 ya?

    Mohon pencerahannya, terima kasih.

  4. kalo misal 3 tabel saya pake many to many relationship, gimana cara nya pake has many through ya mas?kok di saya gagal terus

  5. Mas saya punya 5 table

    * users
    id | name

    * roles
    id | name

    * user_role
    user_id | role_id

    * permissions
    id | name

    * role_permission
    role_id | permission_id

    yang saya tanyakan bagaimana cara supaya pada saat saya sudah login saya mendapatkan data dari tabel permissions aja.

    saya sudah coba pada model User saya buat method seperti ini

    public function permissions()
    {
    $this->hasManyThrough(‘App\Models\Permission’,’App\Models\Role’,’user_id’,’role_id’,’id);
    }

    kemudian di controller User saya gunakan seperti ini
    $user = User::find($idLogin);
    dd($user->permissions);

    error nya ini
    SQLSTATE[42S22]: Column not found: 1054 Unknown column ‘roles.user_id’ in ‘field list’
    (SQL: select `permissions`.*, `roles`.`user_id` from `permissions` inner join `roles` on `roles`.`id` = `permissions`.`permission_id` where `roles`.`user_id` = 1)

    tolong bantuanya mas, terima kasih.

      1. Saya sudah ketemu caranya mas kodenya

        $user = User::find($id);
        
        foreach($user->roles as $v){
            foreach($v->permissions as $vv){
                dd($vv);
            }    
        }
        

        tapi apakah kalau memakai query builder join pada kasus saya akan lebih cepat untuk menampilkan datanya. kalau lebih cepat tolong kasih contohnya pada kasus saya mas. maaf ngerepotin mas soalnya saya newbie jadi belum bisa query join yang rumit.

Tinggalkan Balasan

Please log in using one of these methods to post your comment:

Logo WordPress.com

You are commenting using your WordPress.com account. Logout / Ubah )

Gambar Twitter

You are commenting using your Twitter account. Logout / Ubah )

Foto Facebook

You are commenting using your Facebook account. Logout / Ubah )

Foto Google+

You are commenting using your Google+ account. Logout / Ubah )

Connecting to %s