Autoloading
lang_of_article_differ
want_proper_trans
Including files to your scripts
When you write the program you do not write it in one file. In php you must include or require files into another by using
include 'filename.php';
require 'another.php';
If you use tons of classes in your app you need all them to be included in the header of you file. And that's going not so sweet.
Also, if you include or require some file into your script it being parsed by php even if you don't use the code from it. For example:
<?php
include_once 'some/library.php'; // SomeLibrary class
if ($userLogged) {
$lib = new SomeLibrary();
// do some stuff
} else {
redirect_to('/');
}
In this script SomeLibrary would be always parsed by php and eat your memory and cpu time, even if the user is not logged and is redirected to the main page. So using a include is not always optimal decision. Of course you can include your library only in case user is logged:
<?php
if ($userLogged) {
include_once 'some/library.php'; // SomeLibrary class
$lib = new SomeLibrary();
// do some stuff
} else {
redirect_to('/');
}
Automatic including
But its not always even looks elegant. In fact, php
has ability to include files automatically when they first encountered in the script if they haven't been declared yet in script.
This is done by spl_autoload_register
:
spl_autoload_register(function ($class) {
// this function would be called when php would not find some $class
});
You should set the autoloading function above at the begining of your application initialization and forget about including files after that moment.
spl_autoload_register
accepts one parameter - function which should be invoked when the some class is not found. The parameter $class
of this function would be the name of the class (including namespace) that is not found:
"\Catchmetech\AutoloadingLesson\ExampleController"
If you properly generate names for your classes in system and put them in proper places then it would be no pain for you to configure the autoloader function. The best practice (PSR
) says that namespaces should correspond to folders and each class should be in separate file. So, class in example above should be in folder Catchmetech\AutoloadingLesson
and should be named ExampleController.php
. Of course, each class should use namespaces, as i mentioned in previous lessons :)
So, how to determine what file should i include in my autoloading function? Lets str_replace
the $class
's namespace delimiters \
with proper to our operating system DIRECTORY_SEPARATOR
:
$fileName = str_replace('\\', DIRECTORY_SEPARATOR, $class) . '.php';
Ok, we have a path to the file, relative path because. We should prepend to it $baseDir
which should be the path of the directory where we have our application set:
$baseDir = __DIR__.'/';
$fileName = $baseDir.$fileName;
Also, we should check if the file we looking for really exists on the filesystem by the is_file
, and if not - throw
the exception:
spl_autoload_register(function ($class) {
$base_dir = __DIR__.'/';
$file = $base_dir . str_replace('\\',DIRECTORY_SEPARATOR, $class) . '.php';
if (file_exists($file)) {
require $file;
} else {
throw new \Exception ('can\'t include '.$file.PHP_EOL.' when trying to load `'.$class.'`');
}
});
Voila, we have our first and simplest autoloading function created! Put the code into the top of your bootstrap file of the application and do not use include
statements from now!