Эта постоянная война продолжается в моих мыслях, когда я работаю над проектом Zend Framework – хороший дизайн приложения требует, чтобы количество запросов к базе данных было сведено к минимуму. Каждый запрос является дорогостоящим с точки зрения как времени ожидания, так и времени вычисления РСУБД. И Zend_Db_Table поощряет вас делать много запросов – нет встроенного способа подключения к другим Zend_Db_Tables, например. И нет способа извлечь имя базовой таблицы, учитывая экземпляр Zend_Db_Table, что затрудняет запись запросов Zend_Db_Select в терминах Zend_Db_Table. В некотором смысле Zend_Db_Table рекомендует вам реализовать функции, которые RDBMS уже предоставляет в PHP, что явно неоптимально.
С другой стороны, Zend_Db_Table делает таблицы более похожими на собственные PHP-объекты, абстрагируя сами запросы SQL. Пользователю не нужно беспокоиться о том, чтобы котировать все это часто, а операции SQL – как простые PHP-методы.
Было бы неплохо, если бы было что-то вроде Zend_Db_Table, но которое использовало бы ленивые операции (как это делает Microsoft с LINQ-to-SQL / Entity Framework / и т. Д.), Чтобы скомпоновать то, что кажется несколькими операторами PHP в одном (или на меньше всего) RDBMS quer (y | ies).
Существует ли такая вещь? Включен ли он в Zend или нет?
Я согласен с вами в том, что Zend_Db_Table
иногда играет роль молотка в поисках гвоздя. Это не всегда самый естественный инструмент для написания настраиваемых, исполняемых запросов с объединениями. Мне кажется, что Zend_Db_Table
оптимален в первую очередь для одной таблицы без объединений. Но по-прежнему можно выполнить оптимальное db-запрос с использованием аспектов компонента Zend_Db
.
Как отметил @singles, весь этот доступ к db, вероятно, должен быть похоронен внутри модели (для подхода типа ActiveRecord) или в Mapper (для подхода DataMapper) или в менеджере сущностей (например, Doctrine2).
Для exmaple ваша пользовательская модель BlogPost
может быть BlogPost
экземпляром пользовательского BlogPostDataAccess
который будет BlogPostDataAccess
экземпляром Zend_Db_Adapter
. Все ваши запросы, включая ваши оптимизированные соединения, будут находиться в классе BlogPost_DataAccess
. Запросы SELECT
в классе DataAccess могут быть записаны с использованием soemthing like (псевдокод):
$select = $adapter->select() ->join() ->join() // etc. ->join() ->where() ->limit() ->order();
Смотрите, что я имею в виду?
Обновить
Как насчет переменной $tableMap
? Что-то вроде:
public static $tableMap = array( 'posts' => 'table_posts', 'users' => 'table_users', 'categories' => 'table_categories', // etc );
Затем в ваших запросах вы можете использовать что-то вроде:
$select = $adapter->select(); $select->from(self::$tableMap['users'], array('name', 'email'));
Может быть, добавить методы, называемые setTableMap($tableMap)
, getTableMap()
, getTable($k)
, setTable($k)
, сохранить исходные данные сопоставления в файле конфигурации и затем заполнить статический член во время начальной загрузки.
Некоторые моменты нуждаются в разъяснении:
Zend_Db_Table
не реализует «автосоединение», иначе можно было бы назвать нетерпевую загрузку . Если вам нужна такая функциональность, взгляните на PHP-AR Zend_Db_Table
можно реализовать активную загрузку – я потратил некоторое время на размышления об этом, и я уверен, что это можно сделать. Но у меня нет времени это сделать 🙂 Zend_Db_Table
является частью модели вашего приложения. Вы должны волноваться о том, как ваши данные извлекаются, вас интересуют сами данные. Идем дальше – если вы используете толстую модель, тонкое / тощее отношение регулятора , вы можете быстро реализовать соединение, которое вам нужно внутри метода, что будет достаточно для большинства случаев. К сожалению, используя этот aproach, вы не сможете сохранить данные в соединенных таблицах, и вы должны следить за именами столбцов: вы не можете делать $row->joined_table->field_from_joined_table
– вместо этого вы можете $row->joined_table_field_from_joined_table
.
Подведение итогов – если вы хотите повысить производительность, используйте модели жира, как упоминалось ранее, – сохраняйте всю логику выборки / фильтрации данных в классах моделей, в вашем случае Zend_Db_Table
.
Взгляните на уровень базы данных NotORM . Это может сделать то, что вам нужно;)