ti-enxame.com

Quando usar auto mais de $ isso?

Em PHP 5, qual é a diferença entre usar self e $this?

Quando cada um é apropriado?

1883
Casey Watson

Resposta curta

Use $this para se referir ao objeto atual. Use self para se referir à classe atual. Em outras palavras, use $this->member para membros não estáticos, use self::$member para membros estáticos.

Resposta Completa

Aqui está um exemplo de correct usage de $this e self para variáveis ​​de membro não estáticas e 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();
?>

Aqui está um exemplo de incorreto uso de $this e self para variáveis ​​de membro estático e estático:

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

Aqui está um exemplo de polimorfismo com $this para funções de membro:

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

Aqui está um exemplo de supressão do comportamento polimórfico usando self para funções de membro:

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

A idéia é que $this->foo() chama a função de membro foo() de qualquer que seja o tipo exato do objeto atual. Se o objeto for type X, ele chama X::foo(). Se o objeto for type Y, ele chama Y::foo(). Mas com self :: foo (), X::foo() é sempre chamado.

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

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

1613
John Millikin

A palavra-chave auto fazN&ATILDE;Orefere-se apenas à 'classe atual', pelo menos não de uma maneira que o restringe a membros estáticos. Dentro do contexto de um membro não estático, self também fornece uma maneira de contornar o vtable ( veja wiki on vtable ) para o objeto atual. Assim como você pode usar parent::methodName() para chamar a versão dos pais de uma função, você pode chamar self::methodName() para chamar a implementação atual de classes de um 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();

Isto irá produzir:

Olá, sou Ludwig, o geek
Adeus de Ludwig a pessoa

sayHello() usa o ponteiro $this, então a vtable é invocada para chamar Geek::getTitle(). sayGoodbye() usa self::getTitle(), então a vtable não é usada e Person::getTitle() é chamada. Em ambos os casos, estamos lidando com o método de um objeto instanciado e temos acesso ao ponteiro $this dentro das funções chamadas.

726
nbeagle

NÃO USE self::, use static::

Há outro aspecto do eu: vale a pena mencionar. Irritantementeself:: refere-se ao escopo no ponto de definição não no ponto de execução . Considere esta classe simples com dois métodos:

class Person
{

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

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

}

Se chamarmos Person::status(), veremos "Person is alive". Agora considere o que acontece quando criamos uma classe que herda disso:

class Deceased extends Person
{

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

}

Chamando Deceased::status(), esperamos ver "Person is died", no entanto o que vemos é "Person is alive", pois o escopo contém a definição do método original quando a chamada para self::getStatus() foi definida.

PHP 5.3 tem uma solução. o operadorstatic::resolution implementa a "ligação estática tardia", que é uma maneira sofisticada de dizer que está vinculada ao escopo da classe chamada. Altere a linha em status() para static::getStatus() e os resultados são os esperados. Nas versões mais antigas do PHP você terá que encontrar um kludge para fazer isso.

Veja PHP Documentação

Então, para responder à pergunta não como foi perguntado ...

$this-> refere-se ao objeto atual (uma instância de uma classe), enquanto static:: se refere a uma classe

441
Sqoo

Para realmente entender o que estamos falando quando falamos de self versus $this, precisamos realmente investigar o que está acontecendo em um nível conceitual e prático. Eu realmente não sinto nenhuma das respostas isso apropriadamente, então aqui está minha tentativa.

Vamos começar falando sobre o que é um class e um object.

Classes e Objetos, Conceitualmente

Então, o que é a class? Muitas pessoas definem como blueprint ou template para um objeto. De fato, você pode ler mais Sobre as classes em PHP Aqui . E até certo ponto é o que realmente é. Vamos dar uma olhada em uma aula:

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

Como você pode ver, existe uma propriedade nessa classe chamada $name e um método (function) chamado sayHello().

É muito importante notar que o class é uma estrutura estática. O que significa que a classe Person, uma vez definida, é sempre a mesma onde quer que você olhe.

Um objeto, por outro lado, é o que é chamado de instance de uma classe. O que isso significa é que pegamos o "blueprint" da classe e o usamos para fazer uma cópia dinâmica. Esta cópia agora está especificamente vinculada à variável na qual ela está armazenada. Portanto, quaisquer alterações em um instance são locais para essa instância.

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

Criamos novas instances de uma classe usando o operador new.

Portanto, dizemos que uma classe é uma estrutura global e um objeto é uma estrutura local. Não se preocupe com a sintaxe engraçada do ->, vamos entrar nisso um pouquinho.

