¿Cuándo usar a uno mismo sobre this esto?


En PHP 5, ¿cuál es la diferencia entre usar self y $this?

¿Cuándo es apropiado cada uno?

 1802
Author: 7ochem, 2008-09-30

22 answers

Respuesta corta

Use $this para referirse a la corriente objeto. Use self para referirse a la clase actual. En otras palabras, el uso $this->member para los miembros no estáticos, use self::$member para los miembros estáticos.

Respuesta completa

Aquí hay un ejemplo de correcto uso de $this y self para variables miembro no estáticas y estáticas:

<?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();
?>

Aquí hay un ejemplo de uso incorrecto de $this y self para miembros no estáticos y estáticos 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();
?>

Aquí hay un ejemplo de polimorfismo con $this para funciones miembro:

<?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();
?>

Aquí hay un ejemplo de suprimiendo el comportamiento polimórfico usando self para funciones miembro:

<?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();
?>

La idea es que $this->foo() llama a la función miembro foo() de cualquier >que sea el tipo exacto del objeto actual. Si el objeto es de type X, por lo tanto >llama X::foo(). Si el objeto es de type Y, llama a Y::foo(). Pero con >self::foo(), X::foo() siempre se llama.

De http://www.phpbuilder.com/board/showthread.php?t=10354489:

Por http://board.phpbuilder.com/member.php?145249-laserlight

 1527
Author: John Millikin,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-07-28 06:04:22

La palabra clave self hace NO se refiere meramente a la 'clase actual', al menos no de una manera que restrinja a los miembros estáticos. Dentro del contexto de un miembro no estático, self también proporciona una forma de evitar la vtable ( ver wiki en vtable) para el objeto actual. Así como puedes usar parent::methodName() para llamar a la versión padre de una función, también puedes llamar self::methodName() para llamar a la implementación de clases actual de un método.

class Person {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }

    public function getTitle() {
        return $this->getName()." the person";
    }

    public function sayHello() {
        echo "Hello, I'm ".$this->getTitle()."<br/>";
    }

    public function sayGoodbye() {
        echo "Goodbye from ".self::getTitle()."<br/>";
    }
}

class Geek extends Person {
    public function __construct($name) {
        parent::__construct($name);
    }

    public function getTitle() {
        return $this->getName()." the geek";
    }
}

$geekObj = new Geek("Ludwig");
$geekObj->sayHello();
$geekObj->sayGoodbye();

Esto producirá:

Hola, soy Ludwig el geek{[21]]} Adiós de Ludwig la persona

sayHello() utiliza el puntero $this, por lo que la vtable se invoca para llamar a Geek::getTitle(). sayGoodbye() usa self::getTitle(), por lo que la tabla v no se usa, y Person::getTitle() se llama. En ambos casos, estamos tratando con el método de un objeto instanciado, y tenemos acceso al puntero $this dentro de las funciones llamadas.

 712
Author: nbeagle,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-11-10 08:37:04

NO USAR self::, usar static::

Hay otro aspecto del yo:: que vale la pena mencionar. Fastidiosamente self:: se refiere al ámbito de aplicación en el punto de definición y no en el punto de ejecución. Considere esta clase simple con dos métodos:

class Person
{

    public static function status()
    {
        self::getStatus();
    }

    protected static function getStatus()
    {
        echo "Person is alive";
    }

}

Si llamamos Person::status() veremos "La persona está viva" . Ahora considere lo que sucede cuando hacemos una clase que hereda de esto:

class Deceased extends Person
{

    protected static function getStatus()
    {
        echo "Person is deceased";
    }

}

Llamando Deceased::status() esperaríamos ver " La persona ha fallecido" sin embargo, lo que vemos es "Person is alive" ya que el ámbito contiene la definición del método original cuando se definió la llamada a self::getStatus().

PHP 5.3 tiene una solución. las static:: el operador de resolución implementa el "enlace estático tardío", que es una forma elegante de decir que está vinculado al alcance de la clase llamada. Cambia la línea en status() a static::getStatus() y los resultados son lo que esperarías. En versiones anteriores de PHP tendrás que encontrar un kludge para hacer esto.

Véase PHP Documentación

Así que para responder a la pregunta no como se hizo ...

$this-> se refiere al objeto actual (una instancia de una clase), mientras que static:: se refiere a una clase

 430
Author: Sqoo,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-07-04 08:01:45

