Phalcon で Tag のヘルパを拡張してみる


ヘルパによる表示は Phalcon\Tag クラスを継承して書くとよいらしい.
Form クラスを使っていて form.render() を使ってレンダリングしている場合は Tag クラスを拡張して DI に設定しても影響しないようなので注意.

実装例

以下は Bootstrap の表示に対応するように拡張してみた例. array_merge だとさらに class 追加できないので使い勝手悪いからそこんところよろしく.

Bootstrap/Helpers/Tag.php
<?php

namespace Bootstrap\Helpers;

use Phalcon\Tag as PhTag;

class Tag extends PhTag
{
    /**
     * @param array $parameters
     * @return string
     */
    public static function submitButton($parameters)
    {
        return parent::submitButton(array_merge(array(
            'class' => 'btn btn-primary'
        ), $parameters));
    }

    /**
     * @param array $parameters
     * @return string
     */
    public static function textArea($parameters)
    {
        return parent::textArea(array_merge(array(
            'class' => 'form-control'
        ), $parameters));
    }

    /**
     * @param array $parameters
     * @return string
     */
    public static function textField($parameters)
    {
        return parent::textField(array_merge(array(
            'class' => 'form-control'
        ), $parameters));
    }

    /**
     * @param array $parameters
     * @return string
     */
    public static function passwordField($parameters)
    {
        return parent::passwordField(array_merge(array(
            'class' => 'form-control'
        ), $parameters));
    }

    /**
     * @param array $parameters
     * @return string
     */
    public static function emailField($parameters)
    {
        return static::inputGroup('<div class="input-group-addon">@</div>'.parent::emailField(array_merge(array(
            'class' => 'form-control'
        ), $parameters)));
    }

    /**
     * @param array $parameters
     * @return string
     */
    public static function numberField($parameters)
    {
        return parent::numberField(array_merge(array(
            'class' => 'form-control'
        ), $parameters));
    }

    /**
     * @param array $parameters
     * @return string
     */
    public static function dateField($parameters)
    {
        return parent::dateField(array_merge(array(
            'class' => 'form-control'
        ), $parameters));
    }

    /**
     * @param array $parameters
     * @return string
     */
    public static function numericField($parameters)
    {
        return parent::numericField(array_merge(array(
            'class' => 'form-control'
        ), $parameters));
    }

    /**
     * @param string $str
     * @param string
     */
    private static function inputGroup($str)
    {
        return '<div class="input-group">'.$str.'</div>';
    }
}

DI に下記のように設定するとビュー側で特に指定せずに使えるようになる.

services.php
$di->set('tag', function() {
    return new Bootstrap\Helpers\Tag();
}); 

使用例

volt
{{ text_field('hoge') }}
{{ password_field('hoge') }}
{{ file_field('hoge') }}
{{ check_field('hoge') }}
{{ radio_field('hoge') }}
{{ date_field('hoge') }}
{{ email_field('hoge') }}
{{ numeric_field('hoge') }}
{{ submit_button() }}
{{ select_static('hoge', ['A': 'Active', 'B': 'Inactive'], 'multiple': '') }}
{{ select('hoge', ['A': 'Active', 'B': 'Inactive']) }}
{{ text_area('hoge', 'value': 'This is contents.') }}

下記出力例は表示の都合で改行を追加している.ここでは全部 id が同じになってるけど本当は id は重複してはいけない.

html
<input type="text" id="hoge" name="hoge" class="form-control" />
<input type="password" id="hoge" name="hoge" class="form-control" />
<input type="file" id="hoge" name="hoge" />
<input type="checkbox" id="hoge" name="hoge" />
<input type="radio" id="hoge" name="hoge" />
<input type="date" id="hoge" name="hoge" class="form-control" />
<div class="input-group"><div class="input-group-addon">@</div><input type="email" id="hoge" name="hoge" class="form-control" /></div>
<input type="number" id="hoge" name="hoge" class="form-control" />
<input type="submit" class="btn btn-primary" />
<select id="hoge" name="hoge" multiple="">
    <option value="A">Active</option>
    <option value="B">Inactive</option>
</select>
<select id="hoge" name="hoge">
    <option value="A">Active</option>
    <option value="B">Inactive</option>
</select>
<textarea id="hoge" name="hoge" value="This is contents." class="form-control">This is contents.</textarea>

表示例

DI に登録しない場合

した場合.