phroute icon indicating copy to clipboard operation
phroute copied to clipboard

Called Method On Filter

Open TCB13 opened this issue 10 years ago • 11 comments

Hello,

Supposing I'm implementing an authentication filter similar to the readme example:

$router->filter('auth', function(){    
     // Authentication logic lives here!
});

And I'm implementing the router as:

$router->group(['before' => 'auth'], function($router){
     $router->get("posts/{id}", ["Posts", "getFullDetails"]);
});

Is there a way I can know on my filter callback method the name of the method being called to dispatch the request?

On the example above I would get a parameter on the callback with the string Posts->getFullDetails or similar telling me what method will be called to dispatch the request. Something like:

$router->filter('auth', function($dispatchMethodName){    
    print $dispatchMethodName // Posts->getFullDetails
});

Thank you.

TCB13 avatar Aug 13 '15 21:08 TCB13

I found out that $handler on Dispatcher.php, line 47, has the information I need. However I'm not sure as how to pass it to the filter since it has a $response parameter that seems to be null, always.

Is it safe to pass $handler into there as well?

Thank you.

TCB13 avatar Aug 14 '15 12:08 TCB13

The response is null for before filters, because there hasn't been any response created at that stage. For after filters, the response is whatever was returned from the route handler.

I can see what you are trying to get to, but I don't think there is an easy way to do that currently. Let me think about this over the weekend and see what I can do.

I've been working on a new version of phroute where the objects composition is much better and would allow you to do this much more easily.

mrjgreen avatar Aug 14 '15 19:08 mrjgreen

Hello!

I decided to try to hack it a bit... and it seems to work, please check this commit: f33092127b59b1ba3dba215a04a917d8d381d2a8

I know, its bad, but I tested it in one of my weekend projects and it seems to work fine.

$router->filter("auth", function($result, $handler) {
    print $handler[0] . "->" . $handler[1] . "()";
    exit();
});

// Output: API\Controller\Test->manualMethod()

Your tests still pass. I didn't write a specific test for this because I'm not familiar with your test code ;).

Have a nice weekend!

TCB13 avatar Aug 15 '15 14:08 TCB13

Any news on this?

TCB13 avatar Aug 20 '15 19:08 TCB13

I would also like to know if this is possible. I need to access the handler in a filter.

Ant59 avatar Sep 15 '15 18:09 Ant59

@Ant59 check my experimental commit above. It works in the described way.

TCB13 avatar Sep 15 '15 18:09 TCB13

Great, thanks! I'll give it a go :+1:

Ant59 avatar Sep 15 '15 18:09 Ant59

@Ant59 great! I'll be waiting some feedback.

TCB13 avatar Sep 15 '15 18:09 TCB13

Hmmm, it seems it's not exactly what I wanted. I need to access the handler before dispatch of ALL routes, and I don't want to have to include every route in a filter group since I need it to be extensible for addons to include routes as easy as possible.

Why is the dispatcher class locked up so tight with private visibility? I can't even access these functions from a child class using extend.

Ant59 avatar Sep 15 '15 18:09 Ant59

My code will only give you the class name / method that will be used to dispatch the request later... Then you can do whatever you want with the class name. Whatever you do on the filter will be done before the dispatch actually happens.

In my case, I'm using the filter above so I can get the name of the class/method that will be used to dispatch the request and do simple CRUD permissions on that. For instance... check is there's a user session and if the user has permissions to access Controllers/Users::list if not redirect to login page or some other place before the dispatch happens.

TCB13 avatar Sep 15 '15 18:09 TCB13

@Ant59 Maybe have a look at this version I started to refactor which exposes the handler as a separate entity via an interface.

https://github.com/mrjgreen/phroute/tree/handler

The reason the class is private, is to prevent extension of the class's internal methods. Inheritance is not the best design pattern when attempting to add functionality - instead composition should be favoured.

Obviously pragmatism should come into it too and I don't want to prevent you from being able to do what you need to, but in this case I would rather spend some time completing the new refactored branch, rather than hacking the current one.

mrjgreen avatar Sep 15 '15 18:09 mrjgreen