Tags

, , , ,

Auto-loading classes in PHP is super-easy; there are several ways to solve this problem, you could either create your own autoload function like this:

<?php
$autoload_function = function($classname){
$fileName = __DIR__ . "/" . "{$classname}.php";
if(file_exists($fileName)){
require_once "{$fileName}";
}
};

Or, you can use the built-in functions like this:

spl_autoload_register($autoload_function);

However, this does not solve the problem where we need to use lots of classes, maybe hundreds or thousands of classes that are interconnected; think about a big application. The effectiveness of a big application depends on many factors and one of them is the relationship between the file structure and the auto-loading classes. This relationship should be congenial. The namespace will help us solve the problem, but if we try to adopt the traditional methods, it will unnecessarily make things tedious.

It is because Namespace has a folder-like structure, but you cannot use relative paths. Here the relationship is a key factor. We need to map Namespace in a way so that it matches the folder structures. PSR-4 autoloader solves this problem. Most Composer packages use it these days so we will solve our problem by using PSR-4 autoloader. That will be more effective for our MVC patterns framework we are planning to do at the end.
We will discuss this concept in great detail in the next chapter which is dedicated to the Composer revolution in the PHP world. At present, we will show the limitations of “autoload” and we will also show how effective is PSR-4 autoloader, especially when the application grows in volume.
Our framework has two main folders – “app”, and “public”. We also have an “index.php” file in the root directory, so that it could play the role of the entry point.
In our “composer.json” file we should mention the autoload mapper in this way:

{

"autoload": {

"classmap":[

"app/models"

]

}
}

We have directed the auto-loader to load any class from the “app/models” directory. We need another file in the “models” folder; this “init.php” file will start the initialization process of auto-loading any class anywhere in the application. The code of “init.php” is quite obvious.

<?php
require_once __DIR__ . '/../vendor/autoload.php';

Now we will require this “init.php” file on any page where we need to autoload classes from the “models” folder.
First, we have a “Post.php” file in the “models” folder and the code is:

<?php

class Post
{
public function hello() {

return 'Hello';

}
}

Let us first update our Composer packages and issue this command on the termional:

composer dump-autoload -o

Next, in our entrance point, “index.php” file we can call the “Post” object like this:

hello());

//output

ss@ss-H81M-S1:/var/www/html/hagudu$ php index.php
string(5) "Hello"

Now,, we can add another class “User” the same way, as we have done in “models” folder and by issuing the “composer dump-autoload -o” command, we can call the user object. This approach works perfectly fine for a small application where we don’t have to deal with too many classes. However, as the class dependency increases and the folder structures grow in volume, it will become tedious. You have to add them manually to the “composer.json” file, like this:


{
"autoload": {
"classmap":[
"app/models",
"app/controllers/home"
]
}
}

We have to explicitly declare folders and sub-folders and it grows in volume. The effectiveness of our patterns fails.
PSR-4 autoloader solves this problem completely. Consider this “composer.json” file:

{
"autoload": {

"psr-4": {
"App\\": "app/controllers"
}

}
}

Here, the Namespace “App” points to the folder “app/controllers”; it means, you can add as many sub-folders as possible inside that well-designed folders and the folder-like Namespace will automatically point to them.
Let us create three sub-folders inside “app/controllers” – “home”, “post” and “user”. Their respective code are like this:

// Home.php
<?php namespace App\home;

class Home
{

public function __construct() {

return "I am home.";

}

public function index() {

return "I will return view in future.";

}
}
//User.php
<?php namespace App\user;

class User
{
public function __construct() {

return "I am user controller.";

}
}
//Post.php
<?php namespace App\post;
use App\home\Home as Home;
class Post extends Home
{

public function post() {

return "I am post.";

}
}

And the code of “index.php” file.

index());

The output is quite expected this time since I have inherited “Home” class in my “Post” class.

//output
ss@ss-H81M-S1:/var/www/html/mutudu$ composer dump-autoload -o
Generating optimized autoload files
ss@ss-H81M-S1:/var/www/html/mutudu$ php index.php
string(29) "I will return view in future."

We need not touch the “composer.json” file anymore. We could add as many folders, sub-folders and files inside “app/controllers”.

Advertisements