PHP Class Autoloading - php

I have a "simple framework" whose main instance is $app. Now, what is the best way to implement an autoloader (without using Composer). What I need is to have a class which handles all the autoloading (supporting the various namespaces). I have a few approaches/dilemmas.
At first I thought I should create a "static" class which handles everything. But then something came to my mind. If I use the autoloader before instantiating $app (which contains all the paths), I would need to define the paths outside of $app. And also if an error occours in autoloading a class, I wouldn't be able to handle the error properly (error handler is inside $app, and instantiated after).
Then I thought of dependency injection, making the autoloader an object inside the app. That would resolve the error handling problem, and wouldn't need me to hard code paths or making them globals. But I would have to load many classes (including $app) too before I can instantiate the autoloader.
But really I'm in a world of pain because of this issue, I don't really know where to start, are there some advices I should take into account ? Can you explain me which method should I use and why ?
Thanks.

As a result of the tips I got in this questions, I searched a bit more and found good resources from where to learn.
What's Autoloading ?
Autoloading is basically the process in which the program finds an unknown Class Name and attempts to load it without Class Name being defined. Without an autoloader, this behavior would result in a fatal error (for PHP at least). With an autoloader, things change, and the program will attempt loading Class Name, without knowing where to find it, but relying on functions or classes thought for this purpose, those functions/classes are called Autoloaders.
__autoload() vs spl_autoload_register()
In PHP we have two different ways to achieve autoloading (you might find useful to read it from PHP's site.). The first one is the old __autoload(), the newest is spl_autoload_register(). But what exactly is the difference ? Basically __autoload() is unique, having multiple Autoloaders would cause you many troubles and would get you in solving a problem which can be easily avoided by using the newest spl_autoload_* functions. spl_autoload_register() on the other side allow the program to have multiple Autoloaders by putting them in a stack, in this way the whole system becomes more flexible and much less complicated (having a single Autoloader for different purpose results in having a big unique function handling many requests, this way you'll have less code maintainability and reusability).
Warning: using spl_autoload_register() will overwrite __autoload(), so be careful.
Coding standards (in PHP): PSR-0 vs PSR-4
Let's start by saying that PSR-4 is newer and it was thought to be an improvement of PSR-0, but not compulsory you must use 4 instead of 0, as the standard (PSR-4) states:
It is fully interoperable, and can be used in addition to any other autoloading specification, including PSR-0.
So why should I use one instead of the other ?
Now this is up to you, but as a suggestion PSR-4 solves the "nesting" problem PSR-0, so you should be using the former. Let's suppose I have an application, and my application relies on external components, PSR-0 follows this syntax:
\vendor\(sub_namespaces\)class_name
Where sub_namespaces might be absent. But that translates to a fully qualified path on the hard drive:
path/to/project/vendor/sub/namespaces/class/name.php
Now let's suppose I want to include a library called YourLibrary in my application
\YourDeveloper\YourLibrary\YourFunction
This would translate to
/path/to/project/YourDeveloper/YourLibrary/YourFunction
And here's the problem, what if I want to put that library in a subfolder of mine:
/path/to/project/vendor/vendor_name
PSR-0 is absolute, you can't just modify the namespace to control this behaviour (it would be silly and require too much time) so it would translate to this:
/path/to/project/vendor/YourDeveloper/src/YourDeveloper/YourLibrary/YourFunction
Isn't that extremely nested and redundant ? Well, using PSR-4 you can avoid that and transform that into
/path/to/project/vendor/YourDeveloper/YourLibrary/YourFunction
Without altering the namespaces or the Autoloaders. That's basically how PSR-4 works. This explanation is quite short, but it gives you a glance of why PSR-4 was born and why you SHOULD use it. If you require a more adequate explanation, you can go and read the PSR-0/4 specifications or you can read this beautiful article on sitepoint.
Should I really be caring about standards ?
If you have been in the world of programming for enough time, you probably won't end up asking such question. But if you are, you are probably a new programmer, or you haven't been a programmer long enough, that's why you SHOULD read this answer.
In the IT world, and especially in programming, standards are almost everything. If we hadn't followed standards, we might not even have videos on our computers. If anyone follows their own standard, everything would look messy, and in this case, Autoloaders would become personal; so instead of having one SIMPLE Autoloader, you would end up having many Autoloaders, one for each standard, making your application much more difficult to maintain and to debug (because everyone can make erors).

