Upgrade custom modules to work with Zend 3
You must test your custom modules on a test system before transferring them to your production system. This avoids any negative impact on the operation of your production system. If you have more than one custom module, the modules should all be tested at the same time on the same test system as this ensures that the modules operate correctly with each other and with P4 Code Review.
If you add or edit a module, P4 Code Review will not use that change until the config cache has been reloaded, this forces P4 Code Review to use the module change. You must be an admin or super user to reload the P4 Code Review config cache. Navigate to the User id dropdown menu, select System Information, click the Cache Info tab, and click the System Information.
P4 Code Review 2019.1 uses the Zend 3 framework, previous P4 Code Review versions used the Zend 2 framework. The move to Zend 3 is part of our commitment to move away from using versions of platforms that have reached End-of-Life (EOL).
If you have any custom P4 Code Review modules that were created for P4 Code Review 2018.3 or earlier you must update them so that they will work in P4 Code Review 2019.1 and later.
The section describes the changes that you must make to your custom modules to enable them to work with P4 Code Review 2019.1 and later, it includes:
- Summary of changes for the Zend 3 Framework that impact P4 Code Review
- Upgrade custom modules for P4 Code Review 2019.1 and later
- Further reading: links to a worked example and official Zend documentation
Summary of changes for the Zend 3 Framework that impact P4 Code Review
The following Zend 3 changes are important for P4 Code Review custom modules:
- Custom module file locations have changed to the PSR-4 standard locations shown below. For information on how this affects an existing custom module, see Custom module file locations.
config/
custom.modules.config.php (new file, required)
module/
ModuleName/ (required)
config/ (required)
module.config.php (existing file, required)
src/ (php files here, required)
Controller/
MyIndexController.php
...
other directories (non-php files here, optional)
...
Module.php (existing file, required)
Previously P4 Code Review checked the modules directory and used any modules it found there.
We recommend you follow the ::class description to avoid errors in string representation. For information on changing from invokables definitions to factories, see IndexControllers.
We recommend you follow the ::class description to avoid errors in string representation. For instructions on changing from invokables definitions to factories, see View Helpers.
Your routes must be updated, see Routes.
Your event listeners should be changed to use the new declarative model. For instructions on changing the event listeners, see Event listeners.
Your existing listeners will continue to work for P4 Code Review 2019.1 if you want to keep using them but we strongly recommend you move your event listeners to use the declarative model.
Upgrade custom modules for P4 Code Review 2019.1 and later
This section describes the changes that you need to make to a custom module to refactor it for the Zend 3 framework.
The new language features in PHP 7.x enable you to use [] as a shortcut for array().
Custom module file locations
The file locations for custom modules has changed to the PSR-4 standard location.
For P4 Code Review 2018.3 and earlier the file locations are
module/
MyModuleName/
config/
module.config.php
src/
MyModuleName/
Controller/
MyIndexController.php
Module.php
For P4 Code Review 2019.1 and later the file locations are
Changes:
- The custom.modules.config.php is a new file and is required, see custom.modules.config.php.
- The Controller directory has moved up the file structure so that it is now in the module/MyModuleName/src directory.
- The MyIndexController file has moved up the file structure so that it is now in the module/MyModuleName/src/Controller directory.
- The MyModuleName directory under the src directory is no longer used.
config/
custom.modules.config.php
module/
MyModuleName/
config/
module.config.php
src/
Controller/
MyIndexController.php
Module.php
custom.modules.config.php
The custom.modules.config.php is a new file and is required.
P4 Code Review uses this file to check which custom modules it should load. This gives you control over which modules P4 Code Review loads and prevents modules from being loaded by mistake.
Create the custom.modules.config.php file if it does not already exist. Edit the file so that it contains the following details for each of your modules:
- namespaces array: enter your custom module names and paths
- return array : enter your custom module names
For example, if you have three modules called MyModuleName, AnotherModuleName, and NewModuleName the file content would look similar to:
<?php
\Zend\Loader\AutoloaderFactory::factory(
array(
'Zend\Loader\StandardAutoloader' => array(
'namespaces' => array(
'MyModuleName' => BASE_PATH . '/module/MyModuleName/src',
'AnotherModuleName' => BASE_PATH . '/module/AnotherModuleName/src',
'NewModuleName' => BASE_PATH . '/module/NewModuleName/src',
)
)
)
);
return [
'MyModuleName',
'AnotherModuleName',
'NewModuleName',
];
IndexControllers
Zend has deprecated the use of getServiceLocator() to get services. This means that your invokables must be changed to factories and the factory that creates the index controller must inject the services.
We recommend you follow the ::class description to avoid errors in string representation.
For P4 Code Review 2018.3 and earlier the index controllers used invokables
'controllers' => array(
'invokables' => array(
'MyModuleName\Controller\Index' => 'MyModuleName\Controller\IndexController'
),
),
For P4 Code Review 2019.1 and later the index controllers must use factories
The IndexController should extend Application\Controller\AbstractIndexController, this means that the IndexControllerFactory can automatically inject the services . In this case you can use the P4 Code Review IndexControllerFactory.
Change: Index controller refactored to use factories.
'controllers' => array(
'factories' => [
MyModuleName\Controller\IndexController::class => Application\Controller\IndexControllerFactory::class,
],
),
View Helpers
Zend has deprecated the use of getServiceLocator() to get services. This means that your invokables must be changed to factories and the factory that creates the view helper must inject the services.
We recommend you follow the ::class description to avoid errors in string representation.
For P4 Code Review 2018.3 and earlier the view helpers use invokables definitions
'view_helpers' => array(
'invokables' => array(
'helper1' => 'MyModuleName\View\Helper\Helper1',
'helper2' => 'MyModuleName\View\Helper\Helper2',
),
),
For P4 Code Review 2019.1 and later the view helpers must use factories
In the following example, <YourHelperFactory> should construct the correct helper based on the name and inject services if needed. We recommend using ::class rather than arbitrary strings as this can limit the possibility of errors. The use of classes also makes your factory simpler because reflection can be used to construct the helpers if they all extend a common parent class.
Change: View helpers refactored to use factories.
'view_helpers' => array(
'factories' => array_fill_keys(
[
MyModuleName\View\Helper\Helper1::class,
MyModuleName\View\Helper\Helper2::class,
],
<YourHelperFactory>::class
)
)
Routes
Update your routes in module.config.php to match the new controller definitions.
For P4 Code Review 2018.3 and earlier routes would look similar to
'MyModuleName-message' => array(
'type' => 'Zend\Mvc\Router\Http\Segment',
'options' => array(
'route' => '/MyModuleName/message[/]',
'defaults' => array(
'controller' => 'MyModuleName\Controller\Index',
'action' => 'message'
),
),
),
For P4 Code Review 2019.1 and later routes must be changed to look similar to
Changes:
- The route has been changed for 'type'
- The route has been changed for 'controller'
'MyModuleName-message' => array(
'type' => 'Zend\Router\Http\Segment',
'options' => array(
'route' => '/MyModuleName/message[/]',
'defaults' => array(
'controller' => MyModuleName\Controller\IndexController::class,
'action' => 'message'
),
),
),
Event listeners
Your existing listeners will continue to work for P4 Code Review 2019.1 if you want to keep using them but we strongly recommend you move your event listeners to use the declarative model.
We strongly recommend that you refactor your event listeners to use the declarative model because it has a number of advantages over the previous method:
- AbstractEventListener provides common code for listeners to use
- The declarative model offers better debug options (logging)
- The declarative model is neater, easier to read, easier to support, and easier to maintain
Your listeners should extend Events\Listener\AbstractEventListener. This means that the ListenerFactory can create them without you having to write your own factory.
Look at the code in the AbstractEventListener.php file in module/events/src/Listener of P4 Code Review 2019.1 and later to see the functions that are available to you.
For P4 Code Review 2018.3 and earlier the event listeners look similar to
namespace MyModuleName;
use Zend\Mvc\MvcEvent;
class Module
{
public function onBootstrap(MvcEvent $event)
{
$application = $event->getApplication();
$services = $application->getServiceManager();
$events = $services->get('queue')->getEventManager();
$events->attach(
'*',
function ($event) {
$mail = $event->getParam('mail');
if (!$mail || !isset($mail['htmlTemplate'], $mail['textTemplate'])) {
return;
}
}
-199
);
}
}
For P4 Code Review 2019.1 and later when using the declarative structure the event listeners should look similar to
Changes:
- New listener directory created in the MyModuleName directory, in the following example the directory is called Listener
- New listener PHP file created in the listener directory, in this example it is called Listener.php
- Edit the content of your module.config.php to configure your event listeners, this replaces the attach listener event functionality of the onBootstrap method in the original Module.php file.
namespace MyModuleName\Listener;
use Events\Listener\AbstractEventListener;
use Zend\EventManager\Event;
class Listener extends AbstractEventListener
{
public function handleEmail(Event $event)
{
$mail = $event->getParam('mail');
if (!$mail || !isset($mail['htmlTemplate'], $mail['textTemplate'])) {
return;
}
}
}
Further reading
P4 Code Review supports the Laminas component versions in the LICENSE.txt file, features and functions in the Laminas documentation that were introduced in later versions of Laminas will not work with P4 Code Review. The LICENSE.txt file is in the readme folder of your P4 Code Review installation.
- Worked example of the changes required for a custom email module: EmailExample module upgrade to Zend 3
- Zend 3 framework documentation: https://framework.zend.com/learn
- Zend 3 Quick Start documentation: https://docs.zendframework.com/zend-mvc/quick-start/
- Migration from Zend Framework version 2 to version 3, see https://docs.zendframework.com/tutorials/migration/to-v3/overview/