CodeIgniter自定义库初始化异常求助:循环依赖引发未定义属性
问题根源分析
你遇到的是库之间的循环依赖+初始化时机冲突导致的未定义属性错误,具体触发流程如下:
- 控制器同时加载
lib_wishlists和lib_basket,优先加载lib_wishlists lib_wishlists构造函数中加载lib_basketlib_basket构造函数中尝试加载lib_wishlists(CI会标记该库已在加载队列,不会重复实例化),随后调用init_basketinit_basket中调用lib_wishlists的use_wishlist_as_basket方法- 此时
lib_basket的实例还未完全初始化完成,尚未被赋值到CI实例的属性中,因此$this->CI->lib_basket会触发未定义属性的错误
解决方案
方案一:统一加载+延迟初始化(推荐)
移除库内部的交叉加载逻辑,将依赖加载和初始化步骤统一放到控制器中执行,确保所有依赖都加载完成后再初始化。
修改后的控制器代码
class Tests extends CI_Controller { public function __construct() { parent::__construct(); // 先加载所有依赖库 $this->load->library(['lib_wishlists', 'lib_basket']); // 再执行初始化逻辑 $this->lib_wishlists->initWishlist(); $this->lib_basket->init_basket(); } }
修改后的Lib_wishlists代码
class Lib_wishlists { protected CI_Controller $CI; public function __construct() { $this->CI =& get_instance(); $this->CI->load->database(); // 移除内部加载lib_basket和自动调用initWishlist的逻辑 } public function initWishlist() { // 原构造函数中的初始化逻辑移到这里 } public function use_wishlist_as_basket(array $where = []): ReturnObject { // 此时lib_basket已被控制器加载完成,可正常调用 $addObj = $this->CI->lib_basket->add_product_checks(...); } }
修改后的Lib_basket代码
class Lib_basket { protected CI_Controller $CI; public function __construct() { $this->CI =& get_instance(); // 移除内部加载lib_wishlists和自动调用init_basket的逻辑 } public function init_basket() { if (empty($this->CI->session->userdata('basket'))) { if ($this->CI->auth->logged_in()) { $this->CI->lib_wishlists->use_wishlist_as_basket(...); } else { $this->CI->session->set_userdata('basket', []); } } } }
方案二:懒加载依赖(应急方案)
如果无法调整初始化时机,可以在调用对方方法前检查依赖是否已加载,未加载则手动加载并初始化:
Lib_wishlists中修改use_wishlist_as_basket方法
public function use_wishlist_as_basket(array $where = []): ReturnObject { if (!isset($this->CI->lib_basket)) { $this->CI->load->library('lib_basket'); $this->CI->lib_basket->init_basket(); } $addObj = $this->CI->lib_basket->add_product_checks(...); }
Lib_basket中修改init_basket方法
public function init_basket() { if (empty($this->CI->session->userdata('basket'))) { if ($this->CI->auth->logged_in()) { if (!isset($this->CI->lib_wishlists)) { $this->CI->load->library('lib_wishlists'); $this->CI->lib_wishlists->initWishlist(); } $this->CI->lib_wishlists->use_wishlist_as_basket(...); } else { $this->CI->session->set_userdata('basket', []); } } }
总结
核心原则是避免在库的构造函数中交叉加载依赖和执行初始化逻辑,将初始化时机延后到所有依赖都加载完成之后,即可解决循环依赖导致的未定义属性问题。
内容的提问来源于stack exchange,提问作者Bobyblanco
相关产品推荐
相关产品推荐

