You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PHP两个相互通信的类触发无限循环内存耗尽该如何解决

错误原因

你当前的写法属于构造函数循环依赖:实例化Foo的时候会在构造函数中new Bar,实例化Bar的时候构造函数又会new Foo,无限递归创建对象,最终耗尽PHP分配的内存触发致命错误。

常用解决方案

方案1:依赖注入(通用首选)

不要在构造函数内直接new对方实例,而是通过构造函数参数、setter方法将已经初始化的对方实例注入。如果是框架项目,直接使用框架自带的DI容器即可自动处理循环依赖的实例化,不需要手动编写初始化逻辑。

class UserStatusController
{
    // 注入CouponController实例
    public function __construct(CouponController $couponController)
    {
        $this->couponController = $couponController;
    }
    
    // 注:原代码里private属性是实例属性,不能用self::$badStatus调用,此处已修正
    private $badStatus = "blocked";
    
    public function hasBadStatus(int $id): bool
    {
        $user = User::where(['id' => $id])->get();
        return $user->status == $this->badStatus;
    }
    
    public function actualizeStatus(int $id, string $status): bool
    {
        if ($status == $this->badStatus) {
            // 注:原代码调用deleteCoupon未传用户ID,此处已补全参数
            $this->couponController->deleteCoupon($id);
            return false;
        }
        
        User::where(['id' => $id])->update(['status' => $status]);
        $this->couponController->createCoupon($id);
        return true;
    }
}

class CouponController
{
    // 注入UserStatusController实例
    public function __construct(UserStatusController $userStatusController)
    {
        $this->userStatusController = $userStatusController;
    }
    
    public function createCoupon(int $id): bool 
    {
        if ($this->userStatusController->hasBadStatus($id)) { 
            return false; 
        }
        // 创建优惠券逻辑
        return true;
    }
    
    public function deleteCoupon(int $id): bool 
    {
        // 删除优惠券逻辑
        return true;
    }
}

方案2:懒加载(适配成本最低)

不在构造函数初始化对方实例,第一次用到的时候再创建并缓存为单例,避免重复初始化触发递归。不需要大幅修改原有代码,适合快速修复问题:

class UserStatusController
{
    private $couponController = null;
    private $badStatus = "blocked";
    
    // 首次调用时才初始化CouponController
    private function getCouponController()
    {
        if ($this->couponController === null) {
            $this->couponController = new CouponController();
        }
        return $this->couponController;
    }
    
    public function hasBadStatus(int $id): bool
    {
        $user = User::where(['id' => $id])->get();
        return $user->status == $this->badStatus;
    }
    
    public function actualizeStatus(int $id, string $status): bool
    {
        if ($status == $this->badStatus) {
            $this->getCouponController()->deleteCoupon($id);
            return false;
        }
        
        User::where(['id' => $id])->update(['status' => $status]);
        $this->getCouponController()->createCoupon($id);
        return true;
    }
}

class CouponController
{
    private $userStatusController = null;
    
    // 首次调用时才初始化UserStatusController
    private function getUserStatusController()
    {
        if ($this->userStatusController === null) {
            $this->userStatusController = new UserStatusController();
        }
        return $this->userStatusController;
    }
    
    public function createCoupon(int $id): bool 
    {
        if ($this->getUserStatusController()->hasBadStatus($id)) { 
            return false; 
        }
        // 创建优惠券逻辑
        return true;
    }
    
    public function deleteCoupon(int $id): bool 
    {
        // 删除优惠券逻辑
        return true;
    }
}

方案3:事件中间层解耦(适合复杂项目)

抽离公共事件层,两个类不用直接持有对方实例,通过事件调度完成交互,彻底解耦后扩展性更强,后续新增关联逻辑不需要修改原有类代码:

// 事件定义
class UserStatusUpdated
{
    public $userId;
    public $newStatus;
    public function __construct(int $userId, string $newStatus)
    {
        $this->userId = $userId;
        $this->newStatus = $newStatus;
    }
}

// 简易事件调度器,框架项目可直接使用自带的事件系统
class EventDispatcher
{
    private $listeners = [];
    public function listen(string $event, callable $listener)
    {
        $this->listeners[$event][] = $listener;
    }
    public function dispatch(object $event)
    {
        $eventName = get_class($event);
        if (isset($this->listeners[$eventName])) {
            foreach ($this->listeners[$eventName] as $listener) {
                $listener($event);
            }
        }
    }
}

// 改造后的用户状态类,只负责状态更新和事件触发
class UserStatusController
{
    public function __construct(EventDispatcher $dispatcher)
    {
        $this->dispatcher = $dispatcher;
    }
    
    private $badStatus = "blocked";
    
    public function hasBadStatus(int $id): bool
    {
        $user = User::where(['id' => $id])->get();
        return $user->status == $this->badStatus;
    }
    
    public function actualizeStatus(int $id, string $status): bool
    {
        User::where(['id' => $id])->update(['status' => $status]);
        // 触发状态变更事件
        $this->dispatcher->dispatch(new UserStatusUpdated($id, $status));
        return true;
    }
}

// 改造后的优惠券类,只需要监听事件完成对应操作
class CouponController
{
    public function __construct(EventDispatcher $dispatcher, UserStatusController $userStatusController)
    {
        $this->userStatusController = $userStatusController;
        // 监听用户状态变更事件
        $dispatcher->listen(UserStatusUpdated::class, function(UserStatusUpdated $event) {
            if ($event->newStatus == "blocked") {
                $this->deleteCoupon($event->userId);
            } else {
                $this->createCoupon($event->userId);
            }
        });
    }
    
    public function createCoupon(int $id): bool 
    {
        if ($this->userStatusController->hasBadStatus($id)) { 
            return false; 
        }
        // 创建优惠券逻辑
        return true;
    }
    
    public function deleteCoupon(int $id): bool 
    {
        // 删除优惠券逻辑
        return true;
    }
}

内容的提问来源于stack exchange,提问作者Tenarius

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.06 19:15:02