Pregunta ¿Las variables globales en PHP se consideran malas prácticas? Si es así, ¿por qué?


function foo () {
    global $var;
    // rest of code
}

En mis pequeños proyectos de PHP usualmente sigo el procedimiento. Generalmente tengo una variable que contiene la configuración del sistema, y ​​cuando necesito acceder a esta variable en una función, lo hago global $var;.

¿Es esta mala práctica?


75
2017-10-13 01:19


origen


Respuestas:


Cuando la gente habla de variables globales en otros idiomas, significa algo diferente a lo que hace en PHP. Eso es porque las variables no son De Verdad global en PHP. El alcance de un programa PHP típico es una solicitud HTTP. Las variables de sesión en realidad tienen un alcance más amplio que las variables "globales" de PHP porque normalmente abarcan muchas solicitudes HTTP.

A menudo (¿siempre?) Puede llamar a las funciones miembro en métodos como preg_replace_callback() Me gusta esto:

preg_replace_callback('!pattern!', array($obj, 'method'), $str);

Ver devoluciones de llamada para más.

El punto es que los objetos se han atornillado a PHP y de alguna manera conducen a cierta incomodidad.

No se preocupe demasiado por aplicar estándares o construcciones de diferentes idiomas a PHP. Otro error común es tratar de convertir PHP en un lenguaje POO puro al poner modelos de objetos encima de todo.

Como cualquier otra cosa, use variables "globales", código de procedimiento, un marco particular y OOP porque tiene sentido, resuelve un problema, reduce la cantidad de código que necesita escribir o lo hace más fácil de mantener y entender, no porque piense debieras.


86
2017-10-13 01:22



Las variables globales si no se usan con cuidado pueden dificultar la búsqueda de problemas. Digamos que usted solicita un script php y recibe una advertencia que dice que está tratando de acceder a un índice de una matriz que no existe en alguna función.

Si la matriz a la que intenta acceder es local para la función, verifique la función para ver si cometió un error allí. Puede ser un problema con una entrada a la función para que pueda verificar los lugares donde se llama a la función.

Pero si ese conjunto es global, debe verificar todos los lugares donde usa esa variable global, y no solo eso, debe averiguar en qué orden se accede a esas referencias a la variable global.

Si tiene una variable global en un fragmento de código, dificulta aislar la funcionalidad de ese código. ¿Por qué querrías aislar la funcionalidad? Entonces puedes probarlo y reutilizarlo en otro lugar. Si tiene algún código que no necesita probar y no necesitará volver a usarlo, entonces usar variables globales está bien.


22
2017-10-13 03:34



Estoy de acuerdo con Cletus. Yo agregaría dos cosas:

  1. use un prefijo para poder identificarlo inmediatamente como global (por ejemplo, $ g_)
  2. declararlos en un lugar, no ir a rociarlos alrededor del código.

atentamente, don


15
2017-10-13 01:39



¿Quién puede argumentar en contra de la experiencia, los títulos universitarios y la ingeniería de software? Yo no. Solo diría que al desarrollar aplicaciones PHP de una sola página orientadas a objetos, me divierto más cuando sé que puedo construir todo desde cero sin preocuparme por las colisiones del espacio de nombres. Construir desde cero es algo que muchas personas ya no hacen. Tienen un trabajo, una fecha límite, una bonificación o una reputación de la que preocuparse. Estos tipos tienden a usar tanto código preconstruido con altas apuestas, que no pueden arriesgarse a usar variables globales en absoluto.

Puede ser malo usar variables globales, incluso si solo se usan en el área global de un programa, pero no nos olvidemos de aquellos que solo quieren Diviértete y haz que algo funcione.

Si eso significa usar algunas variables (<10) en el espacio de nombres global, eso solo se usa en el área global de un programa, que así sea. Sí, sí, MVC, inyección de dependencia, código externo, bla, bla, bla, bla. Pero, si ha contenido el 99.99% de su código en espacios de nombres y clases, y el código externo está en la zona de pruebas, el mundo no terminará (repito, el mundo no terminará) si usa una variable global.

