Wallogit.com
2017 © Pedro Peláez
Add extra to composer.json, to overload autoloaded class
Allow to overload autoloaded classes, to include your files instead of supposed ones., (*2)
Sometimes, you need to overload a class from a dependency. But you can't, cause you've found a nice "new Foo\Bar()" somewhere in this dependency..., (*3)
So, if your project use Composer autoload (like Symfony projects for example), you can use steevanb/composer-overload-class., (*4)
With a simple configuration, you can specify to Composer in which file it will find a class (your file), instead of let him find original file with class namespace. Cause you can't change namespace and class name of original class, otherwise all dependencies to this namespace / class name will fail (use Foo\Bar, method parameter type, etc), composer-overload-class will clone Foo\Bar class content into ComposerOverloadClass\Foo namespace., (*5)
Your class need to have exact same namespace as overloaded one, and you can extends ComposerOverloadClass\Foo\Bar if you need., (*6)
, (*7)
Changelog, (*8)
composer require steevanb/composer-overload-class ^1.4
To overload a class, you need to configure it via your composer.json., (*9)
Example taken from steevanb/doctrine-stats, to overload Doctrine ObjectHydrator :, (*10)
# composer.json
{
"scripts": {
"__comment": "Add a script who generate cloned classes, when autoload is generated",
"pre-autoload-dump": "steevanb\\ComposerOverloadClass\\OverloadClass::overload"
},
"extra": {
"__comment": "Path to a writable directory, where overloaded classes will be cloned, with it's namespace prefixed by ComposerOverloadClass, in prod + dev env",
"composer-overload-cache-dir": "var/cache/prod",
"__comment": "Path to a writable directory, in dev env",
"composer-overload-cache-dir-dev": "var/cache/dev",
"__comment": "Classes to overload, in prod + dev env",
"composer-overload-class": {
"__comment": "Fully qualified class name you want to overload",
"Doctrine\\ORM\\Internal\\Hydration\\ObjectHydrator": {
"__comment": "Path to original file, who contains the class you want to overload",
"original-file": "vendor/doctrine/orm/lib/Doctrine/ORM/Internal/Hydration/ObjectHydrator.php",
"__comment": "Path to your file, who contains your class",
"overload-file": "vendor/steevanb/doctrine-stats/ComposerOverloadClass/Doctrine/ORM/Internal/ObjectHydrator.php",
"__comment": "false (default) : duplicate original class, add ComposerOverloadClass namespace prefix, you can extend it",
"__comment": "true : do not duplicate original class, you need to write all code in your classe",
"duplicate-original-file": false
}
},
"__comment": "Classes to overload, in dev env",
"composer-overload-class-dev": {}
},
"autoload": {
"psr-4": {
"ComposerOverloadClass\\": "var/cache/prod/ComposerOverloadClass"
}
},
"autoload-dev": {
"psr-4": {
"ComposerOverloadClass\\": "var/cache/dev/ComposerOverloadClass"
}
},
}
When configuration is finished, you need to re-generate Composer autoload :, (*11)
composer dumpautoload # show overrided files composer dumpautoload -v
That's all folks !, (*12)
Example taken from steevanb/doctrine-stats, to overload Doctrine ObjectHydrator, to add a timer when entities are hydrated :, (*13)
# src/ComposerOverloadClass/Doctrine/ORM/Internal/ObjectHydrator.php
namespace Doctrine\ORM\Internal\Hydration;
use Doctrine\ORM\EntityManagerInterface;
use steevanb\DoctrineStats\Doctrine\ORM\Event\HydrationEventsTrait;
# extends cloned ObjectHydrator class, I just want to change hydrateAllData() code
class ObjectHydrator extends \ComposerOverloadClass\Doctrine\ORM\Internal\Hydration\ObjectHydrator
{
use HydrationEventsTrait;
protected function getEntityManager(): EntityManagerInterface
{
return $this->_em;
}
protected function hydrateAllData(): void
{
$eventId = $this->dispatchPreHydrationEvent();
parent::hydrateAllData();
$this->dispatchPostHydrationEvent($eventId);
}
}