Yii PHP framework: создание запросов с условием IN

Последнее время мне довольно часто приходится работать с фреймворком Yii. И иногда возникают вопросы, ответы на которые не очевидны (во всяком случае для меня).
Попробую объяснить. Сам фреймворк, на мой взгляд, достаточно удобный и документация подробная. Но классов много, и формат передачи данных их методам часто сильно влияет на результат.
Рассмотрим небольшой пример – использование оператора IN.
Т.е. нужно сформировать примерно такой запрос.
-
SELECT * FROM tbl_users WHERE id IN (1, 2, 3)
В Полном руководстве на эту тему информации я не нашел, а копаться в методах CActiveRecord времени не было.
Вообще, я очень не люблю такие ситуации. С одной стороны, понятно как нужно написать запрос, с другой – хочется сделать это красиво, используя встроенную библиотеку. Копаться в документации не хочется, ведь на это уходит время, а запрос можно составить за считанные минуты. Но не все так просто.
Сначала покажу решение «в лоб».
-
$ids = array(1, 2, 3);
-
-
$dataProvider=new CActiveDataProvider('User',array(
-
'criteria'=>array(
-
'condition'=>'id IN ('.implode(',', $ids).')',
-
)
-
));
-
-
$this->render('admin',array(
-
'model'=>$dataProvider,
-
));
Тут мы формируем массив со значениями, которые будут перечислены после IN. А затем, с помощью функции implode преобразуем его в строку и просто вставляем в запрос.
Недостатки такого подхода очевидны.
Во-первых, выглядит код не очень красиво.
Во-вторых, в реальном приложении значения для массива $ids будут откуда-то поступать, возможно, из параметров запроса. И если массив $ids окажется пустым, то при выполнении запроса возникнет ошибка.
В-третьих, полученные значения нужно проверить. А написать что-то вроде
-
'params'=>array(':id'=>implode(', ', $ids)),
не получится, т.к. результат работы функции implode будет взят в кавычки. Т.е. проверку необходимо сделать предварительно.
Как видите, возникают проблемы практически на пустом месте. Нужно написать код проверок, решить, что делать с пустым массивом, затем протестировать этот код. И все ради решения тривиальной задачи.
Решение с помощью библиотеки Yii.
Оно выглядит гораздо проще.
-
$model = User::model()->findAllByAttributes(array('id'=>array(1, 2, 3)));
-
$dataProvider=new CActiveDataProvider('User');
-
$dataProvider->setData($model);
-
-
$this->render('index',array(
-
'dataProvider'=>$dataProvider,
-
));
Метод findAllByAttributes класса CActiveRecord позволяет искать записи в БД по названию поля и значению. При этом если значение является массивом, то используется оператор IN.
Этот же самый код можно записать немного иначе.
-
$dataProvider=new CActiveDataProvider('User');
-
$dataProvider->criteria->addInCondition('id', array(1,2,3));
-
-
$this->render('index',array(
-
'dataProvider'=>$dataProvider,
-
));
Тут уже используется метод addInCondition класса CDbCriteria. Если вы работаете с CActiveDataProvider, то получить доступ к объекту CDbCriteria можно с помощью свойства criteria.
Теперь проведем несколько экспериментов.
Попробуем в массиве передать строку.
-
$dataProvider->criteria->addInCondition('id', array(1,2,'test'));
В результате будет выполнен следующий запрос.
-
SELECT * FROM 'tbl_user' WHERE "id" IN (1, 2, 0)
Т.е. текстовое значение было заменено нулем, что вполне логично, т.к. поле id имеет тип INT.
Если запрос будет выполняться к полю текстового типа, то текстовые и числовые значения будут вставлены в кавычках.
-
$dataProvider->criteria->addInCondition('id', array(1, 'admin','user'));
сформирует такой запрос
-
SELECT * FROM 'tbl_user' WHERE "id" IN ('1','admin', 'user')
А если массив окажется пуст, то фреймворк гарантирует, что из таблицы не будет выбрана ни одна запись.
-
$dataProvider->criteria->addInCondition('id', array());
-
SELECT * FROM 'tbl_user' WHERE 0=1
Как видите, использование встроенных библиотек всё-таки оправдывает время, потраченное на их изучение
Только не забывайте при работе с документацией Yii учитывать один момент. Классы библиотеки тесно связаны между собой, поэтому искать нужно не только в методах класса, с которым вы непосредственно работаете, но и в методах объектов, которые использует этот класс.
Так CActiveDataProvider использует CDbCriteria для формирования условий, CPagination – для разбивки на страницы, CSort – для сортировки и т.д.
Вообще, я заметил, чем больше работаешь с фреймворком, тем логичнее кажутся решения разработчиков и тем проще ориентироваться в документации
Удачи!
Понравилась статья? Подписывайтесь на продолжение
!
Опубликовано в MySQL, PHP, Web разработка, Yii View Comments
-
Дмитрий
-
Владимир
-
Александр
-
Владимир
-
Eight Buddha
-
Eight Buddha
-
Владимир
-
Alexy4b
-
Eight Buddha
-
AmdY
-
Serge Bezborodov
-
BuCeFaL
-
Владимир








