Getting Ready for a PHP Interview: The Static Keyword

  • Tutorial
It's no secret that they like to ask tricky questions at interviews. Not always adequate, not always related to reality, but the fact remains - ask. Of course, the question is a different question, and sometimes the question, which at first glance seems silly to you, is actually aimed at checking how well you know the language you are writing in.

image

Let's try to parse one of these questions - what does the word "static" mean in PHP and why is it used?

The static keyword in PHP has three different meanings. We will analyze them in chronological order, as they appeared in the language.

The first value is a static local variable


function foo() {
  $a = 0;
  echo $a;
  $a = $a + 1;
}
foo(); // 0
foo(); // 0
foo(); // 0


In PHP, variables are local. This means that a variable defined and received a value inside a function (method) exists only during the execution of this function (method). When you exit the method, the local variable is destroyed, and when you re-enter, it is created again. In the code above, such a local variable is the $ a variable - it exists only inside the foo () function and is re-created each time this function is called. The increment of a variable in this code is meaningless, since on the next line of code the function will finish its work and the value of the variable will be lost. No matter how many times we call the foo () function, it will always output 0 ...

However, everything changes if we set the static keyword before assignment:

function foo() {
  static $a = 0;
  echo $a;
  $a = $a + 1;
}
foo(); // 0
foo(); // 1
foo(); // 2


The static keyword, written before assigning a value to a local variable, has the following effects:
  1. Assignment is performed only once, the first time the function is called
  2. The value of the variable marked in this way is saved after the function finishes
  3. On subsequent calls to the function, instead of assigning the variable, it receives the previously saved value

This use of the word static is called a static local variable .

Pitfalls of Static Variables

Of course, as always in PHP, it cannot do without "pitfalls."

Stone one - only constants or constant expressions can be assigned to a static variable. Here is the code:
static $a = bar();

inevitably lead to a parser error. Fortunately, starting with version 5.6, it became possible to assign not only constants, but also constant expressions (for example, “1 + 2” or “[1, 2, 3]”), that is, expressions that are independent of other code and can be calculated at the compilation stage.

Second stone - methods exist in a single copy.
Everything is a little more complicated here. To understand the essence, I will give the code:
class A {
  public function foo() {
    static $x = 0;
    echo ++$x;
  }
}
$a1 = new A;
$a2 = new A;
$a1->foo(); // 1
$a2->foo(); // 2
$a1->foo(); // 3
$a2->foo(); // 4

Contrary to the intuitive expectation of “different objects - different methods”, we clearly see in this example that dynamic methods in PHP “do not multiply”. Even if we have one hundred objects of this class, the method will exist in only one instance, just with each call a different $ this will be thrown into it.

This behavior may be unexpected for an unprepared developer and serve as a source of errors. It should be noted that the inheritance of the class (and method) leads to the fact that a new method is still created:

class A {
  public function foo() {
    static $x = 0;
    echo ++$x;
  }
}
class B extends A {
}
$a1 = new A;
$b1 = new B;
$a1->foo(); // 1
$b1->foo(); // 1
$a1->foo(); // 2
$b1->foo(); // 2


Conclusion: dynamic methods in PHP exist in the context of classes, not objects. And only in runtime is the substitution "$ this = current_object"

The second value - static properties and class methods


In the PHP object model, it is possible to set properties and methods not only for objects - instances of the class, but also for the class as a whole. The static keyword also serves for this:

class A {
  public static $x = 'foo';
  public static function test() {
    return 42;
  }
}
echo A::$x; // 'foo'
echo A::test(); // 42

To access these properties and methods, double-colon constructions ("Paamayim Nekudotayim") are used, such as CLASS_NAME :: $ Variable_NAME and CLASS_NAME :: MethodName ().

It goes without saying that static properties and static methods have their own characteristics and their "pitfalls" that you need to know.

The first feature is commonplace - there is no $ this. Actually, this stems from the very definition of a static method - since it is associated with a class and not an object, the pseudo-variable $ this is not available in it, which indicates the current object in dynamic methods. Which is completely logical.

However, you need to know that unlike other languages, PHP does not define the situation "$ this is written in the static method" at the stage of parsing or compilation. A similar error can occur only in runtime if you try to execute code with $ this inside a static method.

A code like this:
class A {
  public $id = 42;
  static public function foo() {
    echo $this->id;
  }
}

will not lead to any errors until you try to use the foo () method inappropriately:
$a = new A;
$a->foo();
(and immediately get "Fatal error: Using $ this when not in object context")

The second feature - static is not an axiom!
class A {
  static public function foo() {
    echo 42;
  }
}
$a = new A;
$a->foo();

Yes, yes. A static method, if it does not contain $ this in the code, can be called in a dynamic context, like an object method. This is not a bug in PHP.

The converse is not entirely true:
class A {
  public function foo() {
    echo 42;
  }
}
A::foo();

A dynamic method that does not use $ this can be executed in a static context. However, you will receive a warning “Non-static method A :: foo () should not be called statically” of level E_STRICT. It is up to you to either strictly follow code standards or suppress warnings. The first, of course, is preferable.

And by the way, everything written above applies only to methods. Using a static property through "->" is not possible and leads to a fatal error.

The third meaning, which seems to be the most difficult - late static binding


The developers of the PHP language did not stop at two values ​​of the keyword “static” and in version 5.3 they added another “feature” of the language, which is implemented by the same word! It is called "late static binding" or LSB (Late Static Binding).

The essence of LSB is easiest to understand with simple examples:

class Model {
  public static $table = 'table';
  public static function getTable() {
    return self::$table;
  }
}
echo Model::getTable(); // 'table'

The self keyword in PHP always means "the name of the class where this word is written." In this case, self is replaced by the Model class, and self :: $ table is replaced by Model :: $ table.
This language feature is called "early static binding." Why early? Because the binding of self and a concrete class name does not occur in runtime, but at earlier stages - parsing and compiling code. But “static” - because we are talking about static properties and methods.

Let's change our code a bit:

class Model {
  public static $table = 'table';
  public static function getTable() {
    return self::$table;
  }
}
class User extends Model {
  public static $table = 'users';
}
echo User::getTable(); // 'table'


Now you understand why PHP is not intuitive in this situation. self was associated with the Model class when the User class was not yet known, and therefore points to Model.

How to be

To solve this dilemma, a “late” binding mechanism was invented at the runtime stage. It works very simply - just write “static” instead of the word “self” and the connection will be established with the class that calls the given code, and not with the one where it is written:
class Model {
  public static $table = 'table';
  public static function getTable() {
    return static::$table;
  }
}
class User extends Model {
  public static $table = 'users';
}
echo User::getTable(); // 'users'


This is the mysterious “late static binding”.

It should be noted that for convenience in PHP, in addition to the word "static", there is also a special function get_called_class (), which will tell you in the context of which class your code is currently running.

Have a great job interview!

The list of useful links to the manual:

Also popular now: