Missing getServiceLocator method after migration to laminas-mvc 3.x

I have migrated to Laminas an application that uses Doctrine for the connection to the database.

In it I used
db = this-> getServiceLocator () -> get (‘doctrine.connection.orm_default’);
to work on the database.

But now I get this error:
A plugin by the name “getServiceLocator” was not found in the plugin manager Laminas \ Mvc \ Controller \ PluginManager

Could someone tell me how to go about solving it.

Thank you in advance.

Hello and welcome to the forums! :smiley:

The problem is not related to Doctrine but to an older version of zend-mvc:

laminas-servicemanager v3.0 removes Laminas\ServiceManager\ServiceLocatorAwareInterface .

The short answer is to use a factory for your controller. For explanation with code example please look at the migration guide of laminas-mvc: “Migration – ServiceLocatorAware initializers

1 Like

Thanks Frank, i will try that.

I tried it but it doesn’t work.
This are my files:

module.php:

Abm namespace;

use Sheets \ Db \ Adapter \ AdapterInterface;
use Plates \ Db \ ResultSet \ ResultSet;
use Plates \ Db \ TableGateway \ TableGateway;
use Laminates \ ModuleManager \ Feature \ ConfigProviderInterface;

The class module implements ConfigProviderInterface
{
    private $ db;
    public function getConfig ()
    {
        The return includes __DIR__. '/../config/module.config.php';
    }
    public function getControllerConfig ()
    {
        $ db = new AdapterInterface;
        Return [
            'factories' => [
                Controller \ AbmController :: class => function () {
                    return new Controller \ AbmController ($ db);
                },
                Controller \ AbmControllerFactory :: class => function () {
                    return new Controller \ AbmControllerFactory (
                        );
                },
          ],
         ];
    }
}

AbmControllerFactory.php:

namespace Abm \ Controller;
    
use Interop \ Container \ ContainerInterface;

class AbmControllerFactory
{
    public function __invoke (ContainerInterface $ container)
    {
        return new AbmController ($ container-> get ('Db \ ApplicationAdapter'));
    }
}

The problem is because you’re providing a closure factory directly in your getControllerConfig(), and providing one for each of the controller, and the factory. Instead, you should be mapping the controller to its factory within that configuration. Try this instead:

public function getControllerConfig()
{
    return [
        'factories' => [
            Controller\AbmController::class => Controller\AbmControllerFactory::class,
        ],
    ];
}

What the above does is tell the controller plugin manager that when you request the AbmController class, it should instantiate and consume the AbmControllerFactory class in order to create the instance. Your AbmControllerFactory::__invoke() method will now be used to do that, and that method is written correctly in terms of pulling dependencies from the container to inject.

I tried it but obtain:

*Unable to resolve service "Db\ApplicationAdapter" to a factory; are you certain you provided it during configuration?*

Jorge Mario Paván
+54 9 11 5327 9247
jorge.pavan@gmail.com

Have you registered that service in your application? The exception message indicates you haven’t. That’s your next thing to correct.

Thanks matthew. I did resolve it so:

  • putting in config/autoload/doctrine_orm.local.php the db connection parameters
  • and the AbmControllerFactory.php contains:
use Interop\Container\ContainerInterface;
use Doctrine\DBAL\Connection;

class AbmControllerFactory
{
    public function __invoke(ContainerInterface $container)
    {
        return new AbmController($container->get('doctrine.connection.orm_default'));
    }
}