Search code examples
phpdependency-injectionsilexpimplephp-closures

Silex service - $app parameter or "use ($app)" statement?


If I define a service in Silex application, I can either expect the main container (Application) to be passed as a parameter or can take it from the current scope using "use ($app)" statement.

The official documentation at http://silex.sensiolabs.org/doc/services.html has this snippet:

$app['some_service'] = function ($app) {
     return new Service($app['some_other_service'], $app['some_service.config']);
};

But it can be equally written as

$app['some_service'] = function () use ($app) {
     return new Service($app['some_other_service'], $app['some_service.config']);
};

and I've seen a lot of examples of such code. Is it just personal taste or one of them has benefits over another, such as in performance, memory usage or code isolation?


Edit: I've run perfromance comparison of "use" vs parameter vs simple function:

$func = function () use ($app) {...};
$func = function ($app) {...};
function test($app) {...}

The first one is the slowest, but overall difference is less than 25%. And as any micro-optimization, it's noticeable only if you have tens of thousands of these as the time difference between the fastest and slowest was about 1/10,000,000th of a second (0.05s for 1 million reps).

So performance difference should not be considered.


Solution

  • Here is a direct answer: there is no practical difference. The only scenario I can see where use ($app) wouldn't work is if you define some entries in separate files.

    What follows is just if you are curious ;)

    The advantage of passing the container again in the parameters is that it allows Silex to pass another container instance instead. Silex doesn't do that, so it doesn't affect you. But some other containers do.

    The main reason for a container to do that would be if you have a complex setup with multiple containers that are chained one after another: ParentContainer -> SubContainer. When you define an entry in the SubContainer, you want to be able to fetch dependencies from the parent container (which will automatically look in the subcontainer too). So the subcontainer will pass the parentcontainer in the closure parameter.

    That's an advanced (and rare) use case, but it's interesting to know ;)