助手

助手是应用程序表示层中类似于组件的类。它们包含在多个视图、元素或布局之间共享的表示逻辑。本章将向您展示如何配置助手,如何加载助手和使用这些助手,以及创建您自己的自定义助手的简单步骤。

CakePHP 包含许多帮助视图创建的助手。它们有助于创建格式良好的标记(包括表单),帮助格式化文本、时间和数字,甚至可以加速 AJAX 功能。有关 CakePHP 中包含的助手的更多信息,请查看每个助手的章节

配置助手

您通过在视图类中声明助手来配置 CakePHP 中的助手。每个 CakePHP 应用程序都带有一个 AppView 类,它是添加用于全局使用的助手的理想位置

class AppView extends View
{
    public function initialize(): void
    {
        parent::initialize();
        $this->addHelper('Html');
        $this->addHelper('Form');
        $this->addHelper('Flash');
    }
}

要添加来自插件的助手,请使用在 CakePHP 中其他地方使用的 插件语法

$this->addHelper('Blog.Comment');

您不必显式添加来自 CakePHP 或您的应用程序的助手。这些助手可以在第一次使用时延迟加载。例如

// Loads the FormHelper if it has not already been explicitly added/loaded.
$this->Form->create($article);

从插件的视图中,插件助手也可以延迟加载。例如,在“Blog”插件中的视图模板可以延迟加载来自同一插件的助手。

有条件地加载助手

您可以使用当前操作名称来有条件地添加助手

class AppView extends View
{
    public function initialize(): void
    {
        parent::initialize();
        if ($this->request->getParam('action') === 'index') {
            $this->addHelper('ListPage');
        }
    }
}

您也可以使用控制器的 beforeRender 方法来添加助手

class ArticlesController extends AppController
{
    public function beforeRender(EventInterface $event)
    {
        parent::beforeRender($event);
        $this->viewBuilder()->addHelper('MyHelper');
    }
}

配置选项

您可以将配置选项传递给助手。这些选项可用于设置属性值或修改助手的行为

namespace App\View\Helper;

use Cake\View\Helper;
use Cake\View\View;

class AwesomeHelper extends Helper
{
    public function initialize(array $config): void
    {
        debug($config);
    }
}

默认情况下,所有配置选项将与 $_defaultConfig 属性合并。此属性应定义助手所需的任何配置的默认值。例如

namespace App\View\Helper;

use Cake\View\Helper;
use Cake\View\StringTemplateTrait;

class AwesomeHelper extends Helper
{
    use StringTemplateTrait;

    /**
     * @var array<string, mixed>
     */
    protected array $_defaultConfig = [
        'errorClass' => 'error',
        'templates' => [
            'label' => '<label for="{{for}}">{{content}}</label>',
        ],
    ];
}

提供给助手构造函数的任何配置都将在构建期间与默认值合并,合并后的数据将设置为 _config。您可以使用 getConfig() 方法来读取运行时配置

// Read the errorClass config option.
$class = $this->Awesome->getConfig('errorClass');

使用助手配置允许您声明性地配置您的助手并将配置逻辑排除在您的控制器操作之外。如果您具有无法作为类声明的一部分包含的配置选项,则可以在控制器的 beforeRender 回调中设置这些选项

class PostsController extends AppController
{
    public function beforeRender(EventInterface $event)
    {
        parent::beforeRender($event);
        $builder = $this->viewBuilder();
        $builder->helpers([
            'CustomStuff' => $this->_getCustomStuffConfig(),
        ]);
    }
}

别名助手

一个常用的设置是 className 选项,它允许您在视图中创建别名助手。当您想要用自定义实现替换 $this->Html 或其他常见的助手引用时,此功能非常有用

// src/View/AppView.php
class AppView extends View
{
    public function initialize(): void
    {
        $this->addHelper('Html', [
            'className' => 'MyHtml',
        ]);
    }
}

// src/View/Helper/MyHtmlHelper.php
namespace App\View\Helper;

use Cake\View\Helper\HtmlHelper;

class MyHtmlHelper extends HtmlHelper
{
    // Add your code to override the core HtmlHelper
}

上面的代码将在您的视图中将 MyHtmlHelper 别名$this->Html

注意

别名助手会替换该实例在使用该助手的任何位置,包括其他助手内部。

使用助手

在您配置了要在控制器中使用的助手后,每个助手都会在视图中公开为一个公共属性。例如,如果您正在使用 HtmlHelper,您可以通过以下方式访问它

echo $this->Html->css('styles');

