From 956900b08a5c06528ad437fbab9898c8bb64ece3 Mon Sep 17 00:00:00 2001 From: Koldo Picaza <1093654+kpicaza@users.noreply.github.com> Date: Mon, 3 Jul 2023 22:45:18 +0200 Subject: [PATCH] Update docs to v2 --- docs/README.md | 82 +- docs/framework/_sidebar.md | 2 - docs/framework/console-line-tool.md | 52 -- docs/framework/dependency-injection.md | 322 +------ docs/framework/event-system.md | 51 -- docs/framework/getting-started.md | 811 +++++++++++++++++- docs/framework/logger.md | 131 --- .../modules-and-third-party-libraries.md | 38 +- docs/framework/queues.md | 30 +- docs/framework/routing.md | 120 --- docs/framework/running-application.md | 246 +++--- docs/framework/templating.md | 109 --- 12 files changed, 1018 insertions(+), 976 deletions(-) delete mode 100644 docs/framework/logger.md delete mode 100644 docs/framework/routing.md diff --git a/docs/README.md b/docs/README.md index b586151..7c44e85 100644 --- a/docs/README.md +++ b/docs/README.md @@ -1,39 +1,69 @@ # Antidot Framework -A PHP full featured micro-framework designed to allow you to write 100% framework agnostic code. - ## Key Features -* **Preconfigured Coding Style**: [Psr-1](https://www.php-fig.org/psr/psr-1) and [Psr-2](https://www.php-fig.org/psr/psr-2) code sniffer to help to respect standard -* **Logger**: [Psr-3](https://www.php-fig.org/psr/psr-3) implementation by [wshafer/monolog](https://github.com/wshafer/psr11-monolog) -* **Auto-loading**: [Psr-4](https://www.php-fig.org/psr/psr-4) Namespaces auto-loading -* **Request Response Lifecycle**: [Psr-7](https://www.php-fig.org/psr/psr-7) Request and responses using [Laminas Diactoros](https://docs.laminas.dev/laminas-diactoros/) -* **Auto-wired Dependency injection**: [Psr-11](https://www.php-fig.org/psr/psr-11) Auto-wired dependency injection container -* **Event Dispatcher**: [Psr-14](https://www.php-fig.org/psr/psr-14) Event dispatching system -* **Request pipeline**: [Psr-15](https://www.php-fig.org/psr/psr-15) Request handler and Middleware -* **Pipeline based router**: Intuitive to use route system -* **Different Config Translators**: [Laminas config](https://docs.laminas.dev/laminas-config/) style or [Symfony](https://symfony.com/doc/current/best_practices/configuration.html) style -* **Cli**: Ready to use Console Line Tool on top of [Symfony Console Tool](https://symfony.com/doc/current/components/console.html) +The Antidot PHP Framework offers a range of powerful features that make it a versatile choice for +building web applications. Some of the key features include: +### Dependency Injection Container -## Quick Start +Antidot utilizes the Antidot Container, which is a powerful dependency injection container. +It provides a way to manage and configure dependencies within your application, promoting +modularity and testability. With the container, you can easily define and resolve dependencies +across your application. + +### Middleware Stack + +Antidot supports a flexible middleware stack, allowing you to define and execute middleware +components in a specific order. Middleware provides a convenient way to intercept and modify +HTTP requests and responses, enabling functionalities such as authentication, logging, error +handling, and more. Antidot makes it easy to integrate and chain multiple middleware components +to process requests and generate responses. + +### Routing and Controllers + +Antidot provides a robust routing system based on the popular nikic/fast-route package. With +Antidot's fluent interface, you can define routes and bind them to controllers or request +handlers. This allows you to map incoming HTTP requests to specific actions in your application. +Controllers or request handlers implement the `Psr\Http\Server\RequestHandlerInterface`, +enabling you to handle requests and return responses in a standardized way. + +### Error Handling -```bash -composer create-project antidot-fw/antidot-framework-starter project-name -cd project-name -bin/console -php -S 127.0.0.1:8000 ./public -``` +Antidot offers comprehensive error handling capabilities. You can configure error handlers to +catch and process exceptions thrown during the execution of your application. This allows you +to handle errors gracefully and provide appropriate responses to clients. Antidot supports +custom error handlers, allowing you to define how different types of errors are handled based +on your application's requirements. -Or you can try ReactPHP version +### Testing -```bash -composer create-project antidot-fw/reactive-starter project-name -cd project-name -bin/console -php public/index.php # Creates server on 127.0.0.1:8000 -``` +Antidot emphasizes the importance of testing by providing built-in testing tools and utilities. +You can write unit tests for your application's components, including middleware, controllers, +and services. Antidot integrates well with popular testing frameworks like PHPUnit, allowing +you to easily set up and execute tests to verify the correctness of your code. + +### ReactPHP Server with Synchronous API + +One of the standout features of Antidot is its integration with ReactPHP, a powerful event-driven, +non-blocking I/O library for PHP. Antidot leverages ReactPHP to provide a high-performance, +asynchronous web server. Additionally, Antidot extends ReactPHP to support a synchronous API, +allowing developers to write code in a synchronous style without dealing with promises. +This feature provides a familiar programming experience while taking advantage of ReactPHP's +performance benefits. + +### And More... + +Antidot PHP Framework also offers a range of other features, including environment-specific +configuration, PSR-7 integration, PSR-15 middleware compatibility, extensibility through service +providers, and a vibrant community that actively contributes to the framework's development +and improvement. + +--- + +## Quick Start +> Se the [Getting Started Guide](/framework/getting-started) ## Special thanks & Sponsors diff --git a/docs/framework/_sidebar.md b/docs/framework/_sidebar.md index 94e09ab..6b2947f 100644 --- a/docs/framework/_sidebar.md +++ b/docs/framework/_sidebar.md @@ -2,11 +2,9 @@ * **Docs** * [Getting Started](/framework/getting-started.md "Getting started guide for Antidot Framework") * [Running Application](/framework/running-application.md "Running guide for Antidot Framework") - * [Routing](/framework/routing.md) * [Templating](/framework/templating.md) * [Persistence Layer](/framework/persitence.md) * [Dependency Injection](/framework/dependency-injection.md) - * [Logger](/framework/logger.md) * [Event System](/framework/event-system.md) * [Queues](/framework/queues.md) * [Console Line Tool](/framework/console-line-tool.md) diff --git a/docs/framework/console-line-tool.md b/docs/framework/console-line-tool.md index 518ee39..b560401 100644 --- a/docs/framework/console-line-tool.md +++ b/docs/framework/console-line-tool.md @@ -144,56 +144,6 @@ final class SomeCommand extends Command ## Config - - -### ** Symfony style yaml ** - -````yaml -# config/autoload/dependencies.{prod,local,dev}.yaml -services: - App\Application\EventListener\SomeCommand: - tags: - - { name: 'console.command', command: 'some:command:name' } -```` - -### ** Zend style yaml ** - -````yaml -# config/autoload/dependencies.{prod,local,dev}.yaml -console: - commands: - 'some:command:name': App\Application\EventListener\SomeCommand -dependencies: - invokables: - App\Application\EventListener\SomeCommand: App\Application\EventListener\SomeCommand - -```` - -### ** Symfony style php ** - -````php - [ - App\Application\EventListener\SomeCommand::class => [ - 'class' => App\Application\EventListener\SomeCommand::class, - 'tags' => [ - [ - 'name' => 'console.command', - 'command' => App\Application\EventListener\SomeCommand::NAME - ] - ] - ] - ] -]; -```` - -### ** Zend style php ** - ````php diff --git a/docs/framework/dependency-injection.md b/docs/framework/dependency-injection.md index 4bee4de..2d186a9 100644 --- a/docs/framework/dependency-injection.md +++ b/docs/framework/dependency-injection.md @@ -6,29 +6,6 @@ Auto wired dependency injection system, the only thing you have to do is declare ## Auto-wired Invokables - - -### ** Symfony style yaml ** - -````yaml -# config/autoload/dependencies.{prod,local,dev}.yaml -services: - Full\Qualified\ClassName: - -```` - -### ** Zend style yaml ** - -````yaml -# config/autoload/dependencies.{prod,local,dev}.yaml -dependencies: - invokables: - - Full\Qualified\ClassName: Full\Qualified\ClassName - -```` - -### ** Symfony style php ** - ````php [ - Full\Qualified\ClassName::class => [ - 'class' => Full\Qualified\ClassName::class - ], + Full\Qualified\ClassName::class => Full\Qualified\ClassName::class, ] ]; -```` +```` Full\Qualified\ClassName::class => Full\Qualified\ClassName::class, -### ** Zend style php ** - -````php - [ - 'invokables' => [ - Full\Qualified\ClassName::class => Full\Qualified\ClassName::class, - ] - ] -]; -```` - - ## Factory Classes - - -### ** Symfony style yaml ** - -````yaml -# config/autoload/dependencies.{prod,local,dev}.yaml -services: - Full\Qualified\ClassName: - factory: [Full\Qualified\ClassNameFactory, '__invoke'] - -```` - -### ** Zend style yaml ** - -````yaml -# config/autoload/dependencies.{prod,local,dev}.yaml -dependencies: - factories: - - Full\Qualified\ClassName: Full\Qualified\ClassNameFactory - -```` - -### ** Symfony style php ** - ````php [ - Full\Qualified\ClassName::class => [ - 'factory' => [Full\Qualified\ClassNameFactory::class, '__invoke'] - ], + 'factories' => [ + Full\Qualified\ClassName::class => Full\Qualified\ClassNameFactory::class, ] ]; ```` -### ** Zend style php ** - -````php - [ - 'factories' => [ - Full\Qualified\ClassName::class => Full\Qualified\ClassNameFactory::class, - ] - ] -]; -```` - - - -## Complex classes with arguments - - - -### ** Symfony style yaml ** - -````yaml -# config/autoload/dependencies.{prod,local,dev}.yaml -services: - Full\Qualified\ClassName: - arguments: - $foo: '@SomeService' - $bar: '%config.some_parameter%' - -```` - -### ** Zend style yaml ** - -````yaml -# config/autoload/dependencies.{prod,local,dev}.yaml -dependencies: - conditionals: - Full\Qualified\ClassName: - class: Full\Qualified\ClassName - arguments: - foo: SomeService - bar: 'Some.String' - -```` - -### ** Symfony style php ** +## Classes with arguments ````php [ Full\Qualified\ClassName::class => [ + 'class' => Full\Qualified\ClassName::class, 'arguments' => [ '$foo' => Full\Qualified\ClassNameFactory::class, '$bar' => 'some.string', - ] - ], - ] -]; -```` - -### ** Zend style php ** - -````php - [ - 'conditionals' => [ - Full\Qualified\ClassName::class => [ - 'class' => Full\Qualified\ClassName::class, - 'arguments' => [ - '$foo' => Full\Qualified\ClassNameFactory::class, - '$bar' => 'some.string', - ] ], ] ] ]; ```` - - ## Implementing Interfaces - - -### ** Symfony style yaml ** - -````yaml -# config/autoload/dependencies.{prod,local,dev}.yaml -services: - Full\Qualified\ClassNameInterface: - class: Full\Qualified\ClassName - # Or using aliases - Full\Qualified\AnotherClassNameInterface: - alias: 'service.name' -```` - -### ** Zend style yaml ** - -````yaml -# config/autoload/dependencies.{prod,local,dev}.yaml -dependencies: - invokables: - Full\Qualified\ClassNameInterface: Full\Qualified\ClassName - # Or using aliases - aliases: - Full\Qualified\AnotherClassNameInterface: 'service.name' -```` - -### ** Symfony style php ** - ````php [ - Full\Qualified\ClassNameInterface::class => [ - 'class' => Full\Qualified\ClassName::class - ], - // or using alias - Full\Qualified\ClassNameInterface::class => [ - 'alias' => 'service.name' - ], - ] -]; -```` - -### ** Zend style php ** - -````php - [ - 'invokables' => [ - Full\Qualified\ClassNameInterface::class => Full\Qualified\ClassName::class - ], - // or using alias - 'aliases' => [ - Full\Qualified\ClassNameInterface::class => 'service.name' - ], - ] + Full\Qualified\ClassNameInterface::class => Full\Qualified\ClassName::class + ], + // or using alias + 'aliases' => [ + Full\Qualified\ClassNameInterface::class => 'service.name' + ], ]; ```` - - ## Declaring services - - -#### ** Symfony style yaml ** - -````yaml -# config/autoload/dependencies.{prod,local,dev}.yaml -services: - service.name: - class: Full\Qualified\ClassName - -```` - -### ** Zend style yaml ** - -````yaml -# config/autoload/dependencies.{prod,local,dev}.yaml -dependencies: - services: - service.name: Full\Qualified\ClassName - -```` - -### ** Symfony style php ** - ````php [ - 'some.service' => [ - 'class' => Full\Qualified\ClassName::class - ], - ] -]; -```` - -### ** Zend style php ** - -````php - [ - 'services' => [ - 'some.service' => Full\Qualified\ClassName::class, - ] + 'some.service' => Full\Qualified\ClassName::class, ] ]; ```` - - ## Parameter Config The configuration system uses Zend Config Aggregator strategy, this allows us to create complex configs and dependencies depending on the environment, by default it loads first PHP config files and then it parses YAML files merging all in a unique array of data who is available inside the container keyed by `config` @@ -341,60 +101,6 @@ The configuration system uses Zend Config Aggregator strategy, this allows us to $config = $container->get('config'); ```` - - - -#### ** Symfony style yaml ** - -````yaml -# config/autoload/dependencies.{prod,local,dev}.yaml -parameters: - some.key: Some value - other.key: - array: of values - array1: - item1: value - item2: value - -```` - -#### ** Zend style yaml ** - -````yaml -# config/autoload/dependencies.{prod,local,dev}.yaml -some.key: Some value -other.key: - array: of values - array1: - item1: value - item2: value - -```` - -#### ** Symfony style php ** - -````php - [ - 'some.key' => 'Some value', - 'other.key' => [ - 'array' => 'of values', - 'array1' => [ - 'item1' => 'value', - 'item2' => 'value', - ] - ] - ] -]; -```` - -#### ** Zend style php ** - ````php diff --git a/docs/framework/event-system.md b/docs/framework/event-system.md index 641cd78..6907611 100644 --- a/docs/framework/event-system.md +++ b/docs/framework/event-system.md @@ -8,55 +8,6 @@ The event dispatcher is available as `Psr\EventDispatcher\EventDispatcherInterfa ## Config - - -### ** Symfony style yaml ** - -````yaml -# config/autoload/dependencies.{prod,local,dev}.yaml -services: - App\Application\EventListener\SomeEventListener: - tags: - - { name: 'event_listener', event: 'Full\Name\SomeEventClass' } -```` - -### ** Zend style yaml ** - -````yaml -# config/autoload/dependencies.{prod,local,dev}.yaml -app-events: - event-listeners: - # Full\Name\To\SomeEvent or some.event.identifier - some-event: - - 'App\Application\EventListener\SomeEventListener' - - 'App\Application\EventListener\SomeOtherEventListener' -```` - -### ** Symfony style php ** - -````php - [ - 'app-events' => [ - 'event-listeners' => [ - // Full\Name\To\SomeEvent::class or some.event.identifier - 'some-event' => [ - App\Application\EventListener\SomeEventListener::class, - App\Application\EventListener\SomeOtherEventListener::class, - ] - ] - ] - ] -]; -```` - -### ** Zend style php ** - ````php - ## Usage For example the usage of Event Dispatcher inner Request Handler diff --git a/docs/framework/getting-started.md b/docs/framework/getting-started.md index 3ab7b5f..2f78156 100644 --- a/docs/framework/getting-started.md +++ b/docs/framework/getting-started.md @@ -2,45 +2,772 @@ ## Installation -### Standard Version - -> https://github.com/antidot-framework/antidot-starter - -Using [composer](https://getcomposer.org/doc/00-intro.md#installation-linux-unix-macos) package manager - -````bash -composer create-project antidot-fw/antidot-framework-starter project-name -```` - -### ReactPHP Version - -> https://github.com/antidot-framework/antidot-starter - -````bash -composer create-project antidot-fw/reactive-starter project-name -```` - -## File Structure - -```` -bin/console -config/config.php -config/config-cli.php -config/container.php -config/container-cli.php -config/autoload/dependencies.prod.yaml -public/index.php -router/middleware.php -router/routes.php -src/ -test/ -var/cache/*.php -var/log/*.log -.gitignore -composer.json -grumphp.yml -phpcs.xml.dist -phpunit.xml.dist -README.md - -```` +To start using the Antidot PHP Framework, you'll need to install it in your project. +The recommended method is to use Composer, the popular dependency manager for PHP. +Make sure you have Composer installed before proceeding with the following steps. + +### Step 1: Create a New Project + +First, open your terminal or command prompt and navigate to the directory where you want +to create your new Antidot project. Then, run the following command: + +```shell +composer create-project antidot-fw/antidot-framework-starter myproject +``` + +This command will create a new directory named `myproject` and install the Antidot PHP Framework skeleton application inside it. + +### Step 2: Configuration + +After the project is created, navigate to the `myproject` directory: + +```shell +cd myproject +``` + +Next, you'll need to configure your application. Copy the example configuration file: + +```shell +bin/console config:development-mode +``` + +This command creates a local configuration file where you can customize the settings specific to your environment. + +### Step 3: Serve the Application + +To run the Antidot PHP Framework application, you can use PHP's built-in web server. In the terminal, run the following command from the project's root directory: + +```shell +XDEBUG_MODE=off bin/console serve # runs Async server with XDebug disabled for better performance +php -S 127.0.0.1:3000 -t public # runs Sync server nice for testing +``` + +This command starts the development server and serves your application on `http://localhost:3000`. + +### Step 4: Verify Installation + +Open your web browser and visit `http://localhost:3000`. If everything is set up correctly, you should see a "Welcome to Antidot!" message. + +Congratulations! You have successfully installed the Antidot PHP Framework. + +Certainly! Here's an example of a "Project Setup" section for the Antidot PHP Framework "Getting Started" guide: + +--- + +## Project Setup + +When working with the Antidot PHP Framework, it's important to set up your project properly to follow the +recommended conventions and ensure a well-organized codebase. Here are the steps to set up your Antidot +project: + +### Project Structure + +The Antidot PHP Framework follows a convention-based project structure that promotes modularity and +separation of concerns. Here's an example of a typical project structure: + +``` +myproject/ +├── config/ +│ ├── services/ +│ │ ├── dependencies.dev.php.dist +│ │ └── dependencies.prod.php +│ ├── cli-config.php +│ ├── cli-container.php +│ ├── config.php +│ └── container.php +├── src/ +│ ├── Command/ +| | └── SomeCommandExample.php +│ ├── Event/ +| | └── SomeEvent.php +│ ├── EventListener/ +| | └── SomeEventListener.php +│ └── Handler/ +│ ├── HomePage.php +| └── SomeMiddleware.php +├── public/ +│ └── index.php +├── router/ +│ ├── middleware.php +│ └── routes.php +├── tests/ +├── var/ +│ └── cache/ +├── vendor/ +└── composer.json +``` + +- The `config` directory contains various configuration files for your application, such as +environment-specific settings, application bootstrap, middleware pipeline, and route definitions. + +- The `src` directory is where you'll place your application's source code. It typically contains +different directories for handling requests, defining middleware, configuring dependencies, and more. + +- The `public` directory is the web server's document root. It contains the entry point of your +application, such as `index.php`, and any publicly accessible assets. + +- The `router` directory is where you store your application's routes and middlewares. + +- The `tests` directory contains unit tests and functional tests for your application. It's a good +practice to write tests to ensure the stability and correctness of your code. + +### Configuration Files + +The `config` directory contains several important configuration files: + +- `config/services/dependencies.dev.php`: This file holds local environment-specific configuration settings. +You can modify this file based on your development environment. + +- `config/services/dependencies.prod.php`: This file holds production environment-specific configuration +settings. You can modify this file based on your development environment. + +- `config/[cli-]config.php`: This file is responsible for bootstrapping your application and +configuring various Config Providers and project config. + +- `config/[cli-]container.php`: This file is responsible for bootstrapping your application container. + +- `router/middleware.php`: This file defines the middleware pipeline for your application. Middleware +components are executed in a specific order, allowing you to handle request and response processing. + +- `router/routes.php`: This file contains the route definitions for your application. You can define +routes and map them to controller actions. + +### Additional Setup + +Depending on your project requirements, you may need to perform additional setup steps, such as +configuring a database connection, setting up caching, or integrating other external libraries. +The specific steps for these configurations may vary based on your needs. + +--- + +## Hello World Example + +Let's get started with a simple "Hello World" example to demonstrate the basic usage of the Antidot +PHP Framework. + +### Step 1: Create a Route + +In the `router/routes.php` file, let's define a route that maps the root URL (`/`) to a controller +action. Open the file and add the following code: + +```php +use Antidot\Framework\Application; +use Psr\Container\ContainerInterface; +use Psr\Http\Message\ResponseInterface; +use Psr\Http\Message\ServerRequestInterface; + +return static function (Application $app, ContainerInterface $container) : void { + $app->get('/', [\App\Handler\HomePage::class], 'home'); +}; +``` + +This code sets up a route that matches the root URL (`/`) and returns a simple HTML response with the +text "Hello, World!". + +### Step 2: Create a Controller + +Next, let's create the controller that will handle the request and generate the response. In the +`src/Handler/HomeHandler.php` file, add the following code: + +```php +namespace App\Handler; + +use Psr\Http\Message\ResponseInterface; +use Psr\Http\Message\ServerRequestInterface; +use Psr\Http\Server\RequestHandlerInterface; +use Nyholm\Psr7\Response; + +class HomePage implements RequestHandlerInterface +{ + public function handle(ServerRequestInterface $request): ResponseInterface + { + return new Response(200, ['Content-Type' => 'text/plain'], 'Hello, World!'); + } +} +``` + +### Step 3: Register the Controller + +In the `config/application.php` file, we need to register the controller as a service. Open the file +and modify the code as follows: + +```php +use App\Handler\HomePage; + +return [ + // ... + + 'services' => [ + HomePage::class => HomePage::class, + ], + + // ... +]; +``` + +This code registers the `HomePage` controller as a service that can be resolved and used in our routes. + +### Step 4: Serve the Application + +To see the "Hello World" example in action, start the development server from the project's root directory: + +```shell +php -S localhost:8000 -t public +``` + +Open your web browser and visit `http://localhost:8000`. You should see the "Hello, World!" message +displayed on the page. + +Congratulations! You've successfully created a simple "Hello World" example using the Antidot PHP +Framework. + +--- + +## Configuration + +The Antidot PHP Framework provides a flexible configuration system that allows you to customize various +aspects of your application. Configuration files are typically located in the `config` directory. Let's +explore the main configuration files used in an Antidot project: + +### `config/container.php` + +The `config/container.php` file is responsible for configuring your application's dependency injection +container. This file sets up the container and defines the services and dependencies your application +needs. You can use the container to define factories, invokables, or other service definitions. + +### `config/config.php` + +The `config/config.php` file is responsible for configuring your application's overall configuration. It +sets up the config providers and config files in a single configuration array. + +### `router/middleware.php` + +The `router/middleware.php` file defines the middleware pipeline for your application. It specifies +the order in which middleware components are executed for each incoming request. You can customize +the pipeline by adding or removing middleware components to fulfill your application's requirements. + +### Environment-Specific Configuration + +Antidot supports environment-specific configuration files that allow you to customize settings based +on the environment in which your application is running. By default, the framework includes the following +environment-specific files: + +- `config/services/[SOME_FILE_NAME].prod.php`: This file holds global configuration settings. You can use this +file to define global settings that should be used in production. + +- `config/services/[SOME_FILE_NAME].dev.php`: This file contains environment-specific configuration settings +for the development environment. You can adjust this file to customize the behavior of your application +during development. + +To use environment-specific configuration files, you can remove the `.dist` suffix from the file names. +For example, rename `config/services/dependencies.dev.php.dist` to `config/services/dependencies.dev.php`. +Antidot will automatically load the corresponding configuration files, overriding the global configuration. + +### Accessing Configuration Settings + +You can access configuration settings throughout your application using the `config` service provided by the dependency injection container. Here's an example of how you can access a configuration setting in a controller: + +```php +// Factory +use Psr\Container\ContainerInterface; + +class MyControllerFactory +{ + private $config; + + public function __incoke(ContainerInterface $container): MyController + { + return new MyController($container->get('config')['debug']); + } +} + +// Controller or Any other Service +use Psr\Http\Message\ResponseInterface; +use Psr\Http\Message\ServerRequestInterface; +use Nyholm\Psr7\Response; + +class MyController { + public function __construct( + private readonly bool $debug + ) { + } + + public function myAction(ServerRequestInterface $request): ResponseInterface + { + // Access a configuration setting + $mySetting = $this->debug; + + // ... + } +} +``` + +In the above example, the controller receives the `$config` array in its constructor, allowing you to +access any configuration setting you need. + +### Additional Configuration + +Depending on your application's requirements, you may need to configure additional components, such as +databases, logging, caching, or external services. The specific configuration steps for these components +may vary based on the libraries or services you are integrating into your Antidot project. Consult the +relevant documentation for those components to ensure proper configuration. + +--- + +Apologies for the confusion. Here's an updated version of the "Dependency Injection" section for the Antidot PHP Framework based on the old Antidot framework documentation: + +--- + +## Dependency Injection + +The Antidot PHP Framework leverages the powerful [PSR-11](https://www.php-fig.org/psr/psr-11/) container +interface to provide a robust dependency injection mechanism. The framework uses its own container +implementation called Antidot Container. + +### Container Configuration + +The container configuration is defined in the `config/container.php` file. This file sets up the container +and defines the services and dependencies your application needs. You can use the container to define +factories, invokables, or other service definitions. + +For example, in the `config/container.php` file, you can find code similar to the following: + +```php +someService = $someService; + } + + public function myAction(ServerRequestInterface $request): ResponseInterface + { + // Use the injected service + $result = $this->someService->doSomething(); + + // ... + } +} +``` + +In the above example, the `MyController` constructor accepts a `SomeServiceInterface` dependency. +The container will automatically resolve the `SomeService` implementation and inject it into the controller +when it is instantiated. + +Let's add the service definition in `config/services/dependencies.prod.php` file: + +```php + [ + MyController::class => MyController::class, + SomeServiceInterface::class => SomeServiceInterface::class, + ] +]; +``` + +### Customizing the Container + +You can customize the container configuration by modifying the `config/config.php` file. This allows +you to define additional services, configure aliases, or customize the container's behavior to fit your +application's needs. + +### Advanced Dependency Injection + +The Antidot PHP Framework also provides support for advanced dependency injection features, such as +autowiring, factories, and delegators. These features allow you to configure more complex dependencies +and handle specific use cases. You can refer to the Antidot framework documentation for more information +on using advanced dependency injection features. + +--- + +## Middleware + +Middleware plays a crucial role in the Antidot PHP Framework. It allows you to intercept and modify the +HTTP request and response objects as they pass through the application's middleware stack. You can use +middleware to perform tasks such as authentication, input validation, logging, and more. + +### Middleware Pipeline + +The Antidot PHP Framework uses a middleware pipeline to handle incoming HTTP requests. The pipeline +consists of a sequence of middleware layers that are executed in the order they are added to the pipeline. + +The pipeline configuration is defined in the `config/pipeline.php` file. This file specifies the middleware +layers and their order. Each middleware layer can perform specific tasks and modify the request and response +objects before passing them to the next layer. + +Here's an example of a `router/middleware.php` file: + +```php +pipe(ErrorMiddleware::class); + $app->pipe(ExceptionLoggerMiddleware::class); + $app->pipe(RequestLoggerMiddleware::class); + $app->pipe(RouteDispatcherMiddleware::class); + $app->pipe(RouteNotFoundMiddleware::class); +}; +``` + +In the above example, we see the pipeline configuration. The `$app->pipe()` method is used to add middleware +layers to the pipeline. In this example, we have added the following middleware layers: + +- `ErrorMiddleware`: This middleware handles error responses for exceptions thrown during request processing. +- `ExceptionLoggerMiddleware`: This middleware handles exceptions thrown during request processing and logs the +error using psr logger interface. +- `RequestLoggerMiddleware`: This middleware gets a log from requests info, its useful for development purposes. +- `RouteDispatcherMiddleware`: This middleware dispatches the matched route's handler. +- `RouteNotFoundMiddleware`: This middleware handles requests for routes that do not exist. + +You can add your own custom middleware to the pipeline by using the `$app->pipe()` method and specifying the +middleware class. + +### Creating Custom Middleware + +To create custom middleware, you need to create a PHP class that implements the +`Psr\Http\Server\MiddlewareInterface` interface. This interface defines a single method `process()` +that accepts a `Psr\Http\Message\ServerRequestInterface` object and a `Psr\Http\Server\RequestHandlerInterface` +object. + +Here's an example of a custom middleware class: + +```php +handle($request); + + // Perform custom processing on the response object + // ... + + return $response; + } +} +``` + +In the above example, the `CustomMiddleware` class implements the `process()` method, where you can perform custom processing on the request and response objects. You can also invoke the next middleware layer by calling the `handle()` method on the `$handler` object. + +### Adding Custom Middleware + +To add your custom middleware to the pipeline, you can use the `$app->pipe()` method in the +`router/middleware.php` file, as shown in the previous example. Simply specify the class name of your +middleware as the argument to the `$app->pipe()` method. + +```php +$app->pipe(CustomMiddleware::class); +``` + +Make sure to add your custom middleware in the desired order within the pipeline to ensure the +proper flow of request and response objects. + +--- + + +## Routing and Controllers + +The Antidot PHP Framework provides a powerful routing system that allows you to define routes and map them +to specific controllers. This makes it easy to handle different HTTP requests and route them to the +appropriate controller for processing. + +### Route Configuration + +The route configuration is defined in the `router/routes.php` file. This file contains a series of route +definitions using the `Application` class. + +Here's an example of a `router/routes.php` file: + +```php +get('/', [App\Handler\HomePageHandler::class], 'home'); + * $app->post('/album', [App\Handler\AlbumCreateHandler::class], 'album.create'); + * $app->put('/album/:id', [App\Handler\AlbumUpdateHandler::class], 'album.put'); + * $app->patch('/album/:id', [App\Handler\AlbumUpdateHandler::class], 'album.patch'); + * $app->delete('/album/:id', [App\Handler\AlbumDeleteHandler::class], 'album.delete'); + */ +return static function (Application $app, ContainerInterface $container) : void { + $app->get('/', [HomePage::class], 'home'); +}; +``` + +In the above example, we define a route for the root URL ("/") using the `get()` method of the +`Application` class. The `get()` method accepts the URL pattern, an array of controller classes, and a +route name. In this case, we specify the `HomePage` controller class as the handler for the route. + +### Creating Controllers + +To handle requests, you need to create controller classes that implement the `RequestHandlerInterface`. +This interface defines a `handle()` method that accepts a `ServerRequestInterface` and returns a +`ResponseInterface`. + +Here's an example of a controller class: + +```php +dependency->doSomething(); + + // Handle the request and generate a response + // ... + + // Return the response + } +} +``` + +In the above example, the `HomePage` controller class accepts a `Dependency` dependency through its +constructor. The Antidot container will automatically resolve the `Dependency` class and inject it into +the controller when it is instantiated. + +Let's add the service definition in `config/services/dependencies.prod.php` file: + +```php + [ + HomePage::class => HomePage::class, + Dependency::class => Dependency::class, + ] +]; +``` + +--- + +## Error Handling + +The Antidot PHP Framework provides a flexible and customizable error handling mechanism that allows you to +handle and respond to errors and exceptions in a consistent way. + +### Error Middleware + +The error handling is done using error middleware, which is responsible for catching exceptions and +generating appropriate error responses. Error middleware is added to the application pipeline, ensuring +that any exceptions thrown during the request handling process are properly handled. + +To add error middleware, you can modify your `router/middleware.php` file. Here's an example of adding error +middleware to the pipeline: + +```php +pipe(ErrorMiddleware::class); + + // Add more middleware to the pipeline + // ... +}; +``` + +In the above example, the `ErrorMiddleware` is added to the pipeline. This middleware catches exceptions +and generates appropriate error responses based on the exception type. + +It prints different error representation depending on you dependencies and debug mode. + +* With Debug mode On The error will be printed in json format. +* With Debug mode On, and `franzl/whoops-middleware` installed as dev dependency you will take whoops +handler for developer friendly error display. +* With Debug mode disabled, the errors will be hidden from user perspective. + +### Custom Error Handling + +You can customize the error handling by creating your own error middleware and adding it to the pipeline. +This allows you to define specific error handling logic based on your application's requirements. + +To create a custom error middleware, you need to implement the `Psr\Http\Server\MiddlewareInterface`. +Here's an example: + +```php +handle($request); + } catch (\Throwable $e) { + // Handle the exception and generate an error response + $response = new Response(); + // Set appropriate status code, headers, and body for the error response + $response->getBody()->write('An error occurred'); + + return $response->withStatus(500); + } + } +} +``` + +In the above example, the `CustomErrorMiddleware` implements the `MiddlewareInterface` and provides custom +error handling logic inside the `process()` method. When an exception is thrown during the request handling +process, the `process()` method catches the exception, generates an error response, and returns it. + +To add your custom error middleware to the pipeline, you can modify the `router/middleware.php` file: + +```php +pipe(CustomErrorMiddleware::class); + + // Add more middleware to the pipeline + // ... +}; +``` + +In the above example, the `CustomErrorMiddleware` is added to the pipeline, ensuring that it is executed +when an error occurs. + +### Error Views + +In addition to generating error responses, you may also want to customize the error views or templates +displayed to the user. The Antidot PHP Framework allows you to define error views based on the HTTP +status code or the exception type. + +To define an error view, you can use a templating engine or a view renderer of your choice. Create +the necessary views for different error scenarios, such as 404 (Not Found) or 500 (Internal Server Error), +and configure the framework to use them. + +The exact process for defining and configuring error views depends on the + +specific templating engine or view renderer you are using. Please refer to the documentation of your +chosen template engine or view renderer for more details. diff --git a/docs/framework/logger.md b/docs/framework/logger.md deleted file mode 100644 index dc8a95a..0000000 --- a/docs/framework/logger.md +++ /dev/null @@ -1,131 +0,0 @@ -# Logger - -> https://github.com/antidot-framework/antidot-logger - -[Psr 3 Logger](https://github.com/php-fig/logger) implementation by Monolog. - -The logger is available as `Psr\Log\LoggerInterface` you can inject in your services constructors out of the box. - -## Config - - - -### ** Symfony style yaml ** - -````yaml -# config/autoload/dependencies.{prod,local,dev}.yaml -parameters: - monolog: - handlers: - default: - type: 'stream' - options: - stream: 'var/log/%date%-default.log' - level: 400 -```` - -### ** Zend style yaml ** - -````yaml -# config/autoload/dependencies.{prod,local,dev}.yaml -monolog: - handlers: - default: - type: 'stream' - options: - stream: 'var/log/%date%-default.log' - level: 400 -```` - -### ** Symfony style php ** - -````php - [ - 'monolog' => [ - 'handlers' => [ - 'default' => [ - 'type' => 'stream', - 'options' => [ - 'stream' => 'var/log/%date%-default.log', - 'level' => Logger::DEBUG, - ] - ] - ] - ] - ] -]; -```` - -### ** Zend style php ** - -````php - [ - 'handlers' => [ - 'default' => [ - 'type' => 'stream', - 'options' => [ - 'stream' => 'var/log/%date%-default.log', - 'level' => Logger::DEBUG, - ] - ] - ] - ] -]; -```` - - - -See [wshafer/monolog]() for full options and handlers support. - -## Usage - -For example the usage of the Logger inner Request Handler - -````php -logger = $logger; - } - - public function handle(ServerRequestInterface $request): ResponseInterface - { - $this->logger->debug('Something happened to be logged.'); - - return new HtmlResponse('