If you writing a framework you should always look at existing ones, which properly allready solved your problem. Then you get inspired or just use that component. A great starting point is symfony, their components are seperated and tested. If you load it with composer or download it manually is your choice ;)
They also have a Classloader http://symfony.com/doc/2.0/components/class_loader.html which you could use as it. Or you just take a look what their approach is.
The Autoloader (or your classloader) should be the included at the beginning of your application and this should be the only class you include directly.
If you want to load your class dynamic your have to take a look how your store your classes, there are diffrent "standard" ways like PSR0 http://www.php-fig.org/psr/psr-0/. If you want your users to add their own classes, when they using your framework you should consider to support multiple standards.

Related

How do I wrap an entire third-party library/framework inside a namespace?

I've written a reasonably well received plugin for WordPress. Several revisions ago, I began including Sensio's Twig in the plugin, in an effort to have a clean separation of concerns for presentation and logic. Recently (well over a year or so since I began including twig), I've been hearing users complain that they can no longer activate the plugin; they get an error stating that "Twig_Autoloader" cannot be redeclared, or something that similarly indicates that there's another instance of Twig in another plugin.
Honestly, I should have thought of that - it was a sad oversight on my part to not consider someone else might be using Twig. I facepalmed on that ;-) Resolving it seems to be trickier than I thought it would be, though. Twig uses an autoloader, PSR-0 compliant, I believe. I can't simply declare a namespace at the head of my plugin and rewrite a few lines to reflect the new namespace, as the autoloader seems to load everything into the global namespace. This is still true if I declare a namespace for the autoloader class - the Autoloader class will use the new namespace for itself, but everything it loads goes into the global namespace.
I could simply check to see if the autoloader class already exists, and then use the other instance, but I'm not guaranteed the same version will be used, which will lead to odd errors down the road. I could manually go and declare a name space in each file that's in the included Twig library, but that seems inelegant and inefficient.
In other languages, I could simply wrap the whole thing in a new class, but PHP doesn't have that particular nicety.
So - what's the best way to do this??
Thanks So Much!

PHP - get all declared resources (traits, classes, functions and constants) within a given script?

I designed a PHP 5.5+ framework comprised of more than 750 different classes to make both web applications and websites.
I would like to, ideally, be able to reduce its size by producing a version of itself containing just the bare essential files and resources needed for a given project (whether it's a website or a web application).
What I want to do is to be able to:
reduce the amount of traits, classes, constants and functions to the bare essential per project
compress the code files to achieve a lesser deployment size and faster execution (if possible)
So far, I've got the second part completed. But the most important part is the first, and that's where I'm having problems. I have a function making use of get_declared_classes() and get_declared_traits(), get_defined_constants() and get_defined_functions() to get the full list of user-defined classes, traits, functions and constants. But it gives me pretty much EVERYTHING and that's not what I want.
Is there a way to get all defined classes, functions and constants (no need for traits as I could run class_uses() on every class and get the list of traits in use by that class) for a single given script?
I know there's the token_get_all() function but I tried it with no luck (or maybe it's I'm using it the wrong way).
Any hint? Any help would be greatly appreciated :)
You can use PHP Parser for this. It constructs abstract syntax trees based on the files you supply to it. Then you can analyze its output for each file, and produce a report usable to you.
Other than that, you can use token_get_all() approach you've mentioned already, and write a small parser yourself. Depending on your project, this might be easier or more difficult. For example, do you use a lot of new X() constructs, or do you tend to pass dependencies via constructors?
Unfortunately, these are about the only viable choices you have, since PHP is dynamically typed language.
If you use dependency injection, however, you might want to take a look at your DI framework's internal cache files, which often contain such dependency maps. If you don't use such framework, I recommend to start doing this, especially since your project is big and that's where dependency injection excels at. PHP-DI, one of such frameworks, proved to be successful in some of my middle-size projects (25k SLOC).
Who knows? Maybe refactoring your project to use DI will let you accomplish the task you want without even getting to know all the dependencies. One thing I'm sure of is that it will help you maintain it.

Are there performance downsides while using autoloading classes in PHP?

