CodeIgniter4 代码模块
CodeIgniter支持代码模块化组合,以便于你构建可重用的代码。模块通常来说是以一个特定主题为中心而构建的,并可被认为是在大型的程序中的一系列微型程序。 我们支持框架中所有标准的文件类型,例如控制器,模型,视图,配置文件,辅助函数,语言文件等。模块可能包含着或多或少的你所需要的以上这些类型中。
命名空间
CodeIgniter所使用的模块功能的核心组件来自于 与PSR4相适应的自动加载 。 虽然所有的代码都可以使用PSR4的自动加载和命名空间,最主要的充分使用模块优势的方式还是为你的代码加上命名空间,并将其添加到 app/Config/Autoload.php 中,在 psr4
这节中。
举例而言,比如我们需要维护一个在应用间复用的简单的博客模块。我们可能会创建一个带有公司名(比如acme)的文件夹来保存所有的模块。 我们可能会将其置于我们的 application 目录旁边,在主项目目录下:
/acme // 新的模块目录
/application
/public
/system
/tests
/writable
打开 app/Config/Autoload.php 并将 Acme 命名空间加入到 psr4
数组成员中:
$psr4 = [
'Config' => APPPATH . 'Config',
APP_NAMESPACE => APPPATH, // 自定义命名空间
'App' => APPPATH, // 确保筛选器等组件可找到,
'Acme' => ROOTPATH.'acme'
];
当我们设置完以上流程后,就可以通过 Acme
命名空间来访问 acme 目录下的文件夹内容。这已经完成了80%的模块工作所需要的内容, 所以你可以通过熟悉命名空间来适应这种使用方式。这样多种文件类型将会被自动扫描并在整个定义的命名空间中使用——这也是使用模块的关键。
在模块中的常见目录结构和主程序目录类似:
/acme
/Blog
/Config
/Controllers
/Database
/Migrations
/Seeds
/Helpers
/Language
/en
/Libraries
/Models
/Views
当然了,不强制使用这样的目录结构,你也可以自定义目录结构来更好地符合你的模块要求,去掉那些你不需要的目录并增加一些新的目录,例如实体(Entites),接口(Interfaces),仓库(Repository)等。
自动发现
很多情况下,你需要指名你所需要包含进来的文件的命名空间全称,但是CodeIgniter可以通过配置自动发现的文件类型,来将模块更方便地整合进你的项目中:
这些是在 app/Config/Modules.php 文件中配置的。
自动发现系统通过扫描所有在 Config/Autoload.php 中定义的PSR4类型的命名空间来实现对于目录/文件的识别。
当我们回顾上面的 acme 命名空间时,需要进行一个小小的调整,使得文件被发现: 每个命名空间中的“模块”需要拥有自己独立定义的命名空间。 Acme 需要被换成 AcmeBlog。当你的模块文件夹确定下来后,如果我们要去找一个Routes文件,自动发现的流程就会去寻找 /acme/Blog/Config/Routes.php 以防在别的应用中进行了查找。
开启/关闭自动发现
你可以开启或关闭所有的系统中的自动发现,通过 $enabled 类变量。False的话就会关闭所有的自动发现,优化性能,但却会让你的模块可用性相对下降。
明确目录项目
通过 $activeExplorers 选项,你可以明确哪些项目是自动发现的。如果这个项目不存在,就不会对它进行自动发现流程,而数组中的其他成员仍旧会被自动发现。
自动发现与Composer
通过Composer安装的包将会默认被自动发现。这只需要Composer识别所需要加载的命名空间是符合PSR4规范的命名空间,PSR0类型的命名空间将不会被发现。
如果在定位文件时,你不想扫描所有Composer已识别的的目录,可以通过编辑 Config\Modules.php
中的 $discoverInComposer
变量来关闭这一功能:
public $discoverInComposer = false;
和文件打交道Working With Files
这节将会详细介绍每种文件类型(控制器,视图,语言文件等)以及在模块中如果使用它们。其中的某些信息在用户手册中将会更为详细地描述,不过在这里重新介绍一下以便了解全局的情况。
路由
默认情况下, 路由 将会在模块内部自动扫描,而这一特性可在 Modules 配置文件中被关闭,如上所述。
注解
由于在当前域内包含了路由文件,$routes
实例已经被定义了,所以当你尝试重新定义类的时候可能会引起错误。
控制器
在主 app/Controller 目录下定义的控制器不会自动被URI路由自动调用,所以需要在路由文件内部手动声明:
// Routes.php
$routes->get('blog', 'Acme\Blog\Controllers\Blog::index');
为了减少不必要的输入, group 路由特性(译者注: 分组路由 </incoming/routing#分组路由> )是一个不错的选择:
$routes->group('blog', ['namespace' => 'Acme\Blog\Controllers'], function($routes)
{
$routes->get('/', 'Blog::index');
});
配置文件
No special change is needed when working with configuration files. These are still namespaced classes and loaded with the new
command:
$config = new \Acme\Blog\Config\Blog();
Config files are automatically discovered whenever using the config() function that is always available.
迁移
迁移文件将通过定义的命名空间自动发现。所有命名空间里找到的迁移每次都会被自动运行。
种子
种子文件可在CLI或其他种子文件里使用,只要提供了完整的命名空间名。如果通过CLI调用,就需要提供双反斜杠定义的类名格式():
> php public/index.php migrations seed Acme\\Blog\\Database\\Seeds\\TestPostSeeder
辅助函数
当使用 helper()
方法时,辅助函数将会通过定义的命名空间自动定位。只要它存在于 Helpers 命名空间目录下:
helper('blog');
语言文件
当使用 lang()
方法时,语言文件是通过定义的命名空间来自动定位的。只要这个文件是遵循主程序目录一样的目录结构来放置的。
库
库总是通过完全命名空间化的类名进行实例化,所以不需要额外的操作:
$lib = new \Acme\Blog\Libraries\BlogLib();
模型
模型总是通过完全命名空间化的类名进行实例化,所以不需要额外的操作:
$model = new \Acme\Blog\Models\PostModel();
视图
视图文件可通过 视图 文档中所述的类命名空间进行加载:
echo view('Acme\Blog\Views\index');