Uma outra coisa sobre a qual devemos falar é que podemos check se uma instância é um instanceof uma classe particular: $bob instanceof Person que retorna um booleano se a instância $bob foi feita usando a classe Person, ou uma criança de Person.

Definindo Estado

Então vamos analisar um pouco o que uma classe realmente contém. Existem 5 tipos de "coisas" que uma classe contém:

  1. Properties - pense nelas como variáveis ​​que cada instância conterá.

    class Foo {
        public $bar = 1;
    }
    
  2. Propriedades estáticas - Pense nelas como variáveis ​​compartilhadas no nível de classe. Isso significa que eles nunca são copiados por cada instância.

    class Foo {
        public static $bar = 1;
    }
    
  3. Methods - Estas são funções que cada instância conterá (e operará em instâncias).

    class Foo {
        public function bar() {}
    }
    
  4. Static Methods - Estas são funções que são compartilhadas em toda a classe. Eles fazem não operam em instâncias, mas apenas nas propriedades estáticas.

    class Foo {
        public static function bar() {}
    }
    
  5. Constantes - constantes resolvidas da classe. Não indo mais fundo aqui, mas adicionando para completar:

    class Foo {
        const BAR = 1;
    }
    

Basicamente, estamos armazenando informações na classe e no container de objetos usando "dicas" sobre static, que identificam se as informações são compartilhadas (e, portanto, estáticas) ou não (e, portanto, dinâmicas).

Estado e Métodos

Dentro de um método, a instância de um objeto é representada pela variável $this. O estado atual desse objeto está lá, e a mutação (alteração) de qualquer propriedade resultará em uma alteração nessa instância (mas não em outras).

Se um método é chamado estaticamente, a variável $thisnão está definida. Isso ocorre porque não há instância associada a uma chamada estática.

O interessante aqui é como as chamadas estáticas são feitas. Então, vamos falar sobre como acessamos o estado:

Estado de acesso

Então, agora que armazenamos esse estado, precisamos acessá-lo. Isso pode ficar um pouco complicado (ou way mais que um pouco), então vamos dividir isso em dois pontos de vista: de fora de uma instância/classe (digamos de uma chamada de função normal ou do escopo global) e dentro de uma instância/classe (de dentro de um método no objeto).

Do lado de fora de uma instância/classe

Do lado de fora de uma instância/classe, nossas regras são bem simples e previsíveis. Nós temos dois operadores, e cada um nos diz imediatamente se estamos lidando com uma instância ou uma classe estática:

  • -> - object-operator - Sempre é usado quando estamos acessando uma instância.

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

    É importante notar que chamar Person->foo não faz sentido (já que Person é uma classe, não uma instância). Portanto, isso é um erro de análise.

  • :: - scope-resolution-operator - Sempre é usado para acessar uma propriedade ou método estático de Classe.

    echo Foo::bar()
    

    Além disso, podemos chamar um método estático em um objeto da mesma maneira:

    echo $foo::bar()
    

    É extremamente importante notar que quando fazemos isso de fora , a instância do objeto é oculta do método bar(). Significa que é exatamente o mesmo que em execução:

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

Portanto, $this não está definido na chamada estática.

De dentro de uma instância/classe

As coisas mudam um pouco aqui. Os mesmos operadores são usados, mas seu significado fica significativamente desfocado.

O object-operator-> ainda é usado para fazer chamadas para o estado da instância do objeto.

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

Chamar o método bar() em $foo (uma instância de Foo) usando o operador de objeto: $foo->bar() resultará na versão da instância de $a.

Então é assim que esperamos.

O significado do operador :: é alterado. Depende do contexto da chamada para a função atual:

  • Dentro de um contexto estático

    Dentro de um contexto estático, todas as chamadas feitas usando :: também serão estáticas. Vamos ver um exemplo:

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

    Chamar Foo::bar() chamará o método baz() estaticamente e, portanto, $this será not ser preenchido. Vale a pena notar que em versões recentes do PHP (5.3+) isso irá disparar um erro E_STRICT, porque estamos chamando estaticamente métodos não estáticos.

  • Dentro de um contexto de instância

    Em um contexto de instância, por outro lado, as chamadas feitas usando :: dependem do receptor da chamada (o método que estamos chamando). Se o método for definido como static, ele usará uma chamada estática. Se não for, ele encaminhará as informações da instância.

    Portanto, olhando o código acima, chamar $foo->bar() retornará true, já que a chamada "estática" acontece dentro de um contexto de instância.

