You don’t necessarily need Composer
Tags: php, composer
Published: 2021-05-16 14:42:23

---
title: You don’t necessarily need Composer
published: true
date: 2021-05-15 22:49:39 UTC
tags: PHP,Composer
canonical_url: https://phpnexus.io/t/you-dont-necessarily-need-composer/83
---

Don't get me wrong, [Composer](https://getcomposer.org/) is an amazing product. It has an easy-to-use API for quick autoloading, supports multiple standards, and has autoloading optimization built-in - it even lets you search and require packages easily. It's a reason Composer is the most used package manager for PHP.

If your project is a lightweight OOP project with no external packages though. Using Composer might be a bit overkill, you could easily implement autoloading using a simple `array` and PHP's `spl_autoload_register` function.

For those not familiar, `spl_autoload_register` is what we can use to add to our own autoloading function to PHPs autoloading queue. We can use that together with a simple `array $classmap` to autoload our small project. Here's our project structure.

- /public/index.php
- /src/**/*.php
- autoload.php

`/public` will be our front-facing entry point, `/src` will hold our classes, and `autoload.php` will handle our autoloading. Our classes will be formatted in PSR-4, with our vendor namespace prefix being used as the key for our internal `$classmap`.

Let's create our `autoload.php` file and add some autoloading to our project.

```php
define('PHPNEXUS_VERSION', '0.0.1');

$classmap = [
    'PHPNexus' => __DIR__ . '/src/',
];

spl_autoload_register(function(string $classname) use ($classmap) {
    $parts = explode('\\', $classname);

    $namespace = array_shift($parts);
    $classfile = array_pop($parts) . '.php';

    if (! array_key_exists($namespace, $classmap)) {
        return;
    }

    $path = implode(DIRECTORY_SEPARATOR, $parts);
    $file = $classmap[$namespace] . $path . DIRECTORY_SEPARATOR . $classfile;

    if (! file_exists($file) && ! class_exists($classname)) {
        return;
    }

    require_once $file;
});
```

Going over our code shows we first define a new **constant** - `PHPNEXUS_VERSION`, this will be used to check if our autoload file has already been loaded later. `$classmap` is an associative array - as previously mentioned our vendor namespace is our key. The value of which is the location to our source files, in this case, that is `/src`. And since `autoloading.php` is in our root, we can take advantage of the `__DIR__` constant.

The first argument of `spl_autoload_register` is the callback function - that's our autoloading function. That function will take a string parameter - when you instantiate a class with `new`, the FQCN gets passed as that parameter's argument.

Next, we are destructuring our `$classname` argument by separating each value into an `array $parts` variable. Since we know our first `$parts` value is our vendor namespace, we use `array_shift` to grab it and use `array_pop` to grab the actual filename since we also know that's the last part of our `$classname`.

We then do a quick check to see if the `$namespace` is in our `$classmap` so we can handle the file location, if that's not the case we simply do an early return out of the function. 

`$path` will be the variable holding the remaining parts of our `$parts` array, since the filename and namespace are already removed, we can assume the rest of the pieces are the rest of our file path.

We then reassemble our file path info into a temporary `$file` variable and check if that file exists. As a precaution, we also include a check to see if the class has already been defined. If either fails - as before, we return out of the function and be on our merry way.

Lastly, if nothing fails all we do is require the `$file` that contains our class so PHP can now initialize it.

To then use our simple autoloading file, in our `public/index.php` we simply add the following if statement.

```php
if (! defined('PHPNEXUS_VERSION')) {
    require_once dirname(__DIR__) . '/autoload.php';
}
```

This does a check for the earlier constant to see if the file has already been included or required earlier, if that fails we require our `autoload.php` file and now we can use our classes, e.g. if we had a `PHPNexus\Request\Request` class located in `/src/Request/Request`.

```php
if (! defined('PHPNEXUS_VERSION')) {
    require_once dirname(__DIR__) . '/autoload.php';
}

use PHPNexus\Request\Request;

$request = new Request($_SERVER);
```

And that's how we can create simple autoloading for our project without having to rely on Composer. As mentioned above though, if your project already requires packages from other sources via Composer, then it's best to stick with Composers autoloader instead.

To leave off, have you ever written your own function to handle autoloading before? Perhaps you didn't know how to do it and you know do, let me know by replying to the topic. Would love to hear your thought on implementing simple autoloading for projects.