Belajar Kode Program

Blog belajar menulis kode program dan aplikasi komputer

Minggu, 16 Juli 2017

Lazy Loading dan Eager Loading pada Yii2

Kali ini kita belajar mengenai ActiveRecord pada Yii, terutama yang berkaitan dengan relasi. Dalam hal memanggil data relasi yang ada pada tabel lain, ada istilah lazy loading dan eager loading. Lazy loading, sesuai namanya yang berarti malas, relasinya hanya dipanggil ketika nanti dibutuhkan. Sementara pada eager loading, sesuai namanya yang berarti bersemangat, data relasinya sudah disiapkan untuk mengantisipasi jika nanti ada yang me-request datanya.
Sekarang kita ambil sebuah kasus relasi antara pengarang dan tulisannya (relasi one-to-many). Pengarang kita buatkan tabel author dan tulisannya kita simpan pada tabel post. Dari kedua tabel tersebut kita membuat dua buah model Author dan Post.

Pada model author, kita buat relasinya seperti ini:
/* Author.php */
//nama field relasinya adalah posts, dari nama fungsi getPosts
public function getPosts()
{
    return $this->hasMany(Post::className(), ['author_id' => 'id']);
}

Pada model Post kita buat relasinya seperti ini:
/* Post.php */
//nama field relasinya adalah author, dari nama fungsi getAuthor
public function getAuthor()
{
    return $this->hasOne(Author::className(), ['id' => 'author_id']);
}

Untuk contoh lazy loading, kodenya adalah seperti ini:
$authors = Author::find()->all();  // mengambil hanya data dari tabel author
foreach($authors as $author) {
    echo "<h2>Author : " . $author->name . "</h2>";
    echo "<ul>";
    foreach($author->posts as $post) {  // memanggil data post satu per satu (queri lagi)
        echo "<li>" . $post->title . "</li>";
    }
    echo "</ul>";
}

Sementara jika kita menerapkan eager loading, sintaksnya menjadi seperti ini:
// memanggil data author sekaligus post dengan fungsi with('nama_field_relasi')
$authors = Author::find()->with('posts')->all();  
foreach($authors as $author) {
    echo "<h2>Author : " . $author->name . "</h2>";
    echo "<ul>";
    foreach($author->posts as $post) {  // tak ada query lagi
        echo "<li>" . $post->title . "</li>";
    }
    echo "</ul>";
}

Pada cara eager loading di atas, sebenarnya kueri yang dijalankan ada dua, yaitu:
SELECT * FROM author;
SELECT * FROM post WHERE author_id IN (1, 3, 7, 10, ... X);

Jika Anda ingin cukup satu kueri saja, gunakan fungsi joinWith('nama_field_relasi') sebagai pengganti fungsi with:
$authors = Author::find()
    ->joinWith('posts') // nama field relasi
    ->where(['like', 'post.title', $keyword])
    ->all();
foreach($authors as $author) {
    echo "<h2>Author : " . $author->name . "</h2>";
    echo "<ul>";
    foreach($author->posts as $post) {  // tidak perlu kueri lagi
        echo "<li>" . $post->title . "</li>";
    }
    echo "</ul>";
}

Nah, contoh di atas menggunakan joinWith yang ternyata punya kelemahan jika kita ingin menggunakan LIMIT.

Contoh sintaks:
$authors = Author::find()->with('posts')->limit(10)->all();

Sintaks tersebut akan menjalankan dua buah kueri berikut:
SELECT * FROM author LIMIT 10;
SELECT * FROM post WHERE author_id IN (1, 3, 7, 10, ... X);

Lain halnya kalau kita menggunakan join, tentu limit yang dimunculkan adalah baris teratas sebatas limit, dengan kueri kira-kira seperti ini:
SELECT * FROM author JOIN post ON post.author_id = author.id LIMIT 10;

Demikian, semoga bermanfaat dan selamat belajar!

Referensi:

  • http://www.yiiframework.com/wiki/834/relational-query-lazy-loadnig-and-eager-loading-in-yii-2-0/

Tidak ada komentar:

Posting Komentar