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

Комментарии

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

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

Templates ESKD and GOST 7.32 for Lyx 1.6.x

Customize your Google