LoginSignup
1
2

More than 5 years have passed since last update.

CakePHP(2.x)で文字数の長さ定義(maxlength)を1箇所にまとめる

Posted at

概要

  • ビューの入力欄の maxlength とモデルのバリデートの maxLength の値を1箇所で管理したい。
  • 下のサンプルだと"100"という値をビューで1回、モデルで1回記述している。
View
<?= $this->Form->input('Post.name', array(
    'type' => 'text',
    'maxlength' => 100,
);?>
Model
public $validate = array(
    'name' => array(
        'rule' => array('maxLength', 100),
        'message' => '%s 字以内で入力して下さい。',
    ),
);

ソースコード

上記の"100"の定義を1箇所にまとめるサンプルを作成しました。
https://github.com/gold1/CakePHP-maxlength-sample
以下、解説していきます。

まずは、カラム名と文字列長さの配列定義をモデルに作成します。

app/Model/It.php
    protected static $maxLengthJp = array(
        'name' =>  30,
        'note' => 100,
    );

配列定義にアクセス/判定を行う関数をAppModelに追加します。

app/Model/AppModel.php
    public static function isMaxLengthJp($column)
    public static function getMaxLengthJp($column)

文字列長さのチェック関数(ruleMaxLengthJp)を独自実装します。

app/Model/AppModel.php
    public function ruleMaxLengthJp($data, $length) {
        $encoding = Configure::read('App.encoding');
        $value = array_shift($data);
        return (mb_strlen($value, $encoding) <= $length);
    }

上記のチェック関数を実行する前にバリデートルールを変更。文字列の長さ定義を設定しています。

app/Model/AppModel.php
    public function modifyValidateRure() {
        // ...
        if ($rule == 'ruleMaxLengthJp') {
            // ルール変更をおこなって文字数を引数に設定する
            $length = static::getMaxLengthJp($column);
            $this->validate[$column][$number]['rule'] = array($rule, $length);
        }

これで validate:rule 部分の記述を移動できました。

app/Model/It.php
    public $validate = array(
        'name' => array(
            'ruleMaxLengthJp' => array(
                'rule'       => 'ruleMaxLengthJp',
                'required'   => true,
                'allowEmpty' => false,
                'last'       => true,
                'message'    => 'name は %s文字までです。',
            ),
        ),

次に FormHelper を継承した Form2Helper を作成して input() を上書きします。maxlength の値をここで設定します。

app/View/Helper/Form2Helper.php
    public function input($fieldName, $options = array()) {
        list($model_name, $column_name) = $this->getModelAndColumnByFieldName($fieldName);
        if ($options['type'] == 'text' ||
            $options['type'] == 'textarea') {
            if (class_exists($model_name) &&
                $model_name::isMaxLengthJp($column_name)) {
                $options = array_merge(
                    array('maxlength' => $model_name::getMaxLengthJp($column_name)),
                    $options
                );
            }
        }
        return parent::input($fieldName, $options);
    }

AppController でこのヘルパーを指定する必要があります。

app/Controller/AppController.php
    public $helpers = array(
        'Form' => array(
            'className' => 'Form2',
        ),
    );

これでビュー側の定義を移動できました。

app/View/It/form.php
<?= $this->Form->input('Post.name', array(
    'type' => 'text',
);?>

最後に

  • プラグイン形式でまとめたかったけど、方法が思いつきませんでした。
1
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
2