构造函数参数自动注入失败需先确认是否漏调 parent::__construct();标量参数须用闭包绑定,环境变量通过 env() 读取,service() 返回 null 要检查注册名和调用时机。

构造函数参数自动注入失败,先确认是否漏了 parent::__construct()
很多新手写控制器时重写了 __construct(),但没调用父类构造函数,结果发现 $this->request、$this->response 都是 null,服务也没注入进来。这不是容器配置问题,而是执行链断了。
- 必须显式写
parent::__construct();,否则 CodeIgniter 4 的基础服务(如请求/响应/会话)压根不会初始化 - 如果只是想注入自定义服务,其实可以不用重写
__construct()——直接在方法参数里声明类型提示,框架会自动注入 - 只有需要在实例化时做预处理(比如权限校验、初始化属性),才需要重写,并且务必把
parent::__construct()放在第一行
标量参数(字符串/数组)传不进构造函数?用闭包绑定
服务容器能自动解析类类型(如 UserService、Database),但对 string、int、array 这类标量参数完全没辙。比如你有个日志类:FileLogger 构造函数要 $logLevel 和 $filePath,容器不知道该塞什么值进去。
- 去
app/Config/Services.php,在public static function custom()方法里加绑定逻辑 - 写法是:
$container->set('FileLogger', function ($container) { return new \App\Libraries\FileLogger('error', WRITEPATH . 'logs/app.log'); }); - 注意:闭包参数
$container可用来解析其他依赖,比如你想在FileLogger里再注入一个Formatter,就用$container->get('Formatter') - 别在闭包里硬编码路径,优先用
WRITEPATH、APPPATH等常量,避免部署时出错
环境变量怎么接入服务容器?别写死,用 env()
开发和生产环境的数据库地址、API密钥、日志级别都不一样,如果直接在 Services.php 里写死字符串,每次部署都要改代码,极易出错。
- 在
.env文件里写:LOG_LEVEL=debug、LOG_PATH=/var/log/myapp - 在闭包绑定里读取:
env('LOG_LEVEL', 'info'),第二个参数是默认值,防止.env没配时崩掉 - 不要用
getenv()或$_ENV,CodeIgniter 4 的env()函数会自动加载.env并缓存,更可靠 - 敏感配置(如数据库密码)也走
.env,千万别提交到 Git
为什么 service('xxx') 返回 null?检查注册名和作用域
调用 service('mylogger') 得到 null,常见原因不是没注册,而是名字对不上或时机不对。
- 注册名必须和
service()里传的字符串完全一致,区分大小写,比如你set('FileLogger'),就不能用service('filelogger') -
set()是运行时绑定,必须在容器初始化完成后执行;Services.php里的静态方法会在框架启动早期自动调用,所以放这里最安全 - 如果在控制器构造函数里调用
service(),确保它在parent::__construct()之后——否则容器还没准备好 - 调试时可临时加一句:
var_dump(\Config\Services::initialized());看容器是否已启动
.env 和类型提示,却没意识到字符串根本不在容器的自动解析范围内。


