Hello World!!!!

'); - } -} -```` diff --git a/docs/framework/modules-and-third-party-libraries.md b/docs/framework/modules-and-third-party-libraries.md index a2f3bd3..8cf8537 100644 --- a/docs/framework/modules-and-third-party-libraries.md +++ b/docs/framework/modules-and-third-party-libraries.md @@ -74,23 +74,23 @@ class DoctrineDBALFactory Register factory in the [Dependency Injection Container](/framework/dependency-injection.md) and add config parameter to it. -```yaml -# See dependency injection container config docs to more info about service -# configuration https://antidotfw.io/framework/dependency-injection.md. -parameters: - dbal: - connection: - dbname: db_name - user: db_user - password: db_secret - host: localhost - port: 3306 - driver: pdo_mysql - options: - # this enables PDO to throw exceptions - 3: 2 - -services: - Doctrine\DBAL\Connection: - factory: App\Container\DoctrineDBALFactory +```php + [ + 'connection' => [ + 'dbname' => 'db_name', + 'user' => 'db_user', + 'password' => 'db_secret', + 'host' => 'localhost', + 'port' => '3306', + 'driver' => 'pdo_mysql', + ] + ], + 'factories' => [ + \Doctrine\DBAL\Connection::class => \App\Container\DoctrineDBALFactory::class, + ], +]; ``` diff --git a/docs/framework/queues.md b/docs/framework/queues.md index 1376375..aca673c 100644 --- a/docs/framework/queues.md +++ b/docs/framework/queues.md @@ -88,18 +88,24 @@ class SomeMessageTypeAction } ``` -```yaml -services: - some_action_service: - class: App\SomeMessageTypeAction -parameters: - queues: - contexts: - default: - message_types: - # message_type: action_service - some_message_type: some_action_service - other_message_type: some_action_service +```php + [ + 'some_action_service' => \App\SomeMessageTypeAction::class, + ], + 'queues' => [ + 'contexts' => [ + 'default' => [ + 'message_types' => [ + 'some_message_type' => 'some_action_service', + 'other_message_type' => 'some_action_service', + ] + ] + ] + ] +]; ``` then start listening a queue: diff --git a/docs/framework/routing.md b/docs/framework/routing.md deleted file mode 100644 index 628b305..0000000 --- a/docs/framework/routing.md +++ /dev/null @@ -1,120 +0,0 @@ -# Routing - -The routing system gives two levels of pipelines, [Global Pipeline](/framework/#Global-Pipeline), and [Routed Pipeline](/framework/#Routed-Pipeline) - -## Global Pipeline - -Consist in a middleware collection that encapsulates complete lifecycle from the begin of the HTTP Request to the end of the HTTP Response - -This image from [Slim Framework](http://www.slimframework.com/docs/v3/concepts/middleware.html) documentation describes perfectly the Middleware pattern - -Middleware - -The config for the Global Pipeline is placed at `router/middleware.php` file. - -````php -pipe(ExceptionLoggerMiddleware::class); - $app->pipe(RequestLoggerMiddleware::class); - // Your Server Request Middleware could gone here. - // $app->pipe(MyCustomMiddlewareMiddleware::class); - $app->pipe(RouteDispatcherMiddleware::class); - $app->pipe(RouteNotFoundMiddleware::class); -}; -```` - -You can add PSR-15 middleware implementations made by the community or made by you. See a list off community [PSR-15 Middleware implementations](https://github.com/middlewares/psr15-middlewares) or make a search in [Packagist](https://packagist.org/?query=psr-15) - -````php -handle($request); - } -} -```` - -## Routed Pipeline - -The **Routed Pipeline** allows us to add specific pipelines to certain routes that will run inside the global pipeline - -The configuration file for Routed Pipeline can be found at `router/routes.php` - -````php -get('/', [App\Handler\HomePageHandler::class], 'home'); - * $app->post('/album', [App\Handler\AlbumCreateHandler::class], 'album.create'); - * $app->put('/album/:id', [App\Handler\AlbumUpdateHandler::class], 'album.put'); - * $app->patch('/album/:id', [App\Handler\AlbumUpdateHandler::class], 'album.patch'); - * $app->delete('/album/:id', [App\Handler\AlbumDeleteHandler::class], 'album.delete'); - * - * Or with multiple request methods: - * - * $app->route('/contact', [App\Handler\ContactHandler::class], ['GET', 'POST', ...], 'contact'); - */ -return static function (Application $app, ContainerInterface $container) : void { - $app->get('/', [SomeMiddleware::class, HomePageRequestHandler::class], 'home'); -}; - -```` - -The Request Handler must be an implementation of `Psr\Http\Server\RequestHandlerInterface` - -````php -

