DEV Community

Cover image for Part 05 - Composer
Johirul Islam
Johirul Islam

Posted on

Part 05 - Composer

Source Code Files of this Chapter

project-root/
├── app/
│   ├── Controllers/
│   │   └── HomeController.php      # new file
│   └── Core/
│       └── Bootstrap.php           # modified file
├── public/
│    └── index.php                  # modified file
│
├── vendor/                         # new directory
│
├── composer.json                   # new file
├── composer.lock                   # new file
└── .gitignore                      # new file
Enter fullscreen mode Exit fullscreen mode

Using Composer

This project is using core php that means no php package will be used. So someone may be surprised that why we are configuring composer?

The answer in a single word is autoload. Autoload will load required PHP classes based on their namespace and directory structure without using the require() or include() statement.

Configure Composer

Go to the project root directory and run following command:

composer init

Above command will create a composer.json file in the project root directory.

Edit composer.json file:

{
    "name": "leafvein/own-framework-php-core-oop",
    "description": "Create Own Framework Using PHP Core OOP",
    "type": "project",
    "require": {
        "php": ">=8.0"
    },
    "autoload": {
        "psr-4": {
            "App\\": "app/"
        }
    },
    "minimum-stability": "dev",
    "license": "MIT"
}
Enter fullscreen mode Exit fullscreen mode

Code Explain:

name : a required attribute that is used as a unique identifier of the application within the composer ecosystem. composer.

description: a short description of the package.

require: another required attribute used to specify your project's dependencies. Current now our project dependency is php 8.

autoload: configure the method to load PHP classes and files of a project automatically. Here PSR-4 is used to map namespace App to app directory.

Install Dependency and Generate Autoload File

From your project-root directory run this command:

composer install
Enter fullscreen mode Exit fullscreen mode

After running composer install command composer will read project dependencies from the composer.json file then create vendor directory and composer.lock file to the project root directory.

vendor: directory stores dependencies and autoload.php file.

composer.lock: file locks version of all dependencies to make an option so that all team members can use the same versions of dependencies.

Integrate the autoload.php File into the Application

We are integrating vendor/autoload.php file through the Bootstrap. So, open the app/Core/Bootstrap.php file and add this line:

require __DIR__ . '/../../vendor/autoload.php';
Enter fullscreen mode Exit fullscreen mode

See full code: app/Core/Bootstrap.php
<?php
declare(strict_types = 1);

require __DIR__ . '/../../vendor/autoload.php';

// load environment
$config = [
    'app_name'=> 'PHP core OOP project'
];

// route define
$route = ltrim($_SERVER['REQUEST_URI'], '/');

echo($route);

if ($route == "get-error") {
    // trigger a fatal error
    trigger_error("An Intentional Error Occurred.", E_USER_ERROR);
}

if ($route == 'get-exception') {
    // throw an exception
    throw new Exception("An Intentional Exception Occurred.");
}

echo 'Welcome to the ' . $config['app_name'];

Enter fullscreen mode Exit fullscreen mode

Load a Controller Class Using Composer Autoload

Create a new app/Controllers/HomeController.php file and add following code:

<?php

namespace App\Controllers;

class HomeController
{
    private $appName;

    public function __construct($appName) {
        $this->appName = $appName;
    }

    public function getGreeting()
    {
        return 'Welcome to the ' . $this->appName;
    }
}

Enter fullscreen mode Exit fullscreen mode

Code Explain

A new Controller Class file is created, now it is require to update classmap of composer autoload. So, run following command:

composer dump-autoload

This command will update classmap of composer autoload to ensure all latest classes are available to use.

Now you will be able to call the controller's method from the bootstrap. Open the app/Core/Bootstrap.php file and add the following code:

use App\Controllers\HomeController;

$homeController = new HomeController($config['app_name']);
echo $homeController->getGreeting();
Enter fullscreen mode Exit fullscreen mode

Code Explain

use App\Controllers\HomeController;

Loading HomeController class using fully qualified class names (FQCNs)

$homeController = new HomeController($config['app_name']);
echo $homeController->getGreeting();

Instantiation of HomeController class and Displaying content of the getGreeting()

See full code: app/Core/Bootstrap.php
<?php
declare(strict_types = 1);

require __DIR__ . '/../../vendor/autoload.php';

use App\Controllers\HomeController;

// load environment
$config = [
    'app_name'=> 'PHP core OOP project'
];

// route define
$route = ltrim($_SERVER['REQUEST_URI'], '/');

