调用一个非对象的成员函数

83

所以我正在重构我的代码来实现更多面向对象编程。我设置了一个类来保存页面属性。

class PageAtrributes 
{
  private $db_connection;
  private $page_title;

    public function __construct($db_connection) 
    {
        $this->db_connection = $db_connection;
        $this->page_title = '';
    }

    public function get_page_title()
    {
        return $this->page_title;
    }

    public function set_page_title($page_title)
    {
        $this->page_title = $page_title;
    }
}

稍后我会这样调用 set_page_title() 函数:

function page_properties($objPortal) {    
    $objPage->set_page_title($myrow['title']);
}

当我这么做时,我收到以下错误信息:

在非对象上调用成员函数 set_page_title()

那么我缺少什么呢?


3
objPage并不是指向PageAttributes对象的一个实例(或者说,任何对象)。尝试对前一行进行var_dump以查看实际上它是什么。 - Adam Wright
首先,创建一个类的实例;其次,定义它,如:$new_instance = new Class();然后将其指向你的方法,如:$new_instance->set_page_title('MyNewTitle')。 - Jurijs Nesterovs
8个回答

49

这意味着$objPage不是一个对象实例。我们能看一下你用来初始化该变量的代码吗?

由于你期望一个特定的对象类型,你也可以利用PHP的类型提示功能文档在逻辑被违反时得到错误信息:

function page_properties(PageAtrributes $objPortal) {    
    ...
    $objPage->set_page_title($myrow['title']);
}

这个函数只接受PageAttributes作为第一个参数。


37

有一种简单的方法可以产生这个错误:

    $joe = null;
    $joe->anything();

会输出以下错误:

致命错误:在 /Applications/XAMPP/xamppfiles/htdocs/casMail/dao/server.php 的第23行,尝试在非对象上调用成员函数anything()

如果PHP直接提示:

  

致命错误:因为(a) joe为空或(b) joe未定义anything(),所以来自Joe的调用未定义,在第##行。

通常情况下,您应该构建您的类,以便在构造函数中不定义 $joe 或者


6
没关系,我今天就是来找这个的。David关于重现这个错误所写的内容证实了我的猜想,否则我就需要测试一下。 :) - oli.G
谢谢你的解释,David。这对我来说比上面的答案更有帮助,因为它用更简单的语言解释了事情,这让我能够进一步独立地调查问题,而不必创建一个新的线程来寻求帮助,因为上面的答案对我仍然没有帮助。 - Andrew-ThinkUp

7
要么 $objPage 不是实例变量,要么你正在用一个不是 PageAttributes 类的实例来覆盖 $objPage

4
这可能意味着当您初始化对象时,您可能已经在代码的另一个部分中重新使用了对象名称。因此将其从对象更改为标准变量。 例如:
$game = new game;

$game->doGameStuff($gameReturn);

foreach($gameArray as $game)
{
   $game['STUFF']; // No longer an object and is now a standard variable pointer for $game.
}



$game->doGameStuff($gameReturn);  // Wont work because $game is declared as a standard variable.  You need to be careful when using common variable names and were they are declared in your code.

2

我建议使用上面被接受的答案。但是,如果你很着急,你可以在page_properties函数内将对象声明为全局变量。

$objPage = new PageAtrributes;

function page_properties() {
    global $objPage;
    $objPage->set_page_title($myrow['title']);
}

我今天才知道...哦天啊。和Java非常不同。 - gumuruh
是的...我也忘了那件事了。 - Paranoid Android
33
那是最糟糕的解决方案。 - tereško
@tereško,你能详细说明为什么这是不好的做法吗? - Matt Clark
1
@MattClark 因为它依赖于全局状态。 - tereško

2
function page_properties($objPortal) {    
    $objPage->set_page_title($myrow['title']);
}

看起来变量 $objPortal 和 $objPage 的名称不同


0

你可以像下面的例子一样在函数中使用'use'

function page_properties($objPortal) use($objPage){    
    $objPage->set_page_title($myrow['title']);
}

0

我意识到我没有将$objPage传递给page_properties()。现在它可以正常工作了。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,