gisostallenberg / velpon-loader
Dynamic glue for classes in a stack
Requires
None
Requires (Dev)
- phpunit/phpunit: ^5.7
Suggests
None
Provides
None
Conflicts
None
Replaces
None
This package is auto-updated.
Last update: 2026-10-27 20:52:12 UTC
README
Velpon loader glues classes defined in a variable stack together. See https://nl.wikipedia.org/wiki/Ceta-Bever for the origin of the name.
⚠️ Avoid in new code
This is not a security problem, it is an architectural one. The loader rewrites class identity at autoload time: it registers a global autoloader and uses
class_alias()to splice plugin classes into an inheritance chain. That means global mutable static state, load-order-dependent behaviour (the stack is applied in reverse), and classes whose real parent your IDE and static analyser cannot see. It can only shape the initial class resolution, never an already-constructed object.Prefer composition over this inheritance trick. Wire the layers explicitly with the decorator pattern (or a DI container), so the chain is plain, debuggable PHP with no autoloader magic:
interface Greeter { public function greet(): string; } final class BaseGreeter implements Greeter { public function greet(): string { return 'hello'; } } // each "plugin" decorates the previous layer final class ShoutGreeter implements Greeter { public function __construct(private Greeter $inner) {} public function greet(): string { return strtoupper($this->inner->greet()); } } $greeter = new ShoutGreeter(new BaseGreeter()); // compose the stack explicitlyFor runtime extension points, use events/listeners or middleware instead of patching the class graph.
Please note that this package is able to initialize an arbitrary class stack for a variable defined stack. It is not able to change already initialized (constructed) classes.
This package is meant to be used in a BC manner for existing projects implementing this style of loading. WARNING: It is strongly discouraged to use this for any new projects. Please use services, events and the like to be able to 'plug' into behavior.
Installation
composer require gisostallenberg/velpon-loader
Usage example
use GisoStallenberg\VelponLoader\VelponLoader; // Note that the stack order is reversed (ClassToPlug extends ClassToPlugPluginOne extends ClassToPlugPluginTwo) VelponLoader::register([ 'plugin_two' => [ 'ClassToPlug' => 'ClassToPlugPluginTwo' ], 'plugin_one' => [ 'ClassToPlug' => 'ClassToPlugPluginOne' ], ]);
Files:
// ClassToPlug.php class ClassToPlugPluggable {} // ClassToPlugPluginOne.php class ClassToPlugPluginOne extends ClassToPlugPluginOneVelpon {} // ClassToPlugPluginTwo.php class ClassToPlugPluginTwo extends ClassToPlugPluginTwoVelpon {}
Todo
Protect abstract classes from constructing without a non abstract parent