Faz sentido? Não pensava assim. É confuso.

Palavras-chave de atalho

Porque amarrar tudo junto usando nomes de classes é bastante sujo, PHP fornece 3 palavras-chave "atalho" básicas para facilitar a resolução de escopo.

  • self - Refere-se ao nome da classe atual. Então self::baz() é o mesmo que Foo::baz() dentro da classe Foo (qualquer método sobre ele).

  • parent - Refere-se ao pai da classe atual.

  • static - Refere-se à classe chamada. Graças à herança, as classes filhas podem substituir métodos e propriedades estáticas. Portanto, chamá-los usando static em vez de um nome de classe nos permite resolver de onde veio a chamada, em vez do nível atual.

Exemplos

A maneira mais fácil de entender isso é começar a analisar alguns exemplos. Vamos escolher uma aula:

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

Agora, também estamos vendo herança aqui. Ignore por um momento que este é um modelo de objeto ruim, mas vamos ver o que acontece quando jogamos com isso:

$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

Portanto, o contador de IDs é compartilhado entre as instâncias e os filhos (porque estamos usando self para acessá-lo. Se usássemos static, poderíamos substituí-lo em uma classe filha).

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

Note que estamos executando o método Person::getName()instance toda vez. Mas estamos usando a parent::getName() para fazer isso em um dos casos (o caso filho). É isso que torna essa abordagem poderosa.

Palavra de cautela # 1

Observe que o contexto de chamada é o que determina se uma instância é usada. Assim sendo:

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

Não é sempre true.

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

Agora é realmente estranho aqui. Estamos chamando uma classe diferente, mas o $this que é passado para o método Foo::isFoo() é a instância de $bar.

Isso pode causar todos os tipos de erros e WTF-ery conceitual. Portanto, sugiro evitar o operador :: de dentro dos métodos de instância em qualquer coisa, exceto nas três palavras-chave "atalho" virtuais (static, self e parent).

Palavra de cautela # 2

Observe que os métodos e propriedades estáticos são compartilhados por todos. Isso os torna basicamente variáveis ​​globais. Com todos os mesmos problemas que vêm com globals. Então, eu hesitaria em armazenar informações em métodos/propriedades estáticos, a menos que você se sinta confortável em ser verdadeiramente global.

Palavra de cautela # 3

Em geral, você desejará usar o que é conhecido como Late-Static-Binding usando static em vez de self. Mas note que eles não são a mesma coisa, então dizer "use sempre static em vez de self é realmente míope. Ao invés disso, pare e pense sobre a chamada que você quer fazer e pense se você quiser que as classes filhas possam sobrescrever isso. resolvido estático chamada.

TL/DR

Que pena, volte e leia. Pode ser muito longo, mas é muito longo porque esse é um assunto complexo

TL/DR # 2

Ok, tudo bem. Em resumo, self é usado para referenciar o nome da classe atual em uma classe, onde $this refere-se ao objeto atual instance. Note que self é um atalho de copiar/colar. Você pode substituí-lo com segurança pelo nome da sua turma e ele funcionará bem. Mas $this é uma variável dinâmica que não pode ser determinada antes do tempo (e pode nem ser sua classe).

TL/DR # 3

Se o operador de objeto for usado (->), então você always sabe que está lidando com uma instância. Se o operador scope-resolution-operator for usado (::), você precisará de mais informações sobre o contexto (já estamos em um contexto de objeto? Estamos fora de um objeto? Etc.).

238
ircmaxell

self (não $ self) refere-se ao type de class, onde $this refere-se ao atual instance da classe. self é para uso em funções de membro estático para permitir que você acesse variáveis ​​de membro estático. $this é usado em funções de membro não estático e é uma referência à instância da classe na qual a função de membro foi chamada.

Como this é um objeto, você usa: $this->member

Porque self não é um objeto, é basicamente um tipo que automaticamente se refere à classe atual, você usa como: self::member

115
MrZebra

$this-> é usado para se referir a uma instância específica de variáveis ​​de uma classe (variáveis ​​de membro) ou métodos.

Example: 
$derek = new Person();

$ derek é agora uma instância específica de Person. Cada Pessoa tem um first_name e um last_name, mas $ derek tem um first_name e last_name específico (Derek Martin). Dentro da instância $ derek, podemos nos referir a eles como $ this-> first_name e $ this-> last_name

