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

Injection of already instantiated object #159

Open
chris97pl opened this issue Feb 25, 2019 · 5 comments
Open

Injection of already instantiated object #159

chris97pl opened this issue Feb 25, 2019 · 5 comments

Comments

@chris97pl
Copy link

Is there a way to inject already instantiated object so it can be resolved as shared with further $dice->create() calls?

From my quick glance at the code adding new entry in $instances array should do the trick. Unfortunately I cannot find the proper method to do this and $instances property is private so can't do it even by extending the Dice class.

Am I missing something?

@garrettw
Copy link

You'll want to check out the documentation on substitution rules.

@TRPB
Copy link
Member

TRPB commented Feb 25, 2019

From a purely theoretical point of view, if you're using a DIC, the DIC would normally have the job of creating the instances so the answer would normally be to give dice the rule for constructing the object.

However, with that said, there are a few different ways to reference existing objects, depending on what you're trying to do. You can supply an existing instance either as constructParams or substitutions:

$instance = new MyInstance();

//Configure dice to substitute any type hinted `SomeInterface` with $instance
$dice = $dice->addRule('SomeClass', [
    'substitutions' => ['SomeInterface' => [\Dice\Dice::INSTANCE => $instance ] ]
]);

// Or pass it in as a constructor argument
$dice = $dice->addRule('SomeClass', [
    'constructParams' => [$instance]
]);

You can also set up a global substitution so it gets applied to any type-hinted constructor argument:

//Configure dice to substitute any type hinted `SomeInterface` with $instance
$dice = $dice->addRule('*', [
    'substitutions' => ['SomeInterface' => [\Dice\Dice::INSTANCE => $instance ] ]
]);

If you need more control, Dice also calls closures if they are provided as instances:

$dice = $dice->addRule('*', [
    'substitutions' => ['SomeInterface' => [\Dice\Dice::INSTANCE => function() use ($instance) {
                                      return $instance
                                    } ]
                               ]
]);

Finally, if your existing object is coming from a factory or another DIC you can use call with chaining:

$dice = $dice->addRule('Something', [
	'instanceOf' => 'Pimple'
	'call' => [
		['get', ['SomeClass'], \Dice\Dice::CHAIN_CALL ]
	]
]):

//Calls $pimple->get('SomeClass') and returns the instance
var_dump($dice->create('Something'))

@chris97pl
Copy link
Author

That is brilliant. I was pretty sure I was missing something and I did. That works perfectly well. Thank you for explaining.

@KarlAustin
Copy link

KarlAustin commented Jun 4, 2020

Is this all still valid? As I've just tried this as my code is a module for someone else's software, so some objects I need are already instantiated, nothing I can do about that.

            $di = new \Dice\Dice();
            $di = $di->addRules([
                '*' => [
                    'substitutions' => [
                        'PDO' => [\Dice\Dice::INSTANCE => $db]
                    ],
                ]]);

Where $db is a valid PDO object from the main application.

When I do this, Dice errors with:

Uncaught TypeError: Argument 1 passed to Dice\Dice::create() must be of the type string, object given
dice.php(181): Dice\Dice->create(Object(PDO), Array)

Also tried it using closures:

            $di = $di->addRules([
                '*' => [
                    'substitutions' => [
                        'PDO' => [\Dice\Dice::INSTANCE => function() use ($db) {
                                      return $db;
                                    }]
                    ],
                ]]);

That gives me a PDO exception for invalid DSN - So it looks like it is still trying to construct a new PDO object rather than sub in mine.

Thanks.

@garrettw
Copy link

garrettw commented Jul 21, 2020

@KarlAustin All you need is

            $di = $di->addRules([
                '*' => [
                    'substitutions' => [
                        'PDO' => $db
                    ],
                ]]);

[\Dice\Dice::INSTANCE => $db] always fails because INSTANCE expects a class name string or a callable. I'm not sure about the latter error, but closures there are really only intended for constructing and returning new objects, since the syntax for using existing objects as I mention above is much simpler.

That said, why not allow Dice to create your PDO object on demand and mark it as shared?

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

4 participants