Lightna Lane is almost there! Read more | Lightna release is coming! Keep me updated
|||
🚧 Documentation in Progress 🚧
This documentation is actively being written and updated daily. Some sections may change or expand as we improve it.
If you have any questions or suggestions, feel free to reach out .
Content

Extending PHP

In Lightna, plugins are the core mechanism for extending functionality. Designed for flexibility and compatibility, they enable seamless method extensions while preventing conflicts between modules.

The plugin mechanism is based on the Interceptor pattern but extends its capabilities, allowing modifications to class methods and properties, including protected ones, without requiring direct overrides.

To maintain stability and avoid complexity, Lightna does not support class rewrites or inheritance chains, ensuring better maintainability across versions.

Declaration

Register the plugin in the backend area:

plugin:
Vendor\BaseModule\App\BaseClass:
- Vendor\MyModule\App\Plugin\MyPlugin

Declare the plugin class:

<?php
 
declare(strict_types=1);
 
namespace Vendor\MyModule\App\Plugin;
 
use Lightna\Engine\App\ObjectA;
 
class MyPlugin extends ObjectA
{
/**
* @noinspection PhpUnused
* @see Vendor\BaseModule\App\BaseClass::baseMethod
*/
public function baseMethodExtended(): array
{
return [ /* Custom Data */];
}
}
@see References the base method, enabling quick navigation in the IDE.
MyPlugin Custom class name for the plugin.
baseMethodExtended The method that extends the base class method. It must be public, match the base class method name, and end with the Extended keyword.

Extending Base Method Result

The first argument of the plugin method is a closure that proceeds with the plugin chain:

public function baseMethodExtended(Closure $proceed): array
{
return merge($proceed(), [ /* Custom Data */ ]);
}
$proceed() Calls the base class method, including any remaining plugins in the chain.
If the base method has arguments, avoid declaring them in the plugin method, and do not pass them to $proceed() for better compatibility.

Accessing Base Method Arguments

To read an argument from the base method, declare it in the plugin method:

public function baseMethodExtended(
Closure $proceed,
string $argument,
): array {
return $argument === 'value' ?
merge($proceed(), [ /* Custom Data */ ]) :
$proceed();
}

Modifying Base Method Arguments

To modify an argument, receive it by reference using & in the plugin method and change its value. Note that you do not need to pass the modified argument into the $proceed() call.

public function baseMethodExtended(
Closure $proceed,
string &$argument,
): array {
$argument = 'custom value';
return $proceed();
}

Modifying Base Protected Properties

Return a closure from the plugin method, which will then be called in the base class scope. This allows access to its protected properties and methods using $this.

public function baseMethodExtended(Closure $proceed): Closure {
return function () use ($proceed): void {
$this->baseProperty = 'custom value';
$proceed();
};
}

Call a method to modify the value of a base class property:

public function baseMethodExtended(): Closure {
$myModel = $this->myModel;
 
return function () use ($myModel): void {
$this->baseProperty = $myModel->getCustomValue($this->baseProperty);
};
}

Planned

  • A future update will enable the compiler to detect any plugin incompatibility with the base class. Plugins will need to specify all properties and methods they rely on during implementation. This will help identify compatibility issues when updating base modules.
  • We are considering adding support for plugin inheritance, allowing a plugin defined for a parent class to apply automatically to all its subclasses.

⚙️  Documentation Review

Noticed an issue or need more details? Submit your feedback for this page.
Leave a Feedback