Updating code changes for laminas 3

Hello,

I am facing many issue while upgrading laminas version 3 from laminas 2,

Main/Module.php under onBootstrap() method

public function onBootstrap(MvcEvent $e)
{

    try {
        HttpException::setLoggingDependencies(
            self::getLogger(),
            self::$config['ws_logdir'],
            self::LOG_CHANNEL_HTTP_EXCEPTIONS
        );
        
        LaminasHttpClient::setLoggingDependencies(
            self::getLogger(),
            self::$config['ws_logdir'],
            self::LOG_CHANNEL_TIMEOUTS
        );
        
        LaminasHttpClient::setHttpClientTimeout(self::$config['LaminasHttpClient_considered_as_timeout_limit']);
    } catch (\InvalidArgumentException $exception) {
        throw $exception;
    }
    $environmentName = explode('-', self::$config['__configName'])[0];

    $typeLike = !empty(self::$config['typeLike']) ? self::$config['typeLike'] : null;

    if (self::$config['type'] === 'devel') {
        /**
         * Let's force E_ALL error reporting level (which includes E_DEPRECATED and E_STRICT) in development
         * environments (except for beta, since we want it to act more like production one).
         *
         * @see https://issues.corp.shipwire.com/browse/PUL-334 and related PR for discussion about that.
         */
        $errorReporting = E_ALL;
        error_reporting($errorReporting);
        if ($typeLike === 'vagrant') {
            // Send all errors to stdout so we see them in rtts and will make them fail
            ini_set("display_errors", true);
        } elseif ($typeLike === 'alpha') {
            // Send all errors to logs so rtts will not break
            ini_set("display_errors", false);
        }
    }

    // Set the User Agent sent from the API Client to the APIs
    AppBootstrap::$clientUserAgent = self::$config['apiClientUserAgent'];

    $newRelicMetric = new NewRelic(
        self::$config['newRelic_default_app_name'] . ' (' . $environmentName . ')',
        self::$config['newRelic_endpoint_rpm'],
        self::$config['newRelic_endpoint_api'],
        self::$config['newRelic_apiKey'],
        self::$config['newRelic_applicationId_shipwire'],
        self::$config['metrics_providers_NewRelic_general_enabled']
    );
    $newRelicMetric->setApplicationName(self::$config['newRelic_default_app_name'] . ' (' . $environmentName . ')');

    $request = $e->getRequest();
    if ($request instanceof \Laminas\Http\PhpEnvironment\Request) {
        $requestUri = $request->getRequestUri();
        if (false !== strpos($requestUri, '?')) {
            [$requestUri,] = explode('?', $requestUri, 2);
        }

        $newRelicMetric->setTransactionName($requestUri);
    }

    self::setupErrorHandling([$newRelicMetric], [], self::$config['debug_backtrace']);
    set_error_handler(['\Shipwire\Log\ErrorHandling', 'errorHandler']);
    set_exception_handler(['\Shipwire\Log\ErrorHandling', 'exceptionHandler']);
    $application = $e->getApplication();

    /** @var \Laminas\ServiceManager\ServiceManager $serviceManager */
    $serviceManager = $application->getServiceManager();
    /** @var \Laminas\ModuleManager\ModuleManager $moduleManager */
    $moduleManager = $serviceManager->get('modulemanager');
    /** @var \Laminas\EventManager\SharedEventManager $sharedEvents */
    $sharedEvents = $moduleManager->getEventManager()->getSharedManager();
    $sharedEvents->attach(
        'Laminas\Mvc\Controller\AbstractRestfulController',
        MvcEvent::EVENT_DISPATCH,
        [$this, 'postProcess'],
        -100
    );
    $sharedEvents->attach(
        Application::class,
        MvcEvent::EVENT_DISPATCH_ERROR,
        [$this, 'errorProcess'],
        999
    );
    $di = $serviceManager->get('DI');
// Disable introspection strategy interface injection patterns (they are buggy).
// foreach ($di->get->definitions() as $def) {
// /** @var RuntimeDefinition $def */
// $def->getIntrospectionStrategy()->setInterfaceInjectionInclusionPatterns([]);
// break;
// }

    /** @var \Laminas\Session\SessionManager $sessionManager */
// $sessionManager = $di->get('session_manager');
$manager = new SessionManager();
\Laminas\Session\Container::setDefaultManager($manager);
// \Laminas\Session\Container::setDefaultManager($sessionManager);
$sessionConfig = new SessionConfig();
$sessionConfig->setCookieDomain(self::$config['cookie_domain']);
$manager->setConfig($sessionConfig);

    /** @var \Laminas\ServiceManager\ServiceManager $controllerManager */
    $controllerLoader = $serviceManager->get('ControllerManager');


    // Initialize Controller instance.

    $controllerLoader->addInitializer(

        function ($instance) use ($di, $sharedEvents) {

            

            /** @var \Main\Controller\Reports\AbstractReportsController $instance */
            if (method_exists($instance, 'init')) {
 
                $appConfigurations = array_merge(self::getGatewayDependencies(), self::getCookieDependencies());
                error_log(print_r($appConfigurations,1));
                $user  = (Auth::hasAuthenticatedUser(
                        $di,
                        $appConfigurations
                    ) || $instance->needsAuth) ? Auth::getAuthenticatedUser(
                    $appConfigurations,
                    $di
                ) : null;

                
                $logChannel = self::getLogChannel($instance);
                
                $instance->init(
                    $di,
                    self::getLogger(),
                    self::$config['ws_logdir'],
                    $logChannel,
                    self::$config['inbound-post-default-mappings'],
                    $user
                );

                /**
                 * Register a post-route match callback to check permissions. We want to processAppPermissions
                 * only for users that do not have APP wide access via PERMISSION_ALL (e.g. CS user role)
                 */
                if ($user instanceof \Shipwire\ApiClient\User && !$user->hasPermission(Permissions::PERMISSION_ALL)) {
                    $sharedEvents->attach(
                        'Laminas\Mvc\Controller\AbstractRestfulController',
                        MvcEvent::EVENT_DISPATCH,
                        [$this, 'processAppPermissions'],
                        1000
                    );
                }
            }
            

        }
    );

    // Initialize the state processor library
    $this->initStateProcessor($di);
    // Add logger
    $serviceManager->setService('logger', self::getLogger());
}

