Acceder a una variable global en una función PHP

83

De acuerdo con la mayoría de las reglas de alcance de los lenguajes de programación, puedo acceder a variables que están definidas fuera de las funciones dentro de ellas, pero ¿por qué no funciona este código?

<?php
    $data = 'My data';

    function menugen() {
        echo "[" . $data . "]";
    }

    menugen();
?>

La salida es [].

Amin Gholibeigian
fuente
3
No lo trate como global, páselo a la función como un argumento
Mark Baker
2
¿Dónde dice el manual tales cosas?
diciembre
Lectura relacionada: PHP global en funciones
Jocelyn
Consulte el segundo ejemplo en esta página: php.net/manual/en/language.variables.scope.php
Amin Gholibeigian
afaik podemos acceder usando $ GLOBALS ['varname'] donde el índice "varname" es $ varname fuera de la función. De hecho, podemos usar print_r ($ GLOBALS) para ver todas las variables globales.
Ahmad

Respuestas:

163

No está funcionando porque se tiene que declarar las variables globales podrás acceder a:

$data = 'My data';

function menugen() {
    global $data; // <-- Add this line

    echo "[" . $data . "]";
}

menugen();

De lo contrario, puede acceder a él como $GLOBALS['data']. Consulte Alcance variable .

Incluso si está un poco fuera de tema, le sugiero que evite el uso de globales y prefiera pasar como parámetros.

Matteo Tassinari
fuente
Gracias, tiene razón, pero no usaron esta línea en el segundo ejemplo del manual: php.net/manual/en/language.variables.scope.php
Amin Gholibeigian
6
De hecho, ese segundo ejemplo estaba allí para mostrar a los lectores lo que no deben hacer:This script will not produce any output because the echo statement refers to a local version of the $a variable, and it has not been assigned a value within this scope.
Matteo Tassinari
2
¡Maldita sea! Tuve que iniciar sesión para votar a favor de esta respuesta solo porque olvidé horriblemente el alcance de las variables php.
Milche Patern
19

Puede realizar una de las siguientes acciones:

<?php
    $data = 'My data';

    function menugen() {
        global $data;
        echo "[" . $data . "]";
    }

    menugen();

O

<?php
    $data = 'My data';

    function menugen() {
        echo "[" . $GLOBALS['data'] . "]";
    }

    menugen();

Dicho esto, el uso excesivo de globales puede generar un código deficiente. Por lo general, es mejor pasar lo que necesita. Por ejemplo, en lugar de hacer referencia a un objeto de base de datos global, debe pasar un identificador a la base de datos y actuar en consecuencia. Esto se llama inyección de dependencia . Le hace la vida mucho más fácil cuando implementa pruebas automatizadas (lo que debería).

jcbwlkr
fuente
12

Es una cuestión de alcance. En resumen, las variables globales deben evitarse para :

O debe pasarlo como parámetro:

$data = 'My data';

function menugen($data)
{
    echo $data;
}

O tenerlo en una clase y acceder a él

class MyClass
{
    private $data = "";

    function menugen()
    {
        echo this->data;
    }

}

Consulte la respuesta de @MatteoTassinari también, ya que puede marcarla como global para acceder a ella, pero las variables globales generalmente no son necesarias, por lo que sería prudente reconsiderar su codificación.

webnoob
fuente
y otra forma es utilizar la palabra clave global (concedido, esta no es la mejor forma).
Jocelyn
1
"Debería" no responde a la pregunta, y este puede no ser el mejor enfoque para todos los casos. Para scripts simples, cambiar parámetros y agregar clases es complicado. Al igual que en JavaScript, en PHP no todo debe estar orientado a objetos y tener un espacio de nombres en el wazoo.
Beejor
@Beejor Dado que el OP tiene una función llamada menugen(), implica que habrá más cosas que simplemente generar un menú. Por ejemplo, ¿qué hay de extender ese menú para agregar más elementos de una fuente diferente, qué hay de seleccionar la página actualmente seleccionada que está en el menú. Tener variables globales aleatorias y lógica por todas partes exige un diseño de programación orientada a objetos. El hecho de que PHP / JS no necesita estar estructurado es una de las principales razones por las que encuentra mucho código desordenado y torpe. Se puede hacer muy bien, pero permite que las personas no piensen en la mantenibilidad en el futuro.
webnoob
ps votar Abajo la respuesta también está un poco fuera de lugar. La respuesta proporciona una solución al problema del OP, solo porque no te gusta, no lo hace mal.
webnoob
1
@Beejor - El problema con ese argumento es que las personas podrían pensar que necesitan una variable global porque no saben nada mejor y no sabrán nada mejor a menos que se lo digan.
webnoob
10

