Hi Anthony, Thanks immensely for your input. Without such action, it's extremely hard to improve the RFC. =) Awesome action from your side. I'll place my comments inline.
On Thu, Nov 10, 2011 at 1:26 PM, Anthony Ferrara <ircmax...@gmail.com> wrote: > Guilherme et al, > > Since you asked me for feedback on how I would suggest improving the > RFC, so here it goes... > > I think I need to make one thing clear first. I don't think that I > can vote yes for this RFC in principle (I just don't agree this > belongs in core). However, with that said if the RFC was clarified > and takes care of the issues that are listed here, I will stop > actively opposing it and may even consider removing my no vote. I say > this not because I want to emphasize anything, but because I want to > make sure that expectations are managed and that nobody is going to > get mad at me for not changing my vote if everything here is > completed. > > Now, with that disclaimer behind us, let's move on to how I would like > the RFC changed (In no particular order): > > 1. The implemented solution **must** under all circumstances play nice > with other autoloaders and code. This means that it should **never** > throw an error under any circumstances. In order to achieve that, > three things would need to happen: > > a) The code that includes the file would need to be wrapped in a > file_exists call to ensure that the include would actually work. This > will prevent issues with different tree structures causing errors to > be thrown. This is actually already supported. The SplClassLoader$mode does exactly that. The $mode can be one of these values: - MODE_NORMAL: Throws error while attempting to include an unexistent file - MODE_SILENT: Does the is_file() check before attempting to require. This helps the case where you may have multiple SplAutoloader instances. - MODE_DEBUG: This one can work together with the other two, allowing a validation of class/interface/trait presence in the file. Basically, it requires the file and then checks if the item exists in scope. This is why you could implement the SplClassLoader like this: $loader = new \SplClassLoader(\SplClassLoader::MODE_SILENT | \SplClassLoader::MODE_DEBUG); // ... > > b) The code that includes the file should be changed to require_once > to eliminate including the same file twice when different classes map > to the same file. For example, this should not fail (assuming both > classes are not in the same file): > > new \Foo\Bar\Baz; > new \Foo\Bar_Baz; > > Both map to the same file, but are distinct classes in PHP. > By changing it to require_once, it'll realize it already included the > file and then skip over that and let another class have its shot. > Actually they do not map the same file. Here is the path of each one: new \Foo\Bar\Baz; => [path]/Foo/Bar/Baz.php new \Foo\Bar_Baz; => [path]/Foo/Bar_Baz.php You may now be in doubt if PEAR1 style is supported. Yes, it is. The point is that code detects for the presence of namespace separator and if it is found, it considers the namespace separator as directory separator; if not, it considers the "_" char as directory separator. We decided that because PEAR1/Zend1/Doctrine1/Symfony1 (and many others) would not be supported if we didn't do that way. It's the solution for BC. Since most of the mentioned ones are already in another major version, consuming PHP 5.3 namespaces, then the default behavior would work nifty. =) Regarding the require_once change, it's not really needed. The reason is because class loading would never be triggered again if the class/trait/interface is already loaded. The require_once is extremely slow than require due to this check. But I really don't have strong feelings to change that is many people find it necessary. > c) No exceptions, warnings, notices, etc should be thrown under any > circumstances *when loading a file*. You could have it throw an > exception (or warning, whatever) if the path passed to the constructor > is invalid, but when loading a class it should never throw one (which > would cause issues or prevent other autoloaders from functioning > properly). And considering that we can use ErrorExceptions, raising > PHP Errors would cause the same problem. Note that this does not > affect the included file as that can do any error. Just the > autoloader itself shouldn't. This means that setMode should be > removed since it would cause the autoloader to stop from "playing > nice". This seems like user choice, but what if a library ships in > normal mode (which is default now) and these issues occur? My view is > that it should *always* be silent. PHP has mechanisms for handling > not-found classes. Autoloading is one, and fatal errors is another. > It's not the job of the autoloader to throw errors... Hm... so there should never have the normal available? I need to think over this again then. While I tend to agree with autoloader never triggering errors or exceptions, the debug mode is the unique way to notice if user during developer haven't done any mistake. Maybe we can only keep the RuntimeException and debug mode possibility, remove the normal and keep it always silent. What do you think? > > 2. The RFC *needs* to address how the implementation may/should evolve > over time. I know it appears that PSR-0 is 100% sufficient now, but > there will come a time when it is no longer so. A perfect example of > that is the discussion that was on the list in the past few > weeks/months about adding function autoloading. What happens at that > point, how could/should this implementation adapt and evolve? I would > suggest not tackling specific possible changes, but more on how > changes would be handled. Would you add new methods? New classes? > Change APIs? How would you maintain backwards compatibility? Can you > maintain BC? First I'll expose one of the things I've been thinking, then I'll discuss the other points. I *do* agree the SplClassLoader should be renamed to something that reminds the PSR-0. Not because of ego, but others highlighted that another PSR in the future that change the behavior of class loader (ie, removing the PEAR1 style support). This would require a change in SplClassLoader which might break existent applications. It's not good. Just like a normal community process, newer recommendations means that they deprecate the previous ones. That way code that still follows the old approach should still be supported, but throwing E_DEPRECATED. Based on that, I'm pro to change the class to SplPsr0ClassLoader or SplPsr0Loader. Now getting back to your point, the PSR-0 and this RFC refers exclusively to OO paradigm. The idea would cover classes, interfaces and traits only. For function autoloading, it's part of another paradigm, so you might be in a procedural paradigm in your code, so the usage of an OO definition is a bit weird to me. Mixing paradigms is not healthy, it increases the complexity of the code and also reduces the readability. Regarding possible new PSRs, the main focus of the group is about good practices and standardization of PHP code. We have an extremely few suggestions that could be portable to C code. All of them (except PSR-0) were not even discussed, but I can give you some idea of possible areas: Cache layer, enhancements to PDO and new data structures. I can't see by now other areas, but they may exist. Anyway, if we get back to the autoloading discussion maybe in 5 years, then what people have pointed our and I previously referred is valid. The class name would have to change already in this RFC, and the behavior would act like I mentioned too. E_DEPRECATED on previous loader and implement the new one. > > 3. The RFC should at least address how other autoloading schemes would > fit into the picture. If we add this PSR-0 style autoloader, can > other style autoloaders be included? I know some will say "do any > others need to be included". But what about things like the automap > extension (which maps classes to files via an array list)? How should > that fit into the picture? I already mentioned that in RFC. You're able to instantiate and register as many autoloaders as you want. Also, you can have your own implementation by implementing the contact (SplAutoload) or extending the default behavior (SplClassLoader, SplPsr0ClassLoader, SplPsr0Loader or whatever name it becomes). The class map would work perfectly, and the only necessary action would be to call the ->add() method. > > 4. The RFC should avoid implementing any pattern or style that may > make future feature addition difficult or pose risks towards such. An > example would be implementing an interface for the autoloader which > defines something like load($class). The problem there is that if > function autoloading is added, the interface won't be able to support > it. So it's stuck in a hard place between changing an implemented > interface (which will bork code significantly on update) and adding a > new interface (which would be the lesser of evils, but would just add > to the deprecated cruft). OO theory defines that whenever you want to have a contract to be followed by any implementation, an interface is required. The contract is something useful that enforces that way you receive would have at least what it was expected/used internally. So, if we agree in the future that the chosen implementation would not contain the methods ->register/->unregister, and spl_autoload_register would accept SplAutoload instances, then the contract is more than required. Regarding the function autoloading, as I discussed previously, it is invalid in this paradigm. I don't see how the contract would change in the future. > > 5. The RFC *must* talk about how user-land classes can and should > extend this core implementation. For example, if users wanted to > change the behavior, can they just subclass and override certain > methods? Are there any "dangerous" methods that shouldn't be > overriden? Should any of the C functions (such as get_filename) be > implemented as a method (possibly protected) to allow for extending > classes to change that behavior? The important thing is that this > will need to be documented prior to release, and it will make our > lives easier documenting recommended best practices if it's already at > least discussed in the RFC. The RFC already defined the visibility of its members, so the methods marked as public/protected are the ones extendable. The ones that can't be extended are marked as private, since its overall behavior cannot be changed. Of course I can expand the RFC by adding a section describing how users can implement their own SplAutoload or even extend the SplClassLoader (ok... type the final name here). Thanks for the tip. I added to my TODO. Should be included until monday. =) > > 6. The RFC should contain a proposed patch (or at least reference > implementation) prior to being voted upon. That way everybody knows > what's being voted on, rather than a wandering text. Because > ultimately it doesn't matter what's written in the RFC as the code > will always win (code wins over docs under all circumstances, as code > doesn't lie). That patch should not change fundamentally (aside from > tweaks or bug fixes) after the vote starts. If it does change, the > vote should be restarted (or at least extended with a note made about > it) as it's not really fair to ask people to vote on a target, and > then move that target. The RFC was not ready when it was opened for voting. I didn't open it. I tried my best to have everything wrapped before the voting starts, but I couldn't. Now we can't get back, but we can for sure reset and vote on the final version of proposal. I'm just taking this time to discuss with interested people how can we make this stable to then propose a new voting round. > > > > Now, one other point. You might want to consider adding __invoke() > support so that you don't need to change spl_autoload_register at all. > That way, you could support spl_autoload_register(new > SplClassLoader()); without needing to touch existing functionality... > > > Thoughts? I tend to reject enforcing the implementation of magic methods. It would be necessary to be part of SplAutoload contract, something that seems weird IMHO. I prefer to stick to the original proposal on this one, but I'm -0 on this one. > > Anthony > PS: Thanks again for investing your time reviewing the RFC and providing your expectations. Without a community review, it's hard to make any RFC stable. I think more people can/should comment on this, and if we find a reasonable consensus, update the RFC with the changes and reopen the poll as soon as possible. I'll be waiting for your feedback. Cheers, -- Guilherme Blanco Mobile: +55 (11) 8118-4422 MSN: guilhermebla...@hotmail.com São Paulo - SP/Brazil -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php