Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactored CallableResolver into a stateless service focused on resolving callables only #1448

Merged
merged 4 commits into from
Aug 20, 2015

Conversation

mnapoli
Copy link
Contributor

@mnapoli mnapoli commented Aug 17, 2015

Per discussions on IRC, I refactored CallableResolver into a stateless service focused on resolving callables only (not wrapping and invoking them).

This will lead to less object instantiations (since the service is now stateless instead of wrapping every middleware/controller callable), as well as better separation of concerns since the class' responsibility is now only to resolve callables. It isn't responsible of invoking callables anymore (responsibility which was spread between here and also the invokation strategy and middleware stack too IIRC).

One detail is that I have moved the $callable->bindTo($container) calls into the CallableResolver itself since it belongs there IMO (because it's about preparing callables for being invokable correctly). That avoids having "callable resolution" code all over the place (App and Route).

Feedback welcome. I'll probably be able to answer and update the PR in 2 days.

…ving callables only

This will lead to less object instantiations (since the service is now stateless instead of wrapping every other callable), as well as better separation of concerns since the class' responsibility is now only to resolve callables. It isn't responsible of invoking callables anymore.

One detail is that I have moved the `$callable->bindTo($container)` calls into the CallableResolver itself since it belongs there (because it's about preparing callables for being invokable correctly). That avoids having "callable resolution" code all over the place (App and Route).
@@ -153,6 +154,8 @@ public function testAddMiddlewareAsString()
$route = $this->routeFactory();

$container = new Container();
$container['MiddlewareStub'] = new MiddlewareStub();

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could someone explain to me how it was working before? I'm afraid I introduced a regression because now I have to register the middleware in the container (and it's not necessary on 3.x).

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It worked before because the CallableResolver was never really invoked, so it did not try to find the MiddlewareStub.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK so that's an improvement then ;)

@mnapoli
Copy link
Contributor Author

mnapoli commented Aug 17, 2015

Also the next step IMO is to remove the CallableResolverAwareTrait (again, per discussions on IRC), but I wanted to do it in a separate pull request.

{
$this->toResolve = $toResolve;
}

/**
* Resolve toResolve into a closure that that the router can dispatch.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Docblock is outdated

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The new signature of the method is public function resolve($toResolve) so it makes sense right?

@JoeBengalen
Copy link
Contributor

Maybe a final check should happen in CallableResolver::resolve() if $resolved is indeed callable.

Currently, anything you pass that is not a string or callable will be returned without modification. And since the resolve() claims to return a callable at all times I think an Exception should be thrown if the resulting $resolved is not callable.

Also I agree on getting rid of the CallableResolverAwareTrait, since its not doing much anymore. Just performing a check (that is not even needed anymore?) and calling CallableResolver::resolve() on the passed argument.

One problem with your current implementation though! Closures will never be bound to the container since it wont get to the CallableResolver. CallableResolverAwareTrait::resolveCallable() will just return the Closure.

Apart from that I think this is an improvement :) Makes much more sense for the CallableResolver to be stateless (as you called it).

Even if a route or middleware is callable, it needs to go through the CallableResolver so that closures are re-bound to the container.
@mnapoli
Copy link
Contributor Author

mnapoli commented Aug 18, 2015

Thanks for the review!

Maybe a final check should happen in CallableResolver::resolve() if $resolved is indeed callable.

Done in ba08a05, an exception will be thrown if the CallableResolver cannot return a real callable.

Closures will never be bound to the container

Oh yeah good catch, I fixed it in e87d996. I also added a test for that to make sure it's staying.

@JoeBengalen
Copy link
Contributor

@ppetermann, good question ... It didn't change in this PR but was already bound to container instead of app. No sure where and why it was changed.

All given examples in de docs assume closures are indeed bound to app.

Edit; found the confusion: Middleware is bound to the container, route callable bound to app.
https://github.com/slimphp/Slim/blob/3.x/Slim/App.php#L237

So this PR should keep that same behaviour.

Currently this PR will break this behaviour.
First in App the route callable will be bound to app: https://github.com/slimphp/Slim/blob/3.x/Slim/App.php#L237

But in the CallableResolver it will be bound to the container (and overwriting the previous bound app)
https://github.com/mnapoli/Slim/blob/simpler_callable_handling/Slim/CallableResolver.php#L74

So in the end route callable will be found to container instead of app, which if wrong.

Edit2:
As @silentworks noted: RouteGroup binds the closure to app too:
https://github.com/slimphp/Slim/blob/3.x/Slim/RouteGroup.php#L61

@juliangut
Copy link
Contributor

CallableResolver is used to resolve both middlewares and routes, so either bindTo is moved out from CallableResolver or it needs a parameter to be told what to bind to?

@silentworks silentworks added pending response Waiting on a response from the original poster Slim 3 labels Aug 18, 2015
@mnapoli
Copy link
Contributor Author

mnapoli commented Aug 19, 2015

Thank you for noticing that. I've restored the way it was before regarding binding Closures to app or container.

@akrabat
Copy link
Member

akrabat commented Aug 19, 2015

Looks good to me.

@akrabat akrabat added this to the 3.0.0 RC1 milestone Aug 19, 2015
@akrabat akrabat removed the pending response Waiting on a response from the original poster label Aug 20, 2015
@akrabat akrabat merged commit 978597b into slimphp:3.x Aug 20, 2015
akrabat added a commit that referenced this pull request Aug 20, 2015
@akrabat
Copy link
Member

akrabat commented Aug 20, 2015

Thanks @mnapoli

@mnapoli mnapoli deleted the simpler_callable_handling branch August 20, 2015 09:23
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants