# 模块 / Modules Pagekit 使用 *模块/Modules* 来组建应用程序的代码。模块的定义是用于提供引导、路由和其他配置选项。可以在这里监听事件、添加自定义类和自己的控制器(controllers)。 ## 定义: index.php 为了加载和配置模块,Pagekit 有一个模块管理器(ModuleManager)。模块管理器会在模块的根目录中寻找 `index.php` 文件并期望它返回一个 PHP 数组。该数组用作模块代码的引导。 通过在数组中设置正确的属性,告知 Pagekit 关于模块的所有细节。 ```php <?php /* * 返回作为模块定义的 PHP 数组 */ return [ // Required: Unique module name 'name' => 'hello', ]; ``` 这个最小的例子是有效的模块定义,即使它被 Pagkit 加载后并不会做任何事。只有在管理面板中启用包,相关的模块才会被加载。 **Note:** 如果你开始探索 Pagekit 的内部结构,你会在许多地方看到相同的模块结构,它是 Pagekit 架构的核心理念。 ## 可用的属性 下表包含所有可以在模块定义数组中使用的键名(KEY)。接下来解释了各个属性的详细信息以及相关示例代码。可以点击 *Details* 直接查看相关部分。 |Key | Description | More| |--------- | --------------------------------- | -----| |`main` | 引导代码,模块被加载时执行 | [Details](#bootstrap-code)| |`autoload` | 注册自动加载的命名空间 | [Details](#register-custom-namespaces)| |`routes` | Mount controllers | [Details](#mount-controllers)| |`permissions` | 定义和注册权限名称 | [Details](#define-permissions)| |`resources` | Register resource shorthands | [Details](#register-resource-shorthands)| |`events` | 监听 Pagekit 或其他模块的事件 | [Details](#listen-to-events)| |`config` | 默认的模块配置 | [Details](#default-module-configuration)| |`nodes` | 注册站点树节点 | [Details](#register-nodes-for-site-tree)| |`node` | 节点配置的默认选项 | [Details](#node-options)| |`settings` | 链接到设置界面 | [Details](#link-to-a-settings-screen)| |`menu` | 将菜单条目添加到管理面板 | [Details](#add-menu-items-to-the-admin-panel)| |`widgets` | 注册小工具 | [Details](#register-widgets)| |`widget` | 小工具配置的默认选项 | [Details](#widget-options)| ## 引导代码 要执行各种 PHP 代码,你可以为 `main` 属性指派一个回调函数。该函数以参数的形式接收 Pagekit 的 Application 容器实例。 ```php use Pagekit\Application; // ... 'main' => function (Application $app) { // bootstrap code } ``` 在每个普通页面请求时,该函数在模块被加载后才被调用。模块的 `index.php` 需要放在可用的包内部,而且需要在管理面板中启用这个包。这意味着扩展需要被安装和启用了才能加载引导代码。如果是在主题内使用它,只有当前激活的主题中的引导代码会被执行。 如果不想指派回调函数和直接把代码存放在 `index.php` 中,你还可以在一个单独的文件里创建一个专用的模块。然后将模块类(module class)的名字(包括命名空间)指定为 `main` 属性的值。 ```php 'main' => 'MyNamespace\\MyModule', ``` **Note** 为使其正常工作,这个被引用的命名空间必须被[自动加载](#register-custom-namespaces)。确保`MyModule` 类实现了`Pagekit\Module\ModuleInterface`接口。 ## 注册自定义命名空间 传递一个命名空间和路径组成的列表,使它们可以被 Pagekit 自动加载。路径是相对于模块的路径,假设模块定义的位置是在 `packages/VENDOR/PACKAGE/index.php`,那么下面例子中的 `src` 位于 `packages/VENDOR/PACKAGE/src`。 ```php 'autoload' => [ 'Pagekit\\Hello\\' => 'src' ] ``` 被链接的目录中的类,可以通过在 Pagekit 代码库中使用 ``use`` 语句引用。 ``` <?php use Pagekit\Hello\HelloExtension; ``` ## 增加控制器 使用 `routes` 熟悉为路由增加控制器。更多细节,阅读[路由和控制器](224133)。 ```php 'routes' => [ '/hello' => [ 'name' => '@hello/admin', 'controller' => [ 'Pagekit\\Hello\\Controller\\HelloController' ] ] ] ``` ## 定义权限 你的模块可以定义权限。这些权限可以在 Pagekit 的用户 &amp; 权限界面指定给各种用户角色。 你定义的唯一权限名称(下例中的 `hello: manage settings`),在代码库中被用作标识符。可以使用此标识符可以防止没有权限的用户执行未授权的操作。 ```php 'permissions' => [ 'hello: manage settings' => [ 'title' => 'Manage settings' ] ] ``` 保护控制器操作的一个简单方式是像下面的例子中这样,使用注释。阅读[路由](224133)中注释这部分了解更多。 ``` <?php class MyController { /** * @Access("hello: manage settings") */ public function settingsAction() { } } ``` ## 注册源代码简写方式 可以注册前缀,作为处理路径时的简写方式。例如使用 `views:admin/settings.php` 来引用 `packages/VENDOR/PACKAGE/views/admin/settings.php`。Pagekit 已经默认为扩展和主题注册了一些路径了。 无论何时,只要在使用 Pagekit 文件系统,它都会工作(例如,在生成文件路径的 URL 时,或者从控制器渲染视图时)。 ```php 'resources' => [ 'views:' => 'views' ], ``` ## 事件监听 事件是在 Pagekit 核心或其他潜在的模块的某些关键点上触发的。每个事件都有一个独一无二的名称来定义它。可以为任意事件注册回调函数。 了解关于事件系统的更多信息,查阅[事件](224132)。 ```php 'events' => [ 'view.scripts' => function ($event, $scripts) { $scripts->register('hello-settings', 'hello:app/bundle/settings.js', '~extensions'); } ] ``` ## 默认的模块配置 在许多情况下,你希望允许用户修改模块的设置,例如提供一个设置页面。要确保你的模块一开始就有配置的值,你可以提供一套默认的模块配置。 ```php 'config' => [ 'default' => 'World' ], ``` 任何对于配置数组的修改,都会在稍后存储到数据库。然后,默认值会与数据库中的值合并,合并后的结果可用作模块对象的配置属性,如你在下面两节的例子所见。 ### 读取配置 要读取模块的配置,可以访问模块实例的 `config` 属性。它是`index.php`中保存的默认配置和存储在数据库中的修改值的合并结果。 ```php $config = $app->module('hello')->config; ``` ### 写入配置 要存储模块配置的修改,使用 `config()` 服务。这些修改会自动传输到数据库。 ```php // Complete config $app->config()->set('hello', $config); // Single Value $app->config('hello')->set('message', 'Custom message'); ``` **Note**. 如果直接从模块中读取配置,它依然是原来的值。在下一次请求后,Pagekit 会合并修改,并使它们可用作 `$module` 实例的 `config` 属性。 ## 注册站点树节点 节点(Node)与路由的最大区别在于,节点可以在站点树视图(Site Tree View)中拖拽,并因此导致了计算出的路由的结果是动态的。 在添加节点之后,它将在站点树中可用。点击 _Add Page_ 按钮查看包含所有可用类型的下拉菜单。 了解关于节点的更多信息,查阅[路由](224133)。 ```php 'nodes' => [ 'hello' => [ // 节点路由的名称 'name' => '@hello', // 显示在管理面板中的标签 'label' => 'Hello', // 此节点的控制器。每个控制器操作都会被附加到路由 'controller' => 'Pagekit\\Hello\\Controller\\SiteController' ] ] ``` ## 节点选项 在站点树中,如果模块想要为内容编辑器添加一个配置界面,可以使用 `node` 属性来添加默认选项到节点对象(关于配置界面的完整说明,查阅[主题教程](../tutorials/theme.md#adding-position-options))。 在下面的例子中,主题定义了自动添加到每个已渲染的节点对象的 `top_style` 属性。在下面的例子中,该属性有一个默认值 `uk-block-muted`,它是渲染 `top`位置的 CSS 类。 ```php 'node' => [ 'top_style' => 'uk-block-muted' ], ``` 在主题的 `template.php` 中渲染页面时,可以从 `$params` 数组访问这个对象。 ```php <?php echo $params['top_style'] ?> ``` 利用 `node` 属性,可以为每个节点设置默认值。要允许用户修改这些值,你需要在管理界面中添加一个界面(典型的形式是编辑页面内容时的 _Theme_ 标签页)。 要允许用户修改你在这里定义的小工具的默认值,可以为管理界面添加一个界面。为此,需要定义一个 javascript 组件来显示编辑页面([Example](https://github.com/pagekit/example-theme/blob/master/app/components/node-theme.vue)),在内容编辑页面注册这个 javascript ([Example](https://github.com/pagekit/example-theme/blob/master/index.php#L43)) ,如果你在使用 webpack,可选择地更新 webpack 配置([Example](https://github.com/pagekit/example-theme/blob/master/webpack.config.js#L5))。完整的说明可以参阅 [主题教程](../tutorials/theme.md#adding-position-options). ## 添加菜单条目到管理面板 可以为管理面板的主导航添加菜单条目。可以将它链接到任意已注册的路由并赋予有限的访问权限。`access` 属性会确认菜单条目是否可见。 ```php 'menu' => [ // 用于菜单结构层次的名称 'hello' => [ // 要显示的表情 'label' => 'Hello', // 要显示的图标 'icon' => 'hello:icon.svg', // 此菜单条目链接到的 URL 'url' => '@hello/admin', // 可选:检查菜单项是否在当前 url 是激活的 // 'active' => '@hello*' // 可选: 针对被指定特定权限的角色的访问限制 // 'access' => 'hello: manage hellos' ], 'hello: panel' => [ // 父级菜单项,使此项显示在二级菜单中 'parent' => 'hello', // See above 'label' => 'Hello', 'icon' => 'hello:icon.svg', 'url' => '@hello/admin' // 'access' => 'hello: manage hellos' ] ], ``` ## 链接到设置页面 链接到渲染设置页面的路由。设置这个属性使 Pagekit 在控制面板列表中的主题或扩展旁渲染一个 _Settings_ 按钮。 ```php 'settings' => '@hello/admin/settings', ``` ## 注册小工具 小工具也是一种模块。使用 `widgets` 小工具可以注册所有小工具模块的定义文件。这些文件都被预期返回一个模块定义格式的 PHP 数组。了解更多关于[小工具](224139)。 ```php 'widgets' => [ 'widgets/form.php' ], ``` ## 小工具选项 如果模块想要为小工具编辑器添加一个配置界面(通常是在开发主题时),可以使用 `widget` 属性来为小工具对象添加默认选项(小工具配置界面的完整例子在[开发 Pagekit 主题](223157)中)。 下面的例子中,主题定义了一个自动添加到每个已渲染的小工具对象的 `panel` 属性。默认地,该属性以空字符串作为它的值。 ```php 'widget' => [ 'panel' => '' ], ``` 在渲染小工具时,可以在 `$widget->theme` 数组中访问这个属性。 ```php <?php echo $widget->theme['panel'] ?> ``` 要允许用户修改你在这里定义的小工具选项的默认值,可以在管理界面中添加一个界面。为此,可以定义一个 javascript组件来显示编辑界面([Example](https://github.com/pagekit/example-theme/blob/master/app/components/widget-theme.vue)),在小工具编辑器页面注册这个 javascript 文件 ([Example](https://github.com/pagekit/example-theme/blob/master/index.php#L47)) ,如果你在使用webpack([Example](https://github.com/pagekit/example-theme/blob/master/webpack.config.js#L7)),可以有选择地更新 webpack 的配置。完整的说明可以在这里找到:[主题教程](223157).