Haciendo del Desarrollo y la Arquitectura Web, ciencia y pasión.

Metodos y variables estaticas

Uno de los aspectos poco usados y mas oscuros de la programacion PHP es la funcionalidad que nos provee la palabra reservada Static. En esta entrada hablaremos de la palabra reservada Static y del operador de resolucion de ambito "::".  A este operador tambien se le conoce por el fantastico e incomprensible nombre Paamayin Nekudotayim, que  literalmente del hebreo quiere decir doble pareja de dos puntos. Dicho esto puedes olvidar su nombre pero es una frikada digna de contar entre cervezas.

Bien, una cerveza... digo.. la palabra reservada Static aplica a variables en una funcion o dentro de una clase, a variables miembro o a los metodos. Veremos todos ellos con algun ejemplo que nos dejaran claro su uso.

Entonces, ¿que es una variable estatica? Una variable estatica es una variable que solo existe en un ambito de una funcion pero que mantiene el valor cuando la funcion termina su ejecucion. Es decir recuerda su valor la proxima vez que se llama a la funcion ¿Como? Si ha terminado su ejecucion, deberia destruirse!! Veamos un ejemplo:


function mifuncion(){
   static $a = 1;
   $a *= 2;
   echo $a.'\n';
}
mifuncion();
mifuncion();
mifuncion();

Podria pensarse que la salida de este codigo daria tres 2 consecutivos dado que hay una inicializacion en cada llamada de la funcion, pero como se ha dicho, la inicializacion solo tiene lugar en una ocasion, con lo que la salida es:

2
4
8

Es importante remarcar que es ilegal asignar a una variable estatica el resultado de una expresion, permitiendo solo, constantes y cadenas y por extension tampoco se podran asignar la salida de una funcion o una operacion como 1+1.

Static en clases, atributo o metodos

 En el caso de atributos miembro de una clase al igual que en variables normales estaticas en una funcion, una variable estatica retiene un unico valor para todas las instancias de la clase.

 


class miObjeto {
  public static $miEstatica = 0;
  public function miMetodo(){
     self::$miEstatica += 2;
     echo self::$miEstatica."\n";
  }
}
$instancia1 = new miObjeto();
$instancia1->miMetodo();
$instancia2 = new miObjeto();
$instancia2->miMetodo();

Y esto producira un:


2
4

Lo cual ya no es tan inesperado. Perfecto.

Ahora hablaremos del operador de ambito de resolucion. Este operador lousaremos siempre que nos refiramos a las variables o metodos estaticos. Lo primero que nos chocara cuando lo usemos es que hay que poner $ delante de la variable, es decir ::$variable, a diferencia del operador flecha cuando instanciamos un objeto. Este operador se puede usar con Self, parent y static, introducido en PHP 5.3.

 


class miObjeto {
   function miMetodoBase(){
     echo "Mi objeto base";
   }
}
class miOtroObjeto  extends miObjeto{
   function miMetodoExtendido(){
     echo "miMetodoExtendido esta declarado en miOtroObjeto";
     self::miMetodoBase();
   }
}
miOtroObjeto::miMetodoExtendido();

Y esto producira un:


miMetodoExtendido esta declarado en miOtroObjeto
My objeto base

Hasta aqui todo en orden, self para mi, en ambito estatico, parent para mi padre, tambien para estatico. Pues ademas se introdujo static, una nueva funcionalidad llamada enlace estatico en tiempo de ejecucion ("late static bindings" en ingles) que permite referirse a la clase invocada en un contexto de herencia estatica:

 


class A {
    public static function foo() {
        echo __CLASS__;
    }
    public static function test() {
        static::foo(); // He aquí el enlace estático en tiempo de ejecución
    }
}

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

B::test();

Al ejecutar este codigo nos devolvera 'B', por que static nos hace referencia a la clase invocada, en este caso, B.

Por ultimo estan los metodos estaticos. Estos se marcan como estaticos y entonces usamos :: para acceder a ellos via el nombre de la clase.

 

class Foo {
    public static function unMetodoEstatico() {
         echo "soy Estatiiico!";
    }
}

Foo::unMetodoEstatico();
$nombre_clase = 'Foo';
$nombre_clase::unMetodoEstatico(); // A partir de PHP 5.3.0

La salida que dara este codigo es "Soy estatico" dos veces.

Sin embargo hay que tener ciertas consideraciones con los metodos estaticos. Si se invoca de manera estatica no se dispondra de la pseudo variable this y no se podra acceder a las propiedades mediante el operador flecha. Con las nuevas versiones de PHP intentar llamar de manera estatica a un metodo no estatico nos devolvera un deprecated y segun la documentacion oficial se eliminara en futuras versiones.

Al ejecutar en PHP7


class Foo {
    public function unMetodoNoEstatico() {
         echo "No soy Estatiiico!";
    }
}

Foo::unMetodoEstatico();
$nombre_clase = 'Foo';
$nombre_clase::unMetodoNoEstatico();

Deprecated:  Non-static method Foo::miMetodoEstatico() should not be called statically in [...][...] on line 8

Sin embargo al probar el codigo anterior en PHP5.2:

 


class Foo {
    public static function miMetodoEstatico() {
        echo "soy estatico";
    }
}


$nombre_clase = 'Foo';
$nombre_clase::miMetodoEstatico(); 

Parse error:  syntax error, unexpected T_PAAMAYIM_NEKUDOTAYIM in [...][...] on line 10

Al probar este codigo en PHP5.2 nos indica que el operador ::, (nuestro amigo Paamayim ;^) ) solo puede ir seguido de nuestra clase y no una variable, mejora que fue añadido a partir de la 5.3