Currently I load in all my classes by including a "all.inc.php" file on every page of my site, this file then goes on to include all the config, classes, functions, etc. that I will use on the whole site.
My issue with this is that often I use classes that only pertain to certain pages/sections of a website, so often I am including a bunch of classes at the start of the page which will not be used.
Obviously autoloading the classes would fix this issue, so my question is, would autoloading the classes give me a performace downside as the server then has to check if a file exists? And if there is a downside, then is this downside worse than having to include a number of classes that may not get used on the page? Or is the difference negatable?
This article has some information and benchmarks: PHP autoload performance (archived). Conclusion:
Autoloading does not significantly degrade performance. Include_path lookup, reading and parsing PHP scripts from disk takes much longer time than that bare autoloading logic costs.
Autoloading a class is almost as fast as including the class in the normal way. Switching to autoloading will improve performance in your case, because PHP loads less files and classes.
Autoloading will improve the performance if the script does not have to search the files each time in the filesystem. If you use namespaces you can have a nice mapping of the namespace and class name to a folder and file like Some/Nice/ClassName would map to Some/Nice/ClassName.php.
If you do not use namespaces and have to search through folders I suggest you to create a custom singleton class to include files that allows you to do something like:
App::uses('Some/Nice', 'ClassName');
In Autoload use the registered path and class name to map it to a path and file combining both args from the uses method in my example. This will allow you some namespace like functionality for class loading until you're ready to change your app to use namespaces.
You should use autoloading with cache index of all available classes/files in project.
Example:
$class_cache=array(
'MyClass'=>'lib/MyClass.php',
'Item'=>'model/Item.php'
);
function __autoload($class_name) {
if(array_key_exists($class_name))
include $class_cache[$class_name];
else
throw new Exception("Unable to load $class_name.");
}
You need to keep class list actual or write some generator for $class_cache.
Each include() and require() (and their _oncesiblings) carry a performance penalty on their own. Disk seeks and reads also come at a cost. It really depends on your code, if you are loading 20 classes but use only 2 or 3 at any single point, then it's definitely worth going the autoloading route.
If performance is your main concern, you should look into merging your class files into a single file and instantiate what you need.
A really old question, but all the answers were actually wrong.
... autoloading takes a significant amount of resources. The number varies a lot and that’s maybe not what you’ve seen in your own app, but a typical 10% wouldn’t be surprising.
from CTO of Blackfire.io, so I'm sure he knows what he is talking about. Read more here

Do most frameworks have autoloader

The framework that I use (Zend) has an autoloader built it. I think this autoloader takes care of loading, not only Zend itself, but also any other libraries the developer may add to the project.
Is it normal practice for a framework to have an autoloader? Any that don't have?
Is it necessary to have an autoloader?
ZF's Autoloader will by default only load ZF's classes. It can (and is supposed to be) configured to also load your custom classes and you can also add additional Autoloader from other frameworks. ZF 2 will have a classmap autoloader in addition to the PSR-0 autoloader. See the Blog Post by ZF's Matthew Weier O'Phinney on Autoloading Benchmarks
Yes, it's common to have autoloaders because you dont want require statements all over your code. It's not strictly necessary though. The native way to achive autoloading is with spl_autoload_register.
Not it is not necessary, but it is very convenient. You don't need a hell of a lot of includes or requires, and units are only loaded when you need the class it contains. And that helps you stucture your code too, because incorrect naming will cause the autoloader to fail.
As stated by other members that not every framework has an Autoloader but I believe that every framework should.
If you can understand what a framework does than you should understand that there designed to be modular, being able to add and remove components easily, if you was to hard code all your libraries models, controllers etc then when you add new libraries you would have to recode for the library to work.
So that's the convenience part of the autoloader, the other part is the performance and resource management side of it, The base idea of the autoloader is to load the files only when required.
so on your index.php page you may need 5 libraries, but on your register.php you may only need 2 libraries, so that using an autoloader will save you 3 includes on your register page.
It also allows a better file structure as your components are separated and organized.
as you may be looking into placing an autoloader into your framework i strongly recommend you look at the PSR-0 standards that is currently in use in Zend and many other high end framework, the link can be found below:
http://groups.google.com/group/php-standards/web/psr-0-final-proposal
Yes, it is a common practice to include autoloader in the framework.
No, I can not think of any major framework without autoloader.
Yes, it is necessary if you want the framework to be flexible enough. It eases the addition of modules / classes to simply copying the files to the correct directory and invoking them from within the code. Autoloader just includes proper files instead of including all of the files (even if they are not needed at the moment).
Additionally, the way the classes are autoloaded can be determined completely by the autoloader mechanism, enforcing eg. proper directory structure or enforcing prior declaration of classes / files that can be autoloaded.
Many frameworks do have autoloaders, one that does not is CodeIgniter and you have to specify which classes you want to load all the time and which classes you want to load inside your controllers / models / views / libraries.
It isn't completely necessary, but it is nice because it generally enforces a file structure and you also don't have to worry about remembering to include files at the top of your scripts.
[Edit]
Apparently clarification is needed on my CodeIgniter statement. Yes there is an auto_load place that lets you specify the libraries/modules that you want to load automatically at the start of every script, and yes there is a loader library, but they are not the same as a real autoloader.
You have to specify which ones you want at the start, it doesn't know that you want to load the Pizza_Store modle until you use the custom
$this->load->model->('foo');
which is equivalent to
include 'application/models/foo.php';
$this->Foo = new foo();
But is not really the same as only having to call $this->foo = new Models_Foo(); and CodeIgniter knowing what you mean by it, which is what happens when an autoloader is used.
[Edit part deux]
Nowehere in the code does it say __autoload, spl_autoload or spl_autoload_register. This is because it maintains PHP 4 compatibility. It is just the way that the framework has been built, there is a false autoload as I stated above, but it does this for each "autoloaded" class:
foreach($autoloaded_class as $type=>$class){
if(is_application_class($class)){
include "application/{$type}/{$class}.php";
}
elseif(is_core($class)){
include "core/{$type}/{$class}.php";
}
}
$array['Foo'] = new Foo();
$controller($array);
Which is essentially calling:
include 'foo.php';
at the top of every file no matter if you need it or not.

