Updated Rector YAML to PHP configuration, as current standard.
If there would be "Miss Deprecation of PHP 7.2", create_function()
would definitely win. They can be very complex, tricky and very hard convert to PHP code. Moreover without tests.
Do you have over 5 create_function()
pieces in your code? Let's see how to migrate them.
Why is this deprecated? Well, the string arguments of few functions behaves like eval()
- that's evil.
<?php
create_function("$a", "return $a");
assert("$value == 5");
And what about quotes?
<?php
create_function("$a", "return $a");
create_function('$a', 'return $a');
You don't want to think which if "
or `
breaks the code - you want make code.
I think it's a good move, so how do we refactor them? Let's start with simple code:
<?php
$callback = create_function('$matches', "return strtolower(\$matches[1]);");
How would you refactor this to anonymous function?
(Pause for deep thinking...)
<?php
$callback = function ($matches) {
return strtolower($matches[1]);
};
As you can see:
Also, notice the \$matches
→ $matches
. That's because quote escaping.
What about this one?
<?php
create_function('$a,$b', "return \"min(b^2+a, a^2,b) = \".min(\$a*\$a+\$b,\$b*\$b+\$a);");
How would you refactor this to anonymous function?
(Pause for deep thinking...)
<?php
function ($a, $b) {
return "min(b^2+a, a^2,b) = " . min($a * $a + $b, $b * $b + $a);
};
The "min(b^2+a, a^2,b) = "
is still a string, because it was escaped string in a string.
Too easy for you? Damn, you're smart.
Can you handle this?
<?php
create_function('$b,$a', 'if (strncmp($a, $b, 3) == 0) return "** \"$a\" '.
'and \"$b\"** Look the same to me! (looking at the first 3 chars)";');
How would you refactor this to anonymous function?
(Pause for deep thinking...)
<?php
function ($b, $a) {
if (strncmp($a, $b, 3) == 0) {
return "** \"{$a}\" and \"{$b}\"** Look the same to me! (looking at the first 3 chars)";
}
};
Ok, but you won't make this code snippet I found in Drupal/Wordpress:
<?php
$this->map_xmlns_func = create_function('$p,$n', 'if(strlen($n[0])>0) $xd
.= ":{$n[0]}"; return "{$xd}=\"{$n[1]}\"";');
How would you refactor this to anonymous function?
(Pause for deep thinking...)
<?php
$this->map_xmlns_func = function ($p, $n) use ($xd) {
if (strlen($n[0]) > 0) {
$xd .= ":{$n[0]}";
}
return "{$xd}=\"{$n[1]}\"";
};
Who did forget use ($xd)
? An anonymous function can't access variables that are not passed as arguments, so without this would crash.
And we could continue and continue with more edgy cases... but I bet you're looking for a solution for your specific function. Well, you could ask on StackOverflow (181 results and counting), but posting each of your 10 cases might get you banned. I have good news for you.
Today in 2019 (almost there), you can instantly upgrade your code and it will take you less time to install & run, then read this whole post so far.
Just setup Rector and run it:
composer require rector/rector --dev
use Rector\Php72\Rector\FuncCall\CreateFunctionToAnonymousFunctionRector;
use Rector\Config\RectorConfig;
return function (RectorConfig $rectorConfig): void {
$rectorConfig->rule(CreateFunctionToAnonymousFunctionRector::class);
};
vendor/bin/rector process src
Happy instant upgrading!
Do you learn from my contents or use open-source packages like Rector every day?
Consider supporting it on GitHub Sponsors.
I'd really appreciate it!