static function in PHP - php

If I call public function using scope resolution operator, It is not giving any error.
class Parent_class
{
public function st_function()
{
echo "*************parent class************\n";
}
}
Parent_class:: st_function();
But in PHP documentation on php.net, it ig given that - Calling non-static methods statically generates an E_STRICT level warning. Also its given that - Static properties cannot be accessed through the object using the arrow operator ->
But its not giving any error. Can anyone explain?
class Parent_class
{
public static function st_function()
{
echo "*************parent class************\n";
}
}
Parent_class:: st_function();
$var = new Parent_class();
$var->st_function();

Static properties can not be accessed through the object, but not static methods.
From the doc.
Declaring class properties or methods as static makes them accessible
without needing an instantiation of the class. A property declared as
static can not be accessed with an instantiated class object (though
a static method can).

If you activate strict error reporting, you will see an error for calling a non-static method statically:
error_reporting(E_ALL | E_STRICT);
For the second part, where you call a static method non-statically, that will work because the paragraph in the manual talks about static properties, not methods. You cannot access Parent_class::static_property like Parent_class->static_property, if it had such a property.
Calling static methods of objects works fine, in that case the $var-> is just a convenience shorthand for Parent_class::.

Try this before your code:
error_reporting(E_ALL | E_STRICT);

Related

PHP Calling self on a non-static method

Why is the 'self'-call to a non-satic method in this example working?
class A{
protected function aNonStaticMethod(){
return __class__;
}
public function aEcho(){
echo self::aNonStaticMethod();
}
}
Thanks for explanation.
In your simple example $this and self is interchangable. But be aware of the different method resolving when dealing with inheritance (i added static for completeness):
class A {
protected function aNonStaticMethod(){
return __class__;
}
public function selfEcho(){
echo self::aNonStaticMethod();
}
public function staticEcho(){
echo static::aNonStaticMethod();
}
public function thisEcho(){
echo $this->aNonStaticMethod();
}
}
class B extends A {
protected function aNonStaticMethod(){
return __class__;
}
}
$b = new B();
$b->selfEcho(); // A
$b->staticEcho(); // B
$b->thisEcho(); // B
Calling non-static method statically
Theoretically it should not work, but as this comment says:
There was no static keyword in php4 but php4 did allow for static
calls. To maintain backwards compatibility this was left in when the
static keyword was added in php5.
This comment is supported by this official php.net wiki:
This is already deprecated if the call occurs from an instance method.
Not annotating methods as static is an obsolete PHP4-ism.
You really should not call non-static method statically - it does not make sense (if there is a static keyword).
Avoid calling non-static methods statically completely!
...because a) it is a bad approach and b) the PHP docs say:
Caution
In PHP 5, calling non-static methods statically generates an E_STRICT level warning.
AND
Warning
In PHP 7, calling non-static methods statically is deprecated, and will generate an E_DEPRECATED warning. Support for calling non-static methods statically may be removed in the future.
Using :: operator for non-static calls - may be a good approach!
As #Kontrollfreak pointed out and as this docs say the :: operator is not limited to static calls:
the double colon, is a token that allows access to static, constant,
and overridden properties or methods of a class
So it is OK if you reference this way a method or properties from a parent class - which is not limited to a direct parent.
EDIT: do not mistake this for Fascade etc. software patterns!
During writing this answer I forgot to mention that there might be cases, when the call is static, but internally it is calling dynamic method - for more info see patterns like Facade or Singleton.
However do NOT mistake these with issue described above! (issue above is about using direct static call on dynamic thing that should be called dynamically, these patterns are about calling static methods statically, which then may dynamically invoke something dynamic (internally)).

PHP Late Static Binding referencing calling class