ClassName :: é usado para se referir a esse tipo de classe e suas variáveis ​​estáticas, métodos estáticos. Se isso ajudar, você pode mentalmente substituir a palavra "static" por "shared". Por serem compartilhados, eles não podem se referir a $ this, que se refere a uma instância específica (não compartilhada). Variáveis ​​estáticas (ou seja, static $ db_connection) podem ser compartilhadas entre todas as instâncias de um tipo de objeto. Por exemplo, todos os objetos de banco de dados compartilham uma única conexão (conexão $ estática).

Variáveis ​​estáticas Exemplo: Fingir que temos uma classe de banco de dados com uma única variável de membro: static $ num_connections; Agora, coloque isso no construtor:

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

Assim como os objetos têm construtores, eles também têm destruidores, que são executados quando o objeto morre ou está indefinido:

function __destruct()
{
    $num_connections--;
}

Toda vez que criamos uma nova instância, ela aumenta nosso contador de conexões em um. Toda vez que destruirmos ou pararmos de usar uma instância, ela diminuirá o contador de conexões em um. Desta forma, podemos monitorar o número de instâncias do objeto de banco de dados que temos em uso com:

echo DB::num_connections;

Como $ num_connections é estático (compartilhado), ele refletirá o número total de objetos de banco de dados ativos. Você pode ter visto essa técnica usada para compartilhar conexões de banco de dados entre todas as instâncias de uma classe de banco de dados. Isso é feito porque a criação da conexão com o banco de dados é demorada, por isso é melhor criar apenas um, e compartilhá-lo (isso é chamado de Singleton Pattern).

Métodos estáticos (isto é, View :: format_phone_number público ($ digits)) podem ser usados ​​sem primeiro instanciar um desses objetos (ou seja, eles não se referem internamente a $ this).

Exemplo 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 você pode ver, a função estática pública prettyName não sabe nada sobre o objeto. Está apenas trabalhando com os parâmetros que você passa, como uma função normal que não faz parte de um objeto. Por que se preocupar, então, se pudéssemos apenas tê-lo como parte do objeto?

  1. Primeiro, anexar funções a objetos ajuda a manter as coisas organizadas, para que você saiba onde encontrá-las.
  2. Em segundo lugar, evita conflitos de nomes. Em um projeto grande, é provável que você tenha dois desenvolvedores criando funções getName (). Se alguém cria um ClassName1 :: getName (), e o outro cria ClassName2 :: getName (), não há problema algum. Sem conflito. Métodos estáticos!

SELF :: Se você está codificando outside o objeto que possui o método estático ao qual você quer se referir, você deve chamá-lo usando o nome do objeto View :: format_phone_number ($ phone_number); Se você está codificando inside o objeto que tem o método estático ao qual você quer se referir, você pode ou usar o nome do objeto View :: format_phone_number ($ pn), OR você pode usar o atalho self :: format_phone_number ($ pn)

O mesmo vale para variáveis ​​estáticas: Exemplo: View :: templates_path versus self :: templates_path

Dentro da classe DB, se estivéssemos nos referindo a um método estático de algum outro objeto, usaríamos o nome do objeto: Exemplo: Session :: getUsersOnline ();

Mas se a classe DB quisesse se referir à sua própria variável estática, ela apenas diria self: Exemplo: self :: connection;

Espero que ajude a esclarecer as coisas :)

96
lo_fye

De esta postagem do blog :

  • self refere-se à classe atual
  • self pode ser usado para chamar funções estáticas e referenciar variáveis ​​de membros estáticos
  • self pode ser usado dentro de funções estáticas
  • self também pode desativar o comportamento polimórfico ignorando o vtable
  • $this refere-se ao objeto atual
  • $this pode ser usado para chamar funções estáticas
  • $this não deve ser usado para chamar variáveis ​​de membro estático. Use self em vez disso.
  • $this não pode ser usado dentro de funções estáticas
29
okconfused

No PHP, você usa a palavra-chave self para acessar propriedades e métodos estáticos.

O problema é que você pode substituir $this->method() com self::method()nunca, se method() for declarado estático ou não. Então qual você deve 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();

Neste exemplo, self::who() sempre produzirá ‘parent’, enquanto $this->who() dependerá de qual classe o objeto possui.

Agora podemos ver que self refere-se à classe na qual ele é chamado, enquanto $this refere-se à classe do objeto atual .

Portanto, você só deve usar a pessoa quando $this não estiver disponível ou quando não quiser permitir que classes descendentes substituam o método atual.

25
ramin rostami

Dentro de uma definição de classe, $ this se refere ao objeto atual, enquanto self refere-se à classe atual.

