Re: [fw-general] Multiple spl_autoload registered handlers
-- Greg wrote (on Thursday, 25 August 2011, 11:55 AM -0500): > > Thats not true. Autoloaders that are shipped with code should only > > be responsible for loading the code they are responsible for (in the > > least). > > Ok, I can agree with that. But thats were overheads can occur > depending on the implementation of the rest of the spl registered > handlers. > > As example, suppose the StandardAutoloader has a registered namespace. > And when the StandardAutoload::autoload function is called and it > determines that the class name is for that namespace but the class can > not be located then by returning false, the next registered spl > autoloader is called - but we just determined that the autoloader > shipped for that namespace could not find the class - so whats the > point in asking any of the other autoloaders? Here's an example: * You've created an application already, and have a classmap for its class resources. * You now need to develop a new feature for that application, which requires new classes. Most, if not all, of these are in a namespace that your classmap already knows. This is exactly the situation the quickstart tries to accommodate. The idea is this: Zend\Loader\AutoloaderFactory::factory(array( 'Zend\Loader\ClassMapAutoloader' => array(__DIR__ . '/../library/.classmap.php'), 'Zend\Loader\StandardAutoloader' => array( 'namespaces' => array('Application\View\Helper' => __DIR__ . '/../application/views/helpers'), 'prefixes' => array( 'Default_View_Helper' => __DIR__ . '/../application/modules/default/views/helpers', 'Zend_View_Helper'=> __DIR__ . '/../library/Zend/View/Helper', ), ), )); The above accommodates both the case where the classmap cannot identify the class (a simple "isset($map[$classname])" check), as well as checking specific namespaces and prefixes. One thing I've not mentioned: the StandardAutoloader allows you to register multiple namespaces and/or vendor prefixes in a single instance. Thus, if you're not using it as a fallback autoloader, it will fail early -- if the class does not match a namespace/prefix in its list, it returns false early. I think this is precisely the behavior you're trying to describe; correct me if I'm wrong. > For example, we want to find the Url view helper, heres our registered > helper namespaces/prefixes. > > $prefixes = array( > 'Default_View_Helper_', > '\Application\View\Helper\', > 'Zend_View_Helper_' > ); > > > foreach($prefixes as $p) { > $class = $p . 'Url'; > > if (class_exists($p . 'Url')) { > return $this->helper['Url'] = new $class(); > } > } > > If there are two spl registered handlers, ClassMap (which knows all of > the classes in the application) and the StandardAutoloader (and in ZF2 > lets say it is fallback enabled). Then if 'Default_View_Helper_Url' > does not exist in the ClassMap Autoloader why should the fallback > strategy of the StandardAutoloader even be executed - it would be a > waste of time and i/o (which for ZF1 is not possible to prevent, if I > can recall, unless there is only one registered spl autoloader). If you don't want it to hit the fallback strategy... then don't register the fallback! The only reason we register it in the quickstart is for rapid application development, when namespaces and vendor prefixes may be in flux. If you don't want or need the fallback, simply don't register it (it's off by default in the ZF2 StandardAutoloader). The reason to use _multiple_ autoloaders is if you have either multiple autoloading strategies you want to employ (e.g. classmap for most-often used classes, PSR-0 for others), or have several different codebases with different class->file system mappings that require multiple strategies (heck, this is true in ZF1 -- library code vs application code hierarchies differ!). The recommendation for production is to _never_ use the fallback autoloader strategy, and only use either classmaps, the StandardAutoloader with explicit namespaces/dir or prefix/dir pairs, or a combination of the two. These strategies ensure failing early. -- Matthew Weier O'Phinney Project Lead| matt...@zend.com Zend Framework | http://framework.zend.com/ PGP key: http://framework.zend.com/zf-matthew-pgp-key.asc -- List: fw-general@lists.zend.com Info: http://framework.zend.com/archives Unsubscribe: fw-general-unsubscr...@lists.zend.com
Re: [fw-general] Multiple spl_autoload registered handlers
Hi Ralph, > > Thats not true. Autoloaders that are shipped with code should only be > responsible for loading the code they are responsible for (in the least). Ok, I can agree with that. But thats were overheads can occur depending on the implementation of the rest of the spl registered handlers. As example, suppose the StandardAutoloader has a registered namespace. And when the StandardAutoload::autoload function is called and it determines that the class name is for that namespace but the class can not be located then by returning false, the next registered spl autoloader is called - but we just determined that the autoloader shipped for that namespace could not find the class - so whats the point in asking any of the other autoloaders? For example, we want to find the Url view helper, heres our registered helper namespaces/prefixes. $prefixes = array( 'Default_View_Helper_', '\Application\View\Helper\', 'Zend_View_Helper_' ); foreach($prefixes as $p) { $class = $p . 'Url'; if (class_exists($p . 'Url')) { return $this->helper['Url'] = new $class(); } } If there are two spl registered handlers, ClassMap (which knows all of the classes in the application) and the StandardAutoloader (and in ZF2 lets say it is fallback enabled). Then if 'Default_View_Helper_Url' does not exist in the ClassMap Autoloader why should the fallback strategy of the StandardAutoloader even be executed - it would be a waste of time and i/o (which for ZF1 is not possible to prevent, if I can recall, unless there is only one registered spl autoloader). Its fine, I can work with what is there. Regards, -- Greg -- List: fw-general@lists.zend.com Info: http://framework.zend.com/archives Unsubscribe: fw-general-unsubscr...@lists.zend.com
Re: [fw-general] Multiple spl_autoload registered handlers
Again, why is this a problem, exactly? What if you have another autoloader registered later that _can_ handle it? If the first dedicated autoloader for that namespace couldn't handle it, chances are no other handler will (or should not). Thats not true. Autoloaders that are shipped with code should only be responsible for loading the code they are responsible for (in the least). Try as we might, the one class per file / 1:1 mapping of namespace/classname to filesystem name is still just a suggested best practice, and we cannot cover every mapping a developer might come up with. That's not to say their code (that you might want to consumer in your ZF application) is not useful, it just means we cannot autoload things that are not of a standard mapping. I've still seen: * devs put class in the file name SomeClass.class.php * devs put multiple classes in a file * devs don't use logical prefixes or namespaces Simply put, the best practice here is to let the 3rd party autoloader handle the 3rd party code. Each autoloader should short-circut/return early if it is being asked to handle a class it is not responsible for. The CONSUMER is ultimately responsible for properly organizing their spl_autoload_ stack in some bootstrapping process and ensuring the code they are consuming actually does play nice with other code. But spl_autoload _IS_ a stack I realize that, the point was that the application code cannot break out of the execution loop if desired. By the time you are executing your application, you should not be concerned with either the who, what, why, or how a class is located an utilized. Simply put, that's too much information for the application layer. This is the whole point of delegation. This is probably a good read for you: http://en.wikipedia.org/wiki/Java_Classloader Things are not so completely different with regards to how JVM and PHP have decided to solve the problem of dynamic class resolution. Ultimately, if you're trying to influence which class of the SAME NAME your application is attempting to use, you probably have some bigger architectural issues to be dealing with. As much as I appreciate that the zf2-quickstart example, is exactly that, but it does somewhat exemplify the point I'm trying to make since in that example, the StandardAutoloader would execute given the namespaces registered even though there are class maps also - I realize it is just example code. My original post was more to draw awareness to potential overhead that could be incurred if the we're not cognitive of the implications (depending on how and what is being used). What exactly is the overhead? In all of my research, multiple small concise autoloaders are always faster than one monolithic autoloader. The idea behind the Zend\Loader component is to give developers options. The options allow developers the ability to write code that will play nice with older 3rd party code (think prefixed code) as well as newer 3rd party code (namespaced). Also also give developers to option to compile classmaps in situations where performance is a top priority. -ralph -- List: fw-general@lists.zend.com Info: http://framework.zend.com/archives Unsubscribe: fw-general-unsubscr...@lists.zend.com
Re: [fw-general] Multiple spl_autoload registered handlers
Hi Matthew, > > Again, why is this a problem, exactly? What if you have another > autoloader registered later that _can_ handle it? If the first dedicated autoloader for that namespace couldn't handle it, chances are no other handler will (or should not). > > But spl_autoload _IS_ a stack I realize that, the point was that the application code cannot break out of the execution loop if desired. As much as I appreciate that the zf2-quickstart example, is exactly that, but it does somewhat exemplify the point I'm trying to make since in that example, the StandardAutoloader would execute given the namespaces registered even though there are class maps also - I realize it is just example code. My original post was more to draw awareness to potential overhead that could be incurred if the we're not cognitive of the implications (depending on how and what is being used). Regards, -- Greg -- List: fw-general@lists.zend.com Info: http://framework.zend.com/archives Unsubscribe: fw-general-unsubscr...@lists.zend.com
Re: [fw-general] Multiple spl_autoload registered handlers
-- Greg wrote (on Wednesday, 24 August 2011, 09:29 PM -0500): > Hi Matthew, > > > My point, or preference is, is that we should try and encourage only > > > registering one autoloader handler for the application. > > > > Why, exactly? What problem does this solve? > > > > This is in fact how the StandardAutoloader (PSR-0 implementation) in ZF2 > > works -- you register explicit namespace/path pairs; if the requested > > class does not match the given namespace, it moves on to the next > > handler. > > In my opinion, therein lays the problem. Each handler's register > method is registering with spl_autoload_register, which the developer > cannot halt if a class for a particular namespace is not found, since > the handler's autoload method typically returns false, causing the > spl_autoloader to move onto the next registered handler (there is no > way of preventing _spl_ from continuing?). Again, why is this a problem, exactly? What if you have another autoloader registered later that _can_ handle it? > For example, say the StandardAutoloader is registered and has had > namespace 'Ant' registered with it. And another handler is also > registered with the spl_autoload_register (similar to what's in the > quickstart). Then if class_exists is called for 'Ant\test', the > standard autoloader will return false (since it doesn't exist), > causing the spl_autoloader to move onto the next registered handler > when it shouldn't, especially when chances are none of the other > handlers know anything about that namespace. While there may be some additional execution cycles, in most cases, the logic behind autoloaders should be written such that the overhead is minimal. This is, in fact, why we're advocating class maps and explicit namespace/path pairs for ZF2 -- so that autoloaders can fail early and quickly if they are incapable of locating a class file. > So instead, I'm thinking, there should be only one (stack like) > handler registered via spl_autoload_register, But spl_autoload _IS_ a stack > and any other handlers would register with that single stack like > handler instead of directly registering with the spl_autoloader. This > would give the handler a way to indicate that the autoloading > mechanism should halt its process and not waste any more cycles or > file/io lookups. So, would the idea of having AutoloaderFactory act as a priority stack, registering a single entity with spl_autoload, but containing many autoloader strategies internally, work for you? As mentioned before, the autoloaders written for ZF2 pretty much work as you indicate -- they fail early if they cannot locate the class file. This would also still allow developers to register additional autoloaders when they want to provide alternate strategies to fall back on. > For example, with the ZF1 code I wanted to try an optimize the > autoloading mechanism after introducing the Class Map back port you > provided. Try making that handler the only autoloader for ZF1, its not > clean. And with a class map to hand there is no need for the View > Helper to file hunt, try changing file_exists to class_exists and > notice the unnecessary subsequent autoloader calls if more than one > handler is registered with spl. This is the nature of autoloading -- it tries every strategy it can until no more are possible before it fails. It's very useful to have multiple strategies available, and to be able to intercept when one or more fail. -- Matthew Weier O'Phinney Project Lead| matt...@zend.com Zend Framework | http://framework.zend.com/ PGP key: http://framework.zend.com/zf-matthew-pgp-key.asc -- List: fw-general@lists.zend.com Info: http://framework.zend.com/archives Unsubscribe: fw-general-unsubscr...@lists.zend.com
Re: [fw-general] Multiple spl_autoload registered handlers
Hi Matthew, >> My point, or preference is, is that we should try and encourage only >> registering one autoloader handler for the application. > > Why, exactly? What problem does this solve? > > This is in fact how the StandardAutoloader (PSR-0 implementation) in ZF2 > works -- you register explicit namespace/path pairs; if the requested > class does not match the given namespace, it moves on to the next > handler. In my opinion, therein lays the problem. Each handler's register method is registering with spl_autoload_register, which the developer cannot halt if a class for a particular namespace is not found, since the handler's autoload method typically returns false, causing the spl_autoloader to move onto the next registered handler (there is no way of preventing _spl_ from continuing?). For example, say the StandardAutoloader is registered and has had namespace 'Ant' registered with it. And another handler is also registered with the spl_autoload_register (similar to what's in the quickstart). Then if class_exists is called for 'Ant\test', the standard autoloader will return false (since it doesn't exist), causing the spl_autoloader to move onto the next registered handler when it shouldn't, especially when chances are none of the other handlers know anything about that namespace. So instead, I'm thinking, there should be only one (stack like) handler registered via spl_autoload_register, and any other handlers would register with that single stack like handler instead of directly registering with the spl_autoloader. This would give the handler a way to indicate that the autoloading mechanism should halt its process and not waste any more cycles or file/io lookups. For example, with the ZF1 code I wanted to try an optimize the autoloading mechanism after introducing the Class Map back port you provided. Try making that handler the only autoloader for ZF1, its not clean. And with a class map to hand there is no need for the View Helper to file hunt, try changing file_exists to class_exists and notice the unnecessary subsequent autoloader calls if more than one handler is registered with spl. Regards, Greg -- List: fw-general@lists.zend.com Info: http://framework.zend.com/archives Unsubscribe: fw-general-unsubscr...@lists.zend.com
Re: [fw-general] Multiple spl_autoload registered handlers
-- Greg wrote (on Wednesday, 24 August 2011, 07:34 PM -0500): > > > if (false === class_exists('ClassA')) { //dynamically check to see if > > > a local overriding class exists via the autoloader > > > $class = new DefaultClass(); > > > } else { > > > $class = new ClassA(); > > > } > > > > What is an "overriding class"? > > In the above 'overriding' is the 'preferred' class to use, else use a > default one (which doesn't have to be of the same namespace). > > > By doing that, you can be sure that the stack of autoloaders is > > exactly as you expect it to be. You can also use the PHP 5.3 only > > feature of spl_autoload_register "prepend flag" to ensure things are > > in the order you expect them to be in: > > Even with the prepend flag it doesn't alleviate the problem, because > if 'Class A' is not found in the first registered autoloader, all of > the other (if any) autoloaders are then called - which in the above > example would be unnecessary. > > To me the problem is somewhat similar to finding a ZF1 View Helper, it > iterates through until it finds one. > > My point, or preference is, is that we should try and encourage only > registering one autoloader handler for the application. Why, exactly? What problem does this solve? Multiple autoloaders helps solve the problem of allowing different autoloading strategies -- which may be due to performance considerations, differences in filesystem hierarchies, etc. I'm not sure why we would desire a single autoloader, so if you could provide some use cases, that would help us better understand your arguments. > I've also wonder it should be similar to ZF1's plugin priority stack, This is somewhat possible with spl_autoload(), as Ralph already indicated; it's also trivially easy to create an optimistic autoloading solution using SplPriorityQueue to loop through strategies. > which may also then provide the developer more control of the > execution stack (if needed). Currently in ZF2, we have an AutoloaderFactory, and you register autoloaders in the order in which you want them searched. This could be altered to use a priority queue internally. It's not exactly "a single autoloader", but then again, it sounds a bit like you're mainly wanting to be able to control the order of execution. This approach could solve that. > I realize that in ZF2 this may not be an issue if say > only the Class Map autoloader is the only registered handler. I don't anticipate this at all, actually. I anticipate a combination of class map autoloading, PSR-0 autoloading with explicity namespace/path pairs, and PSR-0 fallback include_path autoloading. This hybrid approach makes for a good story from development (when namespaces and paths are often in flux) to production (when you need to milk performance). > For example, if the handler could prevent the autloader stack from > automatically continuing onto calling the subsequent registered > handlers because the one for that namespace knows it could not find > and that none of the handlers will either. This is in fact how the StandardAutoloader (PSR-0 implementation) in ZF2 works -- you register explicit namespace/path pairs; if the requested class does not match the given namespace, it moves on to the next handler. -- Matthew Weier O'Phinney Project Lead| matt...@zend.com Zend Framework | http://framework.zend.com/ PGP key: http://framework.zend.com/zf-matthew-pgp-key.asc -- List: fw-general@lists.zend.com Info: http://framework.zend.com/archives Unsubscribe: fw-general-unsubscr...@lists.zend.com
Re: [fw-general] Multiple spl_autoload registered handlers
Hi Ralph, >> if (false === class_exists('ClassA')) { //dynamically check to see if >> a local overriding class exists via the autoloader >> $class = new DefaultClass(); >> } else { >> $class = new ClassA(); >> } > > What is an "overriding class"? In the above 'overriding' is the 'preferred' class to use, else use a default one (which doesn't have to be of the same namespace). > By doing that, you can be sure that the stack of autoloaders is exactly as > you expect it to be. You can also use the PHP 5.3 only feature of > spl_autoload_register "prepend flag" to ensure things are in the order you > expect them to be in: Even with the prepend flag it doesn't alleviate the problem, because if 'Class A' is not found in the first registered autoloader, all of the other (if any) autoloaders are then called - which in the above example would be unnecessary. To me the problem is somewhat similar to finding a ZF1 View Helper, it iterates through until it finds one. My point, or preference is, is that we should try and encourage only registering one autoloader handler for the application. I've also wonder it should be similar to ZF1's plugin priority stack, which may also then provide the developer more control of the execution stack (if needed). I realize that in ZF2 this may not be an issue if say only the Class Map autoloader is the only registered handler. For example, if the handler could prevent the autloader stack from automatically continuing onto calling the subsequent registered handlers because the one for that namespace knows it could not find and that none of the handlers will either. Regards, -- Greg -- List: fw-general@lists.zend.com Info: http://framework.zend.com/archives Unsubscribe: fw-general-unsubscr...@lists.zend.com
Re: [fw-general] Multiple spl_autoload registered handlers
I think you might have meant to post this to the zf-contributors maillist where most ZF2 discussions are happening. if (false === class_exists('ClassA')) { //dynamically check to see if a local overriding class exists via the autoloader $class = new DefaultClass(); } else { $class = new ClassA(); } What is an "overriding class"? The idea in PHP 5.3 and ZF2 is that all classes exist within some namespace. You should never have a class of the same name in the same namespace but on different places on the filesystem. Having multiple registered spl_autoload handlers will incur unnecessary cycles, and the developer will not have the ability of controlling the autoloading stack (e.g circumventing it), I'm wondering if it would be better to have one registered handler similar to the ZF1 plugin priority stack. If you are concerned with multiple code-bases playing nice together, you can always fore-go the Autoloader::register() method that most autoloaders have to to "auto-register" themselves, and simply pass the autoloader object to spl_autoload_register yourself. By doing that, you can be sure that the stack of autoloaders is exactly as you expect it to be. You can also use the PHP 5.3 only feature of spl_autoload_register "prepend flag" to ensure things are in the order you expect them to be in: http://php.net/manual/en/function.spl-autoload-register.php -ralph -- List: fw-general@lists.zend.com Info: http://framework.zend.com/archives Unsubscribe: fw-general-unsubscr...@lists.zend.com
[fw-general] Multiple spl_autoload registered handlers
I'm not sure whether this may be an issue in the end or not. But I am reading reference to fallback autoloader handlers which causes me concern if the developer has to go through hoops to ensure that the application only has one spl_autoload registered handler. My concern here is that if a call to class_exists is used to determine whether a custom (project/module specific) class should be loaded instead of a default class I realize that there might be some grounds of a DI but the following code is what concerns me: if (false === class_exists('ClassA')) { //dynamically check to see if a local overriding class exists via the autoloader $class = new DefaultClass(); } else { $class = new ClassA(); } Having multiple registered spl_autoload handlers will incur unnecessary cycles, and the developer will not have the ability of controlling the autoloading stack (e.g circumventing it), I'm wondering if it would be better to have one registered handler similar to the ZF1 plugin priority stack. -- Greg -- List: fw-general@lists.zend.com Info: http://framework.zend.com/archives Unsubscribe: fw-general-unsubscr...@lists.zend.com