Cakephp プログラミング

[Cakephp3]Formヘルパー不要なタグ出力で悩まされたら

 

Cakephpで、ビュー作成時にFormヘルパーを使用していると、不要な<div>などのタグ出力に悩まされる場合があります。

特に、フレームワークを使い始めて間もない人は、その仕様を把握するだけでも大変。

 

今回は、Cakephp3のFormヘルパーの使用時、不要なタグを出力しないための設定です。

 

 

Formヘルパーを使う

Cakephpフレームワークを使用しながらWEB開発をすると、代表的な例では「お問い合わせフォームを作成したい」といったことがあります。

 

もちろん、従来のようにHTMLを用いて各お問い合わせフォームを作ることも可能なのですが、Formヘルパーを使用した方がCSRF(クロスサイトリクエストフォージェリ)のセキュリティ対策が楽だったり、品質の面でも有利。

そして、使い慣れると開発効率も結果的に爆速(いいすぎかな・・)。なので、是非慣れておきたい所ですね。

 

Formヘルパーの基本的な使い方については、ドキュメントが充実しているので、そちらに任せます。

 

Cake3Formヘルパー(これから新規開発する人はCakephp4がオススメ)

https://book.cakephp.org/3/ja/views/helpers/form.html

 

覚えておきたいsetTemplates

Formヘルパーの基本的な使い方は、ドキュメントに沿えば決して難しくはありません。

 

超ざっくりいうと、

<?= $this->Form->create($entitiyName) ?>

<?= $this->Form->control('hoge') ?>

// 以下、好きなようにフォームを作成して・・

<?= $this->Form->end() ?>

で、あっという間にフォームを作成してくれます。

ですが、このForm->controlが`結構曲者で、フォームのスタイルなどを自由にカスタマイズしたい時に不要なタグ出力をしてしまいます。

 

初心者の方は、「なんで勝手にタグ出力されてんの?なんで消えないの?」 → (躓いて時間を無駄に消費したのち)「素のHTMLの方が楽じゃね?」という思考になりがちです。

 

そこで、利用したいのが、setTemplatesです。

 

各フォームのオプションとして、不要なタグ出力の制御はある程度できる(できないヤツもある・・)のですが、setTemplatesメソッドを使用することで、各フォームにわざわざ個別に設定しなくても、一括でコントロール可能です。

 

やり方はいくつかあるのですが、影響度を小さくするために各ビュー単位で設定する方法を紹介します。

 

■ ビューファイルの先頭に書く(Cake3なら.ctp。Cake4なら.php)

例:

<?php

$this->Form->setTemplates([

   'inputContainer' => {{contents}},

   'label' => false,

]);

上記でやったこと

inputContainer → inputタグに囲まれる<div>を出力させない

label  → labelタグを出力させない

 

このようにして、不要なタグ出力を制御することが可能です。これでスタイルのカスタマイズなどバッチリ!

 

FormHelper で使用するテンプレートのカスタマイズ

https://book.cakephp.org/3/ja/views/helpers/form.html#formhelper

 

setTemplatesの仕様一覧

つい先日、師匠(先生?先輩?仲間?お兄ちゃん?)に教えてもらったsetTemplatesの仕様一覧がサイコーだったので、共有します。

https://github.com/cakephp/cakephp/blob/3.x/src/View/Helper/FormHelper.php#L101-L168

'templates' => [
           // Used for button elements in button().
           'button' => '<button{{attrs}}>{{text}}</button>',
           // Used for checkboxes in checkbox() and multiCheckbox().
           'checkbox' => '<input type="checkbox" name="{{name}}" value="{{value}}"{{attrs}}>',
           // Input group wrapper for checkboxes created via control().
           'checkboxFormGroup' => '{{label}}',
           // Wrapper container for checkboxes.
           'checkboxWrapper' => '<div class="checkbox">{{label}}</div>',
           // Widget ordering for date/time/datetime pickers.
           'dateWidget' => '{{year}}{{month}}{{day}}{{hour}}{{minute}}{{second}}{{meridian}}',
           // Error message wrapper elements.
           'error' => '<div class="error-message">{{content}}</div>',
           // Container for error items.
           'errorList' => '<ul>{{content}}</ul>',
           // Error item wrapper.
           'errorItem' => '<li>{{text}}</li>',
           // File input used by file().
           'file' => '<input type="file" name="{{name}}"{{attrs}}>',
           // Fieldset element used by allControls().
           'fieldset' => '<fieldset{{attrs}}>{{content}}</fieldset>',
           // Open tag used by create().
           'formStart' => '<form{{attrs}}>',
           // Close tag used by end().
           'formEnd' => '</form>',
           // General grouping container for control(). Defines input/label ordering.
           'formGroup' => '{{label}}{{input}}',
           // Wrapper content used to hide other content.
           'hiddenBlock' => '<div style="display:none;">{{content}}</div>',
           // Generic input element.
           'input' => '<input type="{{type}}" name="{{name}}"{{attrs}}/>',
           // Submit input element.
           'inputSubmit' => '<input type="{{type}}"{{attrs}}/>',
           // Container element used by control().
           'inputContainer' => '<div class="input {{type}}{{required}}">{{content}}</div>',
           // Container element used by control() when a field has an error.
           'inputContainerError' => '<div class="input {{type}}{{required}} error">{{content}}{{error}}</div>',
           // Label element when inputs are not nested inside the label.
           'label' => '<label{{attrs}}>{{text}}</label>',
           // Label element used for radio and multi-checkbox inputs.
           'nestingLabel' => '{{hidden}}<label{{attrs}}>{{input}}{{text}}</label>',
           // Legends created by allControls()
           'legend' => '<legend>{{text}}</legend>',
           // Multi-Checkbox input set title element.
           'multicheckboxTitle' => '<legend>{{text}}</legend>',
           // Multi-Checkbox wrapping container.
           'multicheckboxWrapper' => '<fieldset{{attrs}}>{{content}}</fieldset>',
           // Option element used in select pickers.
           'option' => '<option value="{{value}}"{{attrs}}>{{text}}</option>',
           // Option group element used in select pickers.
           'optgroup' => '<optgroup label="{{label}}"{{attrs}}>{{content}}</optgroup>',
           // Select element,
           'select' => '<select name="{{name}}"{{attrs}}>{{content}}</select>',
           // Multi-select element,
           'selectMultiple' => '<select name="{{name}}[]" multiple="multiple"{{attrs}}>{{content}}</select>',
           // Radio input element,
           'radio' => '<input type="radio" name="{{name}}" value="{{value}}"{{attrs}}>',
           // Wrapping container for radio input/label,
           'radioWrapper' => '{{label}}',
           // Textarea input element,
           'textarea' => '<textarea name="{{name}}"{{attrs}}>{{value}}</textarea>',
           // Container for submit buttons.
           'submitContainer' => '<div class="submit">{{content}}</div>',
           // Confirm javascript template for postLink()
           'confirmJs' => '{{confirm}}',
           // selected class
           'selectedClass' => 'selected',
       ],

これで、各フォームパーツ名を見ながら、Cakeのデフォルトのタグ出力の仕様がわかりますね。逆に出力したいタグがあれば、カスタマイズすることで、より使いやすくなるはずです。

 

みんな大好きLaravelだけど(そんなエーかなあ・・)Cakephpも良いフレームワークでっせ。

 

では、今回はこの辺で。

-Cakephp, プログラミング
-