Recently, we came across a problem, while developing a new version of the Notification plugin. We wanted to tidy up our codebase and one of the tasks was to rename some of the namespaces. But how to do it without copying the classes?
The requirements were simple:
- Namespace needs to be mapped for changing on every level, ie.
Namespace\X\Y\Z\Class
but alsoNamespace\X\Y
- We don’t want to copy each class into a separate namespace and maintain duplicates
- We want to throw a deprecation notice if an old namespace is used
The solution is simple, and it’s a combination of class_alias()
function and a custom autoloader. It doesn’t matter we’re using Composer as a main autoloader source.
Go ahead and change your namespaces directly in your source code, and define your autoloader.
spl_autoload_register(function ($class) {
$deprecationMap = [
'Namespace\X\Y\Z\Class' => 'Namespace\A\B\C\Class',
'Namespace\Some\Other' => 'Namespace\SomethingCool',
];
foreach ($deprecationMap as $oldNamespace => $newNamespace) {
// Match the loaded classname.
if (strpos($class, $oldNamespace) !== 0) {
continue;
}
$newClass = str_replace($oldNamespace, $newNamespace, $class);
if (! class_exists($newClass)) {
break;
}
$message = __('Class %1$s is <strong>deprecated</strong>! Use %2$s instead.');
trigger_error(sprintf($message, $class, $newClass), E_USER_DEPRECATED);
class_alias($newClass, $class);
}
});
Simply save this into a file and require it just after Composer’s vendor/autoload.php
or use Composer autoload.files
key to include your file.
This approach checks all the requirements, is simple, and doesn’t require copying your files and maintaining your code in multiple places. The class_alias() function is also compatible back to PHP 5.