There comes a time when for some reason you will want to or have to modify a class or more from a 3rd party bundle. Sadly, some 3rd party bundles are outdated, discontinued or very rigid, and so you're rendered unable to do this via a configuration option. This makes it so that you will either have to create a new fork of that 3rd party library and maintain it yourself or modify or create a bunch of classes. There are cases when you don't want to do any of this and want to keep the work needed to achieve this a minimum.
If you don't mind getting your hands dirty, the following bit will show you how to achieve your goal, although is quite hackish and should only be relied upon when you're not able to go the standard way of doing things.
The component of the system that can help you achieve this is the autoloader.
The autoloader is an instance of Composer\Autoload\ClassLoader
and can be accessed before the system boots from the app/autoload.php
in the standard Symfony2 installation.
There are a bunch of methods on the objects $loader
that is created inside the app/autoload.php
file, that you can use to achieve this:
addClassMap(array $classMap)
add($prefix, $paths, $prepend = false)
addPsr4($prefix, $paths, $prepend = false)
set($prefix, $paths)
setPsr4($prefix, $paths)
The addClassMap
method takes an array as parrameter where the class is the the key and the path is the value.
E.g. :
$loader->addClassMap(array(
'Doctrine\\ORM\\Tools\\Pagination\\Paginator' => __DIR__ . '/../src/SomeVendor/SomeBundle/Pagination/Tools/Paginator.php',
));
The namespace of the new class will stay the same as the namespace of the new class, even though the path is totally now different. This is because in the standard approach the namespace is used to determine the path and the autoloader will try to guess is based on the autoloading config of each bundle (specified in each bundles composer.json) and the PSR autoloading standard.
The only real difference between the add
and addPsr4
and between set
and setPsr4
is that the $prefix
parameters has to end with a backslash (/
) when using the PSR4 methods. Other than that everything is the same.
So if you'd do something like this for a PSR0 method:
$loader->set('SomeVendor\SomeBundle', $paths);
The PSR4 equivalent would be:
$loader->setPsr4('SomeVendor\SomeBundle\\', $paths);
The add
and addPsr4
methods can be used to append or prepend paths for a given namespace while the set
and setPsr4
methods will replace the mapping if any exists already. For all four of these methods the $paths
parameter can either be a string or an array of strings.
The namespace will stay the same if you're using these methods, but, there's a catch here and is very important: the directory path must exist inside these new locations because the autoloader will try to find the file based on the namespace and class inside these new paths.
For example:
If you wanted to remap the SomeVendor\SomeBundle\Directory\SomeClass
which is located in vendor/somevendor/src/SomeVendor/SomeBundle/Directory/SomeClass.php
you'd have to create a new file src/MyVendor/MyBundle/Remapped/SomeVendor/SomeBundle/Directory/SomeClass.php
and add this to your autoloader:
$loader->set('SomeVendor\SomeBundle', array(
'src/MyVendor/MyBundle/Remapped',
'vendor/somevendor/src/SomeVendor/SomeBundle' // this will be the fallback directory to search in, in case the $newDirectory doens't have the file
));
Again, this is non standard and should only be used as a last resort. But, now you know how to do it if you have too.
Let us know what you think.