Otra forma de hacerlo:

<?php

$data = 'My data';

$menugen = function() use ($data) {

    echo "[".$data."]";
};

$menugen();

ACTUALIZACIÓN 2020-01-13: solicitado por Peter Mortensen

A partir de PHP 5.3.0 tenemos soporte de funciones anónimas que pueden crear cierres. Un cierre puede acceder a la variable que se crea fuera de su alcance.

En el ejemplo, el cierre puede acceder $dataporque fue declarado en la usecláusula.

donvercety
fuente
Esta fue la única solución de trabajo en mi caso, donde tenía una función definida como una variable dentro de otra función. Global no funcionó allí.
Kar.ma
Una explicación estaría en orden. Por ejemplo, ¿qué hace esta cosa de "uso"? ¿En qué versiones de PHP se admite esta cosa de "uso"? (Responda editando su respuesta , no aquí en los comentarios (según corresponda). Gracias de antemano.)
Peter Mortensen
No sé por qué el ans aprobado no muestra ningún resultado en la página del complemento de administración de Wordpress, pero este ans funciona bien.
Naimur Hasan
3

Durante muchos años siempre he usado este formato:

<?php
    $data = "Hello";

    function sayHello(){
        echo $GLOBALS["data"];
    }

    sayHello();
?>

Lo encuentro sencillo y fácil de seguir. $ GLOBALS es la forma en que PHP le permite hacer referencia a una variable global. Si ha utilizado cosas como $ _SERVER, $ _POST, etc., entonces ha hecho referencia a una variable global sin saberlo.

Salmos Kalu
fuente
¿Cúal? $GLOBAL(texto) o $GLOBALS(código de muestra)? (Responda editando su respuesta , no aquí en los comentarios (según corresponda).)
Peter Mortensen
es $ GLOBALS no $ GLOBAL. Debe haber una "S". Luego, haga referencia a su nombre de variable como una clave para una matriz asociativa.
Salmos Kalu
Por favor, actualice su respuesta editándolo (para iniciar la edición , haga clic en " editar " , entre el "compartir" y "bandera" Los tres son de la izquierda -. A la izquierda de "editado" y "contestado" , después de la respuesta sí mismo, por encima de este comentario, y sobre los tres comentarios aquí). La información de los comentarios puede desaparecer en cualquier momento. Este no es un foro; la información puede (y debe) actualizarse aquí. Muchas gracias de antemano.
Peter Mortensen
0

Necesitas pasar la variable a la función:

$data = 'My data';

function menugen($data)
{
    echo $data;
}
Producciones importantes
fuente
0
<?php

    $data = 'My data';

    $menugen = function() use ($data) {

        echo "[ $data ]";
    };

    $menugen();
?>

También puedes simplificar

echo "[" . $data . "]"

a

echo "[$data]"
Sanjeev Budha
fuente
echo "[" . $data . "]"y echo "[ $data ]"no son iguales (dos espacios adicionales en la salida para este último).
Peter Mortensen
-1

Si lo desea, puede utilizar la función "definir", pero esta función crea una constante que no se puede cambiar una vez definida.

<?php
    define("GREETING", "Welcome to W3Schools.com!");

    function myTest() {
        echo GREETING;
    }

    myTest();
?>

Constantes PHP

Mohamad Hamouday
fuente
Esto define una constante global, no una variable.
Beejor
3
Las constantes no se pueden cambiar una vez definidas.
Beejor