Do I need Autoloader-Class in PHP always? - php

I just start learning MVC in PHP, so my Question is
if I use PSR-4 for Autoload, why should I create Autoloader-Class or don't I need it anymore?

PSR-4 is a specification that defines how to name your files and how autoloaders should load those files, so anyone can write "PSR-4 compliant" code and "PSR-4 compliant autoloaders" and they will work together, without having to reinvent the wheel for every individual library. Yes, you will still need an autoloader. PHP doesn't do autoloading out of the box, and just structuring your files according to PSR-4 doesn't make them autoload automagically.
The status quo is to use Composer to manage your dependencies, which comes with an autoloader which you can use. Or you use any other library management technique you want and any other autoloader you want, 3rd party library or one you have written yourself.
The alternative (to autoloading in general) is to write individual require_once ... statements, but that's a bit mad in this day and age and a bit of an unnecessary headache.

Related

Converting to namespaces in PHP

I am currently working as a student on php project which has grown since the beginning of time and has about 1800 php-files.
The problem is: it is completely without namespaces, or any of the PSR-4, etc. recommendations. The technical debt is strong with this one :).
We want to use composer (and twig and some libraries more) and having problems including this (especially composer). I think it's because of the overwrite of __autoload() via spl_autoload_register() in the composer-autoloader?
Is there a good and fast way to start integrating namespaces without rewriting the whole project?
You can still use Composer with PSR-0 or classmap.
I'd probably go with the classmap first. Advantages: Can deal with multiple classes per file. Can deal with arbitrary file structures.
Once you achieved using Composer's autoloading, you can start removing either the existing autoloader or those require_once/include_once that are likely spread all over the place.
Once you've got rid of all that file loading legacy and have established Composer autoloading, you can try to organize the code according to PSR-0. This will probably require you to rename files and reposition them. It might also be the case that the classes don't have any identifiable prefixes - which is bad for your PSR-0 autoloading because all these files would belong into one single folder.
Note that until this point you haven't changed the name of any class, so the code should run without any changes.
Using namespaces does not have a very noticeable advantage. You'd be forced to rename all classes, rename all usages of that class name, and all in all it won't provide any noticeable benefit if used alone.
On the other hand, you sound like you do want to refactor everything else as well, so switching to namespaces can be used as a signal for "newer" code.
You can use PSR-4 and PSR-0 at the same time, so it won't affect your renaming of classes (besides the necessary class name changes in all the places).

is it possible to add a namespace to normal class library via composer's autoloader?

