PHPackages                             level-2/axel - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Caching](/categories/caching)
4. /
5. level-2/axel

ActiveLibrary[Caching](/categories/caching)

level-2/axel
============

An autoloader with inbuilt caching

0.8(7y ago)163595[3 issues](https://github.com/Level-2/Axel/issues)BSD-2-ClausePHPPHP &gt;=5.4.0

Since Feb 19Pushed 6y ago4 watchersCompare

[ Source](https://github.com/Level-2/Axel)[ Packagist](https://packagist.org/packages/level-2/axel)[ Docs](https://github.com/Level-2/Transphporm)[ RSS](/packages/level-2-axel/feed)WikiDiscussions master Synced 1mo ago

READMEChangelog (2)DependenciesVersions (3)Used By (0)

Axel
====

[](#axel)

A modular, extensible, fast, ultra-lightweight PHP autoloader with inbuilt caching

Design Philosophy
-----------------

[](#design-philosophy)

Axel is fast but flexible. Axel caches paths by automatically building an internal classmap (effectively just a map of file name =&gt; class name so the require statement becomes require `$classMap[$className]`). This class map can be cached between requests meaning most requests never have to go off looking for files.

Axel can be extended with modules that can locate classes that are not currently in the classmap. Once the module provides the location of the file for a given class, the path is cached and the module is never loaded again. Unless new classes are added to the project, Axel loads a single class which does an array key lookup to read the path.

This approach considerably faster and more flexible than composer as custom modules can be written and it doesn't matter how fast they are. Even if locating a file based on a class name is slow, it only happens once when the class is added. After that, Axel stores the result. This approach allows for things like case insensitive PSR-4 style loaders.

Usage
-----

[](#usage)

To use Axel, firstly include axel.php into your project and create an instance of \\Axel\\Axel.php:

```
require_once 'axel/axel.php';
$axel = new \Axel\Axel;
```

On its own, Axel does not do anything other than register an autoloader. Once it's been initialised you can tell it where to find your files by adding modules to it.

Note: The `Axel` instance is immutable and adding modules can be done via the `addModule` method:

```
$axel = $axel->addModule($moduleName);
```

Once you have fully configured the autoloader you need to register it:

```
require_once 'axel/axel.php';
$axel = new \Axel\Axel;
$axel = $axel->addModule($moduleName);
$axel->register();
```

Module: PSR4
------------

[](#module-psr4)

The PSR4 module allows you to map a namespace to a directory for example, if you have a project in `./lib/mylibrary/` you can map the namespace `MyLibrary` to the directory using:

```
$axel = $axel->addModule(new \Axel\Module\PSR4('./lib/MyLibrary', '\\MyLibrary'));
```

Then, when the autoloader is triggered with

```
new \MyLibrary\Foo();
```

Axel will now try to load the file `./lib/MyLibrary/Foo.php`

PSR4 can also be applied more generally so you don't have to create an instance of it for each library you're using. If all your libraries are in `./lib` you can map the root namespace to the dir and have everything work:

```
$axel =  $axel->addModule(new \Axel\Module\PSR4('./lib/'));
```

This will add `./lib` as the root directory:

```
new \MyLibrary\Foo();
new \MyOtherLibrary\Bar\Baz();
```

Will load the files `./lib/MyLibrary/Foo.php` and `./lib/MyOtherLibrary/Bar/Baz.php`

### Case-sensitivity

[](#case-sensitivity)

Because it's [generally a bad idea to make autoloaders case-sensitive](https://r.je/php-autoloaders-should-not-be-case-sensitive.html), Axel works in a case-insensitive way where possible.

```
$axel = $axel->addModule(new \Axel\Module\PSR4('./lib/'));

new \MyLibrary\Foo();
```

Will look for the class in the file `./lib/MyLibrary/Foo.php` however, if that file does not exist, it wil see if there's a lowercase version of the file `./lib/mylibrary/foo.php` and load that.

This is a best-of-both-worlds approach as it supports libraries using the widespread well intentioned but misguided PSR-4 standard that enforces case-sensitivity as well as libraries that use lowercase filenames.

Unlike composer, this allows you to register a PSR4 autoloader for any part of your project without having to write an additional autoloader:

```
$axel = $axel->addModule(new \Axel\Module\PSR4('./Conf', '\\Conf'));
$axel = $axel->addModule(new \Axel\Module\PSR4('./Models', '\\Models'));
$axel = $axel->addModule(new \Axel\Module\PSR4('./Controllers', '\\OnlineShop\\Controllers'));
```

Module: Composer
----------------

[](#module-composer)

Axel contains a module that allows reading `composer.json` to allow easy access to modules installed via composer.

A drop-in replacement for composer's autoloader. It's faster and allows you to use Axel (Note: Currently only supports PSR-4, not classmap!) to load libraries installed via composer without using composer's autoload.php giving you a single autoloader for everything in the project.

Just load the module and tell Axel the path to the directory containing your `composer.json`. This will recursively load all vendor `composer.json` files and register them with the autoloader.

```
$axel =  $axel->addModule(\Axel\Module\Composer($axel, './project'));
```

Writing a custom module
-----------------------

[](#writing-a-custom-module)

You can write your own autoload module by implementing the generic \\Autoload\\Module interface which looks like this:

```
namespace Axel;
interface Module {
	public function locate($className);
}
```

Any class which implements this must provide the implementation for the `locate` method. The `locate` method is called by the autoloader and provides the class name to find. It should return the path of the file if it's part of the library or false if not. In its simplest terms a module could look like this:

```
namespace MyLibrary;
class MyAutoloader implements \Axel\Module {
	public function locate($className) {
		if ($className == 'MyClass') return __DIR__ . DIRECTORY_SEPARATOR . 'MyClass.php';
		else if ($className == 'OtherClass') return __DIR__ . DIRECTORY_SEPARATOR . 'OtherClass.php';
		else return false;
	}

}
```

Caching
-------

[](#caching)

Axel supports caching. When caching is enabled, `module::locate` is never called if the result has been retrieived previously. When using autoload.json, the file is only parsed if a file from the library has not been autoloaded before.

To enable caching, create a cache class that implements `\ArrayAccess`. Alternatively and for an example, see [SimpleCache](https://github.com/TomBZombie/SimpleCache/blob/master/SimpleCache.php).

To use a cache with axel, intiate the cache class:

```
require_once 'SimpleCache.php';
$simpleCache = new \SimpleCache\SimpleCache('./tmp');
```

Then pass the cache instance as Axel's constuctor argument:

```
$axel = new \Axel\Axel($simpleCache);
```

Axel will now cache any paths behind the scenes. Any time a class is loaded its path is cached so it does not need to be located next time the script runs.

You can pass any instance that uses `\ArrayAccess` for your cache, behind the scenes this could use memcached, a database or any other caching format such as JSON or XML.

###  Health Score

27

—

LowBetter than 49% of packages

Maintenance16

Infrequent updates — may be unmaintained

Popularity22

Limited adoption so far

Community15

Small or concentrated contributor base

Maturity46

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 84.1% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~0 days

Total

2

Last Release

2645d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/caa6bf0e9aa1359e0d477690cfdad5388d1cde567520c797797f48cc27f34fc2?d=identicon)[TomButler](/maintainers/TomButler)

---

Top Contributors

[![TRPB](https://avatars.githubusercontent.com/u/2454540?v=4)](https://github.com/TRPB "TRPB (37 commits)")[![solleer](https://avatars.githubusercontent.com/u/16144751?v=4)](https://github.com/solleer "solleer (5 commits)")[![ghedipunk](https://avatars.githubusercontent.com/u/249662?v=4)](https://github.com/ghedipunk "ghedipunk (2 commits)")

---

Tags

autoloader

### Embed Badge

![Health badge](/badges/level-2-axel/health.svg)

```
[![Health](https://phpackages.com/badges/level-2-axel/health.svg)](https://phpackages.com/packages/level-2-axel)
```

###  Alternatives

[react/cache

Async, Promise-based cache interface for ReactPHP

444112.4M40](/packages/react-cache)[wp-media/wp-rocket

Performance optimization plugin for WordPress

7431.3M3](/packages/wp-media-wp-rocket)[illuminate/cache

The Illuminate Cache package.

12835.6M1.4k](/packages/illuminate-cache)[colinmollenhour/php-redis-session-abstract

A Redis-based session handler with optimistic locking

6325.6M14](/packages/colinmollenhour-php-redis-session-abstract)[cheprasov/php-redis-client

Php client for Redis. It is a fast, fully-functional and user-friendly client for Redis, optimized for performance. RedisClient supports the latest versions of Redis starting from 2.6 to 6.0

1281.2M21](/packages/cheprasov-php-redis-client)[amphp/redis

Efficient asynchronous communication with Redis servers, enabling scalable and responsive data storage and retrieval.

165634.7k44](/packages/amphp-redis)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
