Архитектура коллекций в Magento
В статье описаны теоретические основы коллекций в Magento — одного из архитектурных решений, повсеместно использующихся в проекте.
Коллекция — это объект, который может содержать определенный набор других объектов определенного класса. По логике организации коллекции в Magento работают как «список» В Magento коллекции реализовывают интерфейсы IteratorAggregate и Countable, что позволяет их «форичить» и подсчитывать количество элементов с помощью функции count():
foreach ($collection as $item) {
echo get_class($item);
}
echo count($collection);
Абстрактная коллекция, Varien_Data_Collection, сконцентрирована на работе с элементами, подсчете количества элементов, разбивке их на страницы, кешированием. В абстрактной коллекции определается класс, который будет инстанциирован при создании каждого элемента. По умолчанию это Varien_Object.
Коллекция декларирует метод load(), который вызывается автоматически при попытке «посчитать» или проитерировать коллекцию. В абстрактной коллекции метод load() лишь задействует метод loadData(), который ничего не делает — реализовать логику по загрузке данных предоставляется наследникам. Кроме работы с элементами (добавление, удаление, геттеры), есть возможность устанавливать фильтры. Реализацию работы фильтров абстрактная коллекция также предоставляет коллекциям, наследующих ее.
Ресурс-модель Varien_Data_Collection_Db
В библиотеке Varien представлены две ресурс-модели, наследующие абстрактную коллекцию — Varien_Data_Collection_Db и Varien_Data_Collection_Filesystem.
Varien_Data_Collection_Db реализовывает абстрактный уровень доступа к БД, используя Zend_Db_Adapter_Abstract. Основные функциональные возможности класса:
- сформировать SQL-запрос без привязки к определенному диалекту
- «скормить» запрос адаптеру для загрузки данных
- загрузить конкретные данные и создать элементы коллекции с помощью «родительских» методов
Особенностью этой ресурс-модели является то, что метод load() выполняет SQL-запрос и грузит данные лишь один раз — при первом вызове. Последующие вызовы load() ни к чему не приведут. То есть, можно «грузить» или итерировать коллекцию сколько угодно раз, не беспокоясь о лишних запросах к БД.
Можно получить объект SQL-запроса коллекции с помощью метода getSelect(). Этот объект может модифицироваться до загрузки коллекции по мере установке фильтров. Непосредственно перед загрузкой объекту запроса устанавливаются все фильтры, сортировка и ограничения выборки. Чтобы получить конечный SQL-запрос, можно вывести объект запроса после загрузкти коллекции:
$collection->load(); echo $collection->getSelect();
Подразумевается, что элементы коллекции будут объектами класса Varien_Object или его наследниками. Впрочем, это не обязательно — достаточно лишь чтобы объект элемента поддерживал метод addData(), аналогичный методу Varien_Object.
Отдельного внимания заслуживает процесс установки фильтра коллекци — метод addFieldToFilter($field, $condition). Метод добавляет условие WHERE в SQL-запрос, абстрагируясь от определенного диалекта и от имени поля в запросе.
- Параметр $field — некое имя «колонки» в результате. Перед вставкой в запрос (точнее, в фильтр запроса), пропускается через «маппер», который может преобразовать имя колонки результата в имя колонки запроса с корелляционным именем.
- Параметр $condition — может быть строкой или массивом — тип сравнения и значение, которое добавить во WHERE запроса. Поддерживаются простые типы сравнения, такие как IS NULL, LIKE, «больше равно», «меньше равно», «равно». Также есть возможность манипулировать интервалами даты.
Для подсчета количества элементов в этой ресурс-модели клонируется объект запроса, полученному объекту применяются фильтры (аналогично как перед загрузкой коллекции), вырезаются ограничения на выборку и сортировки, и колонки запроса заменяются на COUNT(*). Чтобы получить количество без выполнения основного SQL-запроса загрузки, можно вызвать метод getSize().
Ресурс-модель Mage_Core_Model_Mysql4_Collection_Abstract
«Рабочая лошадка». Большинство коллекций Magento основаны на этой ресурс-модели. Добавляет в Varien_Data_Collection_Db немного условностей:
- у SQL-запроса есть «главная» таблица, ей по умолчанию дается корелляционное имя «main_table»
- подразумевается, что все эелементы коллекции — модели, наследники Mage_Core_Model_Abstract. Объявление фабричного имени модели элементов должно происходить в инициализации коллекции
- есть метод save(), который проходится по всем элементам и вызывает им метод save() (реализован в абстрактной модели)
Ресурс-модель Varien_Data_Collection_Filesystem
Файловая коллекция в качестве строк возвращает имена файлов и/или папок, в зависимости от настроек и установленных фильтров. Умеет рекурсивно «ходить» по указанной папке, собирая файлы/папки. Может в результате возвращать сначала все папки, потом все файлы.
Эта ресурс-модель работает по той же схеме, что и Varien_Data_Collection_Db — получает массив данных, считает их, разбивает на страницы и генерирует набор элементов-объектов с указанными «колонками» для текущей «страницы». Принципиальное отличие от БД в том, что приходится загружать весь массив данных, потому что иначе подсчитать их количество (и разбить на страницы) не получится. С целью экономии ресурсов, можно задавать «предварительный» фильтр — регулярные выражения для имен файлов/папок, чтобы они вообще не попадали в выборку.
Базовый набор данных по умолчанию — полное системное имя файла и его базовое имя. Метод _generateRow() можно переопределить и на основании системного имени файла добавить любые другие «колонки».
Метод addFieldToFilter() реализован совместимым с аналогичным в Varien_Data_Collection_Db. Только вместо построения SQL-запроса, здесь строится Одно Большое Условие, которое выполняется с помощью eval() при загрузке данных и генерации элементов. Сама же коллекция и реализовывает простейшие типы сравнения, аналогичные коллекции БД (IS NULL, LIKE, «больше равно», «меньше равно», «равно»).
Общая схема загрузки данных коллекцией

Написать комментарий