はじめに
お仕事で、Zend Frameworkのバージョンアップをしなければならなくなった・・と思ったら、Zend Frameworkはもうなくて、Laminas Projectに移って新たなフレームワークとして公開されている。
いちから勉強しないといけないじゃん、ということで、必要な要件を満たせるかどうかを一歩ずつ調査していく。
要件(4)
4つ目の要件は、「複数のモジュール間で行き来ができること」。
前回、同一モジュール内でのforward/redirectはできることを確認したが、複数モジュール間でできるのかなど、その辺りも含めて確認していく。
検証ポイントは以下の通り。
- 複数モジュール間でforwardができるかどうか
- その際、渡されたパラメータは引き継げるか(当然できるよね、のテンションで)
- 複数モジュール間でredirectができるかどうか
- その際、パラメータは引き継げないことの確認(これはその性質から当然だよね、のテンションで)
導入
こちらでセットアップした環境を(コピーして)使っていく。
私は以下のようにコピーを作成。
cp -pr laminas-setup-3-forward-redirect laminas-setup-4-multiple-modules cd laminas-setup-4-multiple-modules
設定・実装
新たなモジュールAnotherModuleの追加
新たに作るモジュール名をAnotherModuleとする。
composer.jsonを以下のように修正する。
"autoload": {
"psr-4": {
"Application\\": "module/Application/src/",
}
},
を
"autoload": {
"psr-4": {
"Application\\": "module/Application/src/",
"AnotherModule\\": "module/AnotherModule/src/"
}
},
とする。 修正が済んだら、以下のコマンドを実行。
composer dump-autoload
config/modules.config.phpにAnotherModuleを追加する。
<?php
/**
* List of enabled modules for this application.
*
* This should be an array of module namespaces used in the application.
*/
return [
'Laminas\Router',
'Laminas\Validator',
'Application',
'AnotherModule',
'Smarty',
];
続いて、AnotherModuleを作成していく。
mkdir module/AnotherModule mkdir module/AnotherModule/config mkdir -p module/AnotherModule/src/Controller mkdir -p module/AnotherModule/view/another-module mkdir module/AnotherModule/view/another-module/index mkdir module/AnotherModule/view/another-module/forwarded mkdir module/AnotherModule/view/another-module/redirected
module/AnotherModule/config/module.config.phpを以下の内容で作成する。
<?php
declare(strict_types=1);
namespace AnotherModule;
use Laminas\Router\Http\Literal;
use Laminas\Router\Http\Segment;
use Laminas\ServiceManager\Factory\InvokableFactory;
return [
'router' => [
'routes' => [
'another-module' => [
'type' => Segment::class,
'options' => [
'route' => '/another-module[/:action]',
'defaults' => [
'controller' => Controller\IndexController::class,
'action' => 'index',
],
],
],
'forwarded2' => [
'type' => Segment::class,
'options' => [
'route' => '/another-module/forwarded[/:action]',
'defaults' => [
'controller' => Controller\ForwardedController::class,
'action' => 'index',
],
],
],
'redirected2' => [
'type' => Segment::class,
'options' => [
'route' => '/another-module/redirected[/:action]',
'defaults' => [
'controller' => Controller\RedirectedController::class,
'action' => 'index',
],
],
],
],
],
'controllers' => [
'factories' => [
Controller\IndexController::class => InvokableFactory::class,
Controller\ForwardedController::class => InvokableFactory::class,
Controller\RedirectedController::class => InvokableFactory::class,
],
],
'view_manager' => [
'display_not_found_reason' => true,
'display_exceptions' => true,
'doctype' => 'HTML5',
'not_found_template' => 'error/404',
'exception_template' => 'error/index',
'template_map' => [
'another-module/index/index' => __DIR__ . '/../view/another-module/index/index.tpl',
'another-module/index/chrome' => __DIR__ . '/../view/another-module/index/chrome.tpl',
'another-module/index/firefox' => __DIR__ . '/../view/another-module/index/firefox.tpl',
],
'template_path_stack' => [
__DIR__ . '/../view',
],
'strategies' => [
'Smarty\\View\\Strategy',
],
],
];
module/AnotherModule/src/Controller/IndexController.phpを以下の内容で作成する。
<?php
declare(strict_types=1);
namespace AnotherModule\Controller;
use Laminas\Mvc\Controller\AbstractActionController;
use Laminas\View\Model\ViewModel;
class IndexController extends AbstractActionController
{
public function indexAction()
{
$timeStr = 'AnotherModule' . date(' [Y/m/d H:i:s]');
$isFirefox = preg_match('/Firefox/', $_SERVER['HTTP_USER_AGENT']);
return new ViewModel([
'time_str' => $timeStr,
'user_agent' => $_SERVER['HTTP_USER_AGENT'],
'is_firefox' => $isFirefox,
]);
}
}
module/AnotherModule/src/Controller/ForwardedController.phpを以下の内容で作成する。
<?php
declare(strict_types=1);
namespace AnotherModule\Controller;
use Laminas\Mvc\Controller\AbstractActionController;
use Laminas\View\Model\ViewModel;
class ForwardedController extends AbstractActionController
{
public function chromeAction()
{
$a = isset($_GET['a']) ? $_GET['a'] : 'N/A';
$c = isset($_GET['c']) ? $_GET['c'] : 'N/A';
return new ViewModel(['a' => $a, 'c' => $c]);
}
public function firefoxAction()
{
$a = isset($_GET['a']) ? $_GET['a'] : 'N/A';
$c = isset($_GET['c']) ? $_GET['c'] : 'N/A';
return new ViewModel(['a' => $a, 'c' => $c]);
}
}
module/AnotherModule/src/Controller/RedirectedController.phpを以下の内容で作成する。
<?php
declare(strict_types=1);
namespace AnotherModule\Controller;
use Laminas\Mvc\Controller\AbstractActionController;
use Laminas\View\Model\ViewModel;
class RedirectedController extends AbstractActionController
{
public function chromeAction()
{
$a = isset($_GET['a']) ? $_GET['a'] : 'N/A';
$c = isset($_GET['c']) ? $_GET['c'] : 'N/A';
return new ViewModel(['a' => $a, 'c' => $c]);
}
public function firefoxAction()
{
$a = isset($_GET['a']) ? $_GET['a'] : 'N/A';
$c = isset($_GET['c']) ? $_GET['c'] : 'N/A';
return new ViewModel(['a' => $a, 'c' => $c]);
}
}
module/AnotherModule/src/Module.phpを以下の内容で作成する。
<?php
declare(strict_types=1);
namespace AnotherModule;
class Module
{
public function getConfig(): array
{
/** @var array $config */
$config = include __DIR__ . '/../config/module.config.php';
return $config;
}
}
module/AnotherModule/view/another-module/index/index.tplを以下の内容で作成する。
Index view (AnotherModule)
<br />
PHP version: {$smarty.const.PHP_VERSION}
<br />
Time: {$time_str|escape:"html"}
<br />
Firefox: {$is_firefox}
<br />
User-Agent: {$user_agent|escape:"html"}
module/AnotherModule/view/another-module/forwarded/chrome.tplを以下の内容で作成する。
AnotherModule<br>
Forwarded Chrome view
<br>
a={$a}, c={$c}
module/AnotherModule/view/another-module/forwarded/firefox.tplを以下の内容で作成する。
AnotherModule<br>
Forwarded Firefox view
<br>
a={$a}, c={$c}
module/AnotherModule/view/another-module/redirected/chrome.tplを以下の内容で作成する。
AnotherModule<br>
Redirected Chrome view
<br>
a={$a}, c={$c}
module/AnotherModule/view/another-module/redirected/firefox.tplを以下の内容で作成する。
AnotherModule<br>
Redirected Firefox view
<br>
a={$a}, c={$c}
既存モジュールApplicationの修正
module/Application/src/Controller/IndexController.phpを以下のように修正する。
変更点は、以下のメソッドの追加。AnotherModuleへforward/redirectするためのメソッドとなる。
public function redirect2Action()
{
$isFirefox = preg_match('/Firefox/', $_SERVER['HTTP_USER_AGENT']);
if ($isFirefox) {
return $this->redirect()->toRoute('redirected2', ['action' => 'firefox']);
} else {
return $this->redirect()->toRoute('redirected2', ['action' => 'chrome']);
}
}
public function forward2Action()
{
$isFirefox = preg_match('/Firefox/', $_SERVER['HTTP_USER_AGENT']);
if ($isFirefox) {
$forward = $this->forward()->dispatch(\AnotherModule\Controller\ForwardedController::class, ['action' => 'firefox']);
} else {
$forward = $this->forward()->dispatch(\AnotherModule\Controller\ForwardedController::class, ['action' => 'chrome']);
}
return $forward;
}
変更後の内容は以下の通り。
<?php
declare(strict_types=1);
namespace Application\Controller;
use Laminas\Mvc\Controller\AbstractActionController;
use Laminas\View\Model\ViewModel;
class IndexController extends AbstractActionController
{
public function indexAction()
{
$timeStr = date('Y/m/d H:i:s');
$isFirefox = preg_match('/Firefox/', $_SERVER['HTTP_USER_AGENT']);
return new ViewModel([
'time_str' => $timeStr,
'user_agent' => $_SERVER['HTTP_USER_AGENT'],
'is_firefox' => $isFirefox,
]);
}
public function redirectAction()
{
$isFirefox = preg_match('/Firefox/', $_SERVER['HTTP_USER_AGENT']);
if ($isFirefox) {
return $this->redirect()->toRoute('redirected', ['action' => 'firefox']);
} else {
return $this->redirect()->toRoute('redirected', ['action' => 'chrome']);
}
}
public function forwardAction()
{
$isFirefox = preg_match('/Firefox/', $_SERVER['HTTP_USER_AGENT']);
if ($isFirefox) {
$forward = $this->forward()->dispatch(ForwardedController::class, ['action' => 'firefox']);
} else {
$forward = $this->forward()->dispatch(ForwardedController::class, ['action' => 'chrome']);
}
return $forward;
}
public function redirect2Action()
{
$isFirefox = preg_match('/Firefox/', $_SERVER['HTTP_USER_AGENT']);
if ($isFirefox) {
return $this->redirect()->toRoute('redirected2', ['action' => 'firefox']);
} else {
return $this->redirect()->toRoute('redirected2', ['action' => 'chrome']);
}
}
public function forward2Action()
{
$isFirefox = preg_match('/Firefox/', $_SERVER['HTTP_USER_AGENT']);
if ($isFirefox) {
$forward = $this->forward()->dispatch(\AnotherModule\Controller\ForwardedController::class, ['action' => 'firefox']);
} else {
$forward = $this->forward()->dispatch(\AnotherModule\Controller\ForwardedController::class, ['action' => 'chrome']);
}
return $forward;
}
}
module/Application/src/Controller/ForwardedController.phpを以下のように修正する。
return new ViewModel();
を
$a = isset($_GET['a']) ? $_GET['a'] : 'N/A';
$c = isset($_GET['c']) ? $_GET['c'] : 'N/A';
return new ViewModel(['a' => $a, 'c' => $c]);
に修正。 修正後の内容は以下のようになる。
<?php
declare(strict_types=1);
namespace Application\Controller;
use Laminas\Mvc\Controller\AbstractActionController;
use Laminas\View\Model\ViewModel;
class ForwardedController extends AbstractActionController
{
public function indexAction()
{
$timeStr = date('Y/m/d H:i:s');
$isFirefox = preg_match('/Firefox/', $_SERVER['HTTP_USER_AGENT']);
return new ViewModel([
'time_str' => $timeStr,
'user_agent' => $_SERVER['HTTP_USER_AGENT'],
'is_firefox' => $isFirefox,
]);
}
public function chromeAction()
{
$a = isset($_GET['a']) ? $_GET['a'] : 'N/A';
$c = isset($_GET['c']) ? $_GET['c'] : 'N/A';
return new ViewModel(['a' => $a, 'c' => $c]);
}
public function firefoxAction()
{
$a = isset($_GET['a']) ? $_GET['a'] : 'N/A';
$c = isset($_GET['c']) ? $_GET['c'] : 'N/A';
return new ViewModel(['a' => $a, 'c' => $c]);
}
}
module/Application/src/Controller/RedirectedController.phpを以下のように修正する。
return new ViewModel();
を
$a = isset($_GET['a']) ? $_GET['a'] : 'N/A';
$c = isset($_GET['c']) ? $_GET['c'] : 'N/A';
return new ViewModel(['a' => $a, 'c' => $c]);
に修正。 修正後の内容は以下のようになる。
<?php
declare(strict_types=1);
namespace Application\Controller;
use Laminas\Mvc\Controller\AbstractActionController;
use Laminas\View\Model\ViewModel;
class RedirectedController extends AbstractActionController
{
public function indexAction()
{
$timeStr = date('Y/m/d H:i:s');
$isFirefox = preg_match('/Firefox/', $_SERVER['HTTP_USER_AGENT']);
return new ViewModel([
'time_str' => $timeStr,
'user_agent' => $_SERVER['HTTP_USER_AGENT'],
'is_firefox' => $isFirefox,
]);
}
public function chromeAction()
{
$a = isset($_GET['a']) ? $_GET['a'] : 'N/A';
$c = isset($_GET['c']) ? $_GET['c'] : 'N/A';
return new ViewModel(['a' => $a, 'c' => $c]);
}
public function firefoxAction()
{
$a = isset($_GET['a']) ? $_GET['a'] : 'N/A';
$c = isset($_GET['c']) ? $_GET['c'] : 'N/A';
return new ViewModel(['a' => $a, 'c' => $c]);
}
}
以下のファイルを修正する。
module/Application/view/application/forwarded/chrome.tplmodule/Application/view/application/forwarded/firefox.tplmodule/Application/view/application/redirected/chrome.tplmodule/Application/view/application/redirected/firefox.tpl
修正内容は、以下の記述の追加。ファイルの末尾に追加する。
<br>
a={$a}, c={$c}
動作確認
http://192.168.56.xxx/laminas-setup-4-multiple-modules/public/application/forward?a=b&c=dへアクセスする
Applicationモジュールへのforward
Firefoxの場合


http://192.168.56.xxx/laminas-setup-4-multiple-modules/public/application/forward2?a=b&c=dへアクセスする
AnotherModuleモジュールへのforward
Firefoxの場合


http://192.168.56.xxx/laminas-setup-4-multiple-modules/public/application/redirect?a=b&c=dへアクセスする
Applicationモジュールへのredirect
Firefoxの場合


http://192.168.56.xxx/laminas-setup-4-multiple-modules/public/application/redirect2?a=b&c=dへアクセスする
AnotherModuleへのredirect
Firefoxの場合


まとめ
- 複数モジュール間でも、forwardやredirectができることが確認できた
- forwardは、
module/*/config/module.config.phpに記述したコントローラーのクラス名を記述する - redirectは、
module/*/config/module.config.phpに記述したrouteの名前を記述する