Para entender realmente de qué estamos hablando cuando hablamos de self versus $this, necesitamos indagar realmente en lo que está pasando a nivel conceptual y práctico. No me siento ninguna de las respuestas hacer esto correctamente, así que aquí está mi intento.

Comencemos hablando de lo que es una clase y un objeto .

Clases Y Objetos, Conceptualmente

Entonces, ¿qué esuna clase? Mucha gente lo define como un plano o una plantilla para un objeto. De hecho, puedes leer más Sobre Las Clases En PHP Aquí. Y hasta cierto punto eso es lo que realmente es. Veamos una clase:

class Person {
    public $name = 'my name';
    public function sayHello() {
        echo "Hello";
    }
}

Como puede ver, hay una propiedad en esa clase llamada $name y un método (función) llamado sayHello().

Es muy importante notar que la clase es una estructura estática. Lo que significa que la clase Person, una vez definida, es siempre la misma dondequiera que lo mires.

Un objeto por otro lado es lo que se llama una instancia de una Clase. Lo que eso significa es que tomamos el "plano" de la clase, y lo usamos para hacer una copia dinámica. Esta copia ahora está específicamente vinculada a la variable en la que está almacenada. Por lo tanto, cualquier cambio en una instancia es local a esa instancia.

$bob = new Person;
$adam = new Person;
$bob->name = 'Bob';
echo $adam->name; // "my name"

Creamos nuevas instancias de una clase usando el operador new.

Por lo tanto, decimos que un La clase es una estructura global, y un objeto es una estructura local. No te preocupes por esa sintaxis divertida ->, vamos a entrar en eso en un poco.

Otra cosa de la que deberíamos hablar, es que podemos comprobar si una instancia es un instanceof una clase particular: $bob instanceof Person que devuelve un booleano si la instancia $bob se hizo usando la clase Person, o un hijo de Person.

Estado definitorio

Así que vamos a profundizar un poco en lo que una clase en realidad contener. Hay 5 tipos de "cosas" que contiene una clase:

  1. Properties - Piense en ellas como variables que contendrá cada instancia.

    class Foo {
        public $bar = 1;
    }
    
  2. Propiedades estáticas - Piense en estas como variables que se comparten a nivel de clase. Lo que significa que nunca son copiados por cada instancia.

    class Foo {
        public static $bar = 1;
    }
    
  3. Methods - Estas son funciones que cada instancia contendrá (y operará en instancia).

    class Foo {
        public function bar() {}
    }
    
  4. Métodos estáticos - Estas son funciones que se comparten en toda la clase. no operan en instancias, sino solo en las propiedades estáticas.

    class Foo {
        public static function bar() {}
    }
    
  5. Constantes - Constantes de clase resueltas. No yendo más profundo aquí, sino agregando para completar:

    class Foo {
        const BAR = 1;
    }
    

Así que básicamente, estamos almacenando información sobre la clase y el contenedor de objetos usando "sugerencias" sobre static que identifican si la información es compartida (y por lo tanto estática) o no (y por lo tanto dinámica).

Estado y Métodos

Dentro de un método, la instancia de un objeto está representada por la variable $this. El estado actual de ese objeto está ahí, y mutar (cambiar) cualquier propiedad resultará en un cambio en esa instancia (pero no en otras).

Si un método se llama estáticamente, la variable $this no se define. Esto es porque hay ninguna instancia asociada a una llamada estática.

Lo interesante aquí es cómo se hacen las llamadas estáticas. Así que hablemos de cómo accedemos al estado:

Estado de acceso

Así que ahora que hemos almacenado ese estado, necesitamos acceder a él. Esto puede ser un poco complicado (o way más que un poco), así que dividamos esto en dos puntos de vista: desde fuera de una instancia / clase (por ejemplo, desde una llamada a una función normal, o desde el ámbito global), y dentro de una instancia/clase (desde dentro de un método en el objeto).

Desde Fuera De Una Instancia/Clase

