Zend Framework 3 アプリケーションでの日本語ヴァリデーションメッセージ導入まで

先日 Zend Framework 3 のステーブルリリースが行われました。[^1]

Zend Framework 3を使った場合でのアプリケーション - ZendSkeletonApplication ( `zendframework/skeleton-application` )
を利用する場合での、ヴァリデーションメッセージの日本語利用法について以下記載します。

## スケルトンアプリケーションのインストール

composerコマンドでインストールします(例ではインストールパスを `zend-skeleton-app-v3` とします。)

```sh
$php composer.phar create-project -sdev zendframework/skeleton-application zend-skeleton-app-v3
```

インストール時に確認項目が出てきますが、ここでは一旦最小のモジュール類をインストールしてます。

```sh
Generating autoload files

    Do you want a minimal install (no optional packages)? Y/n
y
    Removing optional packages from composer.json
    Updating composer.json
Removing zendframework/zend-skeleton-installer...
  - Removing zendframework/zend-skeleton-installer (0.1.3)
    Removed plugin zendframework/zend-skeleton-installer.
    Removing from composer.json
    Complete!
Do you want to remove the existing VCS (.git, .svn..) history? [Y,n]? Y
```

## 必要モジュール・コンポーネントのインストール

i18n設定をモジュールで利用可能にするため `zend-mvc-i18n` をインストールします。

```sh
$ php composer.phar require zendframework/zend-mvc-i18n
```

composerの確認項目が以下でてきますが、モジュールとして利用可能にするために `[1] config/modules.config.php` を選択します。

```sh
Using version ^1.0 for zendframework/zend-mvc-i18n
./composer.json has been updated
Loading composer repositories with package information
Updating dependencies (including require-dev)
  - Installing zendframework/zend-i18n (2.7.3)
    Downloading: 100%


  Please select which config file you wish to inject 'Zend\I18n' into:
  [0] Do not inject
  [1] config/modules.config.php
  [2] config/development.config.php.dist
  Make your selection (default is 0):1

  Remember this option for other packages of the same type? (y/N)y
Installing Zend\I18n from package zendframework/zend-i18n
  - Installing zendframework/zend-mvc-i18n (1.0.0)
    Downloading: 100%
```

この他に、ヴァリデーションにて利用する各コンポーネントをインストールしておきます。
※ 上記同様に` Please select which config file you wish to inject ` の確認項目がでてきますが同様に  `[1] config/modules.config.php` を選択するとよいでしょう。

```sh
$php composer.phar require zendframework/zend-validator
$php composer.phar require zendframework/zend-filter
$php composer.phar require zendframework/zend-inputfilter
```

## 日本語メッセージのダウンロード

日本語ほか言語リソースを利用する場合、 `zend-i18n-resources` をダウンロードします。

```sh
php composer.phar require zendframework/zend-i18n-resources
```

## 依存コンポーネント・モジュールの確認

ここまでのステップを踏んだ場合、`composer.json` でのrequireセクションは以下の通りになります。

```json
{
    "require": {
        "php": "^5.6 || ^7.0",
        "zendframework/zend-component-installer": "^1.0 || ^0.3 || ^1.0.0-dev@dev",
        "zendframework/zend-mvc": "^3.0.1",
        "zfcampus/zf-development-mode": "^3.0",
        "zendframework/zend-i18n-resources": "^2.5",
        "zendframework/zend-mvc-i18n": "^1.0",
        "zendframework/zend-validator": "^2.8",
        "zendframework/zend-filter": "^2.7",
        "zendframework/zend-inputfilter": "^2.7"
    }
}
```    

また、`config/modules.config.php` では以下のモジュールが設定されているはずです。

```php
<?php
return [
    'Zend\InputFilter',
    'Zend\Filter',
    'Zend\Mvc\I18n',
    'Zend\I18n',
    'Zend\Router',
    'Zend\Validator',
    'Application',
];
```

## 日本語ファイルの指定

アプリケーション用設定ファイル　`config/autoload/global.php` などにて以下の通り日本語ファイルの指定を行います。

```php
<?php
return [
    'translator' => [
        'locale' => 'ja_JP',
        'translation_files' => [
            [
                'type' => 'phparray',
                'filename' => __DIR__.'/../../vendor/zendframework/zend-i18n-resources/languages/ja/Zend_Validate.php',
                'text_domain' => 'default',
                'locale' => 'ja_JP'
            ]
        ]
    ]
];

```

translatorの設定項目は、` Zend\I18n\Translator\Translator::factory()` での引数項目となります。

## コントローラでの利用の確認

今回では Application モジュールでの利用 `module/Application/config/module.config.php` での設定する場合として、
Input filter のドキュメント(https://zendframework.github.io/zend-inputfilter/specs/) を参考に以下のように
設定してみました。

```php
return [
    'controllers' => [
        'factories' => [
            Controller\IndexController::class => function (ContainerInterface $container) {
                $filters = $container->get('InputFilterManager');
                return new Controller\IndexController($filters->get('foobar'));
            }
        ],
    ],
    'input_filters' => array(
        'abstract_factories' => array(
            'Zend\InputFilter\InputFilterAbstractServiceFactory'
        ),
    ),
    'input_filter_specs' => require __DIR__.'/input_filter_specs.php',
];
```

Controller では以下のようなコードにて動作確認できます。

```php
<?php

namespace Application\Controller;

use Zend\Mvc\Controller\AbstractActionController;
use Zend\InputFilter\InputFilterInterface;
use Zend\View\Model\ViewModel;

class IndexController extends AbstractActionController
{
    private $inputFilter;

    public function __construct(InputFilterInterface $inputFilter)
    {
        $this->inputFilter = $inputFilter;
    }

    public function indexAction()
    {
        /** @var \Zend\Stdlib\RequestInterface|\Zend\Http\PhpEnvironment\Request $request */
        $request = $this->getRequest();

        if ($request->isPost()) {
            /** @var \Zend\Stdlib\ParametersInterface $post */
            $post = $request->getPost();

            $inputFilter = $this->inputFilter;
            $inputFilter->setData($post->toArray());
            $inputFilter->isValid();
            $messages = $inputFilter->getMessages();
            var_dump($messages);
            // array(1) { ["name"]=> array(1) { ["isEmpty"]=> string(57) "値は必須です。空値は許可されていません" } }
        }

        return new ViewModel();
    }
}
```

なおZend Frameworkでは、コントローラでのサービスロケータは、`v2.5` にてdeprecatedになり、`v3` にて除去されています。

`[ZF3] [Debate] Remove ServiceLocatorAwareInterface from AbstractController #5168`
https://github.com/zendframework/zendframework/issues/5168

## 設定が反映されない場合は？

ながらく Zend Framework では設定ファイルのキャッシュなどはありませんでしたが、Zend Framework 3 では、 zf-development-modeのオンオフにてキャッシュ状態のチェックが走るようです。

```sh
$ ./vendor/bin/zf-development-mode enable
```

にて、開発モードの設定をオンにします。[^2]


[^1]: https://framework.zend.com/blog/2016-06-28-zend-framework-3.html


[^2]: https://docs.zendframework.com/tutorials/getting-started/skeleton-application/#development-mode