I have a static function being called that is giving a strange error. Here is an example of the php code:
class foo {
public $stat;
public function __construct() {
$this->stat = stat::isValid('two');
}
}
class stat {
protected static $invalidNumbers = array('one', 'two');
function isValid($number) {
return in_array($number, static::$invalidNumbers);
}
}
$foo = new foo();
var_dump($foo->stat);
This code results in the following error:
Fatal error: Access to undeclared static property: foo::$invalidNumbers
However changing static:: to self:: makes the code behave as expected. I was under the impression that in this context using static:: should work.
Why does this error occur using static?
You begin by making a method call in a static context:
stat::isValid('two');
When you do this, PHP "remembers" the context from within which isValid was called specifically so that it can resolve what to bind to when it sees something like static:: inside the method body, determine if some property you are trying to access is visible, and in general be able to implement some OO-related language features.
The actual method isValid is not static, but PHP still allows you to call it using the static method syntax (it does give an E_STRICT warning about that). However, this has the side effect that isValid itself does not participate in modifying the curent calling context for (late) static bindings.
The result: when PHP sees static::$invalidNumbers, it still thinks you are halfway through making a static method call from within the foo class! Once you realize this, it is obvious why static:: resolves to foo:: and it ends up looking for the property at the wrong place.
If you correctly declare isValid as static
static function isValid($number) {
return in_array($number, static::$invalidNumbers);
}
then upon calling the method PHP does update its context internally and manages to bind to the intended member.
You are trying to call the method stat::isValid() statically but have not declared it static. Change the stat class to:
class stat {
protected static $invalidNumbers = array('one', 'two');
// needs to be declared static
static function isValid($number) {
return in_array($number, static::$invalidNumbers);
}
}
Note that, if you add
| E_STRICT
to your error_reporting in php.ini you would see a message like:
Strict standards: Non-static method stat::isValid() should not be called statically, assuming $this from incompatible context in ...
Declare static method properly
Replace
function isValid($number) {
With
public static function isValid($number) {
^--- here

Why does calling this method statically work?

class Duck {
public function quack() {
$this­->swim();
}
public function swim() {
echo 'I\'m swimming!';
}
}
class Plane {
public function fly() {
Duck::quack();
}
public function swim()
{
echo 'I can\'t swim! People are DROWNING!';
}
}
$plane = new Plane();
$plane-­>fly();
I got asked the above question and gave the answer that the output is an error illegally calling static method.
But it actually prints "I'm swimming!".
Could somebody please explain why this happens?
It works by default, but if you turn on E_STRICT you'll get
PHP Strict Standards: Non-static method Duck::quack() should not be called statically in...
PHP sees that you wanted swim() to be actually static and so it let's you simply call it.
Something to note with PHP 5.3 (and public methods):
CAN call public methods statically from anywhere INSIDE Object context (only if inside instantiated object)...even if not declared static
Duck::quack();
CANT call protected method in same scenario.
Duck::quack(); //error
protected function quack() { }
CANT call public properties (instance variables) statically from anywhere INSIDE Object context, unless declared static...
class Duck {
public $hello = 'hello there';
}
class Plane {
Duck::$hello; //error
}
CANT call public methods (or properties) statically from OUTSIDE object context..unless declared static
Duck::quack(); //error
Other languages use this type of engine flexibility, calling any public method statically as long as from inside Object context.
As mentioned (by #poitroae) it works like this by default, but if you turn on E_STRICT you'll get an error.
ALSO:
It is a known idiosyncrasy with PHP that you should'nt be allowed to call $this in this Context. The program should be under Class Context at this point (being called statically) but $this works which is akin to Object Context.
If this were a statically declared Method than calling $this would cause an instant fatal error.
Hope that helps

PHP: Why am I getting errors about static properties?

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 (e.g., class A{function read(){echo "whatever"};} cannot be accessed by a::read() because the -> operator is necessary). Also, static properties cannot be accessed by object code, even if they exist within a function (e.g., 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.). By changing both the method and the property to static, the method can be accessed by static means. By changing both the method and property to non-static makes it so that either can be accessed with object instanciation. 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. 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. :(((
The Strict Standards part is because a::read() is being called in a static context with ::. After declaring $a as a class instance of A, you should call the read() method on the variable using the -> operator:
// 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. It is then referred to in static context using the :: operator instead of the ->. The proper way to access it would beL
// Proper reference to non-static $foo
function read() {
echo $this->foo;
}
Now what does static mean anyway? Static methods and properties refer to class methods and properties that are shared by all current and future class instances. If A::$foo had been declared as:
private static $foo;
then there would be only the one $foo for all of class A in your code. 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();)
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.
// Static method call:
A::read();
To declare properties and methods as static, just add the static keyword:
// 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
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. If the non-static function does modify or access a non-static property with $this->property, it will be a fatal error. 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. That has to be done with E_ALL & E_STRICT.
:: is used to access a static attribute. If you want to access an object attribute then use ->.
$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. 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. :(((
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. If you have the opportunity, I would always try to go the dynamic way, as that yields less coupling in the application.
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. In PHP 4 you could call every method statically, even if it was a dynamic method. Possibly, your book is running behind on the facts.

Difference between :: and -> in PHP

I always see people in serious projects use :: everywhere, and -> only occasionally in local environment.
I only use -> myself and never end up in situations when I need a static value outside of a class. Am I a bad person?
As I understand, the only situation when -> won't work is when I try following:
class StaticDemo {
private static $static
}
$staticDemo = new StaticDemo( );
$staticDemo->static; // wrong
$staticDemo::static; // right
But am I missing out on some programming correctness when I don't call simple public methods by :: ?
Or is it just so that I can call a method without creating an instance?
The double colon is used when you don't instantiate a class
class StaticDemo {...};
StaticDemo::static
if you do instantiate, use -->
class StaticDemo {...};
$s = new StaticDemo();
$s->static;
This is explained further at http://php.net/manual/en/language.oop5.patterns.php
:: is for referencing static properties or methods of a class. -> is for referencing instance properties and methods. You aren't missing out on any programming correctness, and if you are a bad person then it isn't because of this. Which one you use depends on the purpose of your class and how its written. But also, PHP didn't have namespaces until very recently so many people encapsulated their code in static classes to emulate namespaces to avoid naming collisions. It is possible you are seeing code that does that.
You caused a strict standards warning in E_STRICT mode. You are a bad person.
<?php
error_reporting(E_ALL | E_STRICT);
header('Content-type: text/plain');
class Foo {
public $msg = "Hello, public.\n";
public static $msgStatic = "Hello, static.\n";
public function write() {
echo "Hello, write.\n";
}
public static function writeStatic() {
echo "Hello, writeStatic.\n";
}
}
//echo Foo::$msg; // Fatal error: Access to undeclared static property: Foo::$msg
echo Foo::$msgStatic;
echo Foo::write(); // Strict Standards: Non-static method Foo::write() should not be called statically
echo Foo::writeStatic();
echo "------------------------\n";
$f = new Foo;
echo $f->msg;
echo $f->msgStatic; // Strict Standards: Accessing static property Foo::$msgStatic as non static
// Notice: Undefined property: Foo::$msgStatic
echo $f->write();
echo $f->writeStatic();
Output:
Hello, static.
Strict Standards: Non-static method Foo::write() should not be called statically in /home/adam/public_html/2010/05/10/bad.php on line 22
Hello, write.
Hello, writeStatic.
------------------------
Hello, public.
Strict Standards: Accessing static property Foo::$msgStatic as non static in /home/adam/public_html/2010/05/10/bad.php on line 29
Notice: Undefined property: Foo::$msgStatic in /home/adam/public_html/2010/05/10/bad.php on line 29
Hello, write.
Hello, writeStatic.
-> is for an instanciated class.
:: is a static call.
:: is used in inheritance constructors (a child accessing a parent constructor) and when referring to a static method inside another method.
I wouldn't say not using static calls makes you a bad person either!
Yes, you can call a method or access a value without creating an instance.
It would be useful, for example, if you have a value that all instances of a class use. Say this value, however, needs to be initialized at the beginning of your app. You could use something like StaticDemo::static = 42; to initialize it, and then all instances of your class would be able to access it.
As I understand it the static is shared between objects of the same type:
class test{
static function print_test(){
print "hello!";
}
}
$objectA = new test();
$objectB = new test();
The function print_test will be "shared" between the two objects. But the catch is the function print_test() should not reference anything inside the class! even thou PHP 5 accepts it.
Since the function print_test in the example just prints out "hello!" and doesn't reference anything inside the class why allocate memory for it in $objectA and $objectB? Just make one static function and $objectA and $objectB should point to it automatically.
Well that's the theory behind it in other languages, but since php5 allows you to reference $this in a static function I don't believe its a true static function since it would have to be dynamic to get any properties for ($this->variable) that unique object.
:: is used for static methods, which you call if you have no object instance.
Use "->" when in object context and "::" when accessing the class directly. In your example that would be:
class StaticDemo {
public static $staticVar = 'blabla';
public $normalVar = 'foobar';
}
$foo = new StaticDemo();
echo $foo->normalVar; //object context, echoes "foobar"
echo StaticDemo::staticVar; //class or "static" context, echoes "blabla"
Read this for detailed intel.
Or is it just so that I can call a method without creating an instance?
Correct.
The :: (scope resolution operators) are used when calling static methods/members. You don't have to create an instance to do this (like you did in your example).
Using -> and :: in the right context is the key to object-orientated programming correctness. You should only create static variables/methods when they apply to the class as a whole, and not only to a specific instance (object) of the class.
Static methods and properties are independent of a particular instantiation of a class. These must be accessed using double colons (::). Non-static methods and properties should be accessed using ->
This allows you do to some pretty cool things. A trivial example is a counter that keeps track of the number of instances of the class exists:
class foo {
public static $i = 0;
public function __construct() {
self::$i++;
}
}
$a = new foo();
$b = new foo();
echo foo::$i;
// outputs 2
As others have said,
:: 'double colon' is for referencing a static property or method.
-> 'dash arrow' is for referencing a property or method of a class instance.
But also its worth noting that
:: is often used in texts as shorthand to refer to a property or method that belongs to a certain class (whether it's static or instance).
See the 'Note...in documentation...' : http://books.google.co.uk/books?id=qVLjFk_4zVYC&lpg=PA66&dq=php%205%20objects&pg=PA46#v=onepage&q=php%205%20objects&f=false
Well you're right about how to use -> and ::. But sometimes it just doesn't make much sense to create objects of a class. Here's an example
Compare
class Settings
{
public static $setting1;
public static $setting2;
... // lots of other vars and functions
}
if(Setting::$setting1)
//do something
vs
class Settings
{
public $setting1;
public $setting2;
... // lots of other vars and functions
}
$set = new Settings()
if($set->setting1)
//do something
As I said It doesn't make sense to create instances as there's always only required one. in this case static fits better. It turns out in web we mostly deal with this kind of case unless you're dealing with real Objects e.g. users etc hence the prevalence of the former

Categories