Cara menggunakan class-class pada yii\db\conditions

24 Jan 2022

Hari ini saya ingin membagi tips tentang cara penggunaan class yang ada pada namespace yii\db\conditions yang berguna saat kita membuat query yang komplek. Yii itu powerfull tetapi dokumentasinya kurang lengkap dan kurangnya contoh-contoh penggunaan klas/fungsi.

SimpleCondition

Ok kita mulai dari klas SimpleCondition, sesuai dengan namanya klas ini untuk kondisi yang simple-simple aja. Operator yang dapat diguanakan adalah =, >, >=, <, <=, dan !=.

$cond = new SimpleCondition('id', '=', 1);
$row = User::find()->where($cond)->one();
// select * from user where id = 1

Untuk mendapatkan raw sql dari ActiveQuery kita bisa gunakan fungsi getRawSql. Dari contoh kode di atas kita bisa buang one dan tinggal echo seperti ini:

...
$row = User::find()->where($cond);
echo $row->createCommand()->getRawSql(), PHP_EOL;
// select * from user where id = 1

Klas SimpleCondition ini bisa kita gabung dengan klas AndCondition atau OrCondition untuk membuat query yang komplek. Untuk menggabungnya kita buat array yang berisi SimpleCondition, lalu kita taruh pada constructor AndCondition atau OrConditon. Kita lihat contohnya berikut:

AndCondition

Klas untuk menggabungkan kondisi dari SimpleCondition, OrCondition, AndCondition atau yang kompatible dengan parameter klas ini.

$cond = [new SimpleCondition('id', '=', 1), new SimpleConditon('id', '=', 2)];
$where = new AndCondition($cond);
$row = User::find()->where($where)->all();
// select * user where id = 1 and id = 2

OrCondition

Atau dengan OrCondition, cara masih sama kita masukan array yang berisi SimpleCondition kedalam constructor.

$cond = [new SimpleCondition('id', '=', 1), new SimpleConditon('id', '=', 2)];
$where = new OrCondition($cond);
$row = User::find()->where($where)->all();
// select * user where id = 1 or id = 2

Dari dua klas ini OrCondition dan AndCondition kita bisa gunakan untuk menggabung query yang lebih komplek.

$cond1 = [
    new SimpleCondition('id', '>=', 1), 
    new SimpleCondition('id', '<=', 3)
];
$cond2 = new SimpleCondition('level_id', '=', 1);
$cond3 = new SimpleCondition('username', '=', 'admin');
$where = new AndCondition([
    new AndCondition([new OrCondition($cond1), $cond2]),
    $cond3
]);
$row = User::find()->where($where)->all();
// SELECT * FROM `user` WHERE (((`id` >= 1) OR (`id` <= 3)) AND (`level_id` = 1)) AND (`username` = 'admin')

Catatan bahwa AndCondition dan OrCondition hanya bisa menerima array dari SimpleCondition bukan array dari array seperti new AndCondition([[new SimpleCondition, new SimpleCondition]]). atau hasil dari AndCondition dan OrCondition itu sendiri.

BetweenCondition

Kita lanjut ke klas BetweenCondition, klas ini menerima parameter column, operator, intervalStart dan intervalEnd. Parameter operator bisa berupa BETWEEN atau NOT BETWEEN.

$where = new BetweenCondition('id', 'BETWEEN', 1, 4);
$row = User::find()->where($where)->all();
// SELECT * FROM `user` WHERE `id` BETWEEN 1 AND 4

Klas ini juga bisa digunakan untuk AndCondition dan OrCondition.

BetweenColumnsCondition

Klas ini mirip dengan BetweenCondition tetapi intervalnya menggunakan kolumn dari pada value. Klas ini menerima parameter value, operator, intervalStartColumn dan intervalEndColumn. Parameter operator bisa berupa BETWEEN atau NOT BETWEEN. Untuk melihat perbedaannya kita lihat potongan kode berikut ini:

$where = new BetweenColumnsCondition(10, 'BETWEEN', 'min_value', 'max_value');
$row = Demo::find()->where($where);
echo $row->createCommand()->getRawSql(), PHP_EOL;
// SELECT * FROM `demo` WHERE 10 BETWEEN min_value AND max_value

ExistsCondition

Klas ini untuk digunakan untuk memeriksa subquery ada atau tidak, parameter yang harus dilewatkan yaitu operator exists/not exists dan ekpresi (yii\db\Expression).

$where = new ExistsCondition(
    'EXISTS', 
    new \yii\db\Expression('SELECT level_id FROM user_level WHERE level_id = 1')
);
$rows = User::find()->where($where);
echo $rows->createCommand()->getRawSql(), PHP_EOL;
// SELECT * FROM `user` WHERE EXISTS 
// SELECT level_id FROM user_level WHERE level_id = 1

InCondition

Klas ini digunakan untuk query syntax in dan not in. Operator yang bisa digunakan adalah IN dan NOT IN.

$where = new InCondition('id', 'IN', [1, 2]);
$row = User::find()->where($where);
echo $row->createCommand()->getRawSql(), PHP_EOL;
// SELECT * FROM `user` WHERE `id` IN (1, 2)

LikeCondition

Klas ini untuk query kondisi like, operator yang digunakan bisa berupa like, not like, or like, or not like

$where = new LikeCondition('username', 'LIKE', 'admin');
$row = User::find()->where($where);
echo $row->createCommand()->getRawSql(), PHP_EOL;
// SELECT * FROM `user` WHERE `username` LIKE `%admin%`

Value bisa berupa string atau array, jika value berupa array maka operator yang akan digunakan adalah AND.

$where = new LikeCondition('username', 'LIKE', ['admin', 'user']);
$row = User::find()->where($where);
echo $row->createCommand()->getRawSql(), PHP_EOL;
// SELECT * FROM `user` WHERE `username` LIKE `%admin%` AND `username` LIKE `%user%`

NotCondition

Klas ini digunakan untuk membalik kondisi yang dilewatkan pada parameter. Misalnya pada kode diatas kita mencari username yang mengandung kata admin, kita bisa balik kondisinya menjadi yang tidak mengandung user admin dengan klas ini.

$likeCond = new LikeCondition('username', 'LIKE', 'admin');
$where = new NotCondition($likeCond);
$row = User::find()->where($where);
echo $row->createCommand()->getRawSql(), PHP_EOL;
// SELECT * FROM `user` WHERE NOT(`username` LIKE `%admin%`)

Atau bisa juga untuk membalik kondisi pada saat kita mencari user yang idnya bukan 1

$eqCond = new SimpleCondition('id', '=', 1);
$where = new NotCondition($eqCond);
$row = User::find()->where($where);
echo $row->createCommand()->getRawSql(), PHP_EOL;
// SELECT * FROM `user` WHERE NOT(`id` = 1)

Oke dari klas-klas di atas kita membuat query kondisi komplek yang kemudian dapat digunakan pada kondisi where ActiveQuery/Query. Dan juga kode kita akan menjadi lebih ringkas karena kita bisa memisahkan query yang komplek kedalam fungsi-fungsi yang lebih kecil.

Sekian.