Версия: 6.x
burger close
Выборка ORM-объектов из базы данных

Для выборки сущностей из базы данных, следует воспользоваться классом RS::Orm::Request. Данный класс позволяет конструировать запрос к базе данных из частей, схожих по именованию с инструкциями SQL. Результатом выборки может быть как массив массивов, так и массив ORM-объектов(используется гораздо чаще).

Преимущество конструктора запроса в виде объекта заключается в том, что его можно передавать по ссылке и без особых сложностей изменять или дополнять нужную часть запроса.

Чтобы создать экземпляр класса, можно воспользоваться как ключевым словом new, так и вызвать статический метод RS::Orm::Request::make(). Второй вариант позволяет сконструировать и запустить запрос в одну строку.

$q = new \RS\Orm\Request();
//В $result - массив ORM Объектов \Catalog\Model\Orm\Product
$result = $q->select()
->from(new \Catalog\Model\Orm\Product)
->objects();
echo $q; // У объекта перегружен метод __toString. Выведет SQL запрос: SELECT * FROM `readyscript`.`prefix_product`
//В $result - массив ORM Объектов \Catalog\Model\Orm\Product
->select()
->from(new \Catalog\Model\Orm\Product)
->objects();

Построение запроса

Каждый из методов построения запроса дополняет запрос соответствующей секцией и возвращает объект самого себя в качестве результата, что позволяет строить цепочку из методов.

select

RS::Orm::Request::select - Заполняет секцию SELECT у SQL запроса.

echo \RS\Orm\Request::make()
->select('title', 'alias')
->from(new \Catalog\Model\Orm\Product);
//Выведет: SELECT title, alias FROM `readyscript`.`prefix_product`
echo \RS\Orm\Request::make()
->select('title')
->select('alias') //Можно повторно вызывать методы, они будут добавлять через запятую выражение.
->from(new \Catalog\Model\Orm\Product);
//Выведет: SELECT title, alias FROM `readyscript`.`prefix_product`
echo \RS\Orm\Request::make()
->select('COUNT(*)') //Можно указать произвольное выражение
->from(new \Catalog\Model\Orm\Product);
//Выведет: SELECT COUNT(*) FROM `readyscript`.`prefix_product`

update и set

RS::Orm::Request::update - Заполняет секцию UPDATE у SQL запроса

RS::Orm::Request::set - Заполняет секцию SET у SQL запроса

echo \RS\Orm\Request::make()
->update(new \Catalog\Model\Orm\Product)
->set(array(
'title' => 'Новое название' //В этом случае система будет экранировать все данные
))
->where(array('id' => 5));
//->exec() //чтобы выполнить запрос нужно выполнить exec
//Выведет: UPDATE `readyscript`.`prefix_product` SET `title` = 'Новое название' WHERE (`id` = '5')
echo \RS\Orm\Request::make()
->update(new \Catalog\Model\Orm\Product)
->set("title = alias, barcode='12345'") //Можно указывать произвольное выражение
->where(array('id' => 5));
//->exec() //чтобы выполнить запрос нужно выполнить exec
//Выведет: UPDATE `readyscript`.`prefix_product` SET title = alias, barcode='12345' WHERE (`id` = '5')

delete

RS::Orm::Request::delete - Заполняет секцию DELETE у SQL запроса

echo \RS\Orm\Request::make()
->delete(new \Catalog\Model\Orm\Product)
->from(new \Catalog\Model\Orm\Product, 'P')
->from(new \Catalog\Model\Orm\Dir, 'D')
->where('D.id = P.maindir')
->where(array(
'D.dir_id' => '1'
));
//Выведет: DELETE `readyscript`.`prefix_product`
FROM `readyscript`.`prefix_product` as P,
`readyscript`.`prefix_product_dir` as D
WHERE
D.id = P.maindir
AND (`D`.`dir_id` = '1')
echo \RS\Orm\Request::make()
->delete()
->from(new \Catalog\Model\Orm\Product)
->where(array(
'id' => '1'
));
//Выведет: DELETE FROM `readyscript`.`prefix_product` WHERE (`id` = '1')

from

RS::Orm::Request::from - Заполняет секцию FROM у SQL запроса

//По умолчанию используется оператор SELECT *
echo \RS\Orm\Request::make()
->from(new \Catalog\Model\Orm\Product, 'P') //Можно указать таблицу с помощью объекта
->from('`readyscript`.`prefix_product_dir` as D') //Можно указать таблицу строкой
->where('D.id = P.maindir');
//Выведет: SELECT * FROM `readyscript`.`prefix_product` as P, `readyscript`.`prefix_product_dir` as D WHERE D.id = P.maindir

join

RS::Orm::Request::join - Заполняет секцию JOIN у SQL запроса

