PHP Can Static:: Replace Self::

PHP Can static:: replace self::?

You have to ask yourself: "Am I targeting the problem with the adequated approach?"

self:: and static:: do two different things. For instance self:: or __CLASS__ are references to the current class, so defined in certain scope it will NOT suffice the need of static calling on forward.

What will happen on inheritance?

class A {
public static function className(){
echo __CLASS__;
}

public static function test(){
self::className();
}
}

class B extends A{
public static function className(){
echo __CLASS__;
}
}

B::test();

This will print

A

In the other hand with static:: It has the expected behaviour

class A {
public static function className(){
echo __CLASS__;
}

public static function test(){
static::className();
}
}

class B extends A{
public static function className(){
echo __CLASS__;
}
}

B::test();

This will print

B

That is called late static binding in PHP 5.3.0. It solves the limitation of calling the class that was referenced at runtime.

With that in mind I think you can now see and solve the problem adequately. If you are inheriting several static members and need access to the parent and child members self:: will not suffice.

When should I use 'self' over '$this'?

Short Answer

Use $this to refer to the current
object. Use self to refer to the
current class. In other words, use
$this->member for non-static members,
use self::$member for static members.

Full Answer

Here is an example of correct usage of $this and self for non-static and static member variables:

<?php
class X {
private $non_static_member = 1;
private static $static_member = 2;

function __construct() {
echo $this->non_static_member . ' '
. self::$static_member;
}
}

new X();
?>

Here is an example of incorrect usage of $this and self for non-static and static member variables:

<?php
class X {
private $non_static_member = 1;
private static $static_member = 2;

function __construct() {
echo self::$non_static_member . ' '
. $this->static_member;
}
}

new X();
?>

Here is an example of polymorphism with $this for member functions:

<?php
class X {
function foo() {
echo 'X::foo()';
}

function bar() {
$this->foo();
}
}

class Y extends X {
function foo() {
echo 'Y::foo()';
}
}

$x = new Y();
$x->bar();
?>

Here is an example of suppressing polymorphic behaviour by using self for member functions:

<?php
class X {
function foo() {
echo 'X::foo()';
}

function bar() {
self::foo();
}
}

class Y extends X {
function foo() {
echo 'Y::foo()';
}
}

$x = new Y();
$x->bar();
?>

The idea is that $this->foo() calls the foo() member function of whatever is the exact type of the current object. If the object is of type X, it thus calls X::foo(). If the object is of type Y, it calls Y::foo(). But with self::foo(), X::foo() is always called.

From http://www.phpbuilder.com/board/showthread.php?t=10354489:

By http://board.phpbuilder.com/member.php?145249-laserlight

New self vs. new static

will I get the same results?

Not really. I don't know of a workaround for PHP 5.2, though.

What is the difference between new self and new static?

self refers to the same class in which the new keyword is actually written.

static, in PHP 5.3's late static bindings, refers to whatever class in the hierarchy you called the method on.

In the following example, B inherits both methods from A. The self invocation is bound to A because it's defined in A's implementation of the first method, whereas static is bound to the called class (also see get_called_class()).

class A {
public static function get_self() {
return new self();
}

public static function get_static() {
return new static();
}
}

class B extends A {}

echo get_class(B::get_self()); // A
echo get_class(B::get_static()); // B
echo get_class(A::get_self()); // A
echo get_class(A::get_static()); // A

What is the difference between self::$bar and static::$bar in PHP?

When you use self to refer to a class member, you're referring to the class within which you use the keyword. In this case, your Foo class defines a protected static property called $bar. When you use self in the Foo class to refer to the property, you're referencing the same class.

Therefore if you tried to use self::$bar elsewhere in your Foo class but you had a Bar class with a different value for the property, it would use Foo::$bar instead of Bar::$bar, which may not be what you intend:

class Foo
{
protected static $bar = 1234;
}

class Bar extends Foo
{
protected static $bar = 4321;
}

When you call a method via static, you're invoking a feature called late static bindings (introduced in PHP 5.3).

In the above scenario, using self will result in Foo::$bar(1234).
And using static will result in Bar::$bar (4321) because with static, the interpreter takes into account the redeclaration within the Bar class during runtime.

// self
var_dump(Foo::$bar);
// (int) 1234

// static
var_dump(Bar::$bar);
// (int) 4321

You typically use late static bindings for methods or even the class itself, rather than properties, as you don't often redeclare properties in subclasses; an example of using the static keyword for invoking a late-bound constructor can be found in this related question: New self vs. new static

However, that doesn't preclude using static with properties as well.

PHP Calling self on a non-static method

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)).

when using self, parent, static and how?

You'll need to understand the concept of Late Static Binding, which determines when an identifier is bound to code/data. You can tell PHP to bind it early (self::) or later (static::).

Slimming the example down to two classes we get:

class A {
public static function foo() {
self::who(); // PHP binds this to A::who() right away
static::who(); // PHP waits to resolve this (hence, late)!
}

public static function who() {
echo __CLASS__."\n";
}
}

class B extends A {
public static function test() {
self::foo();
}

public static function who() {
echo __CLASS__."\n";
}
}

B::test();


Related Topics



Leave a reply



Submit