É necessário referir-se a um elemento de classe usando self e referir-se a um elemento de objeto usando $ this.

self::STAT // refer to a constant value
self::$stat // static variable
$this->stat // refer to an object variable  
21
Tarun Singhal

Aqui está um exemplo de uso correto de $ this e self para variáveis ​​de membros estáticos e estáticos:

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

De acordo com http://www.php.net/manual/en/language.oop5.static.php não há $self. Há somente $this, para referir-se à instância atual da classe (o objeto), e self, que pode ser usado para se referir a membros estáticos de uma classe. A diferença entre uma instância de objeto e uma classe entra em jogo aqui.

20
cruizer

self refere-se à classe atual (na qual ele é chamado),

$this refere-se ao objeto atual. Você pode usar estática em vez de auto. Veja o exemplo:

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

Saída: filho pai

15
Kabir Hossain

Eu acredito que a questão não era se você pode chamar o membro estático da classe chamando ClassName::staticMember. A pergunta é qual é a diferença entre usar self::classmember e $this->classmember.

Por exemplo, os dois exemplos a seguir funcionam sem erros, quer você use self:: ou $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;
    }
}
14
dr evil

Como ninguém aqui falou sobre performances, aqui está uma pequena referência que eu fiz (5.6):

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

Esses são os resultados para 2 000 000 corridas e aqui está o código que usei:

<?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();
14
tleb
  • O ponteiro do objeto $ this refere-se ao objeto atual.
  • O valor da classe "static" refere-se ao objeto atual.
  • O valor da classe "self" refere-se à classe exata em que foi definido.
  • O valor da classe "pai" refere-se ao pai da classe exata em que foi definido.

Veja o exemplo a seguir, que mostra 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"

Na maioria das vezes você quer se referir à classe atual e é por isso que você usa static ou $this. No entanto, há momentos em que você precisa self porque você quer a classe original, independentemente do que estende. (Muito, muito raramente)

14
Xeoncross

Quando self é usado com o operador ::, ele se refere à classe atual, o que pode ser feito em contextos estáticos e não estáticos. $this refere-se ao próprio objeto. Além disso, é perfeitamente legal usar $this para chamar métodos estáticos (mas não para se referir a campos).

13
mrDjouk

$this refere-se ao objeto de classe atual, self se refere à classe atual (Not object). A classe é o plano do objeto. Então você define uma classe, mas você constrói objetos.

Então, em outras palavras, use self for static e this for none-static members or methods.

também no cenário pai/filho self / parent é usado principalmente para identificar membros e métodos da classe pai e filho.

7
Rakesh Singh

Além disso, $this:: ainda não foi discutido.

Apenas para fins informativos, como de PHP 5.3 ao lidar com objetos instanciados para obter o valor do escopo atual, ao invés de usar static::, pode-se alternativamente usar $this:: desta forma.

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 o código acima não é uma prática comum ou recomendada, mas é simplesmente ilustrar seu uso e é agir mais como um "Você sabia?" em referência à pergunta do autor original.

Também representa o uso de $object::CONSTANT por exemplo echo $foo::NAME; em oposição a $this::NAME;

7
fyrye

Eu me deparei com a mesma pergunta e a resposta simples é:

  • $ this requer uma instância da classe
  • self :: não

Sempre que você estiver usando métodos estáticos ou atributos estáticos e quiser chamá-los sem ter um objeto da classe instanciado você precisa usar self :: para chamá-los, porque $ this sempre requer que o objeto seja criado.

5
Mike

Use self se você quiser chamar um método de uma classe sem criar um objeto/instância dessa classe, salvando assim RAM (às vezes use self para essa finalidade). Em outras palavras, ele está realmente chamando um método estaticamente. Use this para a perspectiva do objeto.

5
minhajul

Caso 1: Use self pode ser usado para constantes de classe

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

Se você quiser chamá-lo fora da classe, use classA::POUNDS_TO_KILOGRAMS para acessar as constantes

Caso 2: para propriedades estáticas

 class classC {
 função pública __construct () {
 self :: $ _ counter ++; $ this-> num = self :: $ _ counter; 
} 
} 
2
li bing zhao

De acordo com o php.net, existem três palavras-chave especiais nesse contexto: self, parent e static. Eles são usados ​​para acessar propriedades ou métodos de dentro da definição de classe.

$this, por outro lado, é usado para chamar uma instância e métodos de qualquer classe, desde que essa classe esteja acessível.

1
Fil