简体   繁体   English

PHP:为什么我收到有关 static 属性的错误?

[英]PHP: Why am I getting errors about static properties?

http://codepad.viper-7.com/I0Zqoi http://codepad.viper-7.com/I0Zqoi

I don't understand what's wrong with this or how to fix it or why.我不明白这有什么问题或如何解决它或为什么。 Can someone who knows a little about programming please explain what's happening behind the scenes, like on the interpreter level?对编程有一点了解的人可以解释一下幕后发生的事情,比如在解释器级别吗? Also, how can I fix my problem, and why do I need to write my code in the way of the correction?另外,我该如何解决我的问题,为什么我需要以更正的方式编写我的代码? Can you tell me, in human language, what is wrong with this and how to make it better?你能用人类的语言告诉我这有什么问题以及如何使它变得更好吗? I guess my book isn't explaining well, and the code inside of it doesn't work.我想我的书解释得不好,里面的代码也不起作用。 :/ Thank you. :/ 谢谢。

class A 
{
  private $foo = 'bar';
  function read()
  {
      echo self::$foo;
  }
}

$a = new A();
a::read();

Strict Standards: Non-static method A::read() should not be called statically in /code/I0Zqoi on line 13

Fatal error: Access to undeclared static property: A::$foo in /code/I0Zqoi on line 8

