【PHP】文字化け文字を含むマルチバイト(全角スペース等)対応のtrim処理

# 概要
PHPで全角のトリムを行う必要があった。ただトリムを行う文字列に文字化け文字が含まれていると 他の trimの記事の方法だときちんと動かなかった。

最初
https://qiita.com/fallout/items/a13cebb07015d421fde3
この記事を参考にして、全角トリムを行ってみたが、
'　町　いなぎ　'のような文字化け文字が含まれていると、
'福井　'が'福井'のように文字化け文字まで削除されてしまった。

# 自分で考えてみたが 美しく作れなかった

結局ループを回して全角と半角スペースを取り除いたが、きれいなコードを書けなかった。CsvUtilityというクラス名もイケてない。

## CsvUtility.php

```php

class CsvUtility {
    /**
     * 全角トリム 文字化け対応 （なんという醜いコードであろう）
     * @param string $trimString
     * @return string
     */
    public static function zenTrim(string $trimString)
    {
        // https://qiita.com/fallout/items/a13cebb07015d421fde3 ↓を参考にしました
        //return preg_replace('/\A[\p{C}\p{Z}]++|[\p{C}\p{Z}]++\z/u', '', $trimString); // '福井　'が'福井'になってしまう
        //return trim(mb_convert_kana($trimString, "s", 'UTF-8')); // 'あ　い'が'あ い'になってしまう
        $spos = 0;
        for ($i = 0; $i < mb_strlen($trimString); $i++) {
            $ch = mb_substr($trimString, $i, 1);
            if ($ch != ' ' && $ch != '　') {
                $spos = $i;
                break;
            }
        }
        if ($spos > 0) {
            $trimString = mb_substr($trimString, $spos);
        }

        $epos = 0;
        for ($i = 0; $i < mb_strlen($trimString); $i++) {
            $ch = mb_substr($trimString, mb_strlen($trimString) - $i - 1, 1);
            if ($ch != ' ' && $ch != '　') {
                $epos = $i;
                break;
            }
        }
        if ($epos > 0) {
            $trimString = mb_substr($trimString, 0, mb_strlen($trimString) - $epos);
        }

        return $trimString;

    }
}

```


---------------
## CsvUtilityTest.php

```php
class CsvUtilityTest extends \Tests\TestCase
{
    /** @@test */
    public function 全角トリム動作確認()
    {
        $this->assertSame(CsvUtility::zenTrim('　　 北九州眞　　　'), '北九州眞');
        $this->assertSame(CsvUtility::zenTrim('　　 髙橋 未来虹　　　'), '髙橋 未来虹');
        $this->assertSame(CsvUtility::zenTrim('　　 ハリー・S・トルーマン　　　'), 'ハリー・S・トルーマン');
        $this->assertSame(CsvUtility::zenTrim(' a '), 'a');
        $this->assertSame(CsvUtility::zenTrim('　あ　'), 'あ');
        $this->assertSame(CsvUtility::zenTrim('　あ　い　'), 'あ　い');
        $this->assertSame(CsvUtility::zenTrim('　あ い　'), 'あ い');
        $this->assertSame(CsvUtility::zenTrim('本多宏顕'), '本多宏顕');
        $this->assertSame(CsvUtility::zenTrim('　  ハリー・S・トルーマン　 　　 　'), 'ハリー・S・トルーマン');
        $this->assertSame(CsvUtility::zenTrim(' Harry S. Truman '), 'Harry S. Truman');
        $this->assertSame(CsvUtility::zenTrim('東京　東子　　　　　　　　　　'), '東京　東子');
        $this->assertSame(CsvUtility::zenTrim('大阪　　　　　　　　　　　　'), '大阪　');
        $this->assertSame(CsvUtility::zenTrim(' 　町　いなぎ　　　　'), '町　いなぎ');
        $this->assertSame(CsvUtility::zenTrim('りんだ　ジェネヴィヴ　　　　'), 'りんだ　ジェネヴィヴ');
    }
}

```

## グリーンビルドになったものの
Testing started at 6:54 ...
php ./vendor/phpunit/phpunit/phpunit --configuration ./phpunit.xml --filter "/(Tests\\Service\\csv\\CsvUtilityTest::全角トリム動作確認)( .*)?$/" --test-suffix CsvUtilityTest.php ./tests/Service/csv --teamcity

PHPUnit 8.5.8 by Sebastian Bergmann and contributors.



Time: 490 ms, Memory: 24.00 MB

OK (1 test, 14 assertions)
Process finished with exit code 0

なんか釈然としない。