Starting with v6, ICanBoogie introduces a new approach to component configuration. While still using PHP files, the framework now employs type-safe domain-specific builders instead of arrays. Going further, some configurations can be inferred from PHP 8.0 attributes, moving configuration concerns closer to the code. These improvements aim to make the configuration process more reliable and developer-friendly.

Type-safe domain-specific configuration builders

Compared to arrays, well-named domain-specific type-safe builders remove the headache of configuration, improve discoverability, and allow immediate validation to avoid mistakes.

For ActiveRecords, for example, we move from an array that requires knowledge about different concepts and can easily be malformed to a domain-specific builder that provides guidance and data validation.

<?php

// …

return [
    Descriptor::MODELS => [
        'articles' => [
            Model::SCHEMA => [
                'article_id' => 'serial',
                'title' => 'varchar',
                'slug' => [ 'varchar', 80 ],
                'body' => 'text',
                'date' => 'date',
            ],
            Model::ACTIVERECORD_CLASS => Article::class,
        ]
    ]
];
<?php

// …

use ICanBoogie\ActiveRecord\ConfigBuilder;
use ICanBoogie\ActiveRecord\SchemaBuilder;

return fn(ConfigBuilder $config) => $config
    ->add_record(
        record_class: Article::class,
        schema_builder: fn (SchemaBuilder $schema) => $schema
            ->add_serial('article_id', primary: true)
            ->add_character('title')
            ->add_character('slug', size: 80)
            ->add_text('body')
            ->add_date('date'),
    )

Infer configuration from PHP 8.0 attributes

Going further, most builders can now infer configuration from PHP 8.0 attributes. They have a use_attributes() method in that case.

Configuring ActiveRecord

Here is an example of ActiveRecord configuration using attributes:

<?php

use App\Modules\Articles\Article;
use ICanBoogie\ActiveRecord\ConfigBuilder;

return fn(ConfigBuilder $config) => $config
    ->use_attributes()
    ->add_connection('primary', 'sqlite:var/db.sqlite')
    ->add_record(Article::class);
<?php

// …

use ICanBoogie\ActiveRecord;

class Article extends ActiveRecord
{
    #[Serial, Id]
    public int $article_id

    #[Character]
    public string $title;

    #[Character(size: 80)]
    public string $slug;

    #[Text]
    public string $body

    #[Date]
    public DateTimeInterface $date;
}

Configuring routing

Here is an example of a routing configuration using attributes:

<?php

use ICanBoogie\Binding\Routing\ConfigBuilder;

return fn(ConfigBuilder $config) => $config
    ->use_attributes();
<?php

// …

#[Route('/equipment')]
final class EquipmentController extends ControllerAbstract
{
    // …

    #[Get('.html')]
    private function list(): void
    {
        // …
    }

    #[Get('/<category_slug:swords|polearms|daggers|axes|bows|staves|shields|headgear|armor|accessories>.html')]
    private function category(string $category_slug): void
    {
        // …
    }

    #[Get('/sets.html')]
    private function sets(): void
    {
        // …
    }

    /**
     * @throws NotFound
     */
    #[Get('/:slug.html')]
    private function show(string $slug): void
    {
        // …
    }
}

Configuring event listeners

Here is an example of event listeners configuration using attributes:

<?php

use ICanBoogie\Binding\Event\ConfigBuilder;

return fn(ConfigBuilder $config) => $config
    ->use_attributes();
<?php

// …

final readonly class RecoverNotFoundListener
{
    // …

    #[Listen]
    public function __invoke(RecoverEvent $event, NotFound $error): void
    {
        // …
    }
}

Summary

Together with PHP 8.0 attributes, well-named domain-specific type-safe builders provide an easy and reliable way to configure an ICanBoogie application.

PS: You can check the source of this website for more examples.