Desde el exterior de una instancia/clase, nuestras reglas son bastante simples y predecibles. Tenemos dos operadores, y cada uno nos dice inmediatamente si estamos tratando con una instancia o una clase estática:

  • -> - object-operator - Esto siempre se usa cuando accedemos a una instancia.

    $bob = new Person;
    echo $bob->name;
    

    Es importante tener en cuenta que llamar Person->foo no tiene sentido (ya que Person es una clase, no una instancia). Por lo tanto, eso es un error de análisis.

  • :: - scope-resolution-operator - Esto siempre se usa para acceder a una propiedad o método estático de Clase.

    echo Foo::bar()
    

    Además, podemos llamar a un método estático en un objeto de la misma manera:{[83]]}

    echo $foo::bar()
    

    Es extremadamente importante notar que cuando hacemos esto desde fuera, la instancia del objeto está oculta del método bar(). Lo que significa que es el exactamente lo mismo que correr:

    $class = get_class($foo);
    $class::bar();
    

Por lo tanto, $this no se define en la llamada estática.

Desde El Interior De Una Instancia/Clase

Las cosas cambian un poco aquí. Se utilizan los mismos operadores, pero su significado se vuelve significativamente borroso.

El operador de objetos -> todavía se utiliza para hacer llamadas al estado de instancia del objeto.

class Foo {
    public $a = 1;
    public function bar() {
        return $this->a;
    }
}

Llamando al método bar() en $foo (una instancia de Foo) usando el operador objeto: $foo->bar() dará como resultado la versión de la instancia de $a.

Así es como esperamos.

El significado del operador :: aunque cambia. Depende del contexto de la llamada a la función actual:

  • Dentro de un contexto estático

    Dentro de un contexto estático, cualquier llamada realizada usando :: también será estática. Veamos un ejemplo:

    class Foo {
        public function bar() {
            return Foo::baz();
        }
        public function baz() {
            return isset($this);
        }
    }
    

    Llamando a {[46] } llamará al método baz() estáticamente, y por lo tanto $this lo hará no estar poblada. Vale la pena señalar que en versiones recientes de PHP (5.3+) esto desencadenará un error E_STRICT, porque estamos llamando a métodos no estáticos estáticamente.

  • Dentro de un contexto de instancia

    Por otro lado, dentro de un contexto de instancia, las llamadas realizadas usando :: dependen del receptor de la llamada (el método que estamos llamando). Si el método se define como static, entonces usará una llamada estática. Si no lo es, reenviará la instancia información.

    Entonces, mirando el código anterior, llamar a $foo->bar() devolverá true, ya que la llamada "estática" ocurre dentro de un contexto de instancia.

¿Tiene sentido? No lo creo. Es confuso.

Palabras clave abreviadas

Debido a que vincular todo usando nombres de clase es bastante sucio, PHP proporciona 3 palabras clave básicas de "atajo" para facilitar la resolución de ámbitos.

  • self - Esto se refiere al nombre de la clase actual. Tan self::baz() es lo mismo que Foo::baz() dentro de la clase Foo (cualquier método en ella).

  • parent - Esto se refiere al padre de la clase actual.

  • static - Esto se refiere a la clase llamada. Gracias a la herencia, las clases secundarias pueden anular métodos y propiedades estáticas. Así que llamarlos usando static en lugar de un nombre de clase nos permite resolver de dónde viene la llamada, en lugar del nivel actual.

Ejemplos

El más fácil una manera de entender esto es empezar a mirar algunos ejemplos. Vamos a elegir una clase:

class Person {
    public static $number = 0;
    public $id = 0;
    public function __construct() {
        self::$number++;
        $this->id = self::$number;
    }
    public $name = "";
    public function getName() {
        return $this->name;
    }
    public function getId() {
        return $this->id;
    }
}

class Child extends Person {
    public $age = 0;
    public function __construct($age) {
        $this->age = $age;
        parent::__construct();
    }
    public function getName() {
        return 'child: ' . parent::getName();
    }
}

Ahora, también estamos viendo la herencia aquí. Ignore por un momento que este es un mal modelo de objetos, pero veamos lo que sucede cuando jugamos con esto:

$bob = new Person;
$bob->name = "Bob";
$adam = new Person;
$adam->name = "Adam";
$billy = new Child;
$billy->name = "Billy";
var_dump($bob->getId()); // 1
var_dump($adam->getId()); // 2
var_dump($billy->getId()); // 3

Así que el contador de ID se comparte entre ambas instancias y los hijos (porque estamos usando self para acceder a él. Si usamos static, podríamos sobrescribirlo en una clase hija).

var_dump($bob->getName()); // Bob
var_dump($adam->getName()); // Adam
var_dump($billy->getName()); // child: Billy

