Build With Zend Framework

To speed up Zend Framework is very effective this trick: collect all of the classes that we need in one file, and then include eAccelerator and include it in the beginning. Single file + eAccelerator steeper than fail.

Below is the story as I did. It's not the most intelligent, and best looking solution, so I'm glad to hear your advice and comments. In General, the topic of this for your advice and comments — such as those on the case, not about any garbage of type of spelling errors. Thank you!



At first I myself agreed, that I will use Zend_Loader (or rather, Zend_Loader_Autoloader — well that's using Zend_Application) and not shipping fail include.

Then I decided to act as follows:
    the
  1. Collect all the magic file, which we need in the APPLICATION_PATH. '/../data/files.txt'
  2. the
  3. APPLICATION_PATH Open. '/../data/files.txt' and collect them into one magical APPLICATION_PATH. '/../data/HotPlug.php' on the road cutting inkluda and comments


So, first: collection fail data.txt.

It turned out that Zend_Loader_PluginLoader able to make such a list myself (but a little crooked), and Zend_Loader_Autoloader — can not. But it does not matter. There ought to inherit autoloader and do everything honestly, but I was too lazy and I phacil himself ZF. Fortunately, the production still won't need to pour hacheney version: HotPlug.php you can collect at home:
the
/* library/Zend/Loader.php */

public static function loadClass($class, $dirs = null)
{
if (class_exists($class, false) || interface_exists($class, false)) {
return;
}

if ((null !== $dirs) && !is_string($dirs) && !is_array($dirs)) {
//require_once 'Zend/Exception.php';
throw new Zend_Exception('Directory argument must be a string or an array');
}

// autodiscover the path from the class name
$file = str_replace('_', DIRECTORY_SEPARATOR, $class) . '.php';
if (!empty($dirs)) {
// use the autodiscovered path
$dirPath = dirname($file);
if (is_string($dirs)) {
$dirs = explode(PATH_SEPARATOR, $dirs);
}
foreach ($dirs as $key = > $dir) {
if ($dir == '.') {
$dirs[$key] = $dirPath;
} else {
$dir = rtrim($dir, '\\/');
$dirs[$key] = $dir . DIRECTORY_SEPARATOR . $dirPath;
}
}
$file = basename($file);
self::loadFile($file, $dirs, true);
} else {
self::_securityCheck($file);
include $file;
}
// add here 
$files = file( APPLICATION_PATH . '/../data/files.txt' );
$files[] = $file;
$files = array_unique($files);
file_put_contents( APPLICATION_PATH . '/../data/files.txt', implode("\n", $files) );
// here
if (!class_exists($class, false) && !interface_exists($class, false)) {
//require_once 'Zend/Exception.php';
throw new Zend_Exception("File \"$file\" does not  exist  or class \"$class\" was not found in the file");
}
}


I discovered your site and ran it for a while. The website I liked, and sprawling APPLICATION_PATH. '/../data/files.txt' no. But it's okay, I thought, and scribbled a build script. Again, should have done it cleverly, beautifully, object-oriented and console, but I was too lazy and I stupidly created combine.php in /htdocs/

the
<?
$skip = array(
T_COMMENT, T_OPEN_TAG, T_CLOSE_TAG, T_DOC_COMMENT, T_ML_COMMENT // nafig comments from HotPlug! and all <? and ?> too nafig
);

$dir = "d:\work\нескажуназвание\library\\";

$files = file('d:\work\нескажуназвание\app\data\files.txt'); 

$res = '<?';

foreach ($files as $file) {
if (substr(trim($file), -4) != '.php')
$file = str_replace('_', '\\', trim($file)) . ".php"; // if there is a class name, not file - reinvent

if (is_file($fileName = trim($dir . $file))) {
$res .= "\n/* $file */\n";
$tokens = token_get_all(file_get_contents($fileName));

$was_require_once = 0;
$was_shit_require_once = 0;

foreach($tokens as $token) {
if (is_array($token)) {
if (in_array($token[0], $skip))
continue;

if ($token[0] == T_WHITESPACE) {
$res .= ''; // less space for all sorts of tabs
continue;
}

if ($was_require_once) {
if ($token[0] == T_CONSTANT_ENCAPSED_STRING) { // sipem require_once, followed by a quoted string. if then there is something like $file - skipet don't! also quite a dirty method, should think
$was_shit_require_once = 1;
} else {
$res .= 'require_once' . $token[1];
}

$was_require_once = 0;
continue;
}

if ($token[0] == T_REQUIRE_ONCE) {
$was_require_once = 1;
} else {
$res .= $token[1];
}


} else {
if (!$was_shit_require_once) // to ";" after the remote require_once remove
$res .= $token; 

$was_shit_require_once = 0;
}
}
$res .= "\n";
}
}

file_put_contents("d:\work\нескажуназвание\app\data\HotPlug.php", $res);



Then I joyfully theincludes this file directly in the index. And you know what it said? He doesn't have enough heap classes. "Wtf?!" I thought, and started to catch the missed classes by writing their handles files.txt and then reassembling HotPlug.php :)
And then it dawned on me that the Loader doesn't know about the file, which is included require_once at the beginning sendowski classes, and therefore they are not going. But they are not includeda %)

Had to write another script that says all these require_once:

the
<?
function getDirectoryTree( $outerDir ){ 
$dirs = array_diff( scandir( $outerDir ), Array( ".", ".." ) ); 
$dir_array = Array(); 
foreach( $dirs as $d ){ 
if( is_dir($outerDir."/".$d) ) $dir_array[ $d ] = getDirectoryTree( $outerDir."/".$d ); 
else $dir_array[ $d ] = $d; 
} 
return $dir_array; 
} 

$dirs = getDirectoryTree("d:\work\пыщь\library\Zend");

function gotcha($fname, $key, $dir) {
if (is_array($fname)) {
array_walk($fname, 'gotcha', $dir . DIRECTORY_SEPARATOR . $key);
return;
}

$fname = $dir . DIRECTORY_SEPARATOR . $fname;
file_put_contents( $fname, preg_replace("/require_once\\s+\'Zend/", "//require_once \'Zend", file_get_contents( $fname )) ); // could be written /(require|include)_once\\s+(\'|\")/ or something, but I was - well you guessed it - too lazy to  test  this preg and I ran the script 4 times in a row. Good, then it is no longer needed at all :)
}

array_walk($dirs, 'gotcha', "d:\work\пыщь\library\Zend");


Now I've reassembled HotPlug.php and that was just perfect!

— Step two

In addition to Zend_Loader_Autoloader, include know more and Zend_Loader_PluginLoader, and included he himself, without Zend_Loader'. But he knows how to gather a list. Here it is:

the
// Somewhere in Bootstrap.php or - I have - to /library/R00/Bootstrap.php from which inherited bootstrap my projects
Zend_Loader_PluginLoader::setIncludeFileCache( APPLICATION_PATH . '/../data/cache.php');


This cache.php after a couple of runs contains a lot include_once'owls, which are necessary to the machine to load these plugins. I did not understand what this increase and decided to ask him to push these files to my files.txt

the
Zend_Loader_PluginLoader::setIncludeFileCache( APPLICATION_PATH . '/../data/files.txt');


Not to parse the line include_once '...'; I pohaci (which I am a bastard after all, eh!) Zend/Loader/PluginLoader.php
the
protected static function _appendIncFile($incFile)
{
if (!file_exists(self::$_includeFileCache)) {
$file = "; // times change
} else {
$file = file_get_contents(self::$_includeFileCache);
}
if (!strstr($file, $incFile)) {
$file .= "\n$incFile\n"; // two change
file_put_contents(self::$_includeFileCache, $file);
}
} 

Again, in production this should not be sent, so that's okay. But at home — well at home, even at home. You must upgrade ZF, and then again to rebuild HotPlug.php well pohatu again, or there will do everything humanly sometime.

Now I ran the website, collecting plugin, and then recompiled my HotPlug.php. My life changed for the better!

Now — tell us about your best practices for solving such problems :) And let's make normal, reasonable, an OO solution without any extra hacks?
Article based on information from habrahabr.ru

Комментарии

Популярные сообщения из этого блога

Templates ESKD and GOST 7.32 for Lyx 1.6.x

Monitoring PostgreSQL + php-fpm + nginx + disk using Zabbix

Custom table in MODx Revolution