如何在CodeIgniter 4中扩展控制器并创建类似CodeIgniter 3的核心控制器
嘿,针对你问的CodeIgniter 4扩展控制器、以及模拟CI3自定义核心控制器的问题,我来给你一步步讲清楚!
在CodeIgniter 4中扩展控制器
CodeIgniter 4里扩展控制器的核心思路是创建一个基础控制器,让所有业务控制器继承它,这样就能复用公共逻辑(比如登录校验、全局数据传递、通用方法)。具体步骤如下:
- 创建基础控制器
在app/Controllers目录下新建一个文件,比如BaseController.php(CI4默认已经有这个文件,你可以直接修改它,也可以自定义名字):
<?php namespace App\Controllers; use CodeIgniter\Controller; class BaseController extends Controller { // 定义公共属性,比如常用助手、会话实例 protected $helpers = ['url', 'form', 'session']; protected $session; // 控制器初始化方法,替代CI3的__construct初始化逻辑 public function initController(\CodeIgniter\HTTP\RequestInterface $request, \CodeIgniter\HTTP\ResponseInterface $response, \Psr\Log\LoggerInterface $logger) { // 必须调用父类的initController,否则框架核心功能会失效 parent::initController($request, $response, $logger); // 初始化会话服务 $this->session = \Config\Services::session(); // 示例:全局登录校验逻辑,未登录则跳转到登录页 if (!$this->session->get('logged_in')) { return redirect()->to('/login'); } } // 自定义公共方法:统一加载视图,自动带上全局数据 protected function loadView($view, $data = []) { // 合并全局数据和当前视图数据 $globalData = ['siteName' => '我的CI4站点']; $data = array_merge($globalData, $data); return view('templates/header', $data) . view($view, $data) . view('templates/footer', $data); } }
- 业务控制器继承基础控制器
之后你的所有业务控制器,都可以继承这个BaseController,直接使用里面的公共属性和方法:
<?php namespace App\Controllers; class Home extends BaseController { public function index() { // 直接使用BaseController里的loadView方法 return $this->loadView('home/index', ['welcomeText' => '欢迎来到首页']); } }
在CodeIgniter 4中创建类似CodeIgniter 3的自定义核心控制器
先回顾下CodeIgniter 3的做法,我们通常在application/core目录下创建MY_Controller.php作为自定义核心控制器,所有业务控制器都继承它:
CodeIgniter 4没有单独的core目录,但我们可以用几乎一样的思路实现,只是文件位置和命名空间需要调整:
- 创建自定义核心控制器
在app/Controllers目录下新建MY_Controller.php(名字和CI3保持一致,符合你的使用习惯):
<?php namespace App\Controllers; use CodeIgniter\Controller; class MY_Controller extends Controller { protected $loggedUser; // 存储登录用户信息 protected $globalData = []; // 全局视图数据 public function initController(\CodeIgniter\HTTP\RequestInterface $request, \CodeIgniter\HTTP\ResponseInterface $response, \Psr\Log\LoggerInterface $logger) { parent::initController($request, $response, $logger); // 加载常用服务和助手 $this->session = \Config\Services::session(); helper(['form', 'url', 'auth']); // 公共登录校验,获取登录用户信息 $this->loggedUser = $this->session->get('user'); if (!$this->loggedUser) { return redirect()->route('login'); // 使用路由名称跳转,更灵活 } $this->globalData['loggedUser'] = $this->loggedUser; } // 封装公共视图加载方法 protected function render($view, $data = []) { $data = array_merge($this->globalData, $data); return view('layouts/header', $data) . view($view, $data) . view('layouts/footer', $data); } }
- 业务控制器继承
MY_Controller
和CI3的用法完全一致,业务控制器直接继承MY_Controller即可复用所有公共逻辑:
<?php namespace App\Controllers; class Dashboard extends MY_Controller { public function index() { $this->globalData['pageTitle'] = '后台仪表盘'; $stats = $this->getDashboardStats(); // 自定义业务方法 return $this->render('dashboard/index', ['stats' => $stats]); } private function getDashboardStats() { // 模拟获取统计数据 return ['totalUsers' => 150, 'totalOrders' => 320]; } }
小提示
- CI4的
initController是控制器初始化的入口,一定要调用父类方法,否则会导致框架核心服务无法正常初始化。 - 如果你想让所有控制器默认继承自定义核心控制器,也可以修改CI4的核心配置,但不建议这么做——手动继承更灵活,也符合框架的设计理念。
内容的提问来源于stack exchange,提问作者Parag Dhali




