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

How could we use DI with this package #393

Open
mhipo1364 opened this issue Jul 5, 2018 · 1 comment
Open

How could we use DI with this package #393

mhipo1364 opened this issue Jul 5, 2018 · 1 comment

Comments

@mhipo1364
Copy link

mhipo1364 commented Jul 5, 2018

Hi guys

I have a problem with calling callbacks in this package, if I write controller full qualified name in the respond method, my controller's action will be called statically, and if I want to instantiate my controller in respond method, I have to inject all dependencies of my controller when I want to instantiate it.

@eimajenthat
Copy link
Contributor

Well, if you have a class with dependencies, and you want to call an instance method (ie. not call it statically), you have to instantiate the object, and therefore have to inject your dependencies. How you do that depends on your application, and isn't directly connected to your the routing framework. You could use a standalone DI library, like:

https://github.com/auraphp/Aura.Di

Or a lot of the bigger frameworks, like Symfony and Laravel have their own solutions you might be able to re-appropriate. Or you could make your own solution from scratch.

However you do it, there is probably a function to call to retrieve your dependency-injected object, like:

<?php
$object = $di->newInstance('Vendor\Package\ClassName'); // Aura DI
App::make('foo'); // Laravel
$this->get('bar'); // Symfony

Whatever DI magic you use to get your object, you can call that in the route closure:

<?php
require_once __DIR__ . '/vendor/autoload.php';
$klein = new \Klein\Klein();
$klein->route('GET', '/foo', function() { $controller = App::make('foo_controller');});
$klein->dispatch();

If your DI system lives in a locally scoped object try the use keyword:

<?php
$klein->route('GET', '/foo', function() use ($di) { $controller = $di->newInstance('Name\Space\FooController');});

If have a lot of controllers that all load from your DI system, you might abstract this out to a method, something like:

<?php
function do_di_and_routing($controller, $action) {
    $controller_instance = $di->newInstance('Name\Space\' . $controller);
    return function() use ($controller_instance, $action) {
        return $controller_instance->$action();
        // alternatively, there are certain edge cases where this might be preferable, I think...
        // but I can't remember why
        // return call_user_func(array($controller_instance, $action));
    }
}

$klein->route('GET', '/foo/bar', function do_di_and_routing('FooController', 'bar'));
$klein->route('GET', '/foo/baz', function do_di_and_routing('FooController', 'baz'));
$klein->route('GET', '/foo/bagels', function do_di_and_routing('FooController', 'bagels'));

The key there is that the function returns a function (a closure, but that's really a function), which can be passed to the route method. Using closures/functions/whatever gives you an absurd amount of flexibility, where you can do all kinds of crazy stuff. Some of it you probably should do, but I think this is relatively safe.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants