PHPackages                             cubadevops/flexi - 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. [PSR &amp; Standards](/categories/psr-standards)
4. /
5. cubadevops/flexi

ActiveProject[PSR &amp; Standards](/categories/psr-standards)

cubadevops/flexi
================

The flexible framework that respects standards

3.1.0(1y ago)56[2 issues](https://github.com/Flexi-PHP/flexi-core/issues)MITPHPPHP &gt;=7.4CI passing

Since Jun 2Pushed 5mo agoCompare

[ Source](https://github.com/Flexi-PHP/flexi-core)[ Packagist](https://packagist.org/packages/cubadevops/flexi)[ Fund](https://www.paypal.com/donate/?hosted_button_id=WE67ZM6EV7U6S)[ RSS](/packages/cubadevops-flexi/feed)WikiDiscussions develop Synced 1mo ago

READMEChangelog (10)Dependencies (8)Versions (13)Used By (0)

Flexi Framework
===============

[](#flexi-framework)

Flexi is a modular PHP framework designed to facilitate the development of scalable and maintainable applications. It leverages Dependency Injection (DI), a flexible routing system, CQRS and an event-driven architecture.

Table of Contents
-----------------

[](#table-of-contents)

- [Features](#features)
- [Structure](#structure)
- [Installation](#installation)
- [Configuration](#configuration)
    - [Services](#services)
    - [Routes](#routes)
    - [Events and Listeners](#events-and-listeners)
    - [Queries](#queries)
    - [Commands](#commands)
- [Usage](#usage)
    - [Router](#router)
    - [Event System](#event-system)
    - [CQRS](#cqrs)
- [Contributing](#contributing)
- [License](#license)

Features
--------

[](#features)

- **Modularity &amp; Extensibility**: Flexi offers a modular architecture that promotes code organization and reusability. Its extensibility allows developers to customize and extend functionality according to specific project requirements. Each module is a self-contained Composer package with its own dependencies, allowing for easy installation, uninstallation, and version management.
- **Automatic Module Discovery**: Modules are automatically discovered and registered. Simply create a module in the `modules/` directory with a `composer.json` file, run `composer modules:sync`, and it's ready to use.
- **Dependency Injection**: Built-in support for Dependency Injection simplifies management and injection of dependencies, enhancing code maintainability and testability. DI in Flexi is implemented using a container that manages service with lazy loading instantiation.
- **Flexible Routing**: With a flexible routing system, developers can easily define and manage HTTP request handling, streamlining development of complex routing logic enriched with middleware support.
- **Event-Driven Architecture**: Flexi's event-driven architecture enables asynchronous handling of events by event listeners, fostering loose coupling and flexibility in application design.
- **CQRS &amp; Scalability**: Support for Command Query Responsibility Segregation (CQRS) promotes scalability and performance optimization. Combined with features like asynchronous processing, Flexi facilitates the development of scalable applications capable of handling high traffic and data loads.
- **Configuration via JSON**: Configuration in Flexi is managed through JSON files, making it easy to define services, routes, events, queries, and commands. This approach simplifies configuration management and promotes consistency across projects. Json Schema will be implemented to validate the configuration files.

Structure
---------

[](#structure)

- **Core**: the `src/` directory contains the core classes and interfaces that make up the framework.
- **Contracts**: the `contracts/` directory contains shared interfaces and base classes used by both core and modules, ensuring loose coupling and standardization.
- **Modules**: the `modules/` directory contains all pieces of code that are not part of the core framework. Each module is a self-contained Composer package with its own `composer.json`, dependencies, controllers, services, and configuration files. Modules are plug-and-play and can be easily installed, uninstalled, or versioned independently.
- **Config**: the `src/Config/` and `modules/*/Config` directories contain configuration files for the framework (`routes`, `commands`, `queries`, `event listeners` and `services`).
- **Console**: the `bin/` directory contains the console application for CLI commands.

Installation
------------

[](#installation)

You can install Flexi Framework using Composer:

```
composer create-project cubadevops/flexi my-app
```

This command creates a minimal ready boilerplate application in the `my-app` directory.

**Steps after install**

To get started with Flexi Framework, ensure you:

- Configure your web server to point to the `public` directory in the root of the project.
- Deny direct access to any directory that is not the `public` directory.
- Serve static files directly and route all other requests to the `index.php` file in the `public` directory.
- Set up the `.env` file with the necessary environment variables for your application.

After setup, browse to the URL of your application to see the welcome page. If you use the default configuration with Docker, you can access the application at .

Module Management
-----------------

[](#module-management)

Flexi features an automatic module discovery system that makes managing modules simple and efficient.

### Available Commands

[](#available-commands)

```
# Sync all modules (auto-discover and register)
composer modules:sync

# List all available modules
composer modules:list

# Get detailed information about a module
php bin/console modules:info Auth

# Validate module configuration
composer modules:validate

# Install a module
php bin/console modules:install ModuleName

# Uninstall a module
php bin/console modules:uninstall ModuleName
```

### Creating a New Module

[](#creating-a-new-module)

```
# 1. Create module structure
mkdir -p modules/MyModule/{Domain,Infrastructure,Config}

# 2. Create composer.json
cat > modules/MyModule/composer.json createResponse();
        $response->getBody()->write('Authorized');

        return $response;
    }
}
```

#### Controller with Dependencies and Business Logic

[](#controller-with-dependencies-and-business-logic)

```
namespace Flexi\Infrastructure\Controllers;

use Flexi\Infrastructure\Bus\QueryBus;
use Flexi\Application\Queries\GetVersionQuery;
use Flexi\Infrastructure\Classes\HttpHandler;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;

class HealthController extends HttpHandler
{
    private QueryBus $query_bus;

    public function __construct(QueryBus $query_bus)
    {
        $this->query_bus = $query_bus;
        parent::__construct(); // Always call parent constructor
    }

    protected function process(ServerRequestInterface $request): ResponseInterface
    {
        // Execute business logic using CQRS pattern
        $version = $this->query_bus->execute(new GetVersionQuery());

        $response = $this->createResponse();
        $response->getBody()->write('Version: ' . $version);

        return $response;
    }
}
```

#### Controller with Template Rendering

[](#controller-with-template-rendering)

```
namespace Flexi\Infrastructure\Controllers;

use Flexi\Domain\Interfaces\TemplateEngineInterface;
use Flexi\Infrastructure\Classes\HttpHandler;
use Flexi\Contracts\Classes\Traits\FileHandlerTrait;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;

class NotFoundController extends HttpHandler
{
    use FileHandlerTrait;

    private TemplateEngineInterface $html_render;

    public function __construct(TemplateEngineInterface $html_render)
    {
        $this->html_render = $html_render;
        parent::__construct();
    }

    protected function process(ServerRequestInterface $request): ResponseInterface
    {
        $body = $this->html_render->render(
            $this->normalize('./src/Infrastructure/Ui/Templates/404.html'),
            ['request' => $request->getUri()->getPath()]
        );

        $response = $this->createResponse(404, 'Not Found');
        $response->getBody()->write($body);

        return $response;
    }
}
```

#### Key Points

[](#key-points)

- **No manual middleware handling**: The `handle()` method is `final` and manages the middleware chain automatically
- **Focus on business logic**: Controllers only implement the `process()` method with their specific logic
- **Dependency injection**: Use constructor injection to receive dependencies from the DI container
- **Template Method pattern**: The framework ensures middlewares are executed before your controller logic
- **PSR-7 compliance**: All controllers work with PSR-7 request/response objects
- **Error handling**: Return appropriate HTTP status codes using `createResponse($code, $reasonPhrase)`

### Middlewares

[](#middlewares)

Middlewares are classes that can be executed before the controller. They can modify the request, response or stop the execution chain. Middlewares should implement the `Psr\Http\Server\MiddlewareInterface` interface.

#### Middleware Implementation Example

[](#middleware-implementation-example)

```
namespace Flexi\Infrastructure\Middlewares;

use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Server\MiddlewareInterface;
use Psr\Http\Server\RequestHandlerInterface;

class AuthCheckMiddleware implements MiddlewareInterface
{
    public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
    {
        // Perform authentication logic here and stop the execution chain if necessary
        // or pass the request
        return $handler->handle($request);
    }
}
```

Testing
-------

[](#testing)

Flexi includes a comprehensive test suite using PHPUnit. Tests use a separate environment configuration to ensure isolation from development and production environments.

### Running Tests

[](#running-tests)

```
# Run all tests
./vendor/bin/phpunit tests/

# Run specific test file
./vendor/bin/phpunit tests/Infrastructure/TestEnvironmentTest.php

# Run with coverage
./vendor/bin/phpunit tests/ --coverage-html coverage/
```

### Test Environment

[](#test-environment)

Tests automatically use `.env.testing` configuration file with test-specific settings:

- **Synchronous event dispatch**: Events are dispatched synchronously for predictable testing
- **In-memory cache**: Faster tests without disk I/O
- **Separate logs**: Test logs go to `var/logs/test.log`
- **Isolated cache**: Test cache uses `var/cache/test/` directory

To customize test environment:

1. Copy `.env.testing.example` to `.env.testing`
2. Modify values as needed
3. Tests will automatically use these values

For more details, see [tests/README.md](tests/README.md).

### Writing Tests

[](#writing-tests)

```
