Humans, world and PHP Frameworks constantly evolve - their code functionality changes. Class or method is renamed, method has 1 new argument or new class is decoupled.
In Symfony world you probably know about Backward Compatibility Promise. It prevents from unexpected and frustrating BC breaks and helps users to upgrade gradually thanks to deprecation messages.
In this post I will show you how to work with deprecation messages.
This technique is quite rare to see (apart PHP frameworks). It's very simple to add to your open-source code workflow though - let me convince you.
To explain last point a bit more: if you write your message in a way, that some parser would be able to understand it, it would be able to refactor other code accordingly.
Read
SomeClass::oldMethod => SomeClass::newMethod
Run
bin/refactor app src
Enjoy new code!
That was the future, now back to the present.
Let's take real example from real code - a class from Nette\Utils
2.4.
What we need to know?
Nette\Utils\Html
objectBefore this change you used:
$html = Html::el('div');
$html->add('<strong>I am brand new!</strong>');
And after this change you will use:
$html = Html::el('div');
$html->addHtml('<strong>I am brand new!</strong>');
This is the snippet from the Nette\Util\Html
class we are interested in:
namespace Nette\Utils;
class Html
{
public function add(...)
{
// ...
}
}
So how to inform all ends users about this?
You can choose from 2 ways to write deprecations messages, based on your preference.
@deprecate
annotationnamespace Nette\Utils;
class Html
{
/**
* @deprecated
*/
public function add(...)
{
$this->addHtml(...);
}
public function addHtml(...)
{
// ...
}
}
This is the least you can do. But you could do better, right?
/**
* @deprecated Method add() is deprecated.
*/
public function add(...)
Should I delete all those methods calls in my code?
/**
* @deprecated Method add() is deprecated, use addHtml() instead.
*/
public function add(...)
A-ha, that's better!
I Have 1 Question for you: What happens when programmer runs $html->add(...)
method now?
...
Well, exactly... nothing. Annotations have no influence on code run, so it will work and programmer won't notice anything.
Luckily, there is option that will actually inform about the deprecation.
trigger_error()
A trigger_error()
is native PHP function, that can inform user about changes in the code.
With the 2nd argument is level of these messages - there is special constant E_USER_DEPRECATED
destined for this case.
namespace Nette\Utils;
class Html
{
public function add(...)
{
# we already know how to write useful mesagges
trigger_error('Method add() is deprecated, use addHtml() instead.', E_USER_DEPRECATED);
$this->addHtml(...);
})
public function addHtml(...)
{
// ...
}
}
You can see it used in similar way in the original code.
What happens when programmer runs $html->add(...)
method with this type of deprecation?
2 things:
In case he or she is not ready for upgrade, it can be disabled in application bootstrap
file:
error_reporting(~E_USER_DEPRECATED);
Source (Czech only)
I said...
It's very simple to add to your open-source code workflow...
...and this is it!
That was Symfony's Backward Compatibility Promise in a nutshell.
Happy coding!
Do you learn from my contents or use open-souce packages like Rector every day?
Consider supporting it on GitHub Sponsors.
I'd really appreciate it!