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

Pass custom arguments to a constructor on $injector->execute() #162

Closed
plashenkov opened this issue Aug 23, 2017 · 5 comments
Closed

Pass custom arguments to a constructor on $injector->execute() #162

plashenkov opened this issue Aug 23, 2017 · 5 comments

Comments

@plashenkov
Copy link

plashenkov commented Aug 23, 2017

Hello!

In execute() method we can pass parameters to a callable, but cannot pass parameters to a class constructor.

Example:

class Foo
{
    public function __construct($constructorArg)
    {
        var_dump($constructorArg);
    }

    public function someMethod($methodArg)
    {
        var_dump($methodArg);
    }
}

$injector->execute('Foo::someMethod', [
    'constructorArg' => 'some-value',
    'methodArg' => 'another-value'
]);

How is it possible to get Auryn inject non-class arguments into a class constructor? Real life example: I have many controllers; I would like to use arguments injection in constructor as well as in methods. I do not want to call define() for each controller in the app. Sure in theory I can parse the 'Foo::someMethod' string myself and instantiate the controller object, but parsing is already nice done inside Auryn (execute() and buildExecutable()), I do not want to duplicate this functionality. Maybe there is some beautiful method to achieve this?

If not, does it make sense to apply args in execute() to a constructor too, not only to a method call?

@Danack
Copy link
Collaborator

Danack commented Aug 23, 2017

How is it possible to get Auryn inject non-class arguments into a class constructor?

$injector->defineParam($name, $value);

I have many controllers; I would like to use arguments injection in constructor as well as in methods. I do not want to call define() for each controller in the app

Where are the args coming from, that you need to define them per controller? Or is this just in a HTTP router scenario?

@plashenkov
Copy link
Author

plashenkov commented Aug 23, 2017

Yep. Router. Args are args from a route. They go to a controller method as well as to a controller itself to provide the user a controller method (let's say $this->getRouteParam('paramName')) located at parent controller class. I.e. the user can get arguments from the route handler (by injecting $args parameter) or by using getRouteParam() method.

Of course, all this can be designed in a different way. For example, through a separate class Request, which will provide route arguments (as well as other methods). Then user can inject this class where he wants it.

Despite this, we yet unable to fully control all constructor arguments when object is created during execute(). defineParam() is global, some local control maybe necessary. Maybe optional third param $constructorArgs = [] for execute() which will be used only for object instantiation (to split up callable's args from constructor's args). What do you think?

Regarding the router scenario: if you can advice something about the right way to do this, I will be grateful. How would you do this (and do in your projects)? Thanks!

@Danack
Copy link
Collaborator

Danack commented Aug 23, 2017

Yep. Router. Args are args from route.

In that case, this is what most people do, for what I understand to be your requirements:

        $route = $router->match($request);
 
        // When route is like "/products/:product_id" and the visitor is on "/product/5"
        // $route->getParams() will return "['product_id' => 5]"
        foreach ($route->getPararms() as $key => $value) {
            $injector->defineParam($key, $value);
        }

       $injector->execute($route->getCallable());

Of course, all this can be designed in a different way. For example, through a separate class Request,

I'm fond of making a more specific type to represent a bag of variables, like variable map, as that makes it easier to unit test controllers.

@plashenkov
Copy link
Author

plashenkov commented Aug 23, 2017

$injector->defineParam($key, $value);

Well, after that these parameters will be available everywhere, not only for this object and this object's method. In each class which will be instantiated via injector further.

This is why I find it useful to have an additional argument in execute() which will allow to exhaustively control instantiating of an object inside this execute() method.

@Danack
Copy link
Collaborator

Danack commented Jun 2, 2023

I'm going to close this issue on the grounds that:

  • it's been almost six years, and no-one has made a PR.

  • I don't think people should be using the custom arguments as they are inherently unsafe, see: Wip separate injector contexts rebase #196

  • Most of the same effect can be done through doing:

$route_injector = clone $injector;
$route_injector->defineParam($key, $value);
$route_injector->execute($route->getCallable());

@Danack Danack closed this as completed Jun 2, 2023
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