Um método ou propriedade static pertence à própria classe e não a um objeto. Você chama um método estático com ClassName::method() e lê uma propriedade estática com ClassName::$property, sem criar um objeto antes. Dentro da classe, self:: se refere aos mesmos membros.
Não há new Temperature() em lugar nenhum. Membros estáticos são úteis para funções auxiliares que não precisam de estado de objeto (conversões, fábricas, validação) e para dados que pertencem à classe como um todo, como um contador.
Propriedades estáticas são compartilhadas por todos os objetos
Uma propriedade normal tem um valor por objeto. Uma propriedade estática tem um valor para a classe inteira, então todos os objetos veem o mesmo. Aqui cada novo User incrementa um contador compartilhado e recebe o próximo ID:
Repare no $ em self::$nextId: propriedades estáticas o mantêm depois do ::, enquanto constantes (self::MAX) não. Uma propriedade estática vive só durante uma requisição PHP. Num site típico (PHP-FPM ou Apache), ela recomeça a cada carregamento de página, então não é lugar para guardar dados entre visitantes.
Métodos estáticos não têm $this
Um método estático roda sem objeto, então $this não existe dentro dele. Um método estático pode chamar outros métodos estáticos com self::, mas não pode ler propriedades normais. Chamar um método normal de forma estática também falha:
A direção oposta funciona: um método normal pode chamar métodos estáticos, como withSeparator() faz com self::make().
self ou static: late static binding
self:: aponta para a classe onde o código está escrito. static:: aponta para a classe em que o método foi chamado em tempo de execução. A diferença só aparece com herança, e importa mais em métodos de fábrica:
Post::createWithSelf() retorna um Model, o que quase nunca é o que quem chamou queria. static aponta para Post porque essa é a classe citada na chamada; o PHP chama isso de late static binding. Use static:: e new static() em métodos feitos para ser herdados, e self:: quando você realmente quer dizer esta classe exata. A mesma regra vale para constantes: static::TABLE pega o TABLE próprio de uma filha, enquanto self::TABLE sempre lê o da classe onde o código está escrito.
Propriedades estáticas herdadas são compartilhadas
Uma classe filha compartilha a propriedade estática da classe pai, a menos que declare a sua. Essa é a surpresa clássica do static: duas subclasses contando no mesmo número.
Apples não tem um $count próprio, então Apples::$count é Counter::$count, e os dois imprimem 2. Pears redeclara a propriedade e conta sozinha. Uma propriedade estática declarada numa trait se comporta de outro jeito: cada classe que usa a trait recebe uma cópia separada.
Variáveis estáticas dentro de funções
static tem um segundo significado dentro do corpo de uma função: uma variável estática mantém o valor entre as chamadas. O valor inicial só é atribuído na primeira vez que a função roda:
O segundo slowSquare(12) pula o cálculo. Como as propriedades estáticas, esses valores recomeçam no fim de cada requisição. A página sobre variáveis explica o escopo de variáveis em geral.
Quando static é a escolha errada
Métodos estáticos são práticos, e isso os torna fáceis de usar demais. Uma classe cujos métodos todos leem e escrevem propriedades estáticas é estado global com um nome de classe: todos que chamam o compartilham, testes não conseguem uma cópia nova, e você não consegue trocar por outra implementação.
Bons usos de static: funções auxiliares puras sem estado (Slug::make()), construtores com nome (Color::fromHex()) e constantes da classe. Se um método precisa de dados que podem ser diferentes entre dois usos, ele quer um objeto.
Perguntas frequentes
Como chamo um método estático no PHP?
Com o nome da classe e ::: MathHelper::square(4). Dentro da mesma classe, use self::square(4) ou static::square(4). Não é preciso objeto, e dentro de um método estático não existe $this.
Qual a diferença entre self e static no PHP?
self:: sempre significa a classe onde o código está escrito. static:: significa a classe em que o método foi de fato chamado, que pode ser uma classe filha; isso se chama late static binding. Então, no método create() de uma classe pai, new self() sempre cria a classe pai, enquanto new static() cria a filha que o chamou.
O que é uma propriedade estática no PHP?
Uma propriedade declarada public static int $count = 0; pertence à classe, então há um único valor compartilhado por todos os objetos dessa classe (e das filhas, a menos que uma filha a redeclare). Leia e escreva com ClassName::$count ou self::$count; repare no $.
Posso chamar um método estático num objeto no PHP?
Sim. $obj->square(4) e $obj::square(4) chamam o método estático da classe do objeto, mas ainda não há $this dentro dele. Chamar um método não estático como ClassName::method() é a direção que falha: desde o PHP 8 lança um Error.
Posso usar $this num método estático?
Não. Um método estático roda sem objeto, então $this não está definido ali e usá-lo lança um Error ("Using $this when not in object context"). Use self:: ou static:: para alcançar outros membros estáticos.