We can do this the easy way, or we can do it the hard way.
-Anonymous
Have you ever done this in your PHP code? I know I certainly have.
The point of this post is to explore a more beneficial (and built-in!) strategy to requiring the files which contain the classes we are using within our PHP code.
A little background
Sometimes when writing code, I get the feeling that there must be a better way.
But even when my intuition is telling me this, it can be difficult to know whether the solution is to “roll my own” custom solution which refactors my code, or possibly to seek out an existing PHP way of doing things.
The latter (if it exists) will often not only solve my immediate problem, but also open my eyes to a bigger picture idea that I had not considered before. That said, I do find that trying to code my own solution first is often beneficial, if for no other reason than to get me to imagine and explore a few potentially “wrong” approaches and realize why they are not ideal.
Requiring the exact files I need for a set of routines within my code is an example of a problem where I had tried a few different times (with varying success) to code my own custom solution. Only later did I realize that autoloading already solves the problem with a much more elegant solution.
Why use autoloading?
Before talking about what autoloading is, let’s focus first on why it matters.
When requiring many files as we are doing in the example above, it’s often the case that we will not actually need all of the files being loaded to complete the current task/pageload/etc.
Any time I see a long list of require‘s, I get the feeling that a blanket/catch-all approach is being implemented without much thought. Even if this isn’t the case, it still doesn’t feel neat or efficient.
Autoloading gives us cleaner code and less worry, not to mention it encourages better organization of our files.
So what is this autoloading you speak of?
Autoloading is essentially the idea that we can instantiate a class object without first explicitly requiring the file that contains said class. Sounds a little magical? I agree! That’s why I got inspired to write this post.
In early versions of PHP 5, autoloading was pretty rough. Basically, we could define a single function called __autoload
that would let us define a way of requiring a file whenever an object got instantiated using an undefined class.
This has essentially been replaced with the newer spl_autoload_register
, but it may be helpful to look at the older method first:
In the examples that follow, please note that they are overly simple, not realistic in most projects, and are intended to demonstrate basic usage of the autoloading functionality with as few complications as possible.
Allowing multiple autoload callback functions
As noted in the comments above, __autoload
isn’t extremely useful within a larger framework where multiple people may be writing their own components.
Thankfully, PHP 5.1.2 introduced a new spl_autoload_register
function which allows multiple functions to be hooked into the autoload process.
When using spl_autoload_register
, we are basically registering a callback function that gets added to a queue. When a class object is instantiated without the class already being defined, PHP will execute all of the registered functions in order, until one of them includes or requires the file containing the class in question.
It is important to note that once the correct file for the class is loaded, the remaining registered functions will not be invoked.
Other ways of doing the same thing
We can also use a string instead of an anonymous function for the first argument of spl_autoload_register
.
If needed, we could also use an array for the first argument to spl_autoload_register
and specify an object method as the callback function. We’ll leave that as an exercise for the reader.
Additional concerns
Since we can register multiple functions with the autoload process, there arises a question about the priority or ordering of the functions to be called. The spl_autoload_register
has two optional parameters that let us address such things.
Final thoughts
Autoloading classes is pretty awesome because it saves us a good bit of hassle, encourages us to pre-plan the file name/class name relationship for our code, and fundamentally makes our code much more readable and clean.
Please note that the above examples were overly simple and were intended to demonstrate basic usage of the autoloading functionality minimal complications. Realistically, one would likely use a package manager like Composer (which has its own autoloader built in) or they would craft their own project-specific autoloader which suits their desired directory and file structure.
We recommend browsing the PHP Standards Recommendations to learn more about best practices. In particular, the 2nd and 4th accepted standards discuss namespaces and autoloading, respectively.
To conclude, we are including a link to an extended, somewhat realistic custom autoloader example which is set up to autoload classes from a namespace called Acme\ExampleProject
.
In the example, we’re thinking of Acme
as the entity or team writing the code and ExampleProject
as the name of a project whose code is being encapsulated.
Leave a Reply