Search by

Сore functionality of the Mini4Work framework.

Package info

gitlab.com/mini4work/core

Issues

pkg:composer/mini4work/core

Statistics

Installs: 27

Dependents: 1

Suggesters: 0

Stars: 0

2.0.0 2026-11-10 17:38 UTC

README

PHP Test suits

Mini4Work Logo

This repository contains the core functionality of the Mini4Work framework. It is designed to be a lightweight and flexible framework foundation, providing essential features such as dependency injection and a modular architecture.

Developers should use this package as a dependency in their projects. Typically, it is automatically included when installing the mini4work/project package.

Application instances

Create an application explicitly and pass dependencies through constructors:

$app = new \M4W\Core\Framework();
$kernel = $app->make(MyKernel::class);
$app->run($kernel);

AbstractKernel receives the Framework in its constructor. Each container resolves Framework::class, the concrete application class, Container::class and 'app' to itself. Creating a container or loading providers never selects a global application.

For optional global helpers and facades, explicitly select a container:

\M4W\Core\Framework::setInstance($app);
app(); // $app
\M4W\Core\Facades\App::make('app'); // $app
\M4W\Core\Framework::resetInstance();

getInstance(), app() and facades throw when no global container is selected. Facades follow the same selected container as app(); the compatibility method Facade::setFacadeApplication() selects or clears that same global container. Singleton services are shared only within their own container.

Kernel lifecycle

Every kernel must extend M4W\Core\Abstract\AbstractKernel. Framework::run() accepts this base class, not arbitrary implementations of the Kernel interface. The constructor and run() are final; constructing a kernel only injects the application and does not load providers.

class MyKernel extends \M4W\Core\Abstract\AbstractKernel
{
    public function serviceProviders(): array
    {
        return [MyServiceProvider::class];
    }

    protected function bootstrap(): void
    {
        // Load runtime-specific configuration before registering providers.
    }

    protected function execute(): void
    {
        // Handle a request, execute a command, or enter a game loop.
    }

    protected function shutdown(): void
    {
        // Release kernel resources, including after partial startup.
    }
}

The enforced order is bootstrap() → all providers' register() → all providers' boot() → execute(). A kernel instance can run only once, including failed runs. Providers must extend AbstractServiceProvider; register() is required, while boot() and shutdown() default to no-ops. Duplicate provider classes are rejected. The default console bindings are included unless the kernel sets protected bool $disableDefaultFacades = true.

On completion or failure, the kernel's shutdown() runs first, followed by provider shutdown() calls in reverse registration order. Even a partially registered provider is included. Cleanup must tolerate partial initialization; constructors should not acquire resources. Every cleanup hook is attempted even when another throws. The original startup/execution exception takes precedence over cleanup exceptions; otherwise the first cleanup exception is propagated.

Kernels own their startup and execution; the framework only delegates to run(). Avoid starting different kernels on the same application unless their providers explicitly support re-registration. Use separate containers for isolated runtimes.

Error handling

Framework registers Interfaces\ExceptionHandler as an early singleton dependency. The default Exception\Handler uses ConsoleService directly and needs neither facades nor a selected global application. It exposes an instance handle(Throwable) method instead of the previous static cause() method.

Kernels may override registerExceptionHandler(), which runs before bootstrap():

protected function registerExceptionHandler(): void
{
    $this->app->singleton(
        \M4W\Core\Interfaces\ExceptionHandler::class,
        MyExceptionHandler::class,
    );
}

Custom handlers must implement ExceptionHandler::handle(Throwable): void. They can combine logging, rendering or delegate to other handlers. The kernel reports startup, execution and cleanup failures, while still propagating the original exception. Handler failures never replace it. No process-global PHP exception handler is installed; each application's handling remains local. Errors before run() can be reported explicitly through $app->make(ExceptionHandler::class)->handle($exception).

Dependency injection

bind() creates a fresh instance on each make(); singleton() keeps the first result. Factories run lazily and receive the container and the make() parameters.

Scalar types and arrays can be bound by type. The reserved names string, int, float, bool and array do not allow singleton registration, including through bind(..., shared: true). Factories for these types run on every make():

$app->bind('string', 'localhost');
$app->bind('int', 8080);
$app->bind('float', 0.5);
$app->bind('bool', false);
$app->bind('array', ['debug' => true]);

$service = $app->make(Service::class, ['port' => 9000]);

Type bindings apply globally to all constructor parameters of that type. Resolution prefers an explicit named make() parameter, then a type binding, then a constructor default, then autowiring a class. Required primitive parameters without bindings fail with an exception identifying the parameter. Primitive bindings must return the exact declared type; values are not coerced. Strings and arrays bound to primitive types are literal values, even when callable; use a closure or invokable object for factories.

Untyped, union and intersection parameters require an explicit value or a constructor default. Circular dependencies raise an exception showing the resolution path.

Contributing

Mini4Work is designed to remain simple and lightweight. If you have any improvements or features to suggest for the core framework, feel free to submit a Pull Request.

License

Mini4Work is distributed by The MIT license.