I know I can achieve this with object Manager – but just wanted to see if there is a better way. Perhaps this case is a good candidate for using the object Manager; however, I would like to do things properly so it'd be good to get some feedback from more experienced developers.
I want to inject an object via a class constructor – and then within the body of the constructor decide what type of object it is.
I will use the Module Manager to check if a module exists – if so then I'd like to use one of its classes. Otherwise, I'd like to use another class in core.
The reason it is possible is because both the classes (the one that might not be available and the one in the core) have the same class name and method that I need to use).
Obviously I can't inject the class that might not exist directly. Here is some code as an example:
/**
* MyClass constructor.
*
* @param {unsure how to define it} $object
* @param \Magento\Framework\Module\Manager $moduleManager
*/
public function __construct({unsure how to define it} $object,
\Magento\Framework\Module\Manager $moduleManager,
)
{
$this->_moduleManager = $moduleManager;
if ($this->_moduleManager->isEnabled('ThirdPartyExtension_PerhapsNotInstalled')) {
$object = $classThatMightNotExist;
} else {
$object = $coreClass;
}
$this->_object = $object;
}
Best Answer
First Approach:
The cleanest way is to not take decisions in the constructor.
Let the
di.xml
do that for you.Let's say the core class you are using if a module is not present is
Some\Core\ClassName
.And the class that should use this core class us
My\Custom\ClassName
.And the class that might not exist is
MyExtension\PerhapsNotInstalled\ClassThatMightNotExist
Make your class constructor like this:
Now, in your module
MyExtension_PerhapsNotInstalled
di.xml
file add this:just make sure that
MyExtension\PerhapsNotInstalled\ClassThatMightNotExist
extends the core classSome\Core\ClassName
.This way, if the module
MyExtension_PerhapsNotInstalled
is not installed, the original core classSome\Core\ClassName
will be used, otherwiseMyExtension\PerhapsNotInstalled\ClassThatMightNotExist
will be used.Second Approach:
If your extension that might not exist, is a third party extension that you cannot control, and you want your code to work with it and without it, you can do this (using the same notations as above):
Create your own class that acts as a factory:
Let's call it
My\Module\Factory
You should inject this new class in the constructor of your
My\Custom\ClassName
class and call thecreate
method from it to determine the class instance you need.Note: This second approach is not really clean, because in theory your dependencies should be explicit and the composition should be done via
di.xml
but I certainly understand the need.Second Note: You are not violating any guidelines of not using the object manager, because OM is allowed in factories and you just created a factory.
And your class does not depend on the OM directly.
I didn't test the code, so watch out for syntax errors.