继承类属性返回NULL问题求助:NewsComments无法访问news_id
问题分析
你遇到的问题核心是对PHP类继承的概念理解有误,同时代码里的属性声明和构造函数调用也存在细节问题:
1. 实例独立,数据不共享
你先实例化了News对象(传入news_id),然后又实例化了NewsComments对象(传入comment_id)——这是两个完全独立的对象,继承关系不会让NewsComments实例自动获取News实例的news_id值。NewsComments的news_id属性只会由它自己的构造函数(继承自News的构造函数)赋值,也就是你传入的comment_id,如果comment_id为空,自然返回null。
2. 属性未显式声明(导致Undefined Property警告)
你的News类里没有显式声明$news_id属性,而是直接在构造函数中动态赋值$this->news_id = $id。虽然PHP允许这种操作,但在继承场景中,这种隐式创建的属性可能会导致子类无法正确识别,从而抛出Undefined property警告。
解决方案
根据你的实际需求,分两种情况处理:
情况一:需要NewsComments关联特定News实例
如果你希望NewsComments实例关联某个已存在的News实例,不要通过继承传递数据,而是通过构造函数注入的方式:
class News extends Privilege { // 显式声明为protected,让子类可以访问 protected $news_id; public function __construct($id = null) { if(!is_null($id)) { $this->news_id = $id; } } // 提供获取news_id的方法(可选,封装属性更安全) public function getNewsId() { return $this->news_id; } } class NewsComments extends News { private $comment_id; // 修改构造函数,接收News实例和comment_id public function __construct(News $news, $comment_id) { // 调用父类构造函数,传入关联的news_id parent::__construct($news->getNewsId()); $this->comment_id = $comment_id; } public function testFunction() { return $this->news_id; // 现在会返回关联的新闻ID } } // 使用方式:先创建News实例,再传入NewsComments $News = new News($_POST['news_id']); $NewsComments = new NewsComments($News, $_POST['comment_id']);
情况二:NewsComments实例自己拥有news_id(不需要关联已有的News实例)
如果你只是希望NewsComments继承News的方法,同时自身实例拥有独立的news_id,需要确保构造函数正确赋值,并且显式声明属性:
class News extends Privilege { protected $news_id; public function __construct($id = null) { if(!is_null($id)) { $this->news_id = $id; } } } class NewsComments extends News { private $comment_id; public function __construct($news_id, $comment_id) { // 必须手动调用父类构造函数,传入news_id parent::__construct($news_id); $this->comment_id = $comment_id; } public function testFunction() { return $this->news_id; // 会返回传入的新闻ID } } // 使用方式:直接传入news_id和comment_id $NewsComments = new NewsComments($_POST['news_id'], $_POST['comment_id']);
关键注意点
- 显式声明属性:在父类中显式声明
protected或public属性,确保子类可以正常访问,避免Undefined Property警告。 - 调用父类构造函数:当子类有自定义构造函数时,必须手动调用
parent::__construct()触发父类的初始化逻辑,否则父类的属性不会被赋值。 - 区分类继承和实例关联:继承是类的结构复用,不是实例数据的共享。如果需要在两个实例间传递数据,用依赖注入(把一个实例传入另一个的构造函数)比依赖继承更合理。
内容的提问来源于stack exchange,提问作者Joshua McNabb
相关产品推荐
相关产品推荐

