標準のHelperを拡張してカスタマイズする方法

CakePHP3、CakePHP4共通です。
CakePHP5ではAppView::loadHelper()がAppView::addHelper()に変更されています。
CakePHP2ではAppControllerの$helpersプロパティでHelperを指定します。
[参考記事] CakePHP2の場合

活用例
Formヘルパー指定の簡略化
一覧ページの検索フォームでページ番号などのパラメータを付与しない

AppView.phpのinitialize()に次のように書くとViewでHelperを呼び出すことができます。

$this->loadHelper('【Viewでのプロパティ名】', ['className' => '【呼び出されるクラス名】']);

標準のHelper(組み込みヘルパー/コアヘルパー)を別のクラスを使用するよう指定できます。

$this->loadHelper('Form', ['className' => 'CustomForm']);

テンプレートを指定する場合は配列に追加します。

$this->loadHelper('Form', ['className' => 'CustomForm', 'templates' => 'form-templates']);

独自のHelperはsrc/View/Helper配下に配置します。


src/View/AppView.php

class AppView extends View
{
    /**
     * Initialization hook method.
     *
     * Use this method to add common initialization code like loading helpers.
     *
     * e.g. `$this->loadHelper('Html');`
     *
     * @return void
     */
    public function initialize(): void
    {
        // 拡張Helperを使用する
        $this->loadHelper('Flash', ['className' => 'CustomFlash']);
        $this->loadHelper('Form', ['className' => 'CustomForm']);
        $this->loadHelper('Html', ['className' => 'CustomHtml']);
        $this->loadHelper('Paginator', ['className' => 'CustomPaginator']);
        $this->loadHelper('Url', ['className' => 'CustomUrl']);
    }
}

src/View/Helper/CustomFlashHelper.php

<?php
declare(strict_types=1);

namespace App\View\Helper;

use Cake\View\Helper\FlashHelper;

/**
 * FlashHelperの拡張ヘルパー
 *
 * @link https://book.cakephp.org/4/ja/views/helpers/flash.html
 */
class CustomFlashHelper extends FlashHelper
{
}

src/View/Helper/CustomFormHelper.php

<?php
declare(strict_types=1);

namespace App\View\Helper;

use Cake\View\Helper\FormHelper;

/**
 * FormHelperの拡張ヘルパー
 *
 * @property \Cake\View\Helper\HtmlHelper $Html
 * @property \Cake\View\Helper\UrlHelper $Url
 * @link https://book.cakephp.org/4/ja/views/helpers/form.html
 */
class CustomFormHelper extends FormHelper
{
}

src/View/Helper/CustomHtmlHelper.php

<?php
declare(strict_types=1);

namespace App\View\Helper;

use Cake\View\Helper\HtmlHelper;

/**
 * HtmlHelperの拡張ヘルパー
 *
 * @property \Cake\View\Helper\UrlHelper $Url
 * @link https://book.cakephp.org/4/ja/views/helpers/html.html
 */
class CustomHtmlHelper extends HtmlHelper
{
}

src/View/Helper/CustomPaginatorHelper.php

<?php
declare(strict_types=1);

namespace App\View\Helper;

use Cake\View\Helper\PaginatorHelper;

/**
 * PaginatorHelperの拡張ヘルパー
 *
 * @property \Cake\View\Helper\UrlHelper $Url
 * @property \Cake\View\Helper\NumberHelper $Number
 * @property \Cake\View\Helper\HtmlHelper $Html
 * @property \Cake\View\Helper\FormHelper $Form
 * @link https://book.cakephp.org/4/ja/views/helpers/paginator.html
 */
class CustomPaginatorHelper extends PaginatorHelper
{
}

src/View/Helper/CustomUrlHelper.php

<?php
declare(strict_types=1);

namespace Cake\View\Helper;

use Cake\View\Helper\UrlHelper;

/**
 * UrlHelperの拡張ヘルパー
 *
 * @link https://book.cakephp.org/4/ja/views/helpers/url.html
 */
class CustomUrlHelper extends UrlHelper
{
}

Formヘルパー指定の簡略化

サイト全てで、$this->Form->control()に同じ指定をしていた場合にCustomFormHelperでcontrol()の指定をすると簡略化できます。

<?= $this->Form->control('title', ['label' => false, 'class' => 'form-control']); ?>
 これを↓のように簡略化することができます
<?= $this->Form->control('title'); ?>

この例の場合は下記のように書きます。

class CustomFormHelper extends FormHelper
{
    /**
     * ラベルとラッパー div を備えたフォーム コントロール要素を生成します。
     *
     * @param string $fieldName This should be "modelname.fieldname"
     * @param array<string, mixed> $options Each type of input takes different options.
     * @return string Completed form widget.
     * @link https://book.cakephp.org/4/ja/views/helpers/form.html#creating-form-controls
     * @psalm-suppress InvalidReturnType
     * @psalm-suppress InvalidReturnStatement
     */
    public function control(string $fieldName, array $options = []): string
    {
        if (!isset($options['label'])) {
            $options['label'] = false;
        }
        
        if (!isset($options['class'])) {
            $options['class'] = 'form-control';
        }

        return parent::control($fieldName, $options);
    }
}

一覧ページの検索フォームでページ番号などのパラメータを付与しない

一覧ページに検索フォームをつけた場合、ページ番号やソートなどのクエリパラメータはoptionでurlを指定しないとフォームのactionに引き継がれます。

<?= $this->Form->create($searchForm, ['url' => ['action' => 'index']]) ?>
 これを↓のように簡略化することができます
<?= $this->Form->create($searchForm) ?>

この例の場合は下記のように書きます。

class CustomFormHelper extends FormHelper
{
    /**
     * HTML フォーム要素を返します。
     *
     * @param mixed $context The context for which the form is being defined.
     *   Can be a ContextInterface instance, ORM entity, ORM resultset, or an
     *   array of meta data. You can use `null` to make a context-less form.
     * @param array<string, mixed> $options An array of html attributes and options.
     * @return string An formatted opening FORM tag.
     * @link https://book.cakephp.org/4/ja/views/helpers/form.html#Cake\View\Helper\FormHelper::create
     */
    public function create($context = null, array $options = []): string
    {
        // 一覧ページの検索フォームでページ番号などのパラメータを付与しないようurlを指定する
        if ($this->_View->getRequest()->getParam('action') == 'index') {
            if (!isset($options['url'])) {
                $options['url'] = ['action' => 'index'];
            }
        }

        return parent::create($context, $options);
    }
}

関連記事

スポンサーリンク

シェルスクリプトを実行すると『そのようなファイルやディレクトリはありません』や『コマンドが見つかりません』と出る場合

ホームページ製作・web系アプリ系の製作案件募集中です。

上に戻る