Построение запросов
Метод find() возвращает объект запроса. К нему по цепочке добавляют условия, сортировку и ограничения, а в конце вызывают метод, который выполняет запрос. Отдельных файлов для запросов нет: их пишут в контроллерах и моделях.
Простой запрос
$posts = Post::find()
->where(['status' => 1])
->all();Запрос вернёт массив объектов Post — все статьи со статусом 1. В базу уйдёт SELECT * FROM post WHERE status = 1.
Сортировка и ограничение
$latest = Post::find()
->where(['status' => 1])
->orderBy(['created_at' => SORT_DESC])
->limit(10)
->all();Получится десять самых новых опубликованных статей. SORT_DESC — по убыванию, SORT_ASC — по возрастанию.
Виды условий
| Запись | Что означает |
|---|---|
['status' => 1, 'user_id' => 5] | Оба равенства сразу |
['id' => [1, 2, 3]] | Значение из списка |
['>', 'created_at', 1767225600] | Сравнение |
['like', 'title', 'php'] | Заголовок содержит слово |
['between', 'id', 10, 20] | Значение в диапазоне |
['not', ['slug' => '']] | Отрицание условия |
Значения в таких условиях Yii подставляет безопасно сам.
Составные условия
Условия добавляют методами andWhere() и orWhere() — это удобно, когда часть из них зависит от запроса посетителя:
// controllers/PostController.php
public function actionSearch(string $q = ''): string
{
$query = Post::find()->where(['status' => 1]);
if ($q !== '') {
$query->andWhere(['like', 'title', $q]);
}
return $this->render('index', ['posts' => $query->all()]);
}Адрес /post/search?q=yii покажет опубликованные статьи со словом «yii» в заголовке, а без параметра — все опубликованные.
Чем заканчивается запрос
| Метод | Что возвращает |
|---|---|
all() | Массив объектов |
one() | Первый объект или null |
count() | Количество строк |
exists() | true, если есть хотя бы одна строка |
column() | Значения первого выбранного столбца |
Метод asArray() перед all() возвращает строки обычными массивами — это быстрее на больших выборках: Post::find()->select(['id', 'title'])->asArray()->all().
Построитель без модели
Для отчётов модели не нужны — подойдёт класс Query:
use yii\db\Query;
$rows = (new Query())
->select(['user_id', 'total' => 'COUNT(*)'])
->from('post')
->groupBy('user_id')
->all();Результат — массив строк с числом статей каждого автора.
Транзакции
Транзакция объединяет несколько изменений: либо выполнятся все, либо ни одно.
Yii::$app->db->transaction(function () use ($post, $comment) {
$post->save();
$comment->post_id = $post->id;
$comment->save();
});Если внутри функции возникнет исключение, все изменения отменятся.
Частая ошибка
Условие, собранное строкой из данных посетителя, — where("title = '$q'") — открывает путь SQL-инъекции: посетитель сможет дописать в запрос свой код. Используйте запись массивом или параметры: where('title = :title', [':title' => $q]).