In a Zend Framework 2 module, I use a closure as factory:
'controllers' => [
'factories' => [
'ZendSkeletonModule\Controller\Skeleton' => function(AbstractPluginManager $pm) {
return new Controller\SkeletonController($pm->getServiceLocator()->get('Doctrine\ORM\EntityManager'));
},
],
],
While this works without any problems, my IDE (PHP Storm) complains at $pm->getServiceLocator()->get('Doctrine\ORM\EntityManager')
with the following message:
Expected \Doctrine\ORM\EntityManagerInterface, got array|object.
Invocation parameter types are not compatible with declared.
That is because in the controller, I use Doctrine\ORM\EntityManagerInterface
as a type hint, I get that.
But why does PHP Storm complain, I don't see anything wrong here? Also, the code works fine, so I am a bit puzzled. Do I need to add some kind of special comment or something to 'help' the IDE?
Assign the EntityManager to a variable with an annotation that PhpStorm's static analysis can use. The get
method on its own is opaque to it:
use Doctrine\ORM\EntityManager;
// snip
'controllers' => [
'factories' => [
'ZendSkeletonModule\Controller\Skeleton' => function(AbstractPluginManager $pm) {
/** @var EntityManager $entityManager */
$entityManager = $pm->getServiceLocator()->get(EntityManager::class);
return new Controller\SkeletonController($entityManager);
},
],
],
A couple additional suggestions:
Rather than using a closure, use a concrete factory class. This is because closures cannot be opcode cached, and also your config array cannot be cached if it contains closures.
A small thing, but assuming PHP 5.5+, consider using \Doctrine\ORM\EntityManager::class
like I did in the example above, instead of a string literal for the get method on the ServiceLocator.