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. Useself
to refer to the
current class. In other words, use
$this->member
for non-static members,
useself::$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 thefoo()
member function of whatever is the exact type of the current object. If the object is oftype X
, it thus callsX::foo()
. If the object is oftype Y
, it callsY::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
andnew 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
Warning: Array_Combine(): Both Parameters Should Have an Equal Number of Elements
Php: Check for Duplicate Values in a Multidimensional Array
Process Mathematical Equations in PHP
Backreference Does Not Work in PHP
How to Paginate Lines in a Foreach Loop with PHP
PHP Curly Braces in Array Notation
PHP - Merge Two Arrays (Same-Length) into One Associative
Get_Result() Doesn't Work Even MySQLnd Is Enabled
How to Convert All Images to Jpg Format in PHP
Order by Before Group by Using Eloquent (Laravel)
How Does PHP Compare Strings with Comparison Operators
Parallel Processing in PHP - How to Do It