Matthew Weier O'Phinney wrote:
We've already identified the HelperBroker as being in need of
refactoring to use Zend_Loader_PluginLoader. However, that class, too,
relies partially on the include_path when the paths provided are not
absolute paths. Have you had a chance to test any components that utilize
the plugin loader? These would include Zend_Form, Zend_View (in trunk
and the 1.6.0 release candidates), and Zend_Filter_Inflector. I'm
curious if the PluginLoader would need to be refactored.
I've only tested on 1.5.3 so far, with view helpers, controller action helpers and controller plug-ins, however so long as all the paths ZF adds by default are absolute, the decision of whether or not to use absolute paths or include the library paths in include_path can be left to the user. As the plugin loader has no addPrefix() method the problem from the HelperBroker isn't an issue, but if there was a situation where only the prefix was provided, then the refactoring would be as simple as checking if there is a path, if there is then load as usual, if there isn't then append the plugin name to the prefix and try to load that class through the autoloader.
I'd love to see this flexibility. Perhaps you could help out with some
contributions? :)
I'd be happy to. Just let me know what needs doing.

Regarding my loader, the reason I decided to write my own was because as my application grew and more modules were added, I was getting an ever increasing number of paths in the include_path (as every module has a models folder, and optionally a library folder with additional classes). Having this many paths in the include_path seriously affects performance (http://framework.zend.com/wiki/display/ZFDEV/Performance+-+Multiple+Include+Path+Order) so I wanted to find a better solution.

What I've ended up with is a simple loader class that uses class prefixes (in a similar but not identical way to the plugin loader) for loading classes from multiple locations very efficiently. It uses a regex to detect the relevant prefix for the current class and attempts to include that file from each related path. It also uses the error suppression method from the incubator Zend_Loader to suppress errors when files are not found. This is more efficient than using is_readable and allows other errors to appear unlike @include_once. I've attached a simplified version of this if anyone wants to take a look/use it.
--
Jack
_paths[$prefix])) { $this->_paths[$prefix] = array(); } $this->_paths[$prefix][] = rtrim($path, DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR; $prefixes = array_map('preg_quote', array_keys($this->_paths), array_fill(0, count($this->_paths), '/')); $this->_regex = '/^(' . implode('|', $prefixes) . ')[_$]/'; } public function loadClass($class) { $this->_loadClass($class); if (!class_exists($class , false)) { throw new Exception("Class '{$class}' could not be loaded"); } } public function autoload($class) { $this->_loadClass($class); } protected function _loadClass($class) { $file = str_replace('_', DIRECTORY_SEPARATOR, $class) . '.php'; set_error_handler(array($this, 'errorHandler')); if (isset($this->_regex ) && preg_match($this->_regex, $class, $match)) { $paths = $this->_paths[$match[1]]; foreach ($paths as $path) { include_once $path . $file; if (class_exists($class , false)) { break; } } } else { include_once $file; } restore_error_handler(); } public function errorHandler($number, $message, $file, $line, array $context) { if (preg_match('/Failed (to open stream|opening .+ for inclusion)/i', $message)) { return true; } return false; } }

Reply via email to