今回のお題
CakePHP3.8を使って実装を進めた際に起きました。
調べてみても意外にヒットしなかったので、自分なりの対処方法を残しておきます。
環境
PHP: 5.6.40
CakePHP: 3.8
OS: CentOS7.2
DB: MySQL5.7.21
今さらPHP5.6かよ、というのは置いておき。。
画面イメージ
よくあるこのような画面です。
今回は身長か体重のどちらかは入力必須(両方入力されていてもOK)というお話です。
CakePHP3実装
model
Usersモデルに以下のカラムがある、という前提で進めます。
身長: height
体重: weight
public function validationDefault(Validator $validator)
{
$validator
->notEmptyString('height', '身長か体重のいずれかを入力してください。', function ($context) {
return (bool) (!$context['data']['height']) && (!$context['data']['weight']);
});
return $validator;
}
カスタムバリデーションで function($value, $context)
を使いますが
$valueは当該の項目、$contextはリクエスト全体をそれぞれ定義します。
今回は$contextを使ってどちらの項目もチェックする、ということをしています。
view
<dt class="title">身長/体重<br>※いずれか必須<span class="must">必須</span></dt>
<dd class="input">
<?= $this->Form->control('height', [
'type' => 'text',
'label' => false,
'required' => false,
]) ?> cm
<?= $this->Form->control('weight', [
'type' => 'text',
'label' => false,
'required' => false,
]) ?> kg
</dd>
こちらでは特に変わったことはしていませんね。
結果イメージ
身長のエラーとして表示されることがわかります。
おまけ
さらに身長・体重にそれぞれバリデーションをかける場合も一緒に記載します。
前提条件
・身長・体重のどちらかは入力必須。
・どちらも半角数字での入力しか認めない。
modelにルールを追加
public function validationDefault(Validator $validator)
{
$validator
->notEmptyString('height', '身長か体重のいずれかを入力してください。', function ($context) {
return (bool) (!$context['data']['height']) && (!$context['data']['weight']);
})
->numeric('height', '身長は半角数字で入力してください。');
$validator
->allowEmptyString('weight', null)
->numeric('weight', '体重は半角数字で入力してください。');
return $validator;
}
heightにnumericのvalidationルールを
weightにはallowEmptyStringとnumericのルールを追加しました。
実行
先ほどのviewをそのまま使うと以下のようになってしまいます。
validationメッセージが表示されると、全体的にレイアウトが崩れてしまいました。
まあ、これはviewの書き方が悪い、とも言えますが。。。
対応策
viewを以下のように変更します。
<dt class="title">身長/体重<br>※いずれか必須<span class="must">必須</span></dt>
<dd class="input">
<?= $this->Form->control('height', [
'type' => 'text',
'label' => false,
'required' => false,
'error' => false,
]) ?> cm
<?= $this->Form->control('weight', [
'type' => 'text',
'label' => false,
'required' => false,
'error' => false,
]) ?> kg
<?= $this->Form->error('height') ?>
<?= $this->Form->error('weight') ?>
</dd>
フォームではエラー表示をオフにし、別のところでエラーを出すようにしました。
結果
崩れていたレイアウトもスッキリしましたね。
まだ需要があるかはわかりませんが、どなたかのお役に立てたのなら嬉しいです。