====== Использование классов из подсистем Query и Criteria ======
===== Использование Query =====
Классы из [[Query|подсистемы Query]] инкапсулируют шаблон sql-запроса и предоставляют средства для расширения (заполнения) этого шаблона. Поясним на примере.
Возьмем класс [[lmb_select_query|lmbSelectQuery]]:
$connection = ...
$query = new lmbSelectQuery('news', $connection);
Если $connection не передать (это опциональный параметр), тогда будет использовано подключение к базе данных по-умолчанию. (см. [[connection|Подключение к базе данных]]).
Этот $query пока аналог запроса "SELECT * FROM news". Попробуем его расширить:
$query->addTable('comments');
$query->addField('comments.*');
$query->addCriteria('date < ' . time() - 60*60*24);
$query->addCriteria('comments.news_id = news.id');
Так как класс [[lmb_select_query|lmbSelectQuery]] поддерживает chaining, а также есть набор алиасов на базовые методы, этот пример можно записать намного компактнее:
$query->from('comments')->field('comments.*')->where('news.date > ' . time() - 60*60*24)->where('comments.news_id = news.id');
Теперь это уже аналог запроса "SELECT comments.* FROM news, comments WHERE news.date < 123456567 AND comments.news_id = news.id". При добавлении нескольких условий при помощи метода where(), они объединяются через AND. см. "логические операции с criteria" ниже для добавления более сложных условий.
После произведения модификаций над query можно выполнить ее, получив record_set. Для lmbSelectQuery используется метод **getRecordSet()** или **fetch()**;
$rs = $query->getRecordSet();
$rs = $query->fetch();//тоже самое
Для классов [[lmb_delete_query]] и [[lmb_update_query]] для выполнения запроса используется метод **execute()**:
$query = new lmbDeleteQuery('news');
$query->execute();
Также из $query можно получить объект утверждения (statement) при помощи метода **getStatement()**, например:
$statement = $query->getStatement();
$rs = $statement->getRecordSet();
Или можно получить готовый sql-код при помощи метода **toString()**:
$sql = $query->toString();
Для создания объекта query в классе [[lmbDBAL|lmbDBAL]] есть статические фабричные методы, например:
$rs = lmbDBAL :: selectQuery('news')->order('date')->fetch()->paginate(0, 10);
lmbDBAL :: deleteQuery('news')->where('date < ' time() . 24*60*68*365)->execute();
===== Когда лучше использовать Query классы =====
Мы предпочитаем использование явного $sql-кода, во всех случаях, когда возможно обойтись без query.
Например, следующий запрос:
$sql = "SELECT comments.* FROM news, comments WHERE news.date < 123456567 AND comments.news_id = news.id";
$rs = lmbDBAL :: fetch($sql);
...можно было бы, конечно, написать и так:
$query = new lmbSelectQuery('news');
$query->from('comments')->field('comments.*')->where('news.date > ' . time() - 60*60*24)->where('comments.news_id = news.id');
return $query->getRecordSet();
Однако излишнее усложнение обычно ни к чему. Использование объектного query полезно в случаях, когда ограничения в запрос могут добавлять набором методов или классов, когда от наличия тех или иных полей в выборках зависит от каких-то внешних данных.
===== Использование критерий Criteria =====
==== Создание критерий ====
Критерии используются обычно совместно с потомками [[lmb_criteria_query]], такими как [[lmb_select_query]], [[lmb_update_query]] и [[lmb_delete_query]] для добавления условий к %where% и %having%.
Самый простой способ создать объект criteria - это создать экземпляр класса [[lmbsql_criteria|lmbSQLCriteria]], который принимает просто часть sql-кода и набор значений для замены в placeholder-ах, например:
$criteria = new lmbSQLCriteria('news_id = ' . (int)$news_id);
// пример с placeholder-ами.
$criteria = new lmbSQLCriteria('news_id = ? AND section_id = ?', array((int)$news_id, (int)$section_id));
// или
$criteria = new lmbSQLCriteria('news_id = :news_id: AND section_id = :section_id:',
array('news_id' => (int)$news_id, 'section_id' => (int)$section_id));
Часто используется также класс [[lmbsql_field_criteria|lmbSQLFieldCriteria]], который позволяет вставлять условия на какие-либо поля выборок, например:
lmb_require('limb/dbal/src/criteria/lmbSQLFieldCriteria.class.php');
$criteria1 = new lmbSQLFieldCriteria('news_id', (int)$news_id);
// или
$criteria1 = new lmbSQLFieldCriteria('news_id', (int)$news_id, lmbSQLFieldCriteria :: EQUAL);
// или
$criteria1 = new lmbSQLFieldCriteria('news_id', (int)$news_id, ' = ');
$criteria2 = new lmbSQLFieldCriteria('name', '%' . $name . '%', lmbSQLFieldCriteria :: LIKE);
// или
$criteria2 = new lmbSQLFieldCriteria('name', '%' . $name . '%', ' LIKE ');
Полный список условий см. в [[lmbsql_field_criteria|описании класса lmbSQLFieldCriteria]].
В классе [[lmbsql_criteria|lmbSQLCriteria]] для есть набор статических фабричных методов для удобного создания различных объектов класса lmbSQLFieldCriteria, например:
$criteria1 = lmbSQLCrireria :: equal('news_id', (int)$news_id);
$criteria2 = lmbSQLCrireria :: like('name', '%' . $name . '%');
$criteria3 = lmbSQLCrireria :: in('section_id', array($section_id1, $section_id2));
Остальные методы см. в описании класса [[lmbsql_criteria|lmbSQLCriteria]].
Для between условий есть класс [[lmbsql_field_between_criteria|lmbSQLFieldBetweenCriteria]]:
lmb_require('limb/dbal/src/criteria/lmbSQLFieldBetweenCriteria.class.php');
$criteria = new lmbSQLFieldBetweenCriteria('date', $date_start, $date_end);
В классе [[lmbsql_criteria|lmbSQLCriteria]] для удобства есть также статический фабричный метод для создания объекта класса lmbSQLFieldBetweenCriteria, например:
$criteria1 = lmbSQLCrireria :: between('date', $date_start, $date_end);
==== Логические операции с критериями ====
Criteria классы поддерживают логические операции:
* **and**
* **or**
* **not**
Поддержка логических операций реализована в базовом класса lmbSQLBaseCriteria поэтому их поддерживают все критерия.
Для **объединения (AND)** условий, используется метод **addAnd($criteria)**, например:
$criteria = new lmbSQLFieldCriteria('ingredient.name', '%'.$name.'%', lmbSQLFieldCriteria :: LIKE);
$new_criteria = new SQLFielBetweenCriteria('value', 10, 20)
$criteria->addAnd($new_criteria);
Для метода addAnd() есть алиас **add($criteria)**, поэтому в более краткой форме пример выше можно записать следующим образом:
$criteria = lmbSQLField :: like('ingredient.name', '%'.$name.'%')->add(lmbSQLField :: between('value', 10, 20));
Для вставки условий **или OR** есть метод **addOr($criteria)**:
$criteria = lmbSQLField :: equal('name', 'Vasa')->addOr(lmbSQLField :: equal('name', 'Ivan'));
Для вставки **отрицания (NOT)** самой критерии есть метод **not()**:
$criteria = lmbSQLField :: equal('name', 'Vasa')->not(); // Даст в результате NOT(name = "Vasa")
Такж есть метод notAll() который применяет к общему критерию, из которых состоит данное, например:
$a = new lmbSQLCriteria('a');
$b = new lmbSQLCriteria('b');
$a->add($b);
$a->notAll(); // В результе получим NOT(a AND b)
Методы логических операций поддерживают **chaining**:
$a = new lmbSQLCriteria('a');
$b = new lmbSQLCriteria('b');
$a->notAll()->add($b);
Можно и посложнее:
$a = new lmbSQLCriteria('a');
$b = new lmbSQLCriteria('b');
$c = new lmbSQLCriteria('c');
$d = new lmbSQLCriteria('d');
$e = new lmbSQLCriteria('e');
$g = new lmbSQLCriteria('g');
$h = new lmbSQLCriteria('h');
$a->addOr($b->addAnd($c))->addAnd($d->addOr($e)->addAnd($g->addOr($h)));
// Получим - a OR (b AND c) AND (d OR e AND (g OR h))