arnapou/explicit

Library - PHP Micro-framework.

v1.0.0 2025-09-11 21:08 UTC

This package is auto-updated.

Last update: 2025-09-12 12:17:34 UTC


README

pipeline coverage

This library is a micro-framework to build your own application.

Installation

composer require arnapou/explicit

packagist 👉️ arnapou/explicit

Introduction

Explicit another PHP framework.

Main goals :

  • KISS (= no magic attributes, ...)
  • very strictly typed
  • very few dependencies
  • readability: the config = your code
  • favor fundamental knowledge (PSRs, common patterns, ...)

You know how it works by just reading the code.

Explicit framework is mainly for projects with a reasonable size which should be the vast majority of projects. A lot of projects do not really need smart caching, dependency injection container dumps for performance, smart regex compilation of routes, ...

If you want to remove the performance overhead of the services initialization, just use a worker mode (see FrankenPHP). It should be enough for the majority of projects.

The price of Explicit is less flexibility: you must use types, you must be careful at the services state (pure stateless). You pay the price by building precisely your project, like a craftsman.

Configuration

Implement your own Configurator.

namespace MyVendor\MyProject;

use Arnapou\Explicit\Configurator;
use Psr\Log\LoggerInterface;

class MyAppConfigurator implements Configurator
{
    /**
     * This is executed only once.
     */
    public function initialize(ExplicitContainer $container): void
    {
        $container->register(LogggerInterface::class, fn() => /** Your Factory */);
    }

    /**
     * This is executed for each handle.
     */
    public function configure(ExplicitContainer $container): void 
    {
        // A healthy project should have this method empty.
        // Mainly used to clear or reset contexts.
    }
}

Or you can extend the basic DefaultConfigurator.

namespace MyVendor\MyProject;

use Arnapou\Explicit\Configurator;
use Arnapou\Explicit\Default\DefaultConfigurator;
use Arnapou\Explicit\Default\DefaultLogConfig;

class MyAppConfigurator extends DefaultConfigurator
{
    public function getLogConfig() : DefaultLogConfig
    {
        return new DefaultLogConfig(filename: '/var/log/my-project.log');
    }
}

Execution

Instantiate a ExplicitHttp PSR-15 RequestHandlerInterface to handle the request, then send the response.

use Arnapou\Explicit\ExplicitHttp;
use MyVendor\MyProject\MyAppConfigurator;

// The main PSR-15 RequestHandlerInterface 
$handler = new ExplicitHttp(new MyAppConfigurator());

// Handle the server request: no argument = automatically created from globals
$response = $handler->handle();

// The response is a custom ResponseInterface you can send directly 
$response->send();

If you want to use a worker mode like into FrankenPHP, you can:

use Arnapou\Explicit\ExplicitHttp;
use Arnapou\Psr\Psr15HttpHandlers\FrankenPhpWrapper;
use MyVendor\MyProject\MyAppConfigurator;

// The main PSR-15 RequestHandlerInterface 
$handler = new ExplicitHttp(new MyAppConfigurator());

// Create the run closure ran at each "loop"
$loop = static fn() => $app->handle()->send();

// Worker mode if FrankenPHP is detected, else single execution
new FrankenPhpWrapper($loop)->run();

Main powerful features

Dependency Injection Container (PSR-11)

You don't have to declare all your service, because the container autofill itself with auto-created classes on-demand. This is 100% based on code constructor signatures, via reflection.

Consequently, you must be strict and careful when declaring injected services. Do not inject stateful object if there state is request-dependant !

This relies on arnapou/psr-container package.

Event Dispatcher (PSR-14)

The built-in event dispatcher is based on arnapou/psr-event package.

On one side you have any listener (callable) with one object Event argument. On the other side you just dispatch the Event with the dispatcher.

That's all: the executed listeners are based on types of the callable signature.

Data Converter

Based on arnapou/dto package.

This basically converts objects from arrays and vice versa.

A few use cases:

  • http query/request data to DTO
  • database query row to Entity
  • JSON payload to object

Thus, you can get rid of mutable arrays everywhere in favor of immutables objects (DTO, value objects, ...). Note that arrays are heavier than objects in PHP memory.

Php versions

DateRef8.4
10/09/20251.0.x, main×