Design Tips for PHP Function Include Files

Good design dictates only writing each function once. In PHP I'm doing this by using include files (like Utils.php and Authenticate.php), with the PHP command include_once. However I haven't been able to find any standards or best practices for PHP include files. What would you at StackOverflow suggest?
I'm looking for:
Naming Standards
Code Standards
Design Patterns
Suggestions for defining return types of common functions
(now I'm just using associative arrays).
One convention I like to use is to put each class in its own file named ClassName.class.php and then set up the autoloader to include the class files. Or sometimes I'll put them all in a classes/ subdirectory and just name them ClassName.php. Depends on how many class vs. non-class includes I'm expecting.
If you organize your utility functions into classes and make them static methods instead, you can get away with writing only a single require_once() in your top level files. This approach may or may not be appropriate for your code or coding style.
As for return types, I try to follow the conventions used in the built-in functions. Return a type appropriate to the request, or return false on failure. Just make sure you use the === operator when checking for false in the results.
The fact that you're concerned about conventions suggests you're already on the right track. If you are familiar with any other OOP language like Java, C++, C#, etc., then you'll find you can follow a lot of the same conventions thanks to the OOP goodness in PHP5.
Whatever naming convention you end up using (I prefer to take cues from either Java or C# wherever possible) make sure if you use include files for functions that they do not actually execute any code upon including, and never include the same file twice. (use include-once or require-once)
Some such standards have been written already. Most large projects will follow and standard of their own.
Here is one written by Zend and is the standard used in the Zend framework.
http://framework.zend.com/manual/en/coding-standard.html
Also, PEAR always had some fairly strict coding standards:
http://pear.php.net/manual/en/standards.php
My preferred answer though is that for your own project you should use what you feel comfortable with, and be internally consistent. For other projects, follow their rules. The consistency allows for greatest code readability. My own standards are not the same as the PEAR ones. I do not indent with four spaces (I use tabs) and I never use camel case like function names, but nonetheless if I am editing something from another project I'll go with whatever that project does.
I've done the following. First, I created an intercepting filter, to intercept all web requests, I also created a version which would work with command line commands.
Both interceptors would go to a boot strap file, which would setup an autoloader. This file as the autoloading function and a hash. For the hash the key is the class name, and the value is the file path to the class file. The autoload function will simply take the class name and run a require on the file.
A few performance tips if you need them, use single quotes in defining the file, as they're slightly faster since they're not interpreted, also use require/include, instead of their _once versions, this is guaranteed to run once, and the former is a fair bit faster.
The above is great, in fact, even with a large code base with a tonne of classes, the hash isn't that big and performance has never been a concern. And more importantly we're not married to some crazy pseudo name space class naming convention, see below.
The other option is delimited name, pseudo name space trick. This is less attractive as name spaces will come with 5.3 and I see this being gross as renaming these across the code base will be less fun. Regardless, this is how it works, assume a root for all your code. Then All classes are named based on the directory traversal required to get there, delimited by a character, such as '_', and then the class name itself, the file will be named after the class, however. This way the location of the class is encoding in the name, and the auto loader can use that. The problem with this method besides really_long_crazy_class_names_MyClass, is that there is a fair bit of processing on each call, but that might be premature optimisation, and again name spaces are coming.
eg.
/code root
ClassA ClassA.php
/subfolder
subFolder_ClassB ClassB.php

Categories