上面的代码将调用 HtmlHelper 上的 css() 方法。您可以使用 $this->{$helperName} 访问任何已加载的助手。

动态加载助手

在某些情况下,您可能需要从视图内部动态加载助手。您可以使用视图的 Cake\View\HelperRegistry 来执行此操作

// Either one works.
$mediaHelper = $this->loadHelper('Media', $mediaConfig);
$mediaHelper = $this->helpers()->load('Media', $mediaConfig);

HelperRegistry 是一个 注册表,并支持 CakePHP 中其他地方使用的注册表 API。

回调方法

助手具有几个回调,允许您扩展视图渲染过程。有关更多信息,请参阅 助手类事件系统 文档。

创建助手

您可以创建自定义助手类以供您的应用程序或插件使用。与 CakePHP 的大多数组件一样,助手类也有一些约定

  • 助手类文件应放在 src/View/Helper 中。例如:src/View/Helper/LinkHelper.php

  • 助手类应以 Helper 结尾。例如:LinkHelper

  • 引用助手名称时,您应该省略 Helper 后缀。例如:$this->addHelper('Link');$this->loadHelper('Link');

您还需要扩展 Helper 以确保一切正常

/* src/View/Helper/LinkHelper.php */
namespace App\View\Helper;

use Cake\View\Helper;

class LinkHelper extends Helper
{
    public function makeEdit($title, $url)
    {
        // Logic to create specially formatted link goes here...
    }
}

包含其他助手

您可能希望使用另一个助手中已有的某些功能。为此,您可以使用 $helpers 数组指定要使用的助手,其格式与您在控制器中使用的格式相同

/* src/View/Helper/LinkHelper.php (using other helpers) */

namespace App\View\Helper;

use Cake\View\Helper;

class LinkHelper extends Helper
{
    protected array $helpers = ['Html'];

    public function makeEdit($title, $url)
    {
        // Use the HTML helper to output
        // Formatted data:

        $link = $this->Html->link($title, $url, ['class' => 'edit']);

        return '<div class="editOuter">' . $link . '</div>';
    }
}

使用您的助手

创建完助手并将其放在 src/View/Helper/ 中后,您可以在视图中加载它

class AppView extends View
{
    public function initialize(): void
    {
        parent::initialize();
        $this->addHelper('Link');
    }
}

加载完助手后,您可以通过访问匹配的视图属性来在视图中使用它

<!-- make a link using the new helper -->
<?= $this->Link->makeEdit('Change this Recipe', '/recipes/edit/5') ?>

注意

HelperRegistry 将尝试延迟加载您在 Controller 中未明确标识的任何助手。

在助手内访问视图变量

如果您想在助手内部访问视图变量,可以使用 $this->getView()->get(),例如

class AwesomeHelper extends Helper
{
    public array $helpers = ['Html'];

    public function someMethod()
    {
        // set meta description
        return $this->Html->meta(
            'description', $this->getView()->get('metaDescription'), ['block' => 'meta']
        );
    }
}

在助手内渲染视图元素

如果您想在助手内部渲染元素,可以使用 $this->getView()->element(),例如

class AwesomeHelper extends Helper
{
    public function someFunction()
    {
        return $this->getView()->element(
            '/path/to/element',
            ['foo'=>'bar','bar'=>'foo']
        );
    }
}

助手类

class Helper

回调

通过在助手类中实现回调方法,CakePHP 会自动将你的助手订阅到相关事件。与之前的 CakePHP 版本不同,你不应该在回调中调用 parent,因为基础助手类没有实现任何回调方法。

Helper::beforeRenderFile(EventInterface $event, $viewFile)

在渲染每个视图文件之前调用。这包括元素、视图、父视图和布局。

Helper::afterRenderFile(EventInterface $event, $viewFile, $content)

在渲染每个视图文件之后调用。这包括元素、视图、父视图和布局。回调可以修改并返回 $content 来更改渲染内容在浏览器中的显示方式。

Helper::beforeRender(EventInterface $event, $viewFile)

beforeRender 方法在控制器 beforeRender 方法之后调用,但在控制器渲染视图和布局之前调用。接收正在渲染的文件作为参数。

Helper::afterRender(EventInterface $event, $viewFile)

在视图渲染完毕但布局渲染开始之前调用。

Helper::beforeLayout(EventInterface $event, $layoutFile)

在布局渲染开始之前调用。接收布局文件名作为参数。

Helper::afterLayout(EventInterface $event, $layoutFile)

在布局渲染完成后调用。接收布局文件名作为参数。