interitty / component-model
Extension of the standard Nette/Component Model by some other features that are specific for use in the Interitty projects.
Requires
- php: ~8.3
- dg/composer-cleaner: ~2.2
- interitty/di: ~1.0
- nette/component-model: ~3.1
Requires (Dev)
- interitty/code-checker: ~1.0
- interitty/phpunit: ~1.0
- nette/application: ~3.2
- nette/bootstrap: ~3.2
- nette/caching: ~3.3
README
Extension of the standard Nette/Component Model by some other features that are specific for use in the Interitty projects.
Requirements
- PHP >= 8.3
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