I want to look at two PHP functions: eval
and exec
. They're so often thrown under the sensible-developers-never-use-these bus that I sometimes wonder how many awesome applications we miss out on.
Like every other function in the standard library, these have their uses. They can be abused. Their danger lies in the amount of flexibility and power they offer even the most novice of developers.
Let me show you some of the ways I've seen these used, and then we can talk about safety precautions and moderation.
Dynamic Class Creation
The first time I ever saw dynamic class creation was in the bowels of CodeIgniter. At the time, CodeIgniter was using it to create ORM classes. eval
is still used to rewrite short open tags for systems that don't have the feature enabled...
More recently, though, my friend Adam Wathan tweeted about using it to dynamically create Laravel facades. Take a look at what the classes usually look like:
namespace Illuminate\Support\Facades;
class Artisan extends Facade
{
protected static function getFacadeAccessor()
{
return "Illuminate\Contracts\Console\Kernel";
}
}
This is from http://ift.tt/2guo630
These facade classes aren't facades in the traditional sense, but they do act as static references to objects stored in Laravel's service locator class. They project an easy way to refer to objects defined and configured elsewhere, and have benefits over traditional static (or singleton) classes. One of these benefits is in testing:
public function testNotificationWasQueued()
{
Artisan::shouldReceive("queue")
->once()
->with(
"user:notify",
Mockery::subset(["user" => 1])
);
$service = new App\Service\UserService();
$service->notifyUser(1);
}
...and though these facades are simple to create, there are a lot of them. That's not the kind of code I find interesting to write. It seems Adam felt the same what when we wrote the tweet.
So, how could we create these facade classes dynamically? I haven't seen Adam's implementation code, but I'm guessing it looks something like:
function facade($name, $className) {
if (class_exists($name)) {
return;
}
eval("
class $name extends Facade
{
protected static function getFacadeAccessor()
{
return $className::class;
}
}
");
}
That's a neat trick. Whether of not you use (or even like) Laravel facades, I'm guessing you can see the benefits of writing less code. Sure, this probably adds to the execution time of each request, but we'd have to profile performance to decide if it even matters much.
Continue reading %The Delicious Evils of PHP%
by Christopher Pitt via SitePoint
No comments:
Post a Comment