Hướng dẫn dùng statically trong PHP

Tip

This page describes the use of the static keyword to define static methods and properties. static can also be used to define static variables and for late static bindings. Please refer to those pages for information on those meanings of static.

Việc khai báo các thuộc tính và phương thức của lớp là static (tĩnh) sẽ giúp ta có thể truy cập các thành phần này mà không cần tạo thể hiện của lớp tương ứng. Một thuộc tính được khai báo là static thì không thể được truy cập thông qua thể hiện của đối tượng của lớp tương ứng (phương thức static thì có thể).

Từ phiên bản PHP 4, nếu không khai báo tầm vực thì thuộc tính và phương thức của lớp sẽ mặc định có tầm vực là public.

Phương thức tĩnh

Do các phương thức được gọi mà không cần phải thông qua thể hiện của đối tượng, nên biến giả $this là không cần và không được sử dụng được trong phương thức tĩnh.

Caution

In PHP 5, calling non-static methods statically generates an E_STRICT level warning.

Warning

In PHP 7, calling non-static methods statically is deprecated, and will generate anE_DEPRECATED warning. Support for calling non-static methods statically may be removed in the future.

Ví dụ về phương thức tĩnh


class Foo {
    public static function 
aStaticMethod() {
        
// ...
    
}
}

Foo::aStaticMethod();
$classname 'Foo';
$classname::aStaticMethod(); // Từ PHP 5.3.0
?>

Thuộc tính tĩnh

Thuộc tính tĩnh không thể được truy cập thông qua việc sử dụng toán tử mũi tên ->.

Cũng giống như bất kỳ biến tĩnh nào, các thuộc tính static chỉ có thể được khởi tạo bằng cách sử dụng một literal hoặc một hằng trước trước phiên bản PHP 5.6; các biểu thức là không được phép. Từ bản PHP 5.6 về sau thì các quy tắc tương tự được áp dụng như biểu thức hằng: một số biểu thức some limited expressions are possible, provided they can be evaluated at compile time.

As of PHP 5.3.0, it's possible to reference the class using a variable. The variable's value cannot be a keyword (e.g. self, parent and static).

Ví dụ về thuộc tính static


class Foo
{
    public static 
$my_static 'foo';

    public function

staticValue() {
        return 
self::$my_static;
    }
}

class

Bar extends Foo
{
    public function 
fooStatic() {
        return 
parent::$my_static;
    }
}

print

Foo::$my_static "\n";

$foo = new Foo();
print 
$foo->staticValue() . "\n";
print 
$foo->my_static "\n";      // Không định nghĩa "thuộc tính" my_static 

print $foo::$my_static "\n";
$classname 'Foo';
print 
$classname::$my_static "\n"// Từ bản PHP 5.3.0

print Bar::$my_static "\n";
$bar = new Bar();
print 
$bar->fooStatic() . "\n";
?>

Lưu ý rằng bạn nên đọc phần Phạm vi của biến nếu bạn đang tìm kiếm từ khóa static sử dụng cho việc khai báo các biến tĩnh bên trong hàm hay phương thức. I myself had this gap in my PHP knowledge until recently and had to google to find this out. I think this page should have a "See also" link to static function variables.
http://www.php.net/manual/en/language.variables.scope.php

Một số lưu ý sử dụng:

Để kiểm tra xem một hàm nào đó có được gọi static hay không thì ta làm như sau:


function foo () {
    
$isStatic = !(isset($this) && get_class($this) == __CLASS__);
}

?>

Here statically accessed property prefer property of the class for which it is called. Where as self keyword enforces use of current class only. Refer the below example:


class a{

static protected

$test="class a";

public function

static_test(){

echo static::

$test// Results class b
echo self::$test// Results class a

}

}

class

extends a{

static protected

$test="class b";

}

$obj = new b();
$obj->static_test();
?>

webmaster at removethis dot weird-webdesign dot de ¶

6 years ago

On PHP 5.2.x or previous you might run into problems initializing static variables in subclasses due to the lack of late static binding:


class {
    protected static 
$a;

        public static function

init($value) { self::$a $value; }
    public static function 
getA() { return self::$a; }
}

class

extends {
    protected static 
$a// redefine $a for own use

        // inherit the init() method

public static function getA() { return self::$a; }
}

B::init('lala');
echo 
'A::$a = '.A::getA().'; B::$a = '.B::getA();
?>

This will output:
A::$a = lala; B::$a =

If the init() method looks the same for (almost) all subclasses there should be no need to implement init() in every subclass and by that producing redundant code.

Solution 1:
Turn everything into non-static. BUT: This would produce redundant data on every object of the class.

Solution 2:
Turn static $a on class A into an array, use classnames of subclasses as indeces. By doing so you also don't have to redefine $a for the subclasses and the superclass' $a can be private.