Hello World!!!

'); - } -} -```` - -> The middleware instances and request handler should be registered as services with [dependency injection](/#Dependency-Injection) component diff --git a/docs/framework/running-application.md b/docs/framework/running-application.md index 1e3032f..2ca0648 100644 --- a/docs/framework/running-application.md +++ b/docs/framework/running-application.md @@ -1,133 +1,173 @@ -# Running Application +# Running the Antidot Framework Application -> https://github.com/antidot-framework/antidot-framework +Once your Antidot PHP Framework application is ready for production, you need to set up a process manager +to ensure that the application runs continuously and can automatically recover from failures. This section +will guide you through the process of running the Antidot Framework server using process management tools +like Supervisor or Systemd. Additionally, we'll cover how to configure a load balancer, such as Nginx or +Caddy, to handle incoming requests and distribute the traffic to your Antidot application. -## Running PHP build in web server +### Supervisor -PHP provides us a built-in web server which is cool for development purposes +Supervisor is a process control system for Unix-like operating systems that provides a reliable way +to manage and monitor processes. To use Supervisor to manage your Antidot Framework application, +follow these steps: -````bash -php -S 127.0.0.1:8000 -t public -```` -![running built in server](/../images/php-built-in-server.jpg) +1. Install Supervisor by running the following command: -## Running Antidot Framework in AWS Lambda using Bref + ```shell + sudo apt-get install supervisor + ``` -This guide helps you run Antidot framework applications on AWS Lambda using Bref. +2. Create a Supervisor configuration file for your application. You can create a file named `antidot.conf` +in the `/etc/supervisor/conf.d/` directory: -A demo application is available on GitHub at -[github.com/antidot-framework/antidot-bref-lambda-demo](https://github.com/antidot-framework/antidot-bref-lambda-demo). + ```shell + sudo nano /etc/supervisor/conf.d/antidot.conf + ``` -### Setup +3. In the Supervisor configuration file, add the following configuration: -Assuming you are in an existing [Antidot Framework project](https://github.com/antidot-framework/antidot-starter), let's -install Bref via Composer: + ```ini + [program:antidot] + command=/usr/bin/php /path/to/your/application/bin/console serve + directory=/path/to/your/application + autostart=true + autorestart=true + stderr_logfile=/var/log/antidot/error.log + stdout_logfile=/var/log/antidot/access.log + ``` -``` -composer require bref/bref -``` + Make sure to replace `/path/to/your/application` with the actual path to your Antidot Framework application. -Then let's create a `serverless.yml` configuration file (at the root of the project) optimized for Antidot Framework: - -```yaml -service: bref-demo-antidot - -provider: - name: aws - region: us-east-1 - runtime: provided.al2 - environment: - # Your project environment variables -# APP_ENV: prod - -plugins: - - ./vendor/bref/bref - -package: - exclude: - - node_modules/** - - tests/** - -functions: - website: - handler: public/index.php - timeout: 28 # in seconds (API Gateway has a timeout of 29 seconds) - layers: -# - ${bref:layer.php-74-fpm} - - ${bref:layer.php-80-fpm} - events: - - http: 'ANY /' - - http: 'ANY /{proxy+}' - console: - handler: bin/console - timeout: 120 # in seconds - layers: -# - ${bref:layer.php-74} # PHP - - ${bref:layer.php-80} # PHP - - ${bref:layer.console} # The "console" layer -``` +4. Save the file and exit the text editor. -Now we still have a few modifications to do on the application to make it compatible with AWS Lambda. +5. Reload the Supervisor configuration to apply the changes: -Since [the filesystem is readonly](https://bref.sh/docs/environment/storage.html) except for `/tmp` we need to customize where the cache -is stored in the `config/config.php` and `config/cli-config.php` files. + ```shell + sudo supervisorctl reread + ``` -```php - dirname('../tmp/cache') . '/config-cache.php', -]; -... -``` +6. Start the Antidot application process: -```php - dirname('../tmp/cache') . 'cli-config-cache.php', -]; -... -``` + ```shell + sudo supervisorctl start antidot + ``` + + Your Antidot Framework application should now be running under the control of Supervisor. + +### Systemd + +Systemd is a suite of basic building blocks for a Linux system that provides a system and service manager. +To use Systemd to manage your Antidot Framework application, follow these steps: + +1. Create a Systemd service unit file for your application. You can create a file named `antidot.service` +in the `/etc/systemd/system/` directory: + + ```shell + sudo nano /etc/systemd/system/antidot.service + ``` + +2. In the Systemd service unit file, add the following configuration: + + ```ini + [Unit] + Description=Antidot Framework Application + After=network.target + + [Service] + ExecStart=/usr/bin/php /path/to/your/application/bin/console serve + WorkingDirectory=/path/to/your/application + Restart=always + User=your_user + Group=your_group + + [Install] + WantedBy=multi-user.target + ``` -### Deploy + Make sure to replace `/path/to/your/application` with the actual path to your Antidot Framework +application. Also, replace `your_user` and `your_group` with the appropriate user and group under +which the application should run. -Your application is now ready to be deployed. Follow [the deployment guide](https://bref.sh/docs/deploy.html). +3. Save the file and exit the text editor. -### Console +4. Reload the Systemd configuration to apply the changes: -As you may have noticed, we define a function of type "console" in `serverless.yml`. That function is using the [Console runtime](https://bref.sh/docs/runtimes/console.html), which lets us run the Antidot Framework Console on AWS Lambda. + ```shell + sudo systemctl daemon-reload + ``` -To use it follow [the "Console" guide](https://bref.sh/docs/runtimes/console.html). +5. Start the Antidot application service: -### Logs + ```shell + sudo systemctl start antidot + ``` -We need to configure Monolog to log into `stderr` as well: + Your Antidot Framework application should now be running as a Systemd service. -```yaml -# config/services/dependencies.prod.yaml - monolog: - handlers: - default: - type: 'stream' - options: - stream: 'php://stderr' - level: 400 +### Monitoring the Application + +With Supervisor or Systemd in place, your Antidot Framework application will run continuously, +automatically restarting if it crashes or if the server restarts. You can monitor the application's +logs to troubleshoot any issues or check its status. + +- For Supervisor, the error and access logs specified in the configuration file +(`/var/log/antidot/error.log` and `/var/log/antidot/access.log`) can be used to monitor +the application's output. + +- For Systemd, you can check the application's logs using the `journalctl` command: + + ```shell + sudo journalctl -u antidot + ``` + + This will display the logs related to the Antidot Framework application. + + +### Load Balancer Configuration (Nginx) + +To distribute the traffic to your Antidot Framework application and provide additional features like +SSL termination and caching, you can use a load balancer like Nginx. Here's an example configuration +for Nginx: + +```nginx +server { + listen 80; + server_name your-domain.com; + + location / { + proxy_pass http://localhost:3000; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + } +} ``` -### Environment variables +In the above configuration, replace `your-domain.com` with your actual domain name or IP address. +The `proxy_pass` directive specifies the address of your Antidot application server, which is running +on port 3000 by default. Adjust the configuration as necessary if you're using a different port. + +### Load Balancer Configuration (Caddy) -You can define your environment variables in `serverless.yml` in the [Globals section](https://github.com/awslabs/serverless-application-model/blob/master/docs/globals.rst): +If you prefer to use Caddy as your load balancer, here's an example configuration: -```yaml -Globals: - Function: - Environment: - Variables: - APP_ENV: prod ``` +your-domain.com { + reverse_proxy localhost:3000 +} +``` + +Replace `your-domain.com` with your actual domain name or IP address. The `reverse_proxy` directive +specifies the address of your Antidot application server, which is running on port 3000 by default. +Adjust the configuration if you're using a different port. + +### Conclusion -The secrets (e.g. database passwords) must however not be committed in this file. +Running the Antidot Framework application in a production environment requires proper port binding and +load balancer configuration. By specifying a custom port for the server and using tools like Nginx or +Caddy as load balancers, you can ensure that the application runs on the desired port and handles +incoming requests efficiently. Also crucial for ensuring its availability and resilience. By using process +management tools like Supervisor or Systemd, you can ensure that the application runs continuously, +automatically restarts when necessary, and provides monitoring capabilities. -To learn more about all this, read the [environment variables documentation](https://bref.sh/docs/environment/variables.html). diff --git a/docs/framework/templating.md b/docs/framework/templating.md index 472340e..6adb729 100644 --- a/docs/framework/templating.md +++ b/docs/framework/templating.md @@ -67,112 +67,6 @@ class SomeRequestHandler implements RequestHandlerInterface ## Config - - -### **Symfony Style yaml** - -```yaml -parameters: - templates: - extension: pug # pug|twig - template: - debug: false # only twig - file_extension: 'twig' # only twig - charset: 'utf-8' # only twig - auto_reload: false # only twig - autoescape: 'html' # only twig - strict_variables: true # only twig - pretty: true # only pug - expressionLanguage: js # only pug - pugjs: false # only pug - localsJsonFile: false # only pug - cache: var/cache/pug - template_path: templates/ - globals: - title: Antidot Framework - filters: [] - extensions: [] # only twig - keywords: [] # only pug - helpers: [] # only pug - default_params: => [] # only pug -``` - -### **Symfony php** - -```php - [ - 'templates' => [ - 'extensino' => 'pug', // only pug - ], - 'template' => [ - 'debug' => false, // only twig - 'file_extension' => 'twig', // only twig - 'charset' => 'utf-8', // only twig - 'auto_reload' => false, // only twig - 'autoescape' => 'html', // only twig - 'strict_variables' => true, // only twig - 'pretty' => true, // only pug - 'expressionLanguage' => 'js', // only pug - 'pugjs' => false, // only pug - 'localsJsonFile' => false, // only pug - 'cache' => 'var/cache/pug', - 'template_path' => 'templates/', - 'globals' => [ - 'title' => 'Antidot Framework' - ], - 'filters' => [ - // 'name' => PHPCallableClass::class, - // 'some_function' => 'php_some_function, - ], - 'extensions' => [ // only twig - // EtensionClassName::class, - ], - 'functions' => [ // only twig - // 'name' => PHPCallableClass::class, - // 'some_function' => 'php_some_function, - ], - 'keywords' => [], // only pug - 'helpers' => [], // only pug - 'default_params' => [], // only pug - ], - ], -]; -``` - -### **Zend style yaml** - -```yaml -templates: - extension: pug # pug|twig -template: - debug: false # only twig - file_extension: 'twig' # only twig - charset: 'utf-8' # only twig - auto_reload: false # only twig - autoescape: 'html' # only twig - strict_variables: true # only twig - pretty: true # only pug - expressionLanguage: js # only pug - pugjs: false # only pug - localsJsonFile: false # only pug - cache: var/cache/pug - template_path: templates/ - globals: - title: Antidot Framework - filters: [] - extensions: [] # only twig - keywords: [] # only pug - helpers: [] # only pug - default_params: => [] # only pug -``` - -### **Zend Style php** - ```php -