module.config.php

'dependencies' => [
'auto' => [
'types' => [
'json-pp' => 'Shipwire\ApiClient\PostProcessor\Json',
'text-pp' => 'Main\PostProcessor\Text',
'file-pp' => 'Shipwire\ApiClient\PostProcessor\File',
'raw-pp' => 'Shipwire\ApiClient\PostProcessor\Raw',

                'db_adapter'                  => 'Laminas\Db\Adapter\Adapter',
                'db_driver'                   => 'Laminas\Db\Adapter\Driver\Mysqli\Mysqli',
                'db_connection'               => 'Laminas\Db\Adapter\Driver\Mysqli\Connection',
                'session_manager'             => 'Laminas\Session\SessionManager',
                'session_save_handler'        => 'Laminas\Session\SaveHandler\Cache',
                'redis_cache_backend'         => 'Laminas\Cache\Storage\Adapter\Redis',
                'redis_cache_backend_options' => 'Laminas\Cache\Storage\Adapter\RedisOptions',

                'LaminasHttpClient' => 'Shipwire\ApiClient\LaminasHttpClient',
                'db_adapter' => [
                    'typeOf' => 'Laminas\Db\Adapter\Adapter',
                    'parameters' => [
                        'driver' => 'db_driver'
                    ],
                ],
                'db_driver' => [
                    'typeOf' => 'Laminas\Db\Adapter\Driver\Mysqli\Mysqli',
                    'parameters' => [
                        'connection' => 'db_connection',
                        'options'    => [
                            'buffer_results' => true
                        ]
                    ],
                ],
                'db_connection' => [
                    'typeOf' => 'Laminas\Db\Adapter\Driver\Mysqli\Connection',
                    'parameters' => [
                        'connectionInfo' => []
                    ],
                ],
// 'state_processor'=>[
// 'parameters' => []
// ],
 'controllers'   => [
            'factories' => [
                //V3
                'json-pp'                       =>  Shipwire\ApiClient\PostProcessor\Json::class,
                'v3Product'                     =>  Main\Controller\V3ProductController::class,
                'v3ProductInsert'               =>  Main\Controller\V3ProductInsertController::class,
                'v3ProductSingle'               =>  Main\Controller\V3ProductSingleController::class,
]

I am facing issue for ControllerManager, According to laminas doc ControllerLoader is not in user in laminas version 3, Hence i have replaced it from ControllerManager but i am not able to call “addInitializer”

` /** @var \Laminas\ServiceManager\ServiceManager $controllerManager */
$controllerLoader = $serviceManager->get('ControllerManager');

    // Initialize Controller instance.

    $controllerLoader->addInitializer(` 

and if i undo the changes then it show error “Unable to resolve service “ControllerLoader” to a factory; are you certain you provided it during configuration?”

Also because of ControllerManager error i am unable to call AbstractController methods,

Please help me for this error,

[Wed Jun 15 23:23:06.944030 2022] [php:notice] [pid 22] [client 172.17.0.1:21991] Exception: Call to a member function addFileChannel() on null --- Backtrace: #0 /var/www/shipwire.www/swclient/vendor/shipwire/internal-shipwire-api-client/src/Shipwire/ApiClient/AbstractController.php(226): Shipwire\\ApiClient\\AbstractController->logAccess()\n#1 /var/www/shipwire.www/swclient/vendor/laminas/laminas-eventmanager/src/EventManager.php(319): Shipwire\\ApiClient\\AbstractController->onDispatch()\n#2 /var/www/shipwire.www/swclient/vendor/laminas/laminas-eventmanager/src/EventManager.php(179): Laminas\\EventManager\\EventManager->triggerListeners()\n#3 /var/www/shipwire.www/swclient/vendor/laminas/laminas-mvc/src/Controller/AbstractController.php(97): Laminas\\EventManager\\EventManager->triggerEventUntil()\n#4 /var/www/shipwire.www/swclient/vendor/laminas/laminas-mvc/src/Controller/AbstractRestfulController.php(307): Laminas\\Mvc\\Controller\\AbstractController->dispatch()\n#5 /var/www/shipwire.www/swclient/vendor/laminas/laminas-mvc/src/DispatchListener.php(132): Laminas\\Mvc\\Controller\\AbstractRestfulController->dispatch()\n#6 /var/www/shipwire.www/swclient/vendor/laminas/laminas-eventmanager/src/EventManager.php(319): Laminas\\Mvc\\DispatchListener->onDispatch()\n#7 /var/www/shipwire.www/swclient/vendor/laminas/laminas-eventmanager/src/EventManager.php(179): Laminas\\EventManager\\EventManager->triggerListeners()\n#8 /var/www/shipwire.www/swclient/vendor/laminas/laminas-mvc/src/Application.php(325): Laminas\\EventManager\\EventManager->triggerEventUntil()\n#9 /var/www/shipwire.www/swclient/public/index.php(15): Laminas\\Mvc\\Application->run()\n#10 {main}, referer: https://merchant.developer.corp.shipwire.com/index/login

—>

[Thu Jun 16 00:45:33.497009 2022] [php:notice] [pid 29] [client 172.17.0.1:41805] Exception: Service with name “json-pp” could not be created. Reason: Could not resolve value for parameter “vars” of type any in class Shipwire\ApiClient\PostProcessor\Json (requested as json-pp) — Backtrace: #0 /var/www/shipwire.www/swclient/vendor/laminas/laminas-servicemanager/src/ServiceManager.php(234): Laminas\ServiceManager\ServiceManager->doCreate()\n#1 /var/www/shipwire.www/swclient/module/Main/Module.php(793): Laminas\ServiceManager\ServiceManager->get()\n#2 /var/www/shipwire.www/swclient/vendor/laminas/laminas-eventmanager/src/EventManager.php(319): Main\Module->errorProcess()\n#3 /var/www/shipwire.www/swclient/vendor/laminas/laminas-eventmanager/src/EventManager.php(171): Laminas\EventManager\EventManager->triggerListeners()\n#4 /var/www/shipwire.www/swclient/vendor/laminas/laminas-mvc/src/DispatchListener.php(146): Laminas\EventManager\EventManager->triggerEvent()\n#5 /var/www/shipwire.www/swclient/vendor/laminas/laminas-eventmanager/src/EventManager.php(319): Laminas\Mvc\DispatchListener->onDispatch()\n#6 /var/www/shipwire.www/swclient/vendor/laminas/laminas-eventmanager/src/EventManager.php(179): Laminas\EventManager\EventManager->triggerListeners()\n#7 /var/www/shipwire.www/swclient/vendor/laminas/laminas-mvc/src/Application.php(325): Laminas\EventManager\EventManager->triggerEventUntil()\n#8 /var/ww

Have you checked the related migration notes for this?

Yes,

  1. For laminas verson 2 we are making use of Laminas/Di/Di and as per documentation, changing it to Laminas/Di/Injector (laminas version 3) gives us error related to Laminas\Di\Injector could not be resolved to a factory.
  2. If we try using it with laminas-servicemanager as suggested for use of IOT, the steps mentioned merely installing laminas-di with laminas-component-installer should make things work but it doesn’t.
  3. We modified the configuration array from di key to dependencies => auto key as suggested in one of the documentation of [laminas.dev(http://laminas.dev/), but that does not seem to work. Background, we migrated from zf2 to laminas-2 and now we have migrated to laminas-3 with respect to the dependencies but the changes need to be done for migration of laminas dependencies v2 to laminas dependencies v3. Also we need to make changes to code as it appears zf2 code needs to be updated to zf3 (which in most documentations mentioned, has to be done prior to migrating to laminas).

We are referring, following steps from laminas documents, but it is no working as expected, for example :

ControllerLoader is deprecated and we are using ControllerManager but addinitializer is not callable, hence it is showing below error,

> according to doc, We need to change the `$invokables` configuration to a combination of `factories` and `aliases`
however it is not working if "invokables" changed to factories.

Please show your changes to the configuration, otherwise it will be difficult or even impossible to understand.