Short example on a DataRecord class without error checking:


abstract class DataRecord {
    private static 
$db// MySQLi-Connection, same for all subclasses
    
private static $table = array(); // Array of tables for subclassespublic static function init($classname$table$db false) {
        if (!(
$db === false)) self::$db $db;
        
self::$table[$classname] = $table;
    }

        public static function

getDB() { return self::$db; }
    public static function 
getTable($classname) { returnself::$table[$classname]; }
}

class

UserDataRecord extends DataRecord {
    public static function 
fetchFromDB() {
        
$result parent::getDB()->query('select * from '.parent::getTable('UserDataRecord').';');// and so on ...
        
return $result// An array of UserDataRecord objects
    
}
}

$db = new MySQLi(...);
UserDataRecord::init('UserDataRecord''users'$db);
$users UserDataRecord::fetchFromDB();
?>

I hope this helps some people who need to operate on PHP 5.2.x servers for some reason. Late static binding, of course, makes this workaround obsolete.

ssj dot narutovash at gmail dot com ¶

8 years ago

It's come to my attention that you cannot use a static member in an HEREDOC string.  The following code

class A
{
  public static $BLAH = "user";

  function __construct()
  {
    echo <<

Hello {self::$BLAH}


EOD;
  }
}

$blah = new A();

produces this in the source code:

Hello {self::}

Solution:

before using a static member, store it in a local variable, like so:

class B
{
  public static $BLAH = "user";

  function __construct()
  {
    $blah = self::$BLAH;
    echo <<

Hello {$blah}


EOD;
  }
}

and the output's source code will be:

Hello user

davidn at xnet dot co dot nz ¶

7 years ago

Static variables are shared between sub classes


class MyParent {

        protected static

$variable;
}

class

Child1 extends MyParent {

        function

set() {self::$variable 2;
    }
}

class

Child2 extends MyParent {

        function

show() {

                echo(

self::$variable);
    }
}

$c1 = new Child1();
$c1->set();
$c2 = new Child2();
$c2->show(); // prints 2
?>

michalf at ncac dot torun dot pl ¶

11 years ago

Inheritance with the static elements is a nightmare in php. Consider the following code:


class BaseClass{
    public static 
$property;
}

class

DerivedClassOne extends BaseClass{
}

class

DerivedClassTwo extends BaseClass{
}

DerivedClassOne::$property "foo";
DerivedClassTwo::$property "bar";

echo

DerivedClassOne::$property//one would naively expect "foo"...
?>

What would you expect as an output? "foo"? wrong. It is "bar"!!! Static variables are not inherited, they point to the BaseClass::$property.

At this point I think it is a big pity inheritance does not work in case of static variables/methods. Keep this in mind and save your time when debugging.

best regards - michal

tolean_dj at yahoo dot com ¶

5 years ago

Starting with php 5.3 you can get use of new features of static keyword. Here's an example of abstract singleton class:

abstract class Singleton {

    protected static

$_instance NULL;/**
     * Prevent direct object creation
     */
    
final private function  __construct() { }/**
     * Prevent object cloning
     */
    
final private function  __clone() { }/**
     * Returns new or existing Singleton instance
     * @return Singleton
     */
    
final public static function getInstance(){
        if(
null !== static::$_instance){
            return static::
$_instance;
        }
        static::
$_instance = new static();
        return static::
$_instance;
    }

    }


?>

gratcypalma at gmail dot om ¶

5 years ago


class foo {
    private static 
$getInitial;

    public static function

getInitial() {
        if (
self::$getInitial == null)
            
self::$getInitial = new foo();
        return 
self::$getInitial;
    }
}

foo::getInitial();

/*
this is the example to use new class with static method..
i hope it help
*/

?>

Mirco ¶

5 years ago

The simplest static constructor.

Because php does not have a static constructor and you may want to initialize static class vars, there is one easy way, just call your own function directly after the class definition.

for example.


function Demonstration()
{
    return 
'This is the result of demonstration()';
}

class

MyStaticClass
{
    
//public static $MyStaticVar = Demonstration(); //!!! FAILS: syntax error
    
public static $MyStaticVar null;

    public static function

MyStaticInit()
    {
        
//this is the static constructor
        //because in a function, everything is allowed, including initializing using other functions
self::$MyStaticVar Demonstration();
    }
MyStaticClass::MyStaticInit(); //Call the static constructor

echo MyStaticClass::$MyStaticVar;
//This is the result of demonstration()
?>

b1tchcakes ¶

3 months ago

trait {
  protected 
$p;
  public function 
testMe() {echo 'static:'.static::class. ' // self:'.self::class ."\n";}
}

class

{ use t; }
class 
extends {}

echo (new

a)->testMe();
echo (new 
b)->testMe();

outputs
static:// self:t
static:// self:t