garotosopa

Pequena utilidade para variáveis estáticas

Publicado em PHP por garotosopa em Setembro 9, 2009

Finalmente, depois de muitos anos, achei que tivesse encontrado uma situação em que variáveis estáticas seriam úteis para mim no PHP.

A diferença da variável estática em uma função é que ela não perde o seu valor quando a execução deixa o seu escopo. Isto é, na próxima vez que a função for executada, a variável terá o mesmo valor que tinha na execução anterior.

Nunca tinha achado muita utilidade pra isso, até porque geralmente as variáveis locais de um método realmente tinham o tempo de vida de cada execução. Quando não, fazia mais sentido utilizar uma propriedade da classe.

Até que recentemente surgiu a necessidade de executar um método que consultava o banco de dados dezenas de vezes em uma única requisição, alterando apenas o parâmetro da query.

Como consultar o banco uma única vez não era viável neste caso, um raciocínio que segui para tentar poupar um pouco o servidor foi efetuar o prepare somente 1 vez para cada query. E aí entrou a variável estática, guardando o resultado do prepare para execuções futuras, na mesma requisição.

<?php
class TrechoDaMinhaClasse {
    public function consultarAlgo($id) {
        static $prepare;
 
        if ( ! $prepare ) {
            $prepare = $this->db->prepare('
                SELECT id, descricao, peso
                FROM minhatabela
                WHERE id = :0
            ');
        }
 
        $rs = $this->db->execute($prepare, array($id));
        
        return new GradeCurricular($rs->fetchRow());
    }
}

Dessa forma, a partir da segunda vez que o método for chamado, ele executa direto o prepared statement com o id que deve ser consultado, sem ter que fazer o prepare de novo.

Para minha surpresa, fazendo um benchmark simples hoje (meses depois de implementar com static, assumindo que seria mais rápido), percebi que poupar o prepare no Oracle não fez muita diferença. Pelo visto o Oracle percebe que é a mesma query e não prepara novamente, ou simplesmente fazer o prepare é tão simples que não faz diferença economizar.

Sendo assim, parece que a pequena utilidade que eu tinha dado a variáveis estáticas não me serviu de nada. Estou apresentando o resultado aqui porque, bem… “Negative results are still results. Even 20 thousand of them”.

Pelo visto vou ficar sem ter utilidade para variáveis estáticas. A não ser que você tenha outros relatos positivos :)

Etiquetado como:

6 Respostas

Subscreva aos comentários comRSS.

  1. Pedro Guedes disse, em Setembro 9, 2009 às 7:09 pm


    class Pedido {
    protected $items;

    function getItems()
    {
    static $loaded;

    if ( ! $loaded ) {

    // Carrega os items do banco

    $loaded = true;

    }

    return $this->items;
    }
    }

  2. garotosopa disse, em Setembro 9, 2009 às 7:31 pm

    Nesse caso não seria mais fácil checar direto if ( ! $this->items ) ?

    Assim não precisa de uma flag estática pra determinar se já foi carregado, e fica até mais parecido com lazy load que se vê por aí.

  3. Willian disse, em Outubro 23, 2009 às 8:48 am

    Se você criasse uma classe para gerar CSS, por exemplo, existiria um método para adicionar o CSS na página. Adicionar o CSS mais de uma vez não é interessante, então você poderia utilizar uma variável estática. Quando o CSS fosse inserido, você adicionaria um valor na variável estática. Se você tentasse adicionar esse mesmo CSS novamente, isso não seria possível, já que você verificaria o valor desta variável estática.
    Valeu.

  4. Anderson Fraga disse, em Outubro 26, 2009 às 4:36 pm

    Preciso ter um controle de que certas funções serão executadas somente uma única vez:

    function unique($foo) {
    static $counter = 0;

    if($counter++ > 1) {
    die(‘ops’);
    }

    // continue…
    }

  5. Anderson Fraga disse, em Outubro 26, 2009 às 4:37 pm

    Ops, ali seria

    function unique($foo) {
    static $counter = 0;

    if($counter++ > 0) {
    die(‘ops’);
    }

    // continue…
    }

  6. garotosopa disse, em Outubro 27, 2009 às 8:40 am

    Pra mim, mesmo que de uma forma diferente, cai no mesmo critério do porquê eu prefiro não usar singleton.

    Acho que a responsabilidade de ser singleton, ou no seu caso de controlar o limite de chamadas à função, está fora do escopo da função em si, isso faz faz parte do universo do sistema e não do pequeno pedaço que a função deveria controlar.

    Preferia que outra parte do código controlasse este limite e que a função agisse normalmente – até pra testar a função seria mais fácil.


Deixe uma resposta