PHP致命错误:不在对象上下文中时使用$ this


137

我有一个问题:

我正在编写没有框架的新WebApp。

在我的index.php中,我正在使用:require_once('load.php');

load.php中,require_once('class.php');用来加载class.php

在我的class.php中,出现此错误:

致命错误:如果不在类的上下文中,则在行上使用$ this ...(在此示例中为11)

我的class.php的编写示例:

class foobar {

    public $foo;

    public function __construct() {
        global $foo;

        $this->foo = $foo;
    }

    public function foobarfunc() {
        return $this->foo();
    }

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

在我的index.php中,我正在加载的可能foobarfunc()是这样的:

foobar::foobarfunc();

但也可以是

$foobar = new foobar;
$foobar->foobarfunc();

为什么会出现错误?


2
巧合的是,我昨天在这个错误中挣扎了大约3个小时!:)
杰克

Answers:


184

在我的index.php中,我正在像这样加载foobarfunc():

 foobar::foobarfunc();  // Wrong, it is not static method

但也可以是

$foobar = new foobar;  // correct
$foobar->foobarfunc();

您不能以这种方式调用方法,因为它不是静态方法。

foobar::foobarfunc();

您应该改用:

foobar->foobarfunc();

但是,如果您创建了一个静态方法,则类似于:

static $foo; // your top variable set as static

public static function foo() {
    return self::$foo;
}

那么您可以使用以下代码:

foobar::foobarfunc();

1
具有相同名称的变量不是问题。$this->foo是一个类成员,而$foo只是函数作用域中的变量(从全局作用域导入)。与成员同名的函数名称也不是问题。
戈登

157
您不能$this在静态方法中使用。
Yacoby

5
有趣的是,一个完全错误的答案仍然会遭到否决。$ this在类上下文中不可用。从上面的示例中,OP将获得相同的错误。
戈登

4
@Sarfraz没有冒犯,但仍然是错的。您可以使用调用实例方法::。它是违背的E_STRICT,但只要方法主体不引用实例范围(例如use),它就可以工作$this。同样,self::foo不会指向$this->foo。它引用一个类常量。两者,self::foo并且self::$foo将提高一个致命错误。
戈登

3
@Sarfraz现在好了。很抱歉打扰您,但是当这成为公认的答案时,我认为有必要指出这些问题:)感谢您的耐心配合。
戈登2010年

27

您正在调用非静态方法:

public function foobarfunc() {
    return $this->foo();
}

使用静态调用:

foobar::foobarfunc();

使用静态调用时,将调用该函数(即使未声明为static,但是由于没有对象的实例,因此也没有$this

所以:

  • 您不应将静态调用用于非静态方法
  • 您的静态方法(或静态调用的方法)不能使用$ this,它通常指向类的当前实例,因为在使用静态调用时没有类实例。


在这里,您的类的方法正在使用该类的当前实例,因为它们需要访问$foo该类的属性。

这意味着您的方法需要类的实例-这意味着它们不能是静态的。

这意味着您不应该使用静态调用:您应该实例化该类,并使用该对象来调用方法,就像在代码的最后一部分所做的那样:

$foobar = new foobar();
$foobar->foobarfunc();


有关更多信息,请随时阅读PHP手册:


另请注意,您的方法中可能不需要此行__construct

global $foo;

使用global关键字将使$foo变量在所有函数和类的外部声明,可以从该方法内部进行查看...而且您可能没有这样的$foo变量。

要访问$foo class-property,您只需要$this->foo像一样使用即可。


11

如果您正在调用foobarfunc分辨率范围操作符::),那么你就调用它静态地,如在类级别而不是实例级,因此你$this不用时对象上下文$this在类上下文中不存在。

如果启用E_STRICT,PHP将对此发出一个通知:

Strict Standards: 
Non-static method foobar::foobarfunc() should not be called statically

改为这样做

$fb = new foobar;
echo $fb->foobarfunc();

在旁注中,我建议不要global在您的课程中使用。如果您需要类内部的其他内容,请将其传递给构造函数。这就是所谓的“ 依赖注入”,它将使您的代码更具可维护性,并减少对外部事物的依赖。


6

首先,您了解一件事,类中的$ this表示当前对象
那就是您在类之外创建来调用类的函数或变量。

因此,当您调用foobar :: foobarfunc()之类的类函数时,不会创建对象。但是在您编写的函数内部,返回$ this-> foo()。现在这里$什么都没有。这就是为什么在class.php中不在对象上下文中使用$ this的原因

解决方案:

  1. 创建一个对象并调用foobarfunc()。

  2. 在foobarfunc()中使用类名调用foo()。


2
或只使用self ::而不是$ this
Motassem MK

4

在静态上下文中调用该函数时,$this根本不存在该函数。

您将不得不使用this::xyz()

为了找出当可以同时在对象实例中静态调用函数时所处的上下文,此问题概述了一种好的方法:如何判断我是静态对象还是对象?


4

快速方法:(new foobar())-> foobarfunc();

您需要加载您的类replace:

foobar::foobarfunc();

创建人:

(new foobar())->foobarfunc();

要么 :

$Foobar = new foobar();
$Foobar->foobarfunc();

或使静态函数使用foobar::

class foobar {
    //...

    static function foobarfunc() {
        return $this->foo();
    }
}

0

$foobar = new foobar; foob​​ar放在$ foobar中,而不是object中。要获取对象,您需要添加括号:$foobar = new foobar();

您的错误只是因为您在类上调用了一个方法,所以没有,$this因为它$this仅存在于对象中。


0

在我看来,这是PHP中的错误。错误

致命错误:未捕获错误:不在对象上下文中时使用$ this

使用出现在函数中$this,但错误是调用函数使用非静态函数作为静态函数。即:

Class_Name
{
    function foo()
    {
        $this->do_something(); // The error appears there.
    }
    function do_something()
    {
        ///
    }
}

虽然错误在这里:

Class_Name::foo();

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.