The only workaround seems to be to add "static" in front of the method.唯一的解决方法似乎是在方法前面添加“静态”。 Apparently, non-static methods cannot be accessed by static means (eg, class A{function read(){echo "whatever"};} cannot be accessed by a::read() because the -> operator is necessary).显然,static 方法不能访问非静态方法(例如,class A{function read(){echo "whatever"};} 不能通过 a::read() 访问,因为 -> 运算符是必需的)。 Also, static properties cannot be accessed by object code, even if they exist within a function (eg, class A{static $variable; function read(){echo $this->variable};} a->read(); won't work because the -> operator is being used to access a function that calls a static property.). Also, static properties cannot be accessed by object code, even if they exist within a function (eg, class A{static $variable; function read(){echo $this->variable};} a->read(); won '不起作用,因为 -> 运算符用于访问调用 static 属性的 function。)。 By changing both the method and the property to static, the method can be accessed by static means.通过将方法和属性都更改为 static,可以通过 static 方式访问该方法。 By changing both the method and property to non-static makes it so that either can be accessed with object instanciation.通过将方法和属性都更改为非静态,可以使用 object 实例化访问任何一个。 It doesn't make sense to me that the debugger is throwing errors because my book says that static properties can be called from non-static methods via object code calls to the non-static methods.调试器抛出错误对我来说没有意义,因为我的书说可以通过 object 代码调用非静态方法从非静态方法调用 static 属性。 So, is the debugger broken?那么,调试器坏了吗? Because I've tried every combination, and the code only seems to work if both the method and property are either static or non-static.因为我已经尝试了所有组合,并且代码似乎只有在方法和属性都是 static 或非静态时才有效。 :((( :(((

The Strict Standards part is because a::read() is being called in a static context with :: .严格标准部分是因为a::read()在 static 上下文中被调用:: After declaring $a as a class instance of A , you should call the read() method on the variable using the -> operator:在将$a声明为A的 class 实例之后,您应该使用->运算符对变量调用read()方法:

// Proper non-static method call
$a = new A();
$a->read();

In the class definition, $foo is declared as a private property, but without the static keyword.在 class 定义中, $foo被声明为私有属性,但没有static关键字。 It is then referred to in static context using the :: operator instead of the -> .然后在 static 上下文中使用::运算符而不是->来引用它。 The proper way to access it would beL访问它的正确方法是L

// Proper reference to non-static $foo
function read() {
  echo $this->foo;
}

Now what does static mean anyway?现在static到底是什么意思? Static methods and properties refer to class methods and properties that are shared by all current and future class instances. Static 方法和属性是指所有当前和未来 class 实例共享的 class 方法和属性。 If A::$foo had been declared as:如果A::$foo被声明为:

private static $foo;

then there would be only the one $foo for all of class A in your code.那么您的代码中将只有一个$foo用于所有 class A Changing $foo would affect all instances of class A , and $foo can be accessed without even creating an instance of the class (like new A(); )更改$foo会影响 class A所有实例,并且$foo甚至可以在不创建 class 实例的情况下访问(如new A();

Likewise, static methods can be called without creating an instance of the class because they do not modify class properties that are not also static.同样,可以在不创建 class 实例的情况下调用 static 方法,因为它们不会修改 class 属性,这些属性也不是 ZA8226259CEF86E953C.

// Static method call:
A::read();

To declare properties and methods as static , just add the static keyword:要将属性和方法声明为static ,只需添加static关键字:

// Property
private static $foo;

// Method
public static function foo() {}

EDIT for more examples :编辑更多示例

class A
{
  // Private property (non-static)
  private $foo;

  // Public property (static)
  public static $bar = 12345;

  // Public (non-static) function to access private $foo
  public function getFoo() { return $this->foo; }

  // Public (non-static) function to set private $foo
  public function setFoo($newfoo) { $this->foo = $newfoo; }

  // Static function 
  public static function incrementBar() { self::$bar++; }
}

Now see it in action:现在看看它的实际效果:

// We haven't created any class instances yet (with the 'new' operator)
// But we can access the static properties & functions:

echo A::$bar . " ";
// prints 12345

A::incrementBar();
echo A::$bar . "\n";
// prints 12346

// Now we'll start working with class instances.
// Create 2 instances of class A
$a = new A();
$a->setFoo(8888);
$b = new A();
$b->setFoo(9999);

// It's a violation of strict standards to call getFoo() statically
// And it's meaningless to do so, because $foo only exists inside a class instance!

// Can't do this... Issues a strict warning since we're calling non-static getFoo() statically
//echo A::getFoo();


// But we can call getFoo() on the class instances:
echo $a->getFoo() . " " . $b->getFoo() . "\n";
// Prints 8888 9999

// Remember $bar was 12346...
echo $a::$bar . " " . $b::$bar . "\n";
// Prints 12346 12346

// Now modify the static property $bar again
// This affects all class instances.
A::incrementBar();
echo $a::$bar . " " . $b::$bar . "\n";
// Prints 12347 12347

I stuffed this whole thing into the codepad as well: http://codepad.viper-7.com/tV6omK我也把整个东西都塞进了键盘: http://codepad.viper-7.com/tV6omK

The book you're reading must not be paying attention to strict standards.您正在阅读的书一定没有注意严格的标准。 If a non-static function does not attempt to access/modify a non-static property, you can call it statically successfully, but it WILL issue a strict warning.如果非静态 function 不尝试访问/修改非静态属性,您可以成功地静态调用它,但它会发出严格的警告。 If the non-static function does modify or access a non-static property with $this->property , it will be a fatal error.如果非静态 function 确实使用$this->property修改或访问非静态属性,这将是一个致命错误。 You can't do that.你不能那样做。

In PHP's error_reporting , the setting of E_ALL for show all errors actually does not include strict warnings.在 PHP 的error_reporting中,显示所有错误的E_ALL的设置实际上并不包含严格的警告。 That has to be done with E_ALL & E_STRICT .这必须通过E_ALL & E_STRICT来完成。

:: is used to access a static attribute. ::用于访问 static 属性。 If you want to access an object attribute then use -> .如果要访问 object 属性,请使用->

$a->read();

... ...

echo $this->$foo;

Although the other answers are definitely correct, here's an answer to your concrete question:尽管其他答案绝对正确,但这是您具体问题的答案:

It doesn't make sense to me that the debugger is throwing errors because my book says that static properties can be called from non-static methods via object code calls to the non-static methods.调试器抛出错误对我来说没有意义,因为我的书说可以通过 object 代码调用非静态方法从非静态方法调用 static 属性。 So, is the debugger broken?那么,调试器坏了吗? Because I've tried every combination, and the code only seems to work if both the method and property are either static or non-static.因为我已经尝试了所有组合,并且代码似乎只有在方法和属性都是 static 或非静态时才有效。 :((( :(((

The author of your book was under the impression that not getting an error message is considered clean code.您的书的作者认为没有收到错误消息被认为是干净的代码。 It's not.它不是。 You shouldn't have a method that can be called both statically as well as dynamically, as the two simply differ too much.您不应该有一个既可以静态调用又可以动态调用的方法,因为两者差别太大了。 Dynamic calls are for objects, where static calls are for classes.动态调用用于对象,其中 static 调用用于类。 If you have the opportunity, I would always try to go the dynamic way, as that yields less coupling in the application.如果你有机会,我总是会尝试 go 动态方式,因为这会在应用程序中产生更少的耦合。

As to why "the debugger is throwing errors" (it's the interpreter throwing E_STRICT warnings, but hey;)): this behaviour has been changed in PHP five dot something.至于为什么“调试器抛出错误”(它是解释器抛出 E_STRICT 警告,但是嘿;)):这种行为在 PHP 五个点的东西中已经改变。 In PHP 4 you could call every method statically, even if it was a dynamic method.在 PHP 4 中,您可以静态调用每个方法,即使它是动态方法。 Possibly, your book is running behind on the facts.可能,你的书在事实方面落后了。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM