Differencebetween Self::$Bar and Static::$Bar in PHP

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.

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

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

Why self::function() and $self- variable or self::$variable even though there is $this- function() and $this- variable (PHP)?

You're right, self is for static self-references while $this is for instantiated ones. self and $this might appear to work everywhere but consider this:

class A
{
public static function foo()
{
$this->bar();
}

public static function bar()
{
echo 'foobar!';
}
}

A::foo(); // Fatal error: Using $this when not in object context

This results in a fatal error because foo() was called statically. It's best to take some time and use them appropriately rather than always using one or the other.

PHP - when to use private static properties in the class

When you declare a normal property, there is a different value of that property for every instance you create of that class (each object you create with new Foo). For a static property, there is one copy of that variable for the whole class.

This is separate from the visibility of that variable - a public static property exists once per class, and can be accessed from everywhere; a private static property exists once per class, but can only be accessed from inside that class's definition.

As a simple example, you could have a counter that gave each instance of the class a unique number. You don't need code outside the class to see or change this counter, so you mark it private, but it needs to be shared amongst all instances, so you mark it static.

class Foo {
// Static counter; shared with every instance
private static $nextID=0;

// Normal instance property: each instance will have its own value
private $myID;

public function __construct() {
// Set the ID for this instance to the next ID
$this->myID = self::$nextID;
// Increment the shared counter
self::$nextID++;
}
}

PHP function pass by reference self::$menus

You are passing it in as a recursive call here:

self::addChild($item_id, $title, $url, $parent_id, $value);

Which might be better as:

static::addChild($item_id, $title, $url, $parent_id, $value);

So just use static::$menus instead of $array if nothing was passed in:

public static function addChild($item_id, $title, $url, $parent_id, &$array=null)
{
if($array === null) {
$array = &static::$menus;
}
// other code
}

Or this might be better since you actually need an array:

if(!is_array($array)) {
$array = &static::$menus;
}

Then for the main calls (not recursive) just omit the $array parameter.

  • What is the difference between self::$bar and static::$bar in PHP?
  • PHP Manual - Late Static Bindings

PHP 5: const vs static

In the context of a class, static variables are on the class scope (not the object) scope, but unlike a const, their values can be changed.

class ClassName {
static $my_var = 10; /* defaults to public unless otherwise specified */
const MY_CONST = 5;
}
echo ClassName::$my_var; // returns 10
echo ClassName::MY_CONST; // returns 5
ClassName::$my_var = 20; // now equals 20
ClassName::MY_CONST = 20; // error! won't work.

Public, protected, and private are irrelevant in terms of consts (which are always public); they are only useful for class variables, including static variable.

  • public static variables can be accessed anywhere via ClassName::$variable.
  • protected static variables can be accessed by the defining class or extending classes via ClassName::$variable.
  • private static variables can be accessed only by the defining class via ClassName::$variable.

Edit: It is important to note that PHP 7.1.0 introduced support for specifying the visibility of class constants.

Static counter of subclass instances in PHP

A lot depends on where you define the count and how you access it. If you have 1 count in the base class, then there is only 1 count. If you have a count in each class, then you need to be aware of how to access the right value. Using self or static is discussed more What is the difference between self::$bar and static::$bar in PHP?

class Vehicle
{
protected static $_count=0;

public static function getCount() {
return static::$_count;
}

public function __construct($type, $year)
{
// Access the count in the current class (Bike or Car).
static::$_count++;
// Access the count in this class
self::$_count++;
}
}

class Bike extends Vehicle
{
protected static $_count=0;
}

class Car extends Vehicle
{
protected static $_count=0;
}

This has both, and in the constructor, it increments them both. This means there is a total of all vehicles and of each type...

echo "Vehicle::getCount()=".Vehicle::getCount().PHP_EOL;
echo "Car::getCount()=".Car::getCount().PHP_EOL;
echo "Bike::getCount()=".Bike::getCount().PHP_EOL;
$a = new Car("a", 1);
echo "Vehicle::getCount()=".Vehicle::getCount().PHP_EOL;
echo "Car::getCount()=".Car::getCount().PHP_EOL;
echo "Bike::getCount()=".Bike::getCount().PHP_EOL;
$a = new Bike("a", 1);
echo "Vehicle::getCount()=".Vehicle::getCount().PHP_EOL;
echo "Car::getCount()=".Car::getCount().PHP_EOL;
echo "Bike::getCount()=".Bike::getCount().PHP_EOL;

gives (not very clear though)...

Vehicle::getCount()=0
Car::getCount()=0
Bike::getCount()=0
Vehicle::getCount()=1
Car::getCount()=1
Bike::getCount()=0
Vehicle::getCount()=2
Car::getCount()=1
Bike::getCount()=1

PHP - Using static attributes and methods

You can use self::method(); operator to call it's own methods and attributes..

Constructor

private function __construct()
{
// Your class variables initialization stuff here
}


Related Topics



Leave a reply



Submit