この記事のゴール
入力を要する処理ではバリデーションが不可欠です。
LaravelのValidatorは利用方法が簡単で汎用性があり、
機能ごとにValidatorクラスを作成する必要がなく、
コード量が少なく、実装時間が短くて済み、
挙動の変更も容易です。(Laravelフレームワークの中では。)
![](https://laravel.com/img/og-image.jpg)
Laravelフレームワークの管理外でこのValidatorを導入して、
その恩恵を美味しく戴いていきます。
※2024/04/28追記:当記事の内容に機能追加してライブラリ化しました。
前提条件
- PHP8.2以降インストール済
- Composerインストール済
PHPプロジェクト構成
次のようなフォルダ構成にしていきます。
[プロジェクトトップ]
├─ src/
| ├─ lang/ [言語設定]
│ │ ├─ en/ [英語]
│ │ │ └─ validation.php [メッセージ設定]
│ │ └─ ja/ [日本語]
│ │ └─ validation.php [メッセージ設定]
│ ├─ lib/ [今回作成するバリデーションライブラリ]
│ │ └─ validation/
│ │ ├─ ValidatorWrapper.php
│ │ └─ ValidatorFactory.php
│ └─ App.php [アプリケーション本体]
├─ vendor/ [Composerパッケージ群]
├─ composer.json
└─ composer.lock
PHPプロジェクト作成
まずは、Laravelを使わないピュアPHPのプロジェクトを作成します。
(というかフォルダを作成するだけ。)
mkdir purephp-validation
作成したフォルダ内に移動します。
cd purephp-validation
illuminate/validationインストール
Laravelフレームワークの個別切り出しコンポーネントである「illuminate/validation」をインストールします。
composer require illuminate/validation
![](https://macocci7.net/blog/wp-content/uploads/2024/04/purephp_validation_01.png)
Validatorのメッセージ設置
まずはフォルダを作成します。
mkdir -p src/lang/en
mkdir -p src/lib/validation
作成したフォルダ「src/lang/en/」の中に「validation.php」を作成します。
下のリンクのファイルをコピーして設置すると良いでしょう。
Laravel framework 11.x 公式リポジトリ内のファイルです。
Validatorラッパー設置
「src/lib/validation/」フォルダ内に「ValidatorWrapper.php」を作成します。
<?php
/**
* This file is a slightly modified version of the following code:
* - BaseCode: https://github.com/jeffochoa/validator-factory/blob/master/src/ValidatorFactory.php
* - BaseTag: https://github.com/jeffochoa/validator-factory/releases/tag/1.0.1
* - Modified: namespace is renamed from 'JeffOchoa'
* - Modified: class name is renamed from 'ValicatorFactory'
* - Modified: path set by the method 'getTranslationsRootPath' adjusted
* - Modified: types of class properties added
* - Modified: types of function parameters added
* - Modified: PHPDoc blocks added.
*/
namespace Purephp\Validation;
use Illuminate\Validation\Factory;
use Illuminate\Filesystem\Filesystem;
use Illuminate\Translation\FileLoader;
use Illuminate\Translation\Translator;
class ValidatorWrapper
{
public string $lang;
public string $group;
public Factory $factory;
public string $namespace;
// Translations root directory
public string $basePath;
public static Translator $translator;
/**
* constructor
* @param string $namespace
* @param string $lang
* @param string $group
*/
public function __construct(
string $namespace = 'lang',
string $lang = 'en',
string $group = 'validation'
) {
$this->lang = $lang;
$this->group = $group;
$this->namespace = $namespace;
$this->basePath = $this->getTranslationsRootPath();
$this->factory = new Factory($this->loadTranslator());
}
/**
* Sets tranlations root path
* @param string $path = ''
* @return $this
*/
public function translationsRootPath(string $path = '')
{
if (!empty($path)) {
$this->basePath = $path;
$this->reloadValidatorFactory();
}
return $this;
}
/**
* Reloads ValidatorFactory
* @return $this
*/
private function reloadValidatorFactory()
{
$this->factory = new Factory($this->loadTranslator());
return $this;
}
/**
* Returns translations root path
* @return string
*/
public function getTranslationsRootPath(): string
{
return dirname(__FILE__) . '/../../';
}
/**
* Loads and returns Translator
* @return Translator
*/
public function loadTranslator(): Translator
{
$loader = new FileLoader(new Filesystem(), $this->basePath . $this->namespace);
$loader->addNamespace($this->namespace, $this->basePath . $this->namespace);
$loader->load($this->lang, $this->group, $this->namespace);
return static::$translator = new Translator($loader, $this->lang);
}
/**
* Method overloading
* @param string $method
* @param array<string, string> $args
* @return mixed|false
* @see https://www.php.net/manual/en/language.oop5.overloading.php#object.call
*/
public function __call(string $method, array $args)
{
return call_user_func_array([$this->factory, $method], $args);
}
}
このクラスを静的に呼び出せるように、同じフォルダにもう一つ
「ValidatorFactory.php」を作成します。
<?php
namespace Purephp\Validation;
require_once __DIR__ . '/ValidatorWrapper.php';
class ValidatorFactory
{
private static string $lang = 'en';
private static string $langPathRoot = __DIR__ . '/../../lang/';
/**
* Sets lang or returns current lang
* @param string $lang = ''
* @return string|null
*/
public static function lang(string $lang = '')
{
if (strlen($lang) === 0) {
return self::$lang;
}
$path = self::$langPathRoot . $lang . '/validation.php';
if (!is_readable($path)) {
throw new \Exception("Cannot read {$path}.");
}
return self::$lang = $lang;
}
/**
* Creates Validator
* @param array<string, mixed> $data
* @param array<string, string> $rule
* @param array<string, string> $messages = []
* @param array<string, string> $attributes = []
* @return \Illuminate\Validation\Validator
*/
public static function make(
array $data,
array $rule,
array $messages = []
array $attributes = []
) {
// @phpstan-ignore-next-line
return (new ValidatorWrapper(
lang: self::$lang
))
->make($data, $rule, $messages, $attributes);
}
}
アプリケーション作成
アプリケーション本体を作成して、上記のクラスを利用したコードを実装していきます。
「src/」フォルダ内に「App.php」を作成します。
<?php
require_once __DIR__ . '/../vendor/autoload.php';
require_once __DIR__ . '/lib/validation/ValidatorFactory.php';
use Purephp\Validation\ValidatorFactory;
// Input
$user = [
'name' => 'ho',
'email' => 'hoge',
'level' => 0,
];
// Valiation Rules
$rules = [
'name' => 'required|string|min:3|max:40',
'email' => 'required|string|email:rfc,dns',
'level' => 'required|integer|min:1|max:99',
];
// Validation
$validator = ValidatorFactory::make($user, $rules);
// Checking Result
if ($validator->fails()) {
var_dump($validator->errors());
} else {
echo "passed.\n";
}
バリデーション実行
作成したアプリケーションを実行して
バリデーションの動作確認をしてみます。
![](https://macocci7.net/blog/wp-content/uploads/2024/04/purephp_validation_02.png)
「$validator->fails()」が機能していることが判ります。
戻り値は「Illuminate\Support\MessageBag」です。
バリデーションのエラーメッセージも表示されていますが、
これはprotectedプロパティで、コード内では取得できません。
次のようにすると、メッセージを配列で取得可能です。
$validator->errors()->messages()
では、バリデーションを通過するように入力値を修正します。
// Input
$user = [
'name' => 'hoge',
'email' => 'hoge@hoge.com',
'level' => 1,
];
再度実行してみます。
![](https://macocci7.net/blog/wp-content/uploads/2024/04/purephp_validation_03.png)
バリデーションを通過しました。
日本語化設定
バリデーションメッセージを日本語にします。
「src/lang/ja/」フォルダを作成し、その中に下のリンクのファイルを設置すると良いでしょう。
Laravel Breeze 日本語化プロジェクトのGithubリポジトリのファイルです。
バリデーション実行の手前に次のコードを挿入します。
// Set lang
ValidatorFactory::lang('ja');
「src/App.php」の完成形は次のような感じです。
<?php
require_once __DIR__ . '/../vendor/autoload.php';
require_once __DIR__ . '/lib/validation/ValidatorFactory.php';
use Purephp\Validation\ValidatorFactory;
// Input
$user = [
'name' => 'ho',
'email' => 'hoge',
'level' => 0,
];
// Valiation Rules
$rules = [
'name' => 'required|string|min:3|max:40',
'email' => 'required|string|email:rfc,dns',
'level' => 'required|integer|min:1|max:99',
];
// Set lang
ValidatorFactory::lang('ja');
// Validation
$validator = ValidatorFactory::make($user, $rules);
// Checking Result
if ($validator->fails()) {
var_dump($validator->errors());
} else {
echo "passed.\n";
}
実行してみます。
![](https://macocci7.net/blog/wp-content/uploads/2024/04/purephp_validation_04.png)
日本語のメッセージが表示されました。
当記事の内容に機能追加してライブラリ化しました。
こちらの記事をご覧ください。
参考サイト
▼ (by Jeff Ochoa) @ Medium
![](https://miro.medium.com/v2/resize:fit:1200/1*42VaFA9d-d7AqW8TtUcUtA.jpeg)
▼ ねうねう技術らくがき日記 @ Hatena Blog
コメント