CodeBlanks Logo Icon CodeBlanks

Summary - Composer

PHP course · Advanced · Lesson 40/92

Set up a project with managed dependencies using composer.json, require and autoload.

Summary - Composer

In this group you learned what Composer is, the structure of the config file, adding packages with require, PSR-4 autoload, installing packages from Packagist, and the install/update difference. Now you will combine them to build a small project with managed dependencies: define the config and use a class through the autoload.

A project skeleton with managed dependencies

In a Composer project, you first write the config file; required packages go into require, namespace mappings go into autoload psr-4. composer install installs packages and produces vendor/autoload.php.

At the top of the code, require_once vendor/autoload.php is called; afterwards every class imported with use loads automatically.

Exercise Config + autoload + class usage

Define namespace App;; inside it add an Application class. Add a public string $name property and a public function __construct() that assigns $this->name = "shop". public function name(): string should return $this->name.

Then define $config = ["name" => "app/shop", "autoload" => ["psr-4" => ["App\\" => "src/"]]]. Create an instance with $app = new \App\Application() and print the $app->name value. Finally print the autoload psr-4 mapping in the form App\ => src/.

Show example solution
string { return $this->name; } }. Write $config = ["name" => "app/shop", "autoload" => ["psr-4" => ["App\\" => "src/"]]];. Print the property with $app = new \App\Application(); echo $app->name . "\n";. Print the mapping with foreach ($config["autoload"]["psr-4"] as $ns => $path) { echo $ns . " => " . $path . "\n"; }.
Example solution:
<?php
namespace App;
class Application {
    public string $name;
    public function __construct() {
        $this->name = "shop";
    }
    public function name(): string {
        return $this->name;
    }
}
$config = ["name" => "app/shop", "autoload" => ["psr-4" => ["App\\" => "src/"]]];
$app = new \App\Application();
echo $app->name . "\n";
foreach ($config["autoload"]["psr-4"] as $ns => $path) {
    echo $ns . " => " . $path . "\n";
}

Exercise PSR-4 classmap builder

Mimic the classmap that composer dump-autoload produces. Write a buildClassmap(array $classes, array $map): array function: for each class in $classes, iterate $map; check strpos against 0, strip the matching prefix with substr, turn the remaining \ into / with str_replace, prepend base and append .php; store the result as $classmap[$class].

Define $map = ["App\\" => "src/"] and $classes = ["App\\Models\\User", "App\\Services\\Auth"]. Build the classmap and print each line as App\Models\User => src/Models/User.php.

Show example solution
array { $classmap = []; foreach ($classes as $class) { foreach ($map as $prefix => $base) { if (strpos($class, $prefix) === 0) { $relative = substr($class, strlen($prefix)); $relative = str_replace("\\", "/", $relative); $classmap[$class] = $base . $relative . ".php"; break; } } } return $classmap; }. Define $map = ["App\\" => "src/"]; $classes = ["App\\Models\\User", "App\\Services\\Auth"];. Print with $classmap = buildClassmap($classes, $map); foreach ($classmap as $class => $file) { echo $class . " => " . $file . "\n"; }.
Example solution:
<?php
function buildClassmap(array $classes, array $map): array {
    $classmap = [];
    foreach ($classes as $class) {
        foreach ($map as $prefix => $base) {
            if (strpos($class, $prefix) === 0) {
                $relative = substr($class, strlen($prefix));
                $relative = str_replace("\\", "/", $relative);
                $classmap[$class] = $base . $relative . ".php";
                break;
            }
        }
    }
    return $classmap;
}
$map = ["App\\" => "src/"];
$classes = ["App\\Models\\User", "App\\Services\\Auth"];
$classmap = buildClassmap($classes, $map);
foreach ($classmap as $class => $file) {
    echo $class . " => " . $file . "\n";
}

Test yourself

  1. What does the config file define?

    • Only the package name
    • Dependencies and autoload
    • Database connection password
    • Browser HTTP headers
    Show answer

    Dependencies and autoload — Correct. The config file carries require and autoload.

All lessons in Advanced