Como definir e usar variáveis globais? Ou por que não usá-los

ATUALIZAÇÃO: Minha pergunta original foi resolvida, mas isso está se transformando em uma discussão válida sobre por que não usar variáveis globais, então estou atualizando a pergunta para refletir isso. A solução foi <?php global $category_link_prop; echo esc_url( $category_link_prop ); ?> como @TomJNowell sugeriu.

ATUALIZAÇÃO 2: Agora faço exatamente o que eu queria. Mas ainda estou usando o escopo global e ficaria feliz em encontrar uma maneira melhor.

Estou tentando configurar um monte de variáveis globais para os permalinks para categorias a serem usados em vários lugares no meu tema. A principal razão para isso é para uso na navegação principal, bem como em uma série de subnavegações que são escolhidas com base na categoria em que a postagem atual está. Este não é um tema Estarei lançando para uso por outros, mas foi construído para um propósito muito específico.

É assim que estou criando eles (colei apenas algumas das variáveis).

function set_global_nav_var() { //proposal global $prop; // Get the ID of a given category $category_id_prop = get_cat_ID( "proposal" ); // Get the URL of this category $category_link_prop = get_category_link( $category_id_prop ); $prop = "<a href="" .esc_url( $category_link_prop ). "" title="Proposal">Proposal</a>"; //Calvinball global $cb; // Get the ID of a given category $category_id_cb = get_cat_ID( "calvinball" ); // Get the URL of this category $category_link_cb = get_category_link( $category_id_cb ); $cb = "<a href="" .esc_url( $category_link_cb). "" title="Calvinball">Calvinball</a>"; } add_action( "init", "set_global_nav_var" ); 

Agora posso fazer <?php global $prop; echo $prop; ?> nos 4 lugares que vai e volta todo o link para o código. Quando isso muda, eu só preciso mudar em um lugar. Estou aberto a alternativas que não envolvem o escopo global.

Comentários

  • Qual link esta declaração echo esc_url ($ category_link_prop); exibe ? Qual é o seu link esperado?
  • Por que você não usaria apenas ‘ get_cat_ID (****) ‘ onde quer que você planejou usar a variável global. Duvido que haja qualquer vantagem de velocidade na forma como você está fazendo isso. Do ponto de vista da legibilidade, ‘ get_cat_ID (****) ‘ ganha com facilidade.
  • Você pode reformular? Eu li sua pergunta e ‘ ainda não tenho certeza do que você deseja fazer e por que deseja fazê-lo. Meu conselho geral seria não usar variáveis globais e não poluir o escopo global
  • isso está soando um pouco como um Problema X / Y . talvez você deva fazer um backup e explicar exatamente qual é o resultado desejado. I ‘ m certeza t aqui ‘ é uma solução muito mais elegante do que definir um monte de vars globais para então apenas codificar as referências a eles em um nav em outro lugar
  • criar uma função que produza seu menu com base no contexto que você passa para ele, dessa forma você pode manter toda a lógica do menu e vars associados encapsulados em um só lugar.

Resposta

Embora eu desaconselhe veementemente isso e não acelere as coisas, seu uso é incorreto.

O WordPress já armazena essas coisas no cache de objetos, você não precisa armazenar o resultado e reutilizar, o WP já faz isso .

É muito provável que seu código esteja mais lento como resultado dessa micro-otimização, não mais rápido!

Como usar globais

Ao tentar usar um global, você deve especificar a palavra-chave global primeiro. Você o especificou aqui ao definir seu valor, mas fora desse escopo, ele precisa ser declarado novamente como uma variável de escopo global.

por exemplo, em functions.php:

  function test() { global $hello; $hello = "hello world"; } add_action( "after_setup_theme", "test" );  

Em single.php, isso não funcionará:

  echo $hello;  

Porque $hello é indefinido. No entanto, funcionará:

  global $hello; echo $hello;  

Claro que você não deve fazer nenhum dos dois. O WordPress já tenta armazenar essas coisas no cache de objetos .

Desvantagens e perigos das variáveis globais

Você não verá nenhum aumento na velocidade ao fazer isso (você poderá ver uma pequena diminuição na velocidade), tudo o que obterá é uma complexidade adicional e a necessidade de digitar muitas declarações globais que não são necessárias.

Você também encontrará outros problemas:

  • código para o qual é impossível escrever testes
  • código que se comporta de maneira diferente toda vez que é executado
  • conflitos em nomes de variáveis de um espaço de nome compartilhado
  • bugs acidentais por se esquecer de declarar global
  • uma completa falta de estrutura para seu armazenamento de dados de códigos
  • e muitos mais

O que você deve usar em vez disso?

Seria melhor usar dados estruturados, como como objetos ou injeção de dependência, ou no seu caso, um conjunto de funções.

Variáveis estáticas

Variáveis estáticas não são bons, mas pense neles como os primos um pouco menos perversos das variáveis globais.Variáveis estáticas estão para variáveis globais, o que o pão coberto de lama está para cianeto.

Por exemplo, aqui está um meio de fazer algo semelhante por meio de variáveis estáticas, por exemplo,

  function awful_function( $new_hello="" ) { static $hello; if ( !empty( $new_hello ) ) { $hello = $new_hello; } return $hello; } awful_function( "telephone" ); echo awful_function(); // prints telephone awful_function( "banana"); echo awful_function(); // prints banana  

Singletons

Singletons são como variáveis estáticas, exceto que a classe contém uma variável estática com uma instância dessa classe . Eles são tão ruins quanto as variáveis globais, apenas com sintaxe diferente. Evite-os.

WP_Cache, a coisa que você tentou fazer, mas o WP já o faz

Se você realmente deseja economize tempo armazenando dados em algum lugar para reutilizar, considere usar o sistema WP_Cache com wp_cache_get etc., por exemplo,

 $value = wp_cache_get( "hello" ); if ( false === $value ) { // not found, set the default value wp_cache_set( "hello", "world" ); }  

Agora, o valor será armazenado em cache durante toda a duração da solicitação do WordPress, será exibido nas ferramentas de depuração e se você tiver um cache de objeto, ele “persistirá em todas as solicitações


Nota lateral 1: Eu observaria que algumas pessoas tentam persistir dados em variáveis globais entre solicitações, sem saber que não é assim que o PHP funciona . Ao contrário de um aplicativo Node, cada solicitação carrega uma nova cópia do aplicativo, que morre quando a solicitação é concluída. Por esta razão, as variáveis globais definidas em uma solicitação não sobrevivem à próxima solicitação

Nota lateral 2: Julgando pela pergunta atualizada, suas variáveis globais não proporcionam nenhum ganho de desempenho. Você deve apenas gerar o HTML como e quando precisar e ele será executado com a mesma rapidez, talvez até um pouco mais rápido. Isso é microotimização.

Comentários

  • Eu sei ‘ um pouco de nozes para usar o escopo global, mas a maioria, senão todas essas variáveis serão usadas em todas as páginas. Eu ‘ estou aberto a ideias melhores. Vou editar a pergunta para tornar minha intenção um pouco mais clara. BTW, funciona perfeitamente bem quando eu faço <?php global $category_link_prop; echo esc_url( $category_link_prop ); ?> de acordo com sua sugestão. Obrigado!
  • Ah, se minha solução funcionar, você poderia marcar como aceita? Suas variáveis globais são tão rápidas quanto fazer a chamada original, você pode tentar usar funções para não ‘ precisar digitar 2 linhas, melhor ainda, um singleton, melhor ainda, torne tudo isso dinâmico e em uma parte do modelo incluída via get_template_part
  • Marcado como aceito como é o que estou fazendo agora, embora possa ir com uma das estratégias que @MarkKaplun está sugerindo abaixo. Usar get_template_part () é uma ideia interessante, mas eu ‘ não tenho certeza se quero ter um diretório cheio de arquivos curtos como esse …
  • oooh não não, você não ‘ quer um arquivo para cada categoria, você ‘ d quer apenas aquele que pega o nome da categoria atual e usa isso . Você não deve ‘ ter que codificar nada, imagine o incômodo de codificar tudo permanentemente
  • Eu coloquei o código em meu child-functions.php que está ativo. Mas não consigo acessar a variável em um arquivo php-include que chamo de uma postagem ” normal ” gerada pelo banco de dados. Por favor me avise, o que eu faço de errado? (Eu o defino como global, é claro.)

Resposta

Não use variáveis globais , tão simples quanto isso.

Por que não use globais

Porque o uso de globais torna mais difícil manter o software a longo prazo.

  • Um global pode ser declarado em qualquer lugar do código, ou em nenhum lugar, portanto, não há nenhum lugar onde você possa olhar instintivamente para encontrar algum comentário sobre para que o global é usado
  • Ao ler o código, você geralmente assume que variáveis são locais para a função e não entendem que mudar seu valor em uma função pode ter uma mudança em todo o sistema.
  • Se elas não tratam de entrada, as funções devem retornar o mesmo valor / saída quando são chamados com os mesmos parâmetros. O uso de globais em uma função introduz parâmetros adicionais que não estão documentados na declaração da função .
  • globais não têm nenhuma construção de inicialização específica e, portanto, você nunca pode ter certeza de quando pode acessar o valor do global e não obtém nenhum erro ao tentar acessar o global antes da inicialização .
  • Outra pessoa (um plugin talvez) pode usar globais com o mesmo nome, estragando seu código, ou você estragando-o dependendo da ordem de inicialização.

O núcleo do WordPress tem maneira muito muito uso de globais. Ao tentar entender como funções básicas como the_content funcionam, você de repente percebe que a variável $more não é local, mas global e precisa pesquisar todo dos arquivos principais para entender quando é definido como verdadeiro.

Então, o que pode ser feito ao tentar parar de copiar & e colar várias linhas de código em vez de armazenar o resultado da primeira execução em um global? Existem várias abordagens, funcionais e OOP.

A função adoçante. É simplesmente um wrapper / macro para salvar o copiar / colar

// input: $id - the category id // returns: the foo2 value of the category function notaglobal($id) { $a = foo1($id); $b = foo2($a); return $b; } 

Os benefícios são que agora há uma documentação sobre o que o antigo global faz, e você tem um ponto óbvio para depuração quando o valor que está sendo retornado não é o que você espera.

Uma vez que você tenha um adoçante, é fácil armazenar o resultado em cache, se necessário (faça isso apenas se descobrir que esta função funciona muito tempo para executar)

function notaglobal($id) { static $cache; if (!isset($cache)) { $a = foo1($id); $b = foo2($a); $cache = $b; } return $cache; } 

Isso oferece o mesmo comportamento de um global, mas com a vantagem de ter uma inicialização garantida toda vez que você acessá-lo.

Você pode ter padrões semelhantes com OOP. Acho que OOP geralmente não adiciona nenhum valor em plug-ins e temas, mas esta é uma discussão diferente

class notaglobal { var latestfoo2; __constructor($id) { $a = foo1($id); $this->latestfoo2 = foo2($a) } } $v = new notaglobal($cat_id); echo $v->latestfoo2; 

Este é um código mais desajeitado, mas se você tem vários valores que você gostaria de pré-calcular porque eles estão sempre sendo usados, este pode ser um caminho a percorrer. Basicamente, este é um objeto que contém todos os seus globais de forma organizada. Para evitar que uma instância deste objeto seja global (você quer uma instância, caso contrário, você recalcula os valores), você pode querer usar um padrão singleton (algumas pessoas argumentam que é uma má ideia, YMMV)

Não gosto de acessar um atributo de objeto diretamente, então em meu código ele irá distorcer um pouco mais

class notaglobal { var latestfoo2; __constructor() {} foo2($id) { if (!isset($this->latestfoo2)) { $a = foo1($id); $b = foo2($a); $this->latestfoo2= $b; } return $this->latestfoo2; } } $v = new notaglobal(); echo $v->foo2($cat_id); 

Comentários

  • Por favor, não ‘ grite . Importa-se de explicar por que e fornecer algum tipo de citação?
  • Acho que você entendeu mal a resposta. Se ele não estivesse ‘ tentando fazer uma otimização inicial, armazenando valores em variáveis globais, seu código teria funcionado. A gritaria é porque seguir os princípios básicos de desenvolvimento de software é algo que não pode ‘ ser enfatizado o suficiente. Pessoas que não entendem esses princípios básicos (disponíveis em seu google local) não devem espalhar código pela rede.
  • IMO, esta é uma resposta, as pessoas que vêm aqui do google devem ver que é uma má ideia até mesmo pensar em usar globais imediatamente.
  • Não ‘ não é suficiente dizer não faça X, você tem que explicar por que ou você se parece com você ‘ estou dizendo por capricho
  • @TomJNowell, acho engraçado que eu tenha sido o único a votar contra a própria pergunta, já que estava obviamente fora do escopo de WASE. Não ‘ não vi o valor de se expandir sobre um assunto que não deveria ter sido iniciado aqui.

Resposta

Sua pergunta está relacionada ao funcionamento do php.

Pegue $ wpdb como exemplo

$ wpdb é uma variável global conhecida.

Você sabe quando ela será declarada e atribuída com valores?

Cada página carregada , sim, sempre que você visita seu site wordpress.

Da mesma forma, você precisa ter certeza de que as variáveis que deseja globalizar serão declaradas e atribuídas com os valores correspondentes a cada página carregada.

Embora eu não seja um designer de tema, posso dizer que after_setup_theme é um gancho de tempo. ele só será acionado quando o tema for ativado.

Se eu fosse você, usaria o init ou outros ganchos. Não, se eu fosse você, não usaria variáveis globais …

Eu realmente não sou bom em explicar as coisas. Portanto, você deve pegar um livro se quiser se aprofundar em PHP.

Resposta

Você sempre pode usar um padrão singleton via getters estáticos.

<ul> <li><?php echo MyGlobals::get_nav_prop( "proposal" )[ "html" ]; ?></li> <li><?php echo MyGlobals::get_nav_prop( "calvinball", "html" ); ?></li> </ul> <?php if ( ! class_exists("MyGlobals") ): class MyGlobals { public $props; public function __construct(){ $this->props = array ( "proposal" => array( "title" => "Proposal", "text" => "Proposal" ), "calvinball" => array( "title" => "Calvinball", "text" => "Calvinball" ), ); } public function get_nav_prop ( $term, $prop = false ) { $o = self::instance(); if ( ! isset( $o->props[$term] ) ) { return falst; } if ( ! isset( $o->props[$term][ "html" ] ) ) { $id = get_cat_ID( $term ); $link = esc_url ( get_category_link( $id ) ); $title = $o->props[$term]["title"]; $text = $o->props[$term]["text"]; $o->props[$term]["html"] = "<a href="".$link."" title="".$title."">".$text."</a>"; $o->props[$term]["link"] = $link; $o->props[$term]["id"] = $id; } if($prop){ return isset($o->props[$term][$prop]) ? $o->props[$term][$prop] : null; } return $o->props[$term]; } // ------------------------------------- private static $_instance; public static function instance(){ if(!isset(self::$_instance)) { self::$_instance = new MyGlobals(); } return self::$_instance; } } endif; // end MyGlobals 

Deixe uma resposta

O seu endereço de email não será publicado. Campos obrigatórios marcados com *