またどこかでCTOっぽいことやってる人のブログ

フリーランスを経て、またどこかでCTOっぽいことをやってる人が書いてます。何か色々やってます。

CakePHP3のbeforeMarshalが便利だった。

Webエンジニアになって何年か経ちますが、Webページに表示される全角英数が嫌いです。
「半角にしてくれよおおおおおおお!!」とよく思います。
全角の方がナントカとか、全角じゃないとダメな時がナントカみたいな話もあると思いますが、嫌いなんです。
ちなみに、半角カナも嫌いです。

昔やってた手法

何も言われなければ、全角英数字は勝手に半角に変換してしまいます。
半角カナは全角カナに変換してDBにブチ込みます。

たとえ会社名だろうが名前だろうが、問答無用で変換します。
そんな時はコントローラで変換したパラメータをモデルに渡していました。
でもある時気がつきました。

なんかダサくね?

調べてみた

調べてみると、CakePHP3には「beforeMarshal」とかいうコールバックがあるそうです。

https://book.cakephp.org/3.0/ja/orm/table-objects.html#beforemarshal

「Model.beforeMarshal イベントは、リクエストデータがエンティティーに変換される前に発行されます」

これじゃね?

使ってみた

モデルかビヘイビアで実装できるようです。
一度ビヘイビアで実装してみたのですが、イマイチでした。
対象のモデルの中で使う方がわかりやすくていいんじゃないかと思います(個人的なアレ)

要は「エンティティに変換される前に変換しますよ」なので、全角から半角にしたりTrim処理したり。
文字列自体を置換したり、そんなことを勝手にやってくれるぽいです。
エンティティに変換される前なので、save処理実行前なんでしょう。

モデルの中でこんな感じに書きました。
モデルだけbakeする派なので、useしている部分は追加分以外は自動生成されたものです。

<?php
namespace App\Model\Table;

use Cake\ORM\Query;
use Cake\ORM\RulesChecker;
use Cake\ORM\Table;
use Cake\Validation\Validator;
use Cake\Event\Event; // これ追加
use ArrayObject; // これ追加

class UsersTable extends Table
{
  public function initialize(array $config) {
    parent::initialize($config);

    $this->setTable('users');
    $this->setDisplayField('id');
    $this->setPrimaryKey('id');

    $this->addBehavior('Timestamp');
  }

  /**
   * データ変換
   * @param \App\Model\Table\Event $event
   * @param ArrayObject $data
   * @param ArrayObject $options
   */
  public function beforeMarshal(Event $event, ArrayObject $data, ArrayObject $options) {
    
    if (isset($data['user_address'])) {
      // 全角英数字を半角に変換 + 半角カナを全角カナに変換
      $data['user_address'] = mb_convert_kana($data['user_address'], 'Ka');
  }
  /* 以下略 */
}

こんな風に書くとsave前に上記の例だと半角英数に変換 + 全角カナに変換してエンティティに渡されます。
エンティティ生成時なので、フォームで入力されたPOSTデータが渡ってくる想定です。

きっと、もっと便利な使い方あると思いますがとりあえず満足したので十分です。
脳内ではマーシャルアーツさんと呼んでしまう、KOFではテリー派だったわたし。