Tenga en cuenta que estamos ejecutando el Person::getName() instance método cada vez. Pero estamos usando el parent::getName() para hacerlo en uno de los casos (el caso hijo). Esto es lo que hace que este enfoque sea poderoso.

Palabra De Precaución #1

Tenga en cuenta que el contexto de llamada es lo que determina si se utiliza una instancia. Por lo tanto:

class Foo {
    public function isFoo() {
        return $this instanceof Foo;
    }
}

No es siempre verdadero.

class Bar {
    public function doSomething() {
        return Foo::isFoo();
    }
}
$b = new Bar;
var_dump($b->doSomething()); // bool(false)

Ahora es realmente raro aquí. Estamos llamando a una clase diferente, pero el $this que se pasa al método Foo::isFoo() es la instancia de $bar.

Esto puede causar todo tipo de errores y WTF-ery conceptual. Por lo tanto, sugiero encarecidamente evitar el operador :: desde métodos de instancia en cualquier cosa excepto en esas tres palabras clave virtuales "atajos"(static, self, y parent).

Palabra De Precaución # 2

Tenga en cuenta que los métodos y las propiedades estáticas son compartidos por todos. Eso las hace básicamente variables globales. Con todos los mismos problemas que vienen con los globales. Así que sería realmente vacilante para almacenar información en métodos/propiedades estáticas a menos que te sientas cómodo con que sea verdaderamente global.

Palabra De Precaución # 3

En general, querrá usar lo que se conoce como Enlace estático tardío usando static en lugar de self. Pero tenga en cuenta que no son la misma cosa, por lo que decir "siempre use static en lugar de self es realmente miope. En su lugar, deténgase y piense en la llamada que desea hacer y piense si desea que las clases secundarias puedan anular esa estática resuelto llamada.

TL / DR

Qué pena, vuelve y léelo. Puede ser demasiado largo, pero es así de largo porque este es un tema complejo

TL /DR # 2

Ok, bien. En resumen, self se usa para hacer referencia a el nombre de clase actual dentro de una clase, donde as $this se refiere al objeto actual instancia. Tenga en cuenta que self es un atajo de copiar/pegar. Puede reemplazarlo con seguridad con el nombre de su clase, y funcionará bien. Pero $this es una dinámica variable que no se puede determinar con anticipación (y puede que ni siquiera sea su clase).

TL /DR # 3

Si se usa el operador objeto (->), entonces siempre sabe que está tratando con una instancia. Si se utiliza el operador scope-resolution (::), necesita más información sobre el contexto (¿ya estamos en un contexto objeto? Estamos fuera de un objeto? sucesivamente).

 231
Author: ircmaxell,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 11:33:26

self (not self self) se refiere al tipo de la clase, donde as $this se refiere a la instancia actual de la clase. self se usa en funciones miembro estáticas para permitirle acceder a variables miembro estáticas. $this se usa en funciones miembro no estáticas, y es una referencia a la instancia de la clase en la que se llamó a la función miembro.

Porque this es un objeto, lo usas como: $this->member

Porque self no es un objeto, es, básicamente, un tipo que automáticamente se refiere a la clase actual, se usa como: self::member

 109
Author: MrZebra,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-05-06 09:49:23

$this-> se utiliza para referirse a una instancia específica de las variables de una clase (variables miembro) o métodos.

Example: 
$derek = new Person();

