In https://stackoverflow.com/a/3313137/569976 ircmaxell says the following:
I use a public static method init() on my static classes that require initialization (or at least need to execute some code). Then, in my autoloader, when it loads a class it checks is_callable($class, 'init'). If it is, it calls that method. Quick, simple and effective...
That post, however, is from 2010 and a lot has changed since then. My question is... does Composer support anything like this?
Composer's autoloader isn't going to automatically call init methods for you, but that doesn't stop you from using your own autoloader instead.
https://getcomposer.org/doc/01-basic-usage.md#autoloading
Note: Composer provides its own autoloader. If you don't want to use that one, you can just include vendor/composer/autoload_*.php files, which return associative arrays allowing you to configure your own autoloader.
Related
I've seen a lot of threads here and in other forums that asked this a lot of times, but I still see using the include function of PHP in the answers?
how can I use this function, not using totally the include function?
Thank you
how can I use this function, not using totally the include function
You cannot totally not use include and that is not the point of using autoloader as you usually need to at least include the autoloader ;). That autoloader is the regular PHP code that is being called by PHP when unknown class use is attempted in the code. It is expected to include right file to make the class known, and the code continues as you'd explicitely include right file by hand in your code. So the main benefit shows up when your code uses classed (OOP) - you do not need to care if you included the class you are about to instantiate the object of or not. You just do new Foo() or call Something::methodName() and if all is set up right it will work.
The function spl_autoload_register is used to register a callback into the autoloader queue.
The PHP autoloader is a functionality of the PHP interpreter that, when a class is not defined, calls the functions registered in the queue, one by one, asking them to load the class, until the class becomes available. It the class is still not available after all the functions were invoked, the interpreter triggers a fatal error.
The autoloader doesn't perform any magic. It is the entire responsibility of the registered functions to make the class available. Most of them use the name and namespace of the missing class to figure out the path of the file that contains the declaration of the class and include it.
That's how the thing works. There are not many ways to produce a class in PHP and, for a reusable autoloader callback, the list starts and ends with include1 (include_once, require or require_once can be used as well but they don't make any difference in this case.)
The autoloader callback itself stays in separate file (for reusability) and usually that file also contains its registration as autoloader callback (the call to spl_autoload_register). All your code have to do is to include this file once in every file that is an entry point of your application.
All things being equal, your application needs to use include at least once and once is also the maximum required number of usages for it. The autoloader callback also uses include (probably also only once) but you don't write autoloader callbacks every day. If you wrote one and you wrote it well you can reuse it. Most people never wrote an autoloader callback and they will never write one.
Using Composer is easy and if you follow the PSR-4 rules of naming the files of your project, Composer can generate an autoloader for your project that knows how to load your classes (behind the scene it uses include, of course). All you have to do is to run composer init in the root directory of your project, run composer install and write include 'vendor/autoload.php'; in the file that represents the entry-point of your application. No other uses of include are required.
1 An autoloader callback is not required to include another file to make the class available. It can generate the code of the class on the fly and eval()-uate it, but the use cases of such approach are very limited. It is used by the testing suites f.e., to generate mock classes.
I have searched many blogs and websites but I didn't find any perfect answer.
whenever I use composer I have to include the autoload.php file and then for each class to autoload I have to use that class with the namespace.now I want to know what is the advantage of this composer where I can easily include the class file by include_once or require_once rather than using both autoload.php and the class file individually.
when I use composer I have to write these code:
include_once("vendor/autoload.php");
use namespace/derectoryname/classname;
whenever I include manually than
include_once("classname.php");
can anyone clear these?
First and foremost, composer main advantage is to handle dependencies (and your dependencies' dependencies, and so on). The autoloader is just frosting on the cake.
The question would be better posed as include vs autoloader, and then it gets slightly more interesting.
First, brevity. With one approach you'll end up using two declarations per file: use and include, whereas using the autoloader you'll just need to declare the use statements, and let the autoloader do the dirty work of actually loading the file.
Also, performance. If you include or require your requirement at the top of your file, you will always load that other file. With the autoloader, you'll only do so if you actually try to use the required class. Until you try to instantiate or use any of the required classes, the autoloader wont hit the filesystem and try to find the required class, making it more efficient, and only doing the work when you actually need the work.
As a somewhat crude example:
use Namespace\Package\Service\ServiceProvider
use Namespace\Package\Exception\ServiceProviderException
if (isset($options['service_id'])) {
try {
$service = ServiceProvider::getService($options['service_id']);
}
catch (ServiceProviderException $e) {
// do your exception handling
}
}
else {
// and now for something entirely different
}
With this, the file that declares ServiceProvider is only going to get loaded if you actually meet the requirements, and the file that declares ServiceProviderException only when if you have to catch the exception (although to be fair it would have been included by the autoloader when ServiceProvider needed to throw that exception, and not before).
On top of that, you've got a neater separation of concerns. Your ClassA that needs to use NameSpace\Package\ClassB is not required to know where you are actually storing that file. It's not its job, and shouldn't care about the actual structure of the filesystem, making the code more portable. Someone somewhere else might have a different vendor structure than you and still get use your code easily if it uses an autoloader, instead of hardcoding file paths in your require statements.
This should be more or less enough to show you that autoloading is a much more modern, efficient, and portable way to work than including your requirements manually.
And since you are already using composer to handle your dependencies, which is awesome, you get the autoloader benefits for free!
I may generally misunderstand something about setting up a custom classloader.
What happens is that once i initialize it:
use Doctrine\Common\ClassLoader;
require_once(DOCTRINE_PATH . '/Common/ClassLoader.php');
classLoader=new ClassLoader('Doctrine', DOCTRINE_PATH);
classLoader->register();
My previously defined function
function __autoload(){}
No longer works.
What am i missing here?
After diving a bit deeper into the autoload documentation, i found that in order to have multiple autoloaders at the same time, the use of
function __autoload(){}
is not a valid route to take. Instead, one has to define a custom autoload function, such as
function MyAutoLoader()
and then use
spl_autoload_register('MyAutoLoader');
to register it onto the autoload stack.
Finally, using this method, my autoloader is no longer overwritten by implementing the Doctrine classloader.
Problem
I am using the SPL Class Loader provided by PSR Group. However, I've come to a chicken-egg paradox.
That is, this will autoload classes preventing explicitly including them. But I first need to include/require this class and the code for instantiating the object
$classLoader = new SplClassLoader('Doctrine\Common', '/path/to/doctrine');
$classLoader->register();
Question
What is common solution for including the autoloader code?
In the case of a front-end controller, I could add the code there. But I'm not always using the front-end controller patter. I suppose I could also use PHP's auto_prepend_file. Interested in the communities input.
You explicitly require the autoloader on the bootstrap stage (the stage where the application is started up).
All subsequent functions/classes are then autoloaded.
When you manually include a PHP class you can do it while the current script is running, right? Then you can decide, if a condition matches you load it and if it doesn't you don't. Like this:
if ( $_SERVER['REQUEST_METHOD'] === 'POST' ) {
include '../../../Whatever/SanitizeUserInput.class.php';
SanitizeUserInput::sanitize($_POST['someFieldName']);
}
But let's say I use the autoload feature with this class. Will it be effectively loaded at the beginning or will it be loaded only if it's used?
I mean, should I add the __autoload function only in classes that I'm 100% sure I'm going to use in any script (e.g. database connection, session management, etc.)?
Thanks
Autoload is called only when you are trying to access desired class. And it would be better to use spl_autoload_register() instead of __autoload
Documentation:
You may define an __autoload() function which is automatically called
in case you are trying to use a class/interface which hasn't been
defined yet.
and
spl_autoload_register() provides a more flexible alternative for
autoloading classes. For this reason, using __autoload() is
discouraged and may be deprecated or removed in the future.
Autoloading kicks in when you are trying to use a class that has not yet been loaded:
include 'foo.php';
new Foo; // autoload not used, because the class already exists
// Bar is not yet loaded here, auto or otherwise
new Bar; // Bar is being autoloaded, because it was not yet loaded
As such, autoloading can be very efficient. It's slightly less efficient than loading classes by hand at the time when you need them, because of the overhead of invoking the autoload function. But keeping track of loaded classes by hand is more work for very little return over autoload.
Try it out, you will see, that whenever PHP stumbles over a class it doesn't know yet, it will call your autoload function. When your autoload function tells PHP in which file the class is, it will load this file.
To make the answer short, PHP only loads the file when needed, that is true even for conditions, so following test class will never be loaded.
if (false)
{
$test = new CTest(); // never loaded with autoload.
}