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

PHP递归对象创建引发内存耗尽,能否实现循环引用对象?

循环引用对象结构的实现方法(解决内存耗尽问题)

你的代码之所以触发Fatal error: Allowed memory size of X bytes exhausted,核心原因是构造函数里的无限递归实例化:当你创建AA的实例时,它的构造函数会创建BB的实例;而BB的构造函数又会反过来创建AA的实例,这个过程无限重复,不断创建新对象占用内存,直到达到PHP的内存限制。

但你想要的循环引用对象结构(Universe→Galaxy→Blackhole→Whitehole→Universe)是完全可以实现的,只要避开这种无限递归的创建方式就行。下面给你两种可行的实现思路:


方法一:先创建所有对象,再手动关联引用

这种方式最直观,先逐个创建每个类的实例,最后再把循环的引用关系赋值上。因为PHP中对象是按引用传递的,赋值时不会创建新实例,只会指向已存在的对象,所以不会触发无限递归。

示例代码:

class Universe {
    public $galaxies = []; // 存储多个Galaxy
}

class Galaxy {
    public $blackhole; // 关联一个Blackhole
    public $stars = []; // 存储多个Star
}

class Blackhole {
    public $whitehole; // 关联一个Whitehole
}

class Whitehole {
    public $universe; // 关联回Universe
}

// 逐步构建对象结构
$universe = new Universe();

// 创建Galaxy并加入Universe
$milkyWay = new Galaxy();
$universe->galaxies[] = $milkyWay;

// 创建Blackhole并关联到Galaxy
$sagA = new Blackhole();
$milkyWay->blackhole = $sagA;

// 创建Whitehole,先关联到Blackhole,再把Universe关联回Whitehole
$whitehole = new Whitehole();
$sagA->whitehole = $whitehole;
$whitehole->universe = $universe;

// 验证循环引用是否生效
var_dump($whitehole->universe->galaxies[0]->blackhole->whitehole === $whitehole); 
// 输出:bool(true),说明循环引用已正确建立

方法二:通过构造函数参数传递已存在的对象

如果你希望在构造函数中完成部分关联逻辑,可以通过构造函数参数把已创建的上级对象传递进去,避免在构造函数中重新创建会触发循环的对象。

示例代码:

class Universe {
    public $galaxies = [];

    public function addGalaxy(Galaxy $galaxy) {
        $this->galaxies[] = $galaxy;
    }
}

class Galaxy {
    public $blackhole;
    public $stars = [];
    private $universe;

    public function __construct(Universe $universe) {
        $this->universe = $universe;
        // 创建Blackhole时把当前Galaxy实例传进去
        $this->blackhole = new Blackhole($this);
    }

    // 给Blackhole提供获取Universe的方法
    public function getUniverse(): Universe {
        return $this->universe;
    }
}

class Blackhole {
    public $whitehole;
    private $galaxy;

    public function __construct(Galaxy $galaxy) {
        $this->galaxy = $galaxy;
        // 创建Whitehole时传入已存在的Universe实例
        $this->whitehole = new Whitehole($galaxy->getUniverse());
    }
}

class Whitehole {
    public $universe;

    public function __construct(Universe $universe) {
        $this->universe = $universe;
    }
}

// 使用方式
$universe = new Universe();
$milkyWay = new Galaxy($universe);
$universe->addGalaxy($milkyWay);

// 验证循环引用
var_dump($milkyWay->blackhole->whitehole->universe === $universe);
// 输出:bool(true)

关键要点总结

  • PHP完全支持对象的循环引用,不需要额外配置;
  • 避免在构造函数中递归创建新的循环对象实例,这是导致内存耗尽的核心原因;
  • 构建循环关系时,始终引用已存在的对象实例,而不是新建。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.21 04:12:02