if ($route == "get-error") {
    // trigger a fatal error
    trigger_error("An Intentional Error Occurred.", E_USER_ERROR);
}

if ($route == 'get-exception') {
    // throw an exception
    throw new Exception("An Intentional Exception Occurred.");
}

$homeController = new HomeController($config['app_name']);
echo $homeController->getGreeting();
Enter fullscreen mode Exit fullscreen mode

Unified Error and Exception Handler

On chapter 03 we've used set_error_handler() and set_exception_handler() to handle error and exception respectively. In this chapter we will use try-catch statement to simplify the Error and Exception Handling.
Open the public/index.php file and modify as below:

- // error handler
- set_error_handler(function ($errno, $errstr, $errfile, $errline) {
-    echo 'Message: ' . $errno   . ' - ' . $errstr . '<br>';
-    echo 'File: '    . $errfile . '<br>';
-    echo 'Line: '    . $errline . '<br>';
- });
-
- // exception handler
- set_exception_handler(function (Exception $e) {
-     echo 'Message: ' . $e->getMessage() . '<br>';
-     echo 'File: '    . $e->getFile()    . '<br>';
-     echo 'Line: '    . $e->getLine()    . '<br>';
-});
-
+ try {
    require __DIR__ . '/../app/Core/Bootstrap.php';
+ } catch (Throwable $e) {
+    echo 'Message: ' . $e->getMessage() . '<br>';
+    echo 'File: '    . $e->getFile()    . '<br>';
+    echo 'Line: '    . $e->getLine()    . '<br>';
+}
Enter fullscreen mode Exit fullscreen mode

Code Explain

Instead of handling Error and Exception separately we are using unified handler Throwable. In PHP 7 and later, a single try-catch block can catch both traditional exceptions and critical internal PHP errors.

See full code: public/index.php
<?php
declare(strict_types = 1);

try {
    require __DIR__ . '/../app/Core/Bootstrap.php';
} catch (Throwable $e) {
    echo 'Message: ' . $e->getMessage() . '<br>';
    echo 'File: '    . $e->getFile()    . '<br>';
    echo 'Line: '    . $e->getLine()    . '<br>';
}
Enter fullscreen mode Exit fullscreen mode

Result

Make sure server is running or go to the project-root directory and run command php -S localhost:8000 -t public/ on the terminal.

  • Browse http://localhost:8000 -> Returns a welcome greeting message output-result-1
  • Browse: http://localhost:8000/get-error -> It will return a 500 Internal Server Error. output-result-2 However, if you check the terminal, you will see more information about what caused the error. output-result-3
    In PHP, errors and exceptions are different concepts, and there are several ways to throw, catch, and handle exceptions and errors.
    In the next part, Part 06 — Error and Exception, we’ll discuss errors and exceptions in PHP in more detail.
  • Browse: http://localhost:8000/get-exception -> Returns exception information output-result-4

    Git : Add .gitignore File and Push Changes to Remote

    If testing result is satisfactory then it is time to push changes to the remote repository.

Run Command:

> git status
Enter fullscreen mode Exit fullscreen mode

As expected you will see the vendor directory in untracked stage but it is not recommended to push the vendor directory to the remote repository. In Git terminology, this is called 'ignore or not track'. Git uses .gitignore file to ignore directory and files.

Create .gitignore file on project-root directory with following content:

/vendor
Enter fullscreen mode Exit fullscreen mode

Add the files that are newly created in this chapter.

> git add HomeController.php composer.json composer.lock .gitignore
Enter fullscreen mode Exit fullscreen mode

git add <file_path> command add specific file content to the staging area for the next commit. We are adding HomeController.php, composer.json, .gitignore, and composer.lock files to the staging area for next commit.

⚠️ composer.lock! 🤔. Yes, commit your composer.lock file to git repository.

⚠️ .gitignore! 🤔 🤔. Yes, yes, Commit the .gitignore file to ensure everyone using the repository ignores the same files.

Add the files that are modified in this chapter.

> git add -p Bootstrap.php
> git add -p index.php
Enter fullscreen mode Exit fullscreen mode

💡 git add -p <file_path> command provides an review option that steps through each hunk (section of changes) in the specified filename and asks you whether you want to stage that specific hunk or not. To add specific section of changes just type y otherwise n. It will prevent you to add any unintentional testing code and it your code will clean.

Commit your changes and push to the remote repository.

> git commit -m "Configured composer"
> git push origin <branch_name>
Enter fullscreen mode Exit fullscreen mode

Learn More

⬇SOURCE CODE: Chapter 05

Top comments (0)