Как использовать RDBMS по-исполнительски поверх Zend_Db_Table? (если вообще…)

Эта постоянная война продолжается в моих мыслях, когда я работаю над проектом 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) , сохранить исходные данные сопоставления в файле конфигурации и затем заполнить статический член во время начальной загрузки.

Некоторые моменты нуждаются в разъяснении:

  1. Как вы сказали – Zend_Db_Table не реализует «автосоединение», иначе можно было бы назвать нетерпевую загрузку . Если вам нужна такая функциональность, взгляните на PHP-AR
  2. В Zend_Db_Table можно реализовать активную загрузку – я потратил некоторое время на размышления об этом, и я уверен, что это можно сделать. Но у меня нет времени это сделать 🙂
  3. Но, глядя с другой стороны – Zend_Db_Table является частью модели вашего приложения. Вы должны волноваться о том, как ваши данные извлекаются, вас интересуют сами данные. Идем дальше – если вы используете толстую модель, тонкое / тощее отношение регулятора , вы можете быстро реализовать соединение, которое вам нужно внутри метода, что будет достаточно для большинства случаев.
    Пример: http://pastebin.com/pNwideWf (я связываюсь с вставкой bin, потому что формирование кода не работает должным образом для меня в редакторе).

К сожалению, используя этот aproach, вы не сможете сохранить данные в соединенных таблицах, и вы должны следить за именами столбцов: вы не можете делать $row->joined_table->field_from_joined_table – вместо этого вы можете $row->joined_table_field_from_joined_table .

Подведение итогов – если вы хотите повысить производительность, используйте модели жира, как упоминалось ранее, – сохраняйте всю логику выборки / фильтрации данных в классах моделей, в вашем случае Zend_Db_Table .

Взгляните на уровень базы данных NotORM . Это может сделать то, что вам нужно;)