I know this is highly unlikely but thought I would ask anyway.
I am using DomPdf to render pdfs.
Currently it does not implement namespaces and loads a lot of classes.
I can autoload the library with composer and "classmap": ["include/"].
Is it in any way possible to autoload this library implementing a custom namespace in order to avoid possible class name conflicts?
Or is there a tool to search and replace in a library to add namespaces?
I would prefer not to touch the library and was just wondering if there is some way this could be done with composer's autoloader.
(I don't currently have conflicts but would like to keep my libs from running into future issues by implementing namespaces wherever I can.)
Conflicts would arise because of two classes having the same name, the same (or absent) namespace, but reside in different files (and paths) and contain different code.
Composer autoloading cannot do anything about this.
If you come into this situation, you have to resolve it on the code level first, i.e. you have to rename one of the classes, probably moving it into a namespace and keeping it's name as a quick help. Effectively renaming it means to fix every other line of code that has references to the old class.
Fortunately this will only happen if you try to include new code into your project, so you'd be able to stop using whatever you started importing, and look around for an alternative instead.

How to include external library in Zend Framework 2?

I played with the zf2-tutorial successfully, but I was totally confused when trying to integrate an external library like "jpgraph". I know I must do this with autoload or servicemanager but it won't work.
The php-files of jpgraph are in the vendor/graph directory. I use a module called Jpgraph, in the controller indexAction I try:
$graph = new Graph($width,$height);
this gives me an error:
Fatal error: Class 'Jpgraph\Controller\Graph' not found in ...
the jpgraph library don't use namespaces.
i also tried this way without success
what's the best way to integrate such things?
I would be glad for every tip or help
Add the library to your composer.json and add the class with Classmap and/or the include path as phpunit does
https://github.com/sebastianbergmann/phpunit/blob/master/composer.json#L48
One option, as Maks3w pointed out, is to use Composer. If you've never heard of or used composer before it's definitely worth a look. I was surprised how easy it was to set up and use 3rd party libraries. It's also very easy to set up your own library to work with composer, and use any source controlled (git or svn) library of your own - works well with GitHub repos - just add a composer.json file.
On the other hand, you do not need to use composer to do what you want, it would make it very easy, but it may be overkill. Zend Framework 2 has a very flexible autoloader system, and although it works well with PSR-0, you can have any class autoloading sytem that you like. Take a look at the different components of Zend\Loader, in particular I think the ClassMapAutoloader will be the one to suit your needs.

How to manage dependency autoloading

When building a library I always provide an Autoloader class that handles autoloading for the library. The autoloader is registered like this:
require_once 'path/to/PHP-Parser/lib/PHPParser/Autoloader.php';
PHPParser_Autoloader::register();
I'm not sure though how to handle it if my library depends on another library. Imagine that PHPParser depends on a PHPLexer. Now when using the library one would need to write:
require_once 'path/to/PHP-Lexer/lib/PHPLexer/Autoloader.php';
PHPLexer_Autoloader::register();
require_once 'path/to/PHP-Parser/lib/PHPParser/Autoloader.php';
PHPParser_Autoloader::register();
If there are more than just one dependency or the dependencies have dependencies themselves, this can get messy quickly.
So how should one handle dependency autoloading?
One idea I had was that the library should handle autoloading for it's dependencies too, but that just doesn't feel right. Another idea would be to not provide an autoloader at all and assume that people use the UniversalClassLoader. That though doesn't seem right either.
Well, there are a few ways to solve this problem, each with their own pros and cons:
Use a common PSR-0 autoloader for all the libraries, and just register the location of the other project when initializing it.
Advantages:
Very simple to implement
Uses same code, so only one autoloader to use
You can register all the paths in your application bootstrap file, so all library autoloading is defined in one place
Disadvantages
Requires all libraries to implement a PSR-0 compatible file structure
Leaks the abstraction level a bit since the application bootstrap needs to bootstrap everything inside the application including each individual library.
Tightly couples the library's file structure to your autoloader (if a library implements a new file that conflicts, it'll break your autoloader even though theirs works file)
Define a custom autoloader for each library.
Advantages
Very simple to implement.
Keeps library autoloading semantics in the library.
Better maintainable code due to separation of responsibility
Disadvantages
Lots of hard-coded classes in your bootstrap file (not a big deal though)
Performance since an autoloaded class must go through multiple autoloaders
Leaks the abstraction level since a library may need more effort to bootstrap than just an autoload
Implement a bootstrap.php for each library (preferably provided by the library)
Advantages
Pretty simple to implement.
Keeps library autoloading semantics in the library
Better code due to separation of concerns
Ability to define non-trivial library bootstrap code without clouding other parts of the application
Disadvantages
Still require a require_once '/path/to/lib/dir/bootstrap.php'; to initialize
Performance (for the same reason as the 2nd solution)
Most 3pd libraries do not implement a bootstrap file, so you may have to maintain one.
Personally, I use the third option. An example is the bootstrap.php file in my CryptLib library. To initialize it, just call bootstrap. You could also use any PSR-0 autoloader and just not call bootstrap.php, and it will work just fine. But with the bootstrap option, if I added functionality which needed to register itself at startup, I could just add it to the bootstrap.php file and it would automatically be executed (rather than telling users that they will need to do "x, y, z" on startup)...
With respect to the universal class loader option that you mentioned (calling spl_autoload_register() with no arguments), I personally don't like that option. First of all, it lowercases the classname (which is in violation of PSR-0, and I don't like it. I have gotten used to case sensitive class -> path mapping, and actually prefer it that way now). Secondly, it always uses relative paths, so it will defeat most opcode caches. There are other issues, but those are the big ones...
If classes in library named by PSR-0 convention, than it's possible to use one autoloader for all libraries. Otherwise, library should provide own autoloader.
add to class constructor
public function __construct(){
$this->Register();
}
after that on page where you whant to make load create an object
$obj = new PHPParser_Autoloader();

Is it bad to use autoloading in PHP?

From php.net:
In PHP 5, this is no longer necessary. 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. By calling this function the scripting engine is given a last chance to load the class before PHP fails with an error.
Now I am wanting to know, is it bad practice to solely use __autoload to load the appropriate classes on a dynamic site?
The way my site is setup is to include files into the index.php file, for example http://www.site.com/index.php?p=PAGE-I-WANT-TO-LOAD
So if I am on the forums section or the blogs section of my site, I want only appropriate classes and functions to be loaded, so I use autoload but I never include a file manually, should I be using __autoload as a last resort or is what I am doing fine even on a high traffic system?
Bad? No. __autoload() is one of my favorite additions to PHP 5. It removes the responsibility (and annoyance) of manually having to include/require the class files necessary to your application. That being said, it's up to you as the developer to ensure that only the 'appropriate classes' are loaded. This is easily done with a structured naming scheme and directory structure. There are plenty examples online of how to properly use __autoload(), do a Google search and you'll find plenty of information.
Autoload is a good way to load only what classes is needed.
In PHP 5 >= 5.1.2, most of the problems with the old __autoload() dissapeared, thanks to spl_autoload_register().
Now I am wanting to know, is it bad practice to solely use __autoload to load the appropriate classes on a dynamic site?
Not at all. You can rely on autoload, all you need to do is to devise a good naming convention and implement an efficient autoloader.
There is one major issue to consider. Autoloading and Zend Guard do not play well together, because Zend Guard tends to rename things, which will mean that the naming convention you decided to use will most likely not be the same. If you will be using Zend Guard (or any other obfuscator for that matter) you will most likely be forced to include all the files by hand.
Here is a quote from the Zend Guard user guide:
Autoloading classes will not work since the filename on the disk would not
match the obfuscated class name.
The only danger to __autoload() is if you define a poor autoloading function. Generally, all you're going to get in terms of a performance hit is a few disk seeks as PHP looks for the right files that contain your classes. The upside is getting rid of all those annoying include() calls.
If you're worried about performance at this level, then you should already be using an opcode cache such as APC.

Categories