Derek derek es ahora una instancia específica de Persona. Cada persona tiene un first_name y un last_name, pero derek derek tiene un first_name y un last_name específicos (Derek Martin). Dentro de la instancia derek derek, podemos referirnos a ellas como this this->first_name y {this->last_name

ClassName:: se usa para referirse a ese tipo de clase, y sus variables estáticas, métodos estáticos. Si te ayuda, mentalmente puede reemplazar la palabra " estático "por"compartido". Debido a que son compartidos, no pueden hacer referencia a this this, que se refiere a una instancia específica (no compartida). Las variables estáticas (es decir, static db db_connection) se pueden compartir entre todas las instancias de un tipo de objeto. Por ejemplo, todos los objetos de base de datos comparten una sola conexión (static connection connection).

Ejemplo de Variables Estáticas: Finge que tenemos una clase de base de datos con una sola variable miembro: static num num_connections; Ahora, pon esto en el constructor:

function __construct()
{
    if(!isset $num_connections || $num_connections==null)
    {
        $num_connections=0;
    }
    else
    {
        $num_connections++;
    }
}

Así como los objetos tienen constructores, también tienen destructores, que se ejecutan cuando el objeto muere o no está configurado:

function __destruct()
{
    $num_connections--;
}

Cada vez que creamos una nueva instancia, aumentará nuestro contador de conexión en uno. Cada vez que destruimos o dejamos de usar una instancia, disminuirá el contador de conexión en uno. De esta manera, podemos monitorear el número de instancias del objeto de base de datos que tenemos en uso con:

echo DB::num_connections;

Porque num num_connections es estático (compartido), reflejará el número total de objetos activos de la base de datos. Es posible que haya visto esta técnica utilizada para compartir conexiones de base de datos entre todas las instancias de una clase de base de datos. Esto se hace porque la creación de la conexión a la base de datos lleva mucho tiempo, por lo que es mejor crear solo una y compartirla (esto se llama patrón de Singleton).

Los métodos estáticos (p. ej. public static View::format_phone_number (digits digits)) se pueden usar SIN instanciar primero uno de esos objetos (p. ej. no se refiera internamente a this esto).

Ejemplo de método estático:

public static function prettyName($first_name, $last_name)
{
    echo ucfirst($first_name).' '.ucfirst($last_name);
}

echo Person::prettyName($derek->first_name, $derek->last_name);

Como puede ver, la función estática pública prettyName no sabe nada sobre el objeto. Solo está trabajando con los parámetros que pasas, como una función normal que no es parte de un objeto. ¿Por qué molestarse, entonces, si pudiéramos tenerlo no como parte del objeto?

  1. Primero, adjuntar funciones a objetos ayuda a mantener las cosas organizadas, para que sepa dónde encontrarlas.
  2. Segundo, evita conflictos de nombres. En un proyecto grande, es probable que dos desarrolladores creen funciones getName (). Si uno crea un ClassName1::getName(), y el otro crea ClassName2:: getName(), no hay problema en absoluto. No hay conflicto. Yay métodos estáticos!

SELF:: Si la codificación fuera el objeto que tiene el método estático que desea consultar, debe llamar utilizando el nombre del objeto View::format_phone_number($número_teléfono); Si estás codificando dentro de el objeto que tiene el método estático al que desea hacer referencia, puede usar el nombre del objeto View::format_phone_number (p pn), O puede usar el atajo self::format_phone_number ({pn)

Lo mismo ocurre con las variables estáticas: Ejemplo: Vista:: templates_path versus self:: templates_path

Dentro de la clase DB, si nos referíamos a un método estático de algún otro objeto, usaríamos el nombre del objeto: Ejemplo: Session:: getUsersOnline ();

Pero si la clase DB quisiera referirse a su propia variable estática, simplemente diría self: Ejemplo: self:: conexión;

Espero que ayude a aclarar las cosas:)

 93
Author: lo_fye,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-02-16 14:10:47

De esta entrada del blog :

  • self se refiere a la clase actual
  • self se puede usar para llamar a funciones estáticas y hacer referencia a variables miembro estáticas
  • self se puede utilizar dentro de funciones estáticas
  • self también puede desactivar el comportamiento polimórfico evitando el vtable
  • $this se refiere al objeto actual
  • $this se puede usar para llamar a funciones estáticas
  • $this no debe utilizarse para llama a variables de miembro estáticas. Utilice self en su lugar.
  • $this no se puede utilizar dentro de funciones estáticas
 27
Author: okconfused,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-01-24 15:46:59

En PHP, se utiliza la palabra clave self para acceder a propiedades y métodos estáticos.

El problema es que puede reemplazar $this->method() con self::method()en cualquier lugar, independientemente de si method() se declara estático o no. Entonces, ¿cuál deberías usar?

Considere este código:

class ParentClass {
    function test() {
        self::who();    // will output 'parent'
        $this->who();   // will output 'child'
    }

    function who() {
        echo 'parent';
    }
}

class ChildClass extends ParentClass {
    function who() {
        echo 'child';
    }
}

$obj = new ChildClass();
$obj->test();

En este ejemplo, self::who() siempre mostrará 'padre', mientras que $this->who() dependerá de la clase que tenga el objeto.

Ahora podemos ver que self se refiere a la clase en la que se llama, mientras que $this se refiere a la clase del objeto actual .

Por lo tanto, debe usar self solo cuando $this no esté disponible, o cuando no desee permitir que las clases descendientes sobrescriban el método actual.

 23
Author: ramin rostami,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-06-28 17:06:03

Dentro de una definición de clase, this esto se refiere al objeto actual, mientras que self se refiere a la clase actual.

Es necesario hacer referencia a un elemento de clase usando self, y hacer referencia a un elemento objeto usando self this.

self::STAT // refer to a constant value
self::$stat // static variable
$this->stat // refer to an object variable  
 19
Author: Tarun Singhal,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-12-14 12:57:19

Aquí hay un ejemplo de uso correcto de this this y self para no estáticos y variables miembro estáticas:

<?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();
?> 
 17
Author: Mohit Bumb,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-12-06 11:26:22

Según http://www.php.net/manual/en/language.oop5.static.php no hay $self. Solo existe $this, para referirse a la instancia actual de la clase (el objeto), y self, que se puede usar para referirse a miembros estáticos de una clase. La diferencia entre una instancia de objeto y una clase entra en juego aquí.

 16
Author: cruizer,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-02-16 14:10:30

Como nadie aquí habló de las actuaciones, he aquí un pequeño punto de referencia que hice (5.6):

 Name     | Time    | Percent  
----------|---------|---------  
 $this->  | 0.99163 | 106.23%  
 self::   | 0.96912 | 103.82%  
 static:: | 0.93348 | 100%

Esos son los resultados de 2 000 000 corridas, y aquí está el código que usé:

<?php

require '../vendor/autoload.php';

// My small class to do benchmarks
// All it does is looping over every test x times and record the
//   time it takes using `microtime(true)`
// Then, the percentage is calculated, with 100% being the quickest
// Times are being rouned for outputting only, not to calculate the percentages
$b = new Tleb\Benchmark\Benchmark(2000000);

class Foo
{
    public function calling_this()
    {
        $this->called();
    }

    public function calling_self()
    {
        self::called();
    }

    public function calling_static()
    {
        static::called();
    }

    public static function called()
    {
    }
}

$b->add('$this->',  function () { $foo = new Foo; $foo->calling_this(); });
$b->add('self::',   function () { $foo = new Foo; $foo->calling_self(); });
$b->add('static::', function () { $foo = new Foo; $foo->calling_static(); });

$b->run();
 12
Author: tleb,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-10-01 05:04:55

self se refiere a la clase actual (en la que se llama),

$this refiere el objeto actual. Puedes usar estática en lugar de auto. Ver el ejemplo:

    class ParentClass {
            function test() {
                    self::which();  // output 'parent'
                    $this->which(); // output 'child'
            }

            function which() {
                    echo 'parent';
            }
    }

    class ChildClass extends ParentClass {
            function which() {
                    echo 'child';
            }
    }

    $obj = new ChildClass();
    $obj->test();

Salida: padre niño

 12
Author: Kabir Hossain,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-02-16 14:12:42

Creo que la pregunta no era si se puede llamar al miembro estático de la clase llamando a ClassName::staticMember. La pregunta era cuál es la diferencia entre usar self::classmember y $this->classmember.

Por ejemplo, los dos ejemplos siguientes funcionan sin errores, ya sea que use self:: o $this->

class Person{
    private $name;
    private $address;

    public function __construct($new_name,$new_address){
        $this->name = $new_name;
        $this->address = $new_address;
    }
}

class Person{
    private $name;
    private $address;
    public function __construct($new_name,$new_address){
        self::$name = $new_name;
        self::$address = $new_address;
    }
}
 11
Author: Akintunde-Rotimi,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-02-16 14:11:20
  • El puntero del objeto this esto se refiere al objeto actual.
  • El valor de clase "static" se refiere al objeto actual.
  • El valor de clase "self" se refiere a la clase exacta en la que se definió.
  • El valor de clase "padre" se refiere al padre de la clase exacta en la que se definió.

Vea el siguiente ejemplo que muestra la sobrecarga.

<?php

class A {

    public static function newStaticClass()
    {
        return new static;
    }

    public static function newSelfClass()
    {
        return new self;
    }

    public function newThisClass()
    {
        return new $this;
    }
}

class B extends A
{
    public function newParentClass()
    {
        return new parent;
    }
}


$b = new B;

var_dump($b::newStaticClass()); // B
var_dump($b::newSelfClass()); // A because self belongs to "A"
var_dump($b->newThisClass()); // B
var_dump($b->newParentClass()); // A


class C extends B
{
    public static function newSelfClass()
    {
        return new self;
    }
}


$c = new C;

var_dump($c::newStaticClass()); // C
var_dump($c::newSelfClass()); // C because self now points to "C" class
var_dump($c->newThisClass()); // C
var_dump($b->newParentClass()); // A because parent was defined *way back* in class "B"

La mayoría de las veces desea referirse a la clase actual, por lo que utiliza static o $this. Obstante, hay momentos en que necesita self porque quieres la clase original independientemente de lo que se extiende. (Muy, muy raramente)

 10
Author: Xeoncross,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-03-22 15:30:00

Cuando self se usa con el operador :: se refiere a la clase actual, que se puede hacer tanto en contextos estáticos como no estáticos. $this se refiere al objeto mismo. Además, es perfectamente legal usar $this para llamar a métodos estáticos (pero no para hacer referencia a campos).

 10
Author: mrDjouk,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-03-22 15:34:05

$this se refiere al objeto de clase actual, self se refiere a la clase actual (No al objeto). La clase es el plano del objeto. Así que defines una clase, pero construyes objetos.

Así que en otras palabras, use self for static y this for none-static members or methods.

También en el escenario hijo/padre self / parent se usa principalmente para identificar a los miembros y métodos de la clase hijo y padre.

 5
Author: Rakesh Singh,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-09-15 06:36:28

Además desde $this:: no se ha discutido todavía.

Solo para fines informativos, a partir de PHP 5.3 cuando se trata de objetos instanciados para obtener el valor de ámbito actual, en lugar de usar static::, se puede usar alternativamente $this:: así.

Http://ideone.com/7etRHy

class Foo
{
    const NAME = 'Foo';

    //Always Foo::NAME (Foo) due to self
    protected static $staticName = self::NAME;

    public function __construct()
    {
        echo $this::NAME;
    }

    public function getStaticName()
    {
       echo $this::$staticName;
    }
}

class Bar extends Foo
{
    const NAME = 'FooBar';

    /**
     * override getStaticName to output Bar::NAME
     */
    public function getStaticName()
    {
        $this::$staticName = $this::NAME;
        parent::getStaticName();
    }
}

$foo = new Foo; //outputs Foo
$bar = new Bar; //outputs FooBar
$foo->getStaticName(); //outputs Foo
$bar->getStaticName(); //outputs FooBar
$foo->getStaticName(); //outputs FooBar

Usar el código anterior no es una práctica común o recomendada, sino que es simplemente para ilustrar su uso, y es actuar más como un "¿Sabías?"en referencia al original la pregunta del póster.

También representa el uso de $object::CONSTANT por ejemplo echo $foo::NAME; en oposición a $this::NAME;

 5
Author: fyrye,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-10-14 17:02:26

Use selfsi desea llamar a un método de una clase sin crear un objeto/instancia de esa clase, guardando así RAM (a veces use self para ese propósito). En otras palabras, en realidad está llamando a un método estáticamente. Use this para la perspectiva del objeto.

 4
Author: minhajul,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-02-16 14:12:05

Caso 1: Use self se puede usar para constantes de clase

 class classA { 
     const FIXED_NUMBER = 4; 
     self::POUNDS_TO_KILOGRAMS
}

Si desea llamarlo fuera de la clase, use classA::POUNDS_TO_KILOGRAMS para acceder a las constantes

Caso 2: Para propiedades estáticas

class classC {
     public function __construct() { 
     self::$_counter++; $this->num = self::$_counter;
   }
}
 1
Author: li bing zhao,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-02-02 21:14:00

Me encontré con la misma pregunta y la respuesta simple es:

  • this esto requiere una instancia de la clase
  • self:: doesn't

Siempre que esté utilizando métodos estáticos o atributos estáticos y desee llamarlos sin tener un objeto de la clase instanciado, debe usar self:: para llamarlos, porque this this siempre requiere que se cree on object.

 1
Author: Mike,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-05-19 15:23:49

Según php.net hay tres palabras clave especiales en este contexto: self, parent y static. Se utilizan para acceder a propiedades o métodos desde dentro de la definición de la clase.

$this, por otro lado, se utiliza para llamar a una instancia y métodos de cualquier clase siempre y cuando esa clase sea accesible.

 0
Author: Fil,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-12-07 12:26:21