En general, no diría que usar variables globales es mala práctica. Yo diría que usar variables globales (indicadores y demás) fuera del área global de un programa es pidiendo problemas y (a largo plazo) mal aconsejado porque puede perder la pista de sus estados con bastante facilidad. Además, yo diría que cuanto más aprendes, menos confiable serás en variables globales porque habrá experimentado la "alegría" de rastrear errores asociados con su uso. Esto solo lo incentivará a encontrar otra manera de resolver el mismo problema. Casualmente, esto tiende a empujar a las personas de PHP en la dirección de aprender a usar espacios de nombres y clases (miembros estáticos, etc.).

El campo de la informática es vasto. Si alejamos a todos de hacer algo porque lo etiquetamos malo, entonces pierden la diversión de comprender verdaderamente el razonamiento detrás de la etiqueta.

Use variables globales si es necesario, pero luego vea si puede resolver el problema sin ellas. Las colisiones, las pruebas y la depuración significan más cuando entiendes íntimamente la verdadera naturaleza del problema, no solo una descripción del problema.


4
2018-01-10 16:47



Como:

global $my_global; 
$my_global = 'Transport me between functions';
Equals $GLOBALS['my_global']

es una mala práctica (como Wordpress) $pagenow) ... hmmm

Concider esto:

$my-global = 'Transport me between functions';

es un error de PHP Pero:

$GLOBALS['my-global'] = 'Transport me between functions';

es NO error, hypens no chocará con variables declaradas por el usuario "común", como $pagenow. Y el uso de MAYÚSCULAS indica un superglobal en uso, fácil de detectar en el código, o rastrear con encontrar en archivos

Yo uso guiones, si soy perezoso para construir clases de todo para una única solución, como:

$GLOBALS['PREFIX-MY-GLOBAL'] = 'Transport me ... ';

Pero en los casos de un uso más amplio, yo uso UNO globales como matriz:

$GLOBALS['PREFIX-MY-GLOBAL']['context-something'] = 'Transport me ... ';
$GLOBALS['PREFIX-MY-GLOBAL']['context-something-else']['numbers'][] = 'Transport me ... ';

El último es para mí, buena práctica sobre los objetivos o el uso de "luz de cola", en lugar de saturar con clases de singleton cada vez para "almacenar en caché" algunos datos. Por favor, haga un comentario si estoy equivocado o me estoy perdiendo algo estúpido aquí ...


0
2017-10-17 05:03



Repostado de la documentación de SO finalizada Beta

Podemos ilustrar este problema con el siguiente pseudo-código

function foo() {
     global $bob;
     $bob->doSomething();
}

Su primera pregunta aquí es obvia

Donde lo hizo $bob ¿viene de?

¿Estas confundido? Bueno. Acabas de aprender por qué los globales son confusos y se consideran una mala práctica. Si esto fuera un programa real, lo próximo que se divierte es buscar todas las instancias de $boby espero que encuentres el correcto (esto empeora si $bob se usa en todas partes). Peor aún, si alguien más va y define $bob (o ha olvidado y reutilizado esa variable) su código puede romperse (en el ejemplo del código anterior, tener el objeto equivocado, o no tener ningún objeto, causaría un error fatal). Dado que prácticamente todos los programas PHP hacen uso de código como include('file.php'); su trabajo de mantenimiento de código como este se vuelve exponencialmente más difícil cuanto más archivos agregue.

¿Cómo evitamos Globals?

La mejor manera de evitar los globales es una filosofía llamada Inyección de dependencia. Aquí es donde pasamos las herramientas que necesitamos a la función o clase.

function foo(\Bar $bob) {
    $bob->doSomething();
}

Esto es mucho más fácil de entender y mantener No hay forma de adivinar dónde $bob se configuró porque la persona que llama es responsable de saber eso (nos está transmitiendo lo que necesitamos saber). Mejor aún, podemos usar tipo de declaraciones para restringir lo que se está pasando. Entonces sabemos que $bob es una instancia de Bar clase, o una instancia de un hijo de Bar, lo que significa que sabemos que podemos usar los métodos de esa clase. Combinado con un autocargador estándar (disponible desde PHP 5.3), ahora podemos buscar dónde Bar se define. PHP 7.0 o posterior incluye declaraciones de tipo expandido, donde también puede usar tipos escalares (como int o string)


-2
2017-08-24 00:21