по мотивам коммента mocksoul из темы PHP: Введение в Zend Framework
В кратце, речь шла о том, что одним из недостатков фреймворка является его концепция «один класс – один файл». И хотя, с моей точки зрения, это не является недостатком архитектуры ZF, это является недостатком PHP. Проблемы начинаются когда PHP начинает инклюдить десятки и сотни файлов, да еще проверять их на once.
Предложенное решение – сборка всех инклюдов в один файл. Класс, представленный ниже – не претендует на окончательный универсальный вариант решения проблемы. Он всего лишь демонстрирует один из методов сборки инклюдов. В данном случае он собирает только файлы фреймворка, игнорируя все остальные.
В конце работы скрипта вставить строки
С помощью этого класса я собрал более 60 файлов ZF из моего проекта (модули Controller, Session, Auth, View, Uri, Db, Config, Version, Debug, Registry). Собранный файл занял 231 кб.
Время работы скрипта с использованием собранного файла быстрее скрипта с использованием большого количества инклюдов более чем в 8 раз.
Проблема
В кратце, речь шла о том, что одним из недостатков фреймворка является его концепция «один класс – один файл». И хотя, с моей точки зрения, это не является недостатком архитектуры ZF, это является недостатком PHP. Проблемы начинаются когда PHP начинает инклюдить десятки и сотни файлов, да еще проверять их на once.
Предложенное решение – сборка всех инклюдов в один файл. Класс, представленный ниже – не претендует на окончательный универсальный вариант решения проблемы. Он всего лишь демонстрирует один из методов сборки инклюдов. В данном случае он собирает только файлы фреймворка, игнорируя все остальные.
Класс
<?php
class ZendMake
{
/**
* Сборка заинклюденных файлов с удалением комментов, require/include, и проч
*
* param string $dest Абсолютное имя скомпиленного файла
* param string $includes Массив файлов ZF для сборки
* return array
*/
public static function make($dest, $includes = null)
{
$includes = is_array($includes)? $includes: self::_getZendIncludes();
// Удалить теги '<?php' '? >', комменты, пустые перводы строк и require/include[_once]
$pattern[] ='%(^\<\?php|\?\>$)%m';
$replacement[] = '';
$pattern[] ='%/\*.*?\*/%sm';
$replacement[] = '';
$pattern[] ='%//.*$%m';
$replacement[] = '';
$pattern[] ='%(require_once|include_once|require|include) [("\'](.*?)[)"\'];%sm';
$replacement[] = '';
$pattern[] ='%(\n){2,}%';
$replacement[] = "\n";
$body = "<?php\n";
foreach ($includes as $fname) {
$body .= preg_replace($pattern, $replacement, file_get_contents($fname, true));
}
$size = file_put_contents($dest, $body);
return array('includes' => $includes, 'compiledBody' => $body, 'compiledSize' => $size);
}
/**
* Выбрать уникальные файлы ZF заинклюденные в проект
*
* return array
*/
private static function _getZendIncludes()
{
$required = array();
$included_files = get_included_files();
foreach ($included_files as $fname) {
if (!(strpos($fname, 'Zend') > 0) || (strstr($fname, __CLASS__. '.php'))) {
continue;
}
$required[] = str_replace('\\', '/', substr($fname, strpos($fname, 'Zend'), strlen($fname)));
// Все requires
$pattern ='%(require_once|include_once|require|include) [("\'](.*?)[)"\'];%sm';
preg_match_all($pattern, file_get_contents($fname), $pocket);
$required = array_merge($pocket[2], $required);
}
return array_unique($required);
}
}
Использование
В конце работы скрипта вставить строки
require 'ZendMake.php';
$result = ZendMake::make($libDir. 'Zend.Make.php');
Zend_Debug::dump($result['includes']);
Zend_Debug::dump($result['compiledSize']);
Результаты
С помощью этого класса я собрал более 60 файлов ZF из моего проекта (модули Controller, Session, Auth, View, Uri, Db, Config, Version, Debug, Registry). Собранный файл занял 231 кб.
Время работы скрипта с использованием собранного файла быстрее скрипта с использованием большого количества инклюдов более чем в 8 раз.