Proper way to include SPL Class Loader - php

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.

Related

Using spl_autoload_register without using include

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.

Is PHP 5's autoload inefficient?

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.
}

Why does Codeigniter assume I want to create an instance of the class when using $this->load?

In Codeigniter, when we use $this->load('class_name') in the controller, CI will try to create an instance of the class/model using its constructor.
But sometimes, I don't actually need an instance from that class, I just want to call some static functions from it. Also, there is a big limitation with $this->load('class_name'), it does not allow me to pass parameters to the constructor (unless we extend or modify the core class of CI).
I think the $this->load('class_name') function should only do a require_once on the class php file for me, and let me freely do things (create instance/call static functions) with the class in the controller.
Should I simply ignore this function and use require_once or writing my own __autoload function to load up the classes? This way, I just feel strange because it seems I am not writing codes inside the CI box.
You can pass parameters to your constructor. See the "Passing Parameters When Initializing Your Class" section in the user guide.
I found CodeIgniter's object creation and loading to be very limiting. I want full control over my code, and little magic in the background. I have instead started using Doctrine's Class Loader. It's very lightweight and is essentially SPL autoloading (also a good alternative). You don't need the whole Doctrine shebang with ORM and all that stuff, just the ClassLoader. There's some configuration tinkering to get this right, but it works wonders.
With PHP 5.3 I now have namespaced classes in the Application directory. For instance I created a new class in the Tests directory: Application\Tests\SomeTest.php
That test could look something like this:
namespace Tests;
class SomeTest {
...
}
I would use this class in my code (controllers, views, helpers) by simply using the fully qualified namespace (i.e. $test = new \Tests\SomeTest) or a "use" statement at the top of my code (use \Tests\SomeTest as SomeTest).
In this way I intend to replace all libraries and models with OO namespaced variants. There are many benefits to this: fast autoloading with SPL, full IDE intellisense support for classes/methods (CodeIgniter is really bad for that), your code is more portable to other frameworks or projects.
That said, I still use a lot of the CodeIgniter engine. This basically means I have $CI =& get_instance() in most of my classes. It's still a work in progress and I think the main reason I need CI is for it's database access. If I can factor that out ... and use something like Dependency Injection, then I won't need CodeIgniter in my classes at all. I will simply be using it for it's MVC framework, and using it's methods occasionally in my controllers.
I know this goes above and beyond your question, but hopefully it's some food for though - and it helps me to get it in writing too.

ZF Autoloader to load ancestor and requested class

I am integrating Zend Framework into an existing application. I want to switch the application over to Zend's autoloading mechanism to replace dozens of include() statements.
I have a specific requirement for the autoloading mechanism, though. Allow me to elaborate.
The existing application uses a core library (independent from ZF), for example:
/Core/Library/authentication.php
/Core/Library/translation.php
/Core/Library/messages.php
this core library is to remain untouched at all times and serves a number of applications. The library contains classes like
class ancestor_authentication { ... }
class ancestor_translation { ... }
class ancestor_messages { ... }
in the application, there is also a Library directory:
/App/Library/authentication.php
/App/Library/translation.php
/App/Library/messages.php
these includes extend the ancestor classes and are the ones that actually get instantiated in the application.
class authentication extends ancestor_authentication { }
class translation extends ancestor_translation { }
class messages extends ancestor_messages { }
usually, these class definitions are empty. They simply extend their ancestors and provide the class name to instantiate.
$authentication = new authentication();
The purpose of this solution is to be able to easily customize aspects of the application without having to patch the core libraries.
Now, the autoloader I need would have to be aware of this structure. When an object of the class authentication is requested, the autoloader would have to:
1. load /Core/Library/authentication.php
2. load /App/Library/authentication.php
My current approach would be creating a custom function, and binding that to Zend_Loader_Autoloader for a specific namespace prefix.
Is there already a way to do this in Zend that I am overlooking? The accepted answer in this question kind of implies there is, but that may be just a bad choice of wording.
Are there extensions to the Zend Autoloader that do this?
Can you - I am new to ZF - think of an elegant way, conforming with the spirit of the framework, of extending the Autoloader with this functionality? I'm not necessary looking for a ready-made implementation, some pointers (This should be an extension to the xyz method that you would call like this...) would already be enough.
To extend what Gordon already pointed out, I'd create my own autoloader class that implements Zend_Loader_Autoloader_Interface and push that onto the Zend_Loader_Autoloader-stack.
class My_Autoloader implements Zend_Loader_Autoloader_Interface
{
public function autoload($class)
{
// add your logic to find the required classes in here
}
}
$autoloader = Zend_Loader_Autoloader::getInstance();
// pushAutoloader() or unshiftAutoloader() depending on where
// you'd like to put your autoloader on the stack
// note that we leave the $namespace parameter empty
// as your classes don't share a common namespace
$autoloader->pushAutoloader(new My_Autoloader(), '');
I wouldn't go with the Zend_Loader approach as, even though not deprecated yet, the new Zend_Loader_Autoloader seems to be best practice currently.
See the manual on Zend_Loader:
By default, the autoloader is configured to match the "Zend_" and "ZendX_" namespaces. If you have your own library code that uses your own namespace, you may register it with the autoloader using the registerNamespace() method.
$autoloader->registerNamespace('My_');
Note that the autoloader follows the ZF Naming Convention, so Zend_Foo_Bar will look in Zend/Foo/Bar.php.
However,
You can also register arbitrary autoloader callbacks, optionally with a specific namespace (or group of namespaces). Zend_Loader_Autoloader will attempt to match these first before using its internal autoloading mechanism.
$autoloader->pushAutoloader(array('ezcBase', 'autoload'), 'ezc');
Another way would be to create custom class Loader extending Zend_Loader and then register it with:
Zend_Loader::registerAutoload('My_Loader');
ZF will then use this autoloader instead of the default one.

Requiring classes in Zend Framework based library

Simple question. Why use require_once to include classes that you use within a file? For example, if I create a class that extends Zend_Db_Table_Abstract, I don't really need to have this in the class declaration file:
require_once "Zend/Db/Table/Select.php";
They are included by the auto-loader anyway. Is there a performance gain for explicitly declaring the "imports"? Is it for unit testing?
Simple Answer: If you aren't using the autoloader, the functionality will not break.
Its not necessary to do this in your project if you know for a fact you will be using the autoloader, but if you are working on a framework (like Zend) that will be used by other developers as well, you will want to have re-usability with least amount of compatibility issues, therefore you really should require explicit dependencies.
Another benefit is that it helps you see when your classes are becoming dependent on too many other classes. This helps you keep your coupling to a minimum while designing your objects.
An example from Zend/Db/Table/Select.php
/**
* #see Zend_Db_Select
*/
require_once 'Zend/Db/Select.php';
/**
* #see Zend_Db_Table_Abstract
*/
require_once 'Zend/Db/Table/Abstract.php';
You can get rid of these calls in your IDE by replacing "require_once" with "// require_once" require_once should be used only for class loading. Other, for example inserting an array from file like $file = include "test.php";, don't use it (or don't need to use it).

Categories