Routing and anonymous classes

65 views
Skip to first unread message

Diego Cano Lagneaux

unread,
Nov 21, 2017, 6:46:20 AM11/21/17
to Fat-Free Framework
I am writing a simple JsonAPI server, and I've written a basic controller that can handle most objects. For each model I have, I extend this controller with a new class that contains essentially this:
class NewChild extends BasicController {
   
public function __construct() {
     parent
::__construct("NewChild");
   
}
}
Then, I create all REST routes for this controller (the actual methods being defined in the BasicController).

Since it is a bit redundant to write this for each model, I was thinking I could write an anonymous class, automatically, for each model I have, and then pass this class to the routes. However, I don't think this is possible right now in F3. right? Does anyone know how I could do such a thing?

ikkez

unread,
Nov 21, 2017, 7:25:19 AM11/21/17
to Fat-Free Framework
Hi. Well you could use a route parameter for this, and check in the basic controller if it's a valid argument:

class BasicController {

   protected $model;

   public function beforeroute($f3,$args) {
     if (!in_array($args['child'],['NewChildA','NewChildB'])
       $f3->error(404);
     else $this->model = new $args['child'];
   }
}

$f3->route('GET /@child', 'BasicController->get');

Diego Cano Lagneaux

unread,
Nov 21, 2017, 7:40:23 AM11/21/17
to Fat-Free Framework
That's not a bad idea. It's not as clean as I would have hoped, but I guess I could make it work... I would still prefer to be able to pass an argument to the constructor of the controller or have anonymous classes though.

Nuwanda

unread,
Nov 21, 2017, 3:38:56 PM11/21/17
to Fat-Free Framework
This seems to be a problem in all such frameworks where the routes are entry points and the arguments to the class or function are supplied by the framework itself. You can't truly inject.

The request parameter idea would work. Or you could run some logic in a bootstrap file before the routes are processed, set a global variable like $f3->childClass = 'childClass', and then access that in the constructor. But I'm not sure what that gains you.

ved

unread,
Nov 21, 2017, 4:32:30 PM11/21/17
to Fat-Free Framework
If you know for a fact that workflow is always the same and that BasicController is always only extended, maybe set a beforeroute to do something like:

class BasicController {
   
function beforeroute() {
        parent
::__construct(get_class());
   
}
}

This is completely untested and not really something I'd personally consider but just throwing it out there.

Diego Cano Lagneaux

unread,
Nov 22, 2017, 6:04:55 AM11/22/17
to Fat-Free Framework
This wouldn't work, since if we're extending the class then we can directly set the Model in the extended constructor. What I am trying to avoid is to have to extend the controller for each model, and only do it in case I am writing specific code for one.

For now, sadly, I only see two viable options. One, write the child controllers and stop complaining. Two, Ikkez's idea of using the route param. I could use this as a fallback, maybe with a generic child controller that would contain the "find the model" logic, as to no overload the BasicController. 

xfra35

unread,
Nov 22, 2017, 9:14:56 AM11/22/17
to Fat-Free Framework
Just out of curiosity: how would an anonymous class solve your issue?

Diego Cano Lagneaux

unread,
Nov 23, 2017, 4:59:34 AM11/23/17
to Fat-Free Framework


El miércoles, 22 de noviembre de 2017, 15:14:56 (UTC+1), xfra35 escribió:
Just out of curiosity: how would an anonymous class solve your issue?

My initial idea was to, in a foreach(model) loop, create the class, then the routes calling that class.

I have since realized this, although maybe viable, would not be the best way. Simply having the possibility to pass arguments to the constructor of the classes in the route declaration would have been better.

Since none of these are possible though, I've used ikkez's suggestion.
Reply all
Reply to author
Forward
0 new messages