今回は、「入力の空白文字のトリム」の最後です。

以下のようなフォームでは、入力の変数に配列を使用することできます。


<form>
...
<div>あなたの趣味を以下に記入してください:</div>
<ul>
  <li><input type="text" name="hobby[]" value=""></li>
  <li><input type="text" name="hobby[]" value=""></li>
...
</form>

これらがプログラムには、

hobby[0] = "映画鑑賞";
hobby[1] = " 読書";
hobby[2] = "テニス ";
..

という形で入ってきます。

しかし、前回のミドルウェアの定義では、このような配列には対応できませんので、以下のように書き直しました。

namespace App\Http\Middleware;

use Closure;

class TrimInput {

    /**
     * Handle an incoming request.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Closure  $next
     * @return mixed
     */
    public function handle($request, Closure $next)
    {
        $input = $request->all();

        $request->merge(self::trim($input));

        return $next($request);
    }

    public static function trim($value)
    {
        if (is_array($value))
        {
            $value = array_map(['self', 'trim'], $value);
        }
        elseif (is_string($value))
        {
            $value = preg_replace('/(^\s+)|(\s+$)/u', '', $value);
        }

        return $value;
    }
}

一見複雑そうに見えますが、それほどでもありません。まず、回帰を使用するためにトリムの関数を分けました。クラスメソッドとしています。他でも使用するなら自身のライブラリのメソッドとしてもよいです。そのトリムのメソッドでは、パラメが配列のときには回帰を使用して配列の個々の値をトリムします。

これに伴い、ユニットテストも書き換えました。

use Illuminate\Foundation\Testing\WithoutMiddleware;
use Illuminate\Foundation\Testing\DatabaseMigrations;
use Illuminate\Foundation\Testing\DatabaseTransactions;

class SignupTest extends TestCase
{
    use DatabaseTransactions;

    /**
     * @dataProvider providerTrimpInput
     */
    public function testTrimpInput2($data, $expected)
    {
        $input = [
            'email'                 => 'success@gmail.com',
            'password'              => 'testtest',
            'password_confirmation' => 'testtest',
            'last_name'             => $data['last_name'],
            'first_name'            => '太郎',
            'hobby'                 => $data['hobby']
        ];

        $this->visit('/signup')
            ->submitForm('保存', $input)
            ->see('会員登録完了');

        $member = \App\Member::where('email', 'success@gmail.com')->first();

        $this->assertEquals($expected['last_name'], $member->last_name);
        $this->assertEquals($expected['hobby'], unserialize($member->hobbies));
    }

    public function providerTrimpInput()
    {
        return [
            [ //半角スペース
                ['last_name' => ' 山田 ', 'hobby' => [' 映画鑑賞 ', ' 読書 ', '']],
                ['last_name' => '山田',   'hobby' => ['映画鑑賞', '読書', '']],
            ],
            [ //全角スペース
                ['last_name' => ' 山田 ', 'hobby' => [' 映画鑑賞 ', ' 読書 ', '']],
                ['last_name' => '山田',     'hobby' => ['映画鑑賞', '読書', '']],
            ],

        ];
    }
}

前回のテストでは、

      $this->visit('/signup')
           ->type('success@gmail.com', 'email')
   ...
      ->press('保存')
           ->see('会員登録完了')

のように、入力をシミュレートするのに、type()の関数を使用しましたが、今回のテストでは、配列の入力は残念ながらtype()では対応できません。そこで、type()press()をまとめた、submitForm()を使っています。

データプロバイダーの方も、last_namehobbyのおいてそれぞれ値を変えることができるように、インデックスをつけました。

さて、これで前回の全角スペースとともに配列値でのトリムも可能となりました。空白文字をトリムするミドルウェアの完成です。

実行できるコードはこのリンクから、コード。タグは、2015-10-19となっています。

git fetch && git checkout -b 2015-10-19

By khino