interitty/component-model

Extension of the standard Nette/Component Model by some other features that are specific for use in the Interitty projects.

v1.0.4 2024-03-15 11:38 UTC

This package is auto-updated.

Last update: 2024-04-15 10:51:06 UTC


README

Extension of the standard Nette/Component Model by some other features that are specific for use in the Interitty projects.

Requirements

Installation

The best way to install interitty/component-model is using Composer:

composer require interitty/component-model

Then register the extension in the Nette config file:

# app/config/config.neon
extensions:
    componentLocator: Interitty\ComponentModel\Nette\DI\ComponentLocatorExtension

In order to work comfortably with the ComponentLocator, there is a Interitty\ComponentModel\ComponentLocatorTrait which can be used in the Presenter where it should be available.

<?php

declare(strict_types=1);

namespace App\Presenters;

use Interitty\ComponentModel\ComponentLocatorTrait;
use Nette\Application\UI\Presenter;

abstract class BasePresenter extends Presenter
{
    use ComponentLocatorTrait;
}

Configuration

The Component locator can maintain and provides any component factory defined as a service, class, or interface. The component will be available by the name used as a key of the factories array or by the name retrieved from the service, class, or interface.

componentLocator:
    factories:
        # componentName: Namespaced\ComponentFactoryInterface
        # componentName: Namespaced\ComponentFactory
        # componentName: @ComponentFactoryService
        # - Namespaced\ComponentFactoryInterface
        # - Namespaced\ComponentFactory
        # - @ComponentFactoryService

There is also by default enabled mechanism autoRegister that automatically collects all services of Interitty\ComponentModel\ComponentFactoryInterface type and register them into the Component locator.

The name of the registered component is derived from the service name, the interface, or a class name. It can fall into the duplicity of the component name because the namespace of the services is not reflected. Second and other services with the same derived component name are simply skipped. To register them with another name simply use the previous factories mechanism together.

componentLocator:
    autoRegister: true

services:
    - Namespaced\ComponentFactory
    testFactory:
        implement: Namespaced\ComponentFactoryInterface

By default, the generated constants are used for component names in the ComponentLocatorHelperTrait, which makes the code even clearer and helps in faster navigation. However, some people still prefer to use the standard string. The use of components in the generated output can be influenced in the settings just like the namespace or location of the generated code.

# Example of default component locator settings
componentLocator:
    autoRegister: true # Can be `false` to disable automatic registration of any `ComponentFactoryInterface` compatible services
    constants: true # Can be `false` to use string names
    helperNamespace: 'Interitty\\ComponentModel' # Can be `null` to disable generating `ComponentLocatorHelperTrait` helper
    tempDir: %tempDir% # Can be any writable directory

Usage

Usually, the component still needs to be configured or connected to others. This can be done in the same way as before, by creating a specific factory method.

public function createComponentTestControl(string $name = 'test'): TestControl
{
    $control = $this->createLocatedComponent($name);
    assert($control instanceof TestControl);

    // Any necessary settings

    return $control;
}

When the generated ComponentLocatorHelperTrait helper is used, just overload the original factory method if necessary:

public function createComponentTestControl(string $name = 'test'): TestControl
{
    $control = parent::createComponentTestControl($name);
    // Any necessary settings
    return $control;
}

Helper trait

To work with this Component locator, just use the the basic ComponentLocatorTrait which provides everything you need. However, it's usually handy to be able to extend the component settings in their factories and have getters to access them directly. For this purpose, the extension also has the ability to generate a helper ComponentLocatorHelperTrait at build time of the Dependency Injection Container, which contains the following methods.

So just use this generated helper in the Presenter where the components are to be available instead of the basic one.

<?php

declare(strict_types=1);

namespace App\Presenters;

use Interitty\ComponentModel\ComponentLocatorHelperTrait;
use Nette\Application\UI\Presenter;

abstract class BasePresenter extends Presenter
{
    use ComponentLocatorHelperTrait;
}

Suitable application settings for PHPStan

The extension itself can generate an auxiliary Trait and immediately load it to make it available to the rest of the application regardless of its name, namespace, or location. PHPStan, however, requires that it be loaded using an autoloader. To achieve this, you need to have the file generated to a namespace and an appropriate location that is identified by the autoloader.

To do this, just set the appropriate parameters in the neon configuration.

componentLocator:
    helperNamespace: 'App\Controls' # Same namespace as the rest of application
    tempDir: %appDir%/Controls