ACTUALIZACIÓN: Mi pregunta original ha sido resuelta, pero esto se está convirtiendo en una discusión válida sobre por qué no usar variables globales, así que estoy actualizando la pregunta para reflejar eso. La solución fue <?php global $category_link_prop; echo esc_url( $category_link_prop ); ?>
como sugirió @TomJNowell.
ACTUALIZACIÓN 2: Ahora lo tengo haciendo exactamente lo que quería. Pero todavía estoy usando el alcance global y estaría feliz de encontrar una mejor manera.
Estoy tratando de configurar un montón de variables globales para que los enlaces permanentes a las categorías se usen en varios lugares de mi tema. La razón principal de esto es que se usa tanto en la navegación principal como en una serie de subnavegaciones que se eligen en función de la categoría en la que se encuentra la publicación actual. Esto no es un tema Lo lanzaré para que lo usen otros, pero está diseñado para un propósito muy específico.
Así es como los estoy creando actualmente (solo he pegado algunas de las variables).
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" );
Ahora puedo hacer <?php global $prop; echo $prop; ?>
en los 4 lugares que van y recuperar el enlace completo para el código. Cuando eso cambie, solo necesito cambiarlo en un lugar. Estoy abierto a alternativas que no involucran el alcance global.
Comentarios
- ¿Qué enlace hace eco esta declaración? Esc_url ($ category_link_prop); muestra ? ¿Cuál es su enlace esperado?
- ¿Por qué no usaría simplemente ‘ get_cat_ID (****) ‘ donde sea que planeó usar la variable global. Dudo que haya alguna ventaja de velocidad de la forma en que lo hace. Desde el punto de vista de la legibilidad, ‘ get_cat_ID (****) ‘ gana indiscutiblemente.
- ¿Puedes reformular? Leí tu pregunta y ‘ todavía no estoy seguro de lo que quieres hacer y por qué quieres hacerlo. Mi consejo general sería no usar variables globales y no contaminar el alcance global
- esto suena un poco como un Problema X / Y . Quizás debería hacer una copia de seguridad y explicar exactamente cuál es el resultado deseado. Yo ‘ estoy seguro de que aquí ‘ una solución mucho más elegante que configurar un grupo de variables globales para luego codificar referencias a ellas en un navegador en otro lugar
- crear una función que genere su menú según el contexto que le pase, de esa manera puede mantener toda la lógica del menú y las variables asociadas encapsuladas en un solo lugar.
Respuesta
Si bien desaconsejo esto, y no acelerará las cosas, su uso es incorrecto.
WordPress ya almacena estas cosas en el caché de objetos, no es necesario almacenar el resultado y reutilizarlo, WP ya lo hace .
¡Es muy probable que su código se esté ejecutando más lento como resultado de esta microoptimización, no más rápido!
Cómo usar Globals
Cuando intente utilizar un global, primero debe especificar la palabra clave global
. Lo ha especificado aquí al definir su valor, pero fuera de ese alcance debe volver a declararse como una variable de alcance global.
p. Ej. en functions.php
:
function test() { global $hello; $hello = "hello world"; } add_action( "after_setup_theme", "test" );
En single.php
, esto no funcionará:
echo $hello;
Porque $hello
no está definido. Sin embargo, esto funcionará :
global $hello; echo $hello;
Por supuesto que no debería hacer ninguna de las dos cosas. WordPress ya intenta almacenar en caché estas cosas en el caché de objetos .
Desventajas y peligros de las variables globales
No verá ningún aumento de velocidad al hacer esto (puede ver una pequeña disminución de velocidad), todo lo que obtendrá es complejidad adicional y la necesidad de escribir muchas declaraciones globales que no son necesarias.
También encontrará otros problemas:
- código para el que es imposible escribir pruebas
- código que se comporta de manera diferente cada vez que se ejecuta
- choques en nombres de variables de un espacio de nombres compartido
- errores accidentales por olvidar declarar
global
- una falta total de estructura al almacenamiento de datos de sus códigos
- y muchos más
¿Qué debería usar en su lugar?
Sería mejor que utilizara datos estructurados, como como objetos o inyección de dependencia, o en su caso, un conjunto de funciones.
Variables estáticas
Variables estáticas no son buenos, pero piense en ellos como el primo un poco menos malvado de las variables globales.Las variables estáticas son para variables globales, lo que el pan cubierto de barro es para cianuro.
Por ejemplo, aquí hay una forma de hacer algo similar a través de variables estáticas, por ejemplo
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 son como variables estáticas, excepto que la clase contiene una variable estática con una instancia de esa clase . Son tan malos como las variables globales, solo que con una sintaxis diferente. Evítalos.
WP_Cache, lo que intentaste hacer, pero WP ya lo hace
Si realmente quieres Ahorre tiempo almacenando los datos en algún lugar para reutilizarlos, considere usar el sistema WP_Cache
con wp_cache_get
, etc., por ejemplo,
$value = wp_cache_get( "hello" ); if ( false === $value ) { // not found, set the default value wp_cache_set( "hello", "world" ); }
Ahora el valor se almacenará en caché durante la duración de la solicitud de WordPress, se mostrará en las herramientas de depuración y si tiene un caché de objetos, «persistirá en todas las solicitudes
Nota al margen 1: Me gustaría señalar que algunas personas intentan conservar datos en variables globales a través de solicitudes, sin saber que así no es como funciona PHP . A diferencia de una aplicación de nodo, cada solicitud carga una copia nueva de la aplicación, que luego muere cuando se completa la solicitud. Por esta razón, las variables globales establecidas en una solicitud no sobreviven a la siguiente solicitud
Nota al margen 2: a juzgar por la pregunta actualizada, sus variables globales no le brindan ninguna ganancia de rendimiento. Debería generar el HTML como y cuando lo necesite y se ejecutará igual de rápido, quizás incluso un poquito más rápido. Esto es micro-optimización.
Comentarios
- Lo sé ‘ es un poco loco para usar alcance global, pero la mayoría, si no todas, estas variables se utilizarán en cada página. Estoy ‘ abierto a mejores ideas. Voy a editar la pregunta para aclarar un poco mi intención. Por cierto, funciona perfectamente bien cuando lo hago
<?php global $category_link_prop; echo esc_url( $category_link_prop ); ?>
según su sugerencia. ¡Gracias! - Ah, si mi solución funciona, ¿podría marcar como aceptada? Tus variables globales son tan rápidas como hacer la llamada original, puedes intentar usar funciones en su lugar para que no ‘ necesites escribir 2 líneas, mejor aún, un singleton, mejor aún, haga que todo eso sea dinámico y en una parte de la plantilla incluida a través de get_template_part
- Marcado como aceptado como lo que estoy haciendo ahora, aunque puedo seguir una de las estrategias que @MarkKaplun sugiere a continuación. Usar get_template_part () es una idea interesante, pero ‘ no estoy seguro de querer tener un directorio lleno de archivos cortos como ese …
- oooh no no, no ‘ no querría un archivo para cada categoría, ‘ solo querría el que toma el nombre de la categoría actual y lo usa . No deberías ‘ no tener que codificar nada, imagina la molestia de codificarlo todo
- Puse el código en mi child-functions.php que está activo. Pero no puedo acceder a la variable en un archivo php-include al que llamo desde una publicación » normal » generada por una base de datos. Por favor avíseme, ¿qué hago mal? (Lo defino como global, por supuesto.)
Respuesta
No use variables globales , así de simple.
¿Por qué no use globals
Porque el uso de globals dificulta el mantenimiento del software a largo plazo.
- Un se puede declarar en cualquier parte del código, o en ninguna parte, por lo tanto, no hay ningún lugar en el que puedas mirar instintivamente para encontrar algún comentario sobre para qué se usa el global
- Al leer el código, generalmente asumes que las variables son locales a la función y no entienden que cambiar su valor en una función podría tener un cambio en todo el sistema.
- Si no manejan la entrada, las funciones deben devolver el mismo valor / salida cuando se llaman con los mismos parámetros. El uso de globales en una función introduce parámetros adicionales que no se documentan en la declaración de la función .
- Los globales no tienen ninguna construcción de inicialización específica y, por lo tanto, nunca puede estar seguro de cuándo puede acceder al valor del global, y no obtiene ningún error al intentar acceder al global antes de la inicialización. .
- Alguien más (tal vez un complemento) podría usar globales con el mismo nombre, arruinando su código o usted arruinando su dependiendo del orden de inicialización.
El núcleo de WordPress tiene mucho mucho uso de los globales. Mientras intenta comprender cómo funcionan las funciones básicas como the_content
, de repente se da cuenta de que la variable $more
no es local sino global y necesita buscar por completo de los archivos principales para comprender cuándo se establece en verdadero.
Entonces, ¿qué se puede hacer cuando se intenta detener la copia & pegando varias líneas de código en lugar de almacenar el resultado de la primera ejecución en un global? Hay varios enfoques, funcional y OOP.
La función edulcorante. Es simplemente un contenedor / macro para guardar el copiar / pegar
// input: $id - the category id // returns: the foo2 value of the category function notaglobal($id) { $a = foo1($id); $b = foo2($a); return $b; }
Los beneficios son que ahora hay una documentación de lo que hace el anterior global, y usted tiene un punto obvio para depurar cuando el valor que se devuelve no es el esperado.
Una vez que tenga un edulcorante, es fácil almacenar en caché el resultado si es necesario (hágalo solo si descubre que esta función toma mucho tiempo para ejecutarse)
function notaglobal($id) { static $cache; if (!isset($cache)) { $a = foo1($id); $b = foo2($a); $cache = $b; } return $cache; }
Esto te da el mismo comportamiento de un global pero con la ventaja de tener una inicialización asegurada cada vez que accedes a él.
Puede tener patrones similares con OOP. Encuentro que la programación orientada a objetos generalmente no agrega ningún valor en complementos y temas, pero esta es una discusión diferente
class notaglobal { var latestfoo2; __constructor($id) { $a = foo1($id); $this->latestfoo2 = foo2($a) } } $v = new notaglobal($cat_id); echo $v->latestfoo2;
Este es un código más torpe, pero si tiene varios valores que le gustaría precalcular porque siempre se están utilizando, esto puede ser un camino a seguir. Básicamente, este es un objeto que contiene todos sus globales de una manera organizada. Para evitar hacer una instancia de este objeto (desea en una instancia, de lo contrario, vuelve a calcular los valores) es posible que desee utilizar un patrón singleton (algunas personas sostienen que es una mala idea, YMMV)
No me gusta acceder a un atributo de objeto directamente, por lo que en mi código se deformará un poco más
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);
Comentarios
- Por favor, no ‘ t grite . ¿Le importaría explicar por qué y proporcionar algún tipo de cita?
- Creo que no entendió la respuesta. Si no estuviera ‘ t tratando de hacer una optimización temprana almacenando valores en variables globales, su código habría funcionado. El grito se debe a que seguir los principios básicos de desarrollo de software establecidos es algo que ‘ t no se puede enfatizar lo suficiente. Las personas que no comprenden esos principios básicos (disponibles en su google local) no deben difundir el código en la red.
- En mi opinión, esta es una respuesta, las personas que vienen aquí desde google deberían ver que es una mala idea incluso pensar en usar globales de inmediato.
- No es suficiente ‘ decir que no hagas X, tienes que explicar por qué o te pareces a ‘ lo digo por capricho
- @TomJNowell, me parece gracioso que yo fuera el único que rechazó la pregunta, ya que obviamente estaba fuera del alcance de WASE. No ‘ no vi el valor de expandir un tema que no debería haber comenzado aquí en absoluto.
Respuesta
Su pregunta está relacionada con cómo funciona php.
Tome $ wpdb como ejemplo
$ wpdb es una variable global muy conocida.
¿Sabe cuándo se declarará y se le asignarán valores?
Cada página cargada , sí, cada vez que visita su sitio de wordpress.
De manera similar, debe asegurarse de que las variables que desea globalizar se declaren y se les asignen los valores correspondientes en cada página cargada.
Aunque no soy un diseñador de temas, puedo decir que after_setup_theme es uno gancho de tiempo. sólo se activará cuando se active el tema.
Si fuera usted, usaría init u otros ganchos. No, si yo fuera usted, no usaría variables globales en absoluto …
Realmente no soy bueno para explicar las cosas. Por lo tanto, debe elegir un libro si desea profundizar en PHP.
Respuesta
Siempre puede usar un patrón singleton a través de captadores 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