klein / klein.php

A fast & flexible router
MIT License
2.66k stars 290 forks source link

Injecting $app, $req, $res, $services params to controllers? #313

Open Aristona opened 8 years ago

Aristona commented 8 years ago

Hey,

I have a code like this:

$klein->respond(function ($request, $response, $service, $app) {
     // Bunch of stuff
});

I want to pass them into a class (not controllers) but doing this each time looks crazy.

$klein->respond(function ($req, $res, $service, $app) {
     $something = new App\Something($req, $res, $service, $app, $myParams);
});

Is there any trick or patterns to pass those values to those classes on the fly. For example, can something like this be done?

class Controller
{
     protected $req, $res, $service, $app;
     public function__construct($req, $res, $service, $app)
     {
            $this->req = $req;
            $this->res = $res;
            $this->service = $service;
            $this->app = $app;
     }
}

class HomeController extends Controller
{
     protected $myParams
     public function__construct($myParams)
     {
            $this->myParams = $myParams;
     }
}

$klein->respond(function ($req, $res, $service, $app) {
     $something = new App\HomeController($myParams);
     dd($something->req); // same as $req
});

I just want to inject $req, $res, $service, $app to my classes somehow.

Any tip would be appreciated.

gandazgul commented 8 years ago

Don't inject it on the class but pass it along to each action method like klein does:

class HomeController extends Controller
{
    public function homeAction($req, $resp, $service, $app)
    {
        return $resp;
    }
}

$controller = new HomeController();

$klein->respond([$controller, 'homeAction']);
Aristona commented 8 years ago

That can be improved I think. Passing 4 parameters to every single method sounds pretty bad imo.

gandazgul commented 8 years ago

The parameters are optional if you are not going to use them then don't put them on the method signature. On Feb 1, 2016 2:45 PM, "Anıl ÜNAL" notifications@github.com wrote:

That can be improved I think. Passing 4 parameters to every single method sounds pretty bad imo.

— Reply to this email directly or view it on GitHub https://github.com/chriso/klein.php/issues/313#issuecomment-178148435.

Aristona commented 8 years ago

I just want to pass them into each controller without having to all 4 variables into methods as seperate parameters. I don't enjoy passing them into methods as parameters everywhere because the app barely be maintainanle like that. That's why I asked this question in first place.

Whenever I create a controller, I want them to be injected into the class (without having to specify that myself, Klein should resolve the call itself and append the parameters automatically) so I can organize my code much easier.

Thanks for your contributions though, but that's not I'm asking for.

jk3us commented 8 years ago

klein includes a simple dependency injector (see $app->register in the docs). Instead of $something = new App\Something($req, $res, $service, $app, $myParams);, you could register something as a dependency:

$app->register("something", function() {
    return new App\Something($req, $res, $service, $app, $myParams);
});

Then, when you need it, you just ass $app for an instance:

$something = $app->something;

and it creates the object with the correct params injected. If you want "smarter" injection, you may want something like php-di, which can look at your classes and try to guess what to inject.

thinsoldier commented 7 years ago

Request, Response, and Service can be pulled from within the $klein object so I just pass that to my controller or add it to a global singleton registry object.

$klein->respond('/search/[results:action]/?[i:page]?', function() use ($klein) {

    $klein->service()->layout('app/layouts/2-column.php');

    $control = new SearchController( $klein );
    $control->run();

});