echo \RS\Orm\Request::make()
->from(new \Catalog\Model\Orm\Product, 'P')
->join(new \Catalog\Model\Orm\Dir, 'D.id = P.maindir', 'D')
->join(new \Catalog\Model\Orm\Unit, 'U.id = P.unit', 'U')
->where(array(
'P.id' => 1
));
//Выведет: SELECT * FROM `readyscript`.`prefix_product` as P
// INNER JOIN `readyscript`.`prefix_product_dir` as D ON D.id = P.maindir
// INNER JOIN `readyscript`.`prefix_product_unit` as U ON U.id = P.unit
// WHERE P.id = '1'
echo \RS\Orm\Request::make()
->from(new \Catalog\Model\Orm\Product, 'P')
->join(new \Catalog\Model\Orm\Dir, 'D.id = P.maindir', 'D', 'LEFT')
->where(array(
'P.id' => 1
));
//Выведет: SELECT * FROM `readyscript`.`prefix_product` as P
// LEFT JOIN `readyscript`.`prefix_product_dir` as D ON D.id = P.maindir
// WHERE P.id = '1'

leftJoin

RS::Orm::Request::leftjoin - Вызывает метод join с заранее установленным типом - LEFT

echo \RS\Orm\Request::make()
->from(new \Catalog\Model\Orm\Product, 'P')
->leftjoin(new \Catalog\Model\Orm\Dir, 'D.id = P.maindir', 'D')
->leftjoin(new \Catalog\Model\Orm\Unit, 'U.id = P.unit', 'U')
->where(array(
'P.id' => 1
));
//Выведет: SELECT * FROM `readyscript`.`prefix_product` as P
// LEFT JOIN `readyscript`.`prefix_product_dir` as D ON D.id = P.maindir
// LEFT JOIN `readyscript`.`prefix_product_unit` as U ON U.id = P.unit
// WHERE P.id = 1

where

RS::Orm::Request::where - Заполняет секцию WHERE у SQL запроса

echo \RS\Orm\Request::make()
->select('*')
->from(new \Catalog\Model\Orm\Product, 'P')
->from(new \Catalog\Model\Orm\Dir, 'D')
->where("D.id = P.maindir AND (P.id='#id' OR P.title='#title')", //Можно указать произвольное условие, переменные будут экранированы
array(
'id' => 1,
'title' => 'Монитор'
)
);
//Выведет: SELECT *
// FROM
// `readyscript`.`prefix_product` as P,
// `readyscript`.`prefix_product_dir` as D
// WHERE
// D.id = P.maindir AND (P.id='1' OR P.title='Монитор')
echo \RS\Orm\Request::make()
->select('*')
->from(new \Catalog\Model\Orm\Product, 'P')
->from(new \Catalog\Model\Orm\Dir, 'D')
->where(array(
'maindir' => 1
))
->where(
array(
'id' => 1,
'title' => 'Монитор'
),
null,
'AND', //Оператор связи с предыдущим условием
'OR' //Оператор связи между элементами массива
);
//Выведет: SELECT *
// FROM
// `readyscript`.`prefix_product` as P,
// `readyscript`.`prefix_product_dir` as D
// WHERE
// (`maindir` = '1') AND (`id` = '1' OR `title` = 'Монитор')

whereIn

RS::Orm::Request::whereIn - Заполняет секцию WHERE ... IN () у SQL запроса

echo \RS\Orm\Request::make()
->select('*')
->from(new \Catalog\Model\Orm\Product)
->whereIn('id', array(1,2,3,4,5));
//Выведет: SELECT * FROM `readyscript`.`prefix_product` WHERE id IN ('1','2','3','4','5')

openWGroup и closeWGroup

RS::Orm::Request::openWgroup - Добавляет открывающую скобку для группировки условий

RS::Orm::Request::closeWGroup - Добавляет закрывающую скобку для группировки условий

echo \RS\Orm\Request::make()
->select('*')
->from(new \Catalog\Model\Orm\Product)
->where(array('maindir' => 1))
->openWGroup('AND')
->where("title = '#title' OR id = '#id'", array(
'title' => 'Моноблок',
'id' => 1
))
->closeWGroup();
//Выведет: SELECT * FROM `readyscript`.`prefix_product` WHERE (`maindir` = '1') AND ( title = 'Моноблок' OR id = '1')

offset

RS::Orm::Request::offset - Устанавливает offset для LIMIT offset, limit у SQL запроса

echo \RS\Orm\Request::make()
->select('*')
->from(new \Catalog\Model\Orm\Product)
->offset(5)
->limit(3);
//Выведет: SELECT * FROM `readyscript`.`prefix_product` LIMIT 5, 3
//Аналог:
echo \RS\Orm\Request::make()
->select('*')
->from(new \Catalog\Model\Orm\Product)
->limit(5, 3);
//Выведет: SELECT * FROM `readyscript`.`prefix_product` LIMIT 5, 3

limit

RS::Orm::Request::limit - Заполняет секцию LIMIT у SQL запроса

echo \RS\Orm\Request::make()
->select('*')
->from(new \Catalog\Model\Orm\Product)
->limit(5);
//Выведет: SELECT * FROM `readyscript`.`prefix_product` LIMIT 5
echo \RS\Orm\Request::make()
->select('*')
->from(new \Catalog\Model\Orm\Product)
->limit(3, 5);
//Выведет: SELECT * FROM `readyscript`.`prefix_product` LIMIT 3, 5

orderby

RS::Orm::Request::orderby - Заполняет секцию ORDER BY у SQL запроса

echo \RS\Orm\Request::make()
->select('*')
->from(new \Catalog\Model\Orm\Product)
->orderby('maindir, title');
//Выведет: SELECT * FROM `readyscript`.`prefix_product` ORDER BY maindir, title

groupby

RS::Orm::Request::groupby - Заполняет секцию GROUP BY у SQL запроса

echo \RS\Orm\Request::make()
->select('title, COUNT(title)')
->from(new \Catalog\Model\Orm\Product) //Можно указать таблицу с помощью объекта
->groupby('title');
//Выведет: SELECT title, COUNT(title) FROM `readyscript`.`prefix_product` GROUP BY title

having

RS::Orm::Request::having - Заполняет секцию HAVING у SQL запроса

echo \RS\Orm\Request::make()
->select('title, COUNT(title)')
->from(new \Catalog\Model\Orm\Product)
->groupby('title')
->having("COUNT('title') = 1");
//Выведет: SELECT title, COUNT(title) FROM `readyscript`.`prefix_product` GROUP BY title HAVING COUNT('title') = 1

Просмотр текущего состояния объекта

Текущее состояние различных секций запроса можно узнавать, обращаясь к соответствующему свойству объекта:

  • select
  • delete
  • having
  • groupby
  • from
  • joins
  • where
  • limit
  • offset
  • orderby
  • set

Присваивая свойству null, можно сбрасывать значение секции.

->select('title, COUNT(title)')
->from(new \Catalog\Model\Orm\Product) //Можно указать таблицу с помощью объекта
->where(array(
'id' => 1
))
->groupby('title');
echo $q->select; //Выведет title, COUNT(title)
echo $q->where; //Выведет (`id` = '1')
echo $q->groupby; //Выведет title
$q->groupby = null; //выключили секцию groupby

Выполнение запроса. Получение результата

Чтобы получить результат в виде массива объектов, необходимо вызвать метод RS::Orm::Request::objects(). Метод имеет следующие аргументы:

  • $class_name - object или string, необязательный. Задает класс возвращаемых объектов. Если аргумент не задан, то будет возвращен список из объектов класса, который был указан в последней секции from.
  • $key - string, необязательный. Задает поле, значение которого пойдет в ключ массива. Если не задано, то будет создан нумерованный массив.
  • $allow_sublist - bool, необязательный, по умолчанию - false. Имеет значение, если задан $key. Если указать true, то результат будет возвращен в виде ['key' => [object, object,...], 'key' => [object, object,...], иначе результат будет возвращен в виде ['key' => object, 'key' => object]
$array_of_products = \RS\Orm\Request::make()
->from(new \Catalog\Model\Orm\Product) //Можно указать таблицу с помощью объекта
->objects();
$array_of_products = \RS\Orm\Request::make()
->from(new \Catalog\Model\Orm\Product, 'P')
->from(new \Catalog\Model\Orm\Dir, 'D')
->where('D.id = P.maindir')
->objects(new \Catalog\Model\Orm\Product); //Можно уточнить класс результата запроса

Метод RS::Orm::Request::exec() выполняет запрос к базе данных и возвращает результат в виде объекта RS::Db::Result. Объект RS::Db::Result содержит указатель на ресурс результата запроса к MySQL, а также ряд методов по извлечению из него данных.

$result_resource = \RS\Orm\Request::make()
->from(new \Catalog\Model\Orm\Product) //Можно указать таблицу с помощью объекта
->exec();
echo 'Всего строк:'.$result_resource->rowCount();
while($row = $result_resource->fetchRow()) {
var_dump($row); //Массив с колонками из БД
}

Чтобы выполнить запрос и вернуть первый объект из списка, следует использовать метод Метод RS::Orm::Request::object(). Метод имеет следующие аргументы:

  • $class_name - object или string, необязательный. Задает класс возвращаемых объектов. Если аргумент не задан, то будет возвращен список из объектов класса, который был указан в последней секции from.
->from(new \Catalog\Model\Orm\Product)
->where(array('id' => 1))
->object();
->from(new \Catalog\Model\Orm\Product, 'P') //Можно указать таблицу с помощью объекта
->from(new \Catalog\Model\Orm\Dir, 'D')
->where('D.id = P.maindir')
->where(array(
'P.id' => 1
))
->object(new \Catalog\Model\Orm\Product);