📜 ⬆️ ⬇️

Build Zend Framework

To speed up the Zend Framework, such a trick is very effective: we collect all the classes we need in one file, and then turn on the eAccelerator and enable it at the very beginning. One file + eAcselerator is steeper than many files.

Under the cut - the story, as I did. This is not the smartest, best and most beautiful solution, so I am glad to hear your advice and comments. In general, this topic - for the sake of your advice and comments - those that are in the case, and not about any garbage like spelling errors. Thank!


')
I first agreed with myself that I would use Zend_Loader (more precisely, Zend_Loader_Autoloader - well, something that Zend_Application uses there), and not load the files with the included ones.

Then I decided to act like this:
  1. We collect all the magic files that we need in the APPLICATION_PATH. '/../data/files.txt'
  2. Open the APPLICATION_PATH. '/../data/files.txt' and collect them into one magic APPLICATION_PATH. '/../data/HotPlug.php', cutting out inclusions and comments along the way


So, the first: collection of files in data.txt.

It turned out that Zend_Loader_PluginLoader is able to compile such a list itself (but a little crookedly), but Zend_Loader_Autoloader is not able to. But it does not matter. It would have been worth inheriting an autoloader and doing everything honestly, but I was vpadlu and I zakhachil ZF. Fortunately, production will still not need to be poured into a hacked version: HotPlug.php can be collected at home:
 / * 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 from 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));
 // get 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 opened my website and ran around it for a while. I liked the site, and the growing APPLICATION_PATH. '/../data/files.txt' is not. But it's okay, I thought, and sketched a script for the assembly. Again, it was worth making it smart, beautiful, object-oriented and console, but I was vpadlu and I stupidly created combine.php in / htdocs /

 <?
	 $ skip = array (
		 T_COMMENT, T_OPEN_TAG, T_CLOSE_TAG, T_DOC_COMMENT, T_ML_COMMENT // See comments from HotPlug!  and all sorts of <?  and?> also nafig
	 );
	
	 $ dir = "d: \ work \ undefeasibility \ library \\";
	
	 $ files = file ('d: \ work \ undefeatable \ 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 a file name, we modify it
			
		 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 on any tabs
						 continue;
					 }
				
					 if ($ was_require_once) {
						 if ($ token [0] == T_CONSTANT_ENCAPSED_STRING) {// skip require_once, followed by a string in quotes.  if something like $ file then goes - no need to skip!  too dirty method, you 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 require_once removed delete
						 $ res. = $ token; 
						
					 $ was_shit_require_once = 0;
				 }
			 }
			 $ res. = "\ n";
		 }
	 }
	
	 file_put_contents ("d: \ work \ undefeatable \ app \ data \ HotPlug.php", $ res);



After that I joyfully smacked this file right in the index. And you know what it said to me? What he lacks heaps of classes. “Wtf ?!” - I thought and began to catch the missing classes, writing them in files.txt, and then reassembling HotPlug.php :)

And here it dawned on me that Loader did not know about those files that include require_once at the beginning of the Zend classes, and therefore they are not going to. But they do not include%)

I had to write another script that comments on all these require_once:

 <?
 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 \ test \ 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)));  // it would be worth writing / (require | include) _once \\ s + (\ '| \ ") / or something like that, but I was - well, you guessed it - I had to test this preg and I ran the script 4 times in a row. Fortunately, after that he is no longer needed at all :)
 }

 array_walk ($ dirs, 'gotcha', "d: \ work \ pysch \ library \ Zend");


Now I rebuilt HotPlug.php and everything was just wonderful!

- Step Two

In addition to Zend_Loader_Autoloader, Zend_Loader_PluginLoader also controls inclusions, and it includes itself, without Zend_Loader. But he knows how to collect a list. Like this:

 // Somewhere in Bootstrap.php, or - for me - in /library/R00/Bootstrap.php, from which my project's bootstraps are inherited
 Zend_Loader_PluginLoader :: setIncludeFileCache (APPLICATION_PATH. '/../Data/cache.php');


This cache.php after a couple of launches contains many include_once's that are needed to automatically load these plugins. I didn’t understand what the increase was and decided to ask him to shove these files into my files.txt

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


Not to parse the string include_once '...'; I pachachil (what a bastard I am, all the same, but!) Zend / Loader / PluginLoader.php
 protected static function _appendIncFile ($ incFile)
     {
         if (! file_exists (self :: $ _ includeFileCache)) {
             $ file = '';  // change time
         } else {
             $ file = file_get_contents (self :: $ _ includeFileCache);
         }
         if (! strstr ($ file, $ incFile)) {
             $ file. = "\ n $ incFile \ n";  // two change
             file_put_contents (self :: $ _ includeFileCache, $ file);
         }
     } 

Again, you don't need to send this to the production, so that's okay. And at home - at home, let it be at home. It will be necessary to update the ZF, and then rebuild HotPlug.php again - well, I'll pull up one more time, or I'll do everything humanly there somehow.

Now I was still running around the site, collecting plugins, and then rebuilt HotPlug.php. My life has changed for the better!

Now - tell us about your best practices for solving this problem :) And let's make a normal, reasonable OO solution without extra hacks?

Source: https://habr.com/ru/post/73273/


All Articles