Several weeks ago, a correspondent presented a legacy situation that I've never had to deal with. He was working his way through Modernizing Legacy Applications in PHP, and realized the codebase was storing serialized PHP objects in a database. He couldn't refactor the class names without seriously breaking the application.
I was carefully moving my classes to a PSR-0/4 structure when I found this. The application saves the output of
serialize($shoppingCart)in a BLOB column, and unserializes it later to recreate the ShoppingCart object. The serialized object string looks like this:
See how the class name is embedded in the serialized string? If I rename the ShopppingCart class to PSR-0/4 namespace, then the old class won't be found when the application tries to
unserialize()the serialized representation. How can I begin refactoring this without breaking the whole application?
Before I was able to reply, my correspondent ended up changing the serialization strategy to use JSON, which was a rather large change. It ended up well, but it turns out there is a less intrusive solution:
If you're in a serialized situation, and you need to change a class name, you can use a
class_alias() to point the old class name to the new one. (Call
class_alias() early in execution, probably before you register your autoloader.) You can then rename and move the class according to PSR-0/4 rules, and PHP will handle the rest for you.
For example, if you renamed ShoppingCart to Domain\Orders\Cart, you might do this:
Now when you call
unserialize($shoppingCart) to create an object, PHP will create it as an instance of Domain\Orders\Cart instead of ShoppingCart. Re-serialized representations of the recreated object will retain the new class name, not the old one:
As soon as there are no more serialized representations using the old class name, you can remove the
class_alias() call entirely.