80 votos

Global en funciones PHP

¿Cuál es la utilidad de la palabra clave global?

¿Hay razones para preferir un método a otro?

  • De seguridad?
  • El rendimiento?
  • ¿Algo más?

Método 1:

function exempleConcat($str1, $str2)
{
  return $str1.$str2;
}

Método 2:

function exempleConcat()
{
  global $str1, $str2;
  return $str1.$str2;
}

¿Cuándo tiene sentido utilizar global?

Para mí, es que parece ser peligroso... pero puede ser sólo una falta de conocimiento. Estoy interesado en el documentado (por ejemplo, con el ejemplo de código, enlace a documentación...) por razones técnicas.

Gracias de antemano!


Recompensa

Esta es una buena pregunta general sobre el tema, yo (@Gordon) estoy ofreciendo una recompensa a obtener respuestas. Si su respuesta es en acuerdo con la mía o le da un punto de vista diferente, no importa. Desde la global tema viene cada ahora y entonces, podríamos utilizar una buena "canónica" respuesta a link.

130voto

Gordon Puntos 156415

Globals son malos

Esto es cierto para la global de palabras clave así como todo lo demás que llega desde el ámbito local al ámbito global (estática, los únicos, los registros, las constantes). Usted no quiere hacer uso de ellos. Una llamada de función no debería tener que depender de algo externo, por ejemplo,

function fn()
{
    global $foo;              // never ever use that
    $a = SOME_CONSTANT        // do not use that
    $b = Foo::SOME_CONSTANT;  // do not use that unless self::
    $c = $GLOBALS['foo'];     // incl. any other superglobal ($_GET, …)
    $d = Foo::bar();          // any static call, incl. Singletons and Registries
}

Todos estos harán de su código de depender del exterior. Lo cual significa que usted tiene que saber el total global del estado de tu aplicación antes fiable puede llamar a cualquiera de estos. La función no puede existir sin ese entorno.

El uso de las superglobales puede que no sea una evidente falla, pero si usted llama a su código desde una Línea de Comandos, usted no tiene $_GET o $_POST. Si el código se basa en las aportaciones de éstos, se están limitando a un entorno web. Sólo resumen de la solicitud en un objeto y utilizar en su lugar.

En caso de acoplamiento codificados los nombres de clases (estática, constantes), su función no puede existir sin que la clase esté disponible. Eso es un problema menor cuando las clases desde el mismo espacio de nombres, pero cuando se inicia la mezcla de diferentes espacios de nombres, está creando una maraña.

La reutilización es severamente obstaculizada por todo lo anterior. Así es la unidad de pruebas.

Asimismo, su función de firmas están mintiendo cuando a la par de ámbito global

function fn()

es un mentiroso, porque sostiene que puedo llamar a esa función sin pasar nada. Es sólo cuando me miro en el cuerpo de la función que tengo que aprender que tengo para el medio ambiente en un determinado estado.

Si su función requiere argumentos para ejecutar, hacerlas explícitas y pasar en:

function fn($arg1, $arg2)
{
    // do sth with $arguments
}

nos transmite claramente a partir de la firma de lo que se requiere para ser llamado. No es dependiente sobre el medio ambiente a estar en un estado específico. Usted no tiene que hacer

$arg1 = 'foo';
$arg2 = 'bar';
fn();

Es una cuestión de tirar en el mundial (palabra clave) vs presión (argumentos). Cuando usted empuje en o inyectar las dependencias, la función no se basan en el exterior ya. Cuando usted haga fn(1) de no disponer de una variable que contiene de 1 a algún lugar en el exterior. Pero cuando se tire en global $one dentro de la función, a la par de ámbito global y esperan que tenga una variable que se define en algún lugar. La función no es independiente de la de entonces.

Peor aún, cuando el cambio de variables globales dentro de la función, el código rápidamente ser totalmente incomprensible, porque sus funciones están teniendo efectos colaterales en todo el lugar.

En la falta de un ejemplo mejor, considere la posibilidad de

function fn()
{
    global $foo;
    echo $foo;     // side effect: echo'ing
    $foo = 'bar';  // side effect: changing
}

Y, a continuación, haga

$foo = 'foo';
fn(); // prints foo
fn(); // prints bar <-- WTF!!

No hay manera de ver que $foo fue cambiado de estas tres líneas. ¿Por qué llamar a la misma función con los mismos argumentos, todos de un cambio repentino de su salida o cambiar un valor en el estado global? Una función debe hacer X para una determinada entrada Y. Siempre.

Esto se torna aún más grave cuando se utiliza la programación orientada a objetos, debido a que la programación orientada a objetos es acerca de encapsulación y por llegar a un ámbito global, se están rompiendo la encapsulación. Todos estos embarazos Únicos y Registros que ve en marcos código de olores que debe ser eliminado en favor de la Inyección de Dependencia. Separar el código.

Más Recursos:

31voto

deceze Puntos 200115

La gran razón en contra de la global es que significa que la función depende de otro ámbito. Esto va a causar problemas muy rápidamente.

$str1 = 'foo';
$str2 = 'bar';
$str3 = exampleConcat();

frente

$str = exampleConcat('foo', 'bar');

Que requieren $str1 y $str2 que se establezcan en el ámbito de la llamada de la función de trabajo significa que introducir dependencias innecesarias. Usted no puede cambiar el nombre de estas variables en este ámbito más sin tener que cambiar de nombre en la función, así, y así también en todos los otros ámbitos que usted está usando esta función. Esto pronto se convirtiera en un caos cuando usted está tratando de mantener un registro de sus nombres de variable.

global es un mal patrón, incluso para la inclusión global de las cosas, tales como $db de los recursos. No va a venir el día cuando se desea cambiar el nombre de $db pero no puede, porque su aplicación depende del nombre.

La limitación y la separación del ámbito de las variables es esencial para la escritura de cualquier medio camino de aplicaciones complejas.

27voto

Loek Bergman Puntos 1072

Globals son inevitables.

Es un viejo debate, pero aun así me gustaría añadir algunas reflexiones porque me pierda en el mencionado respuestas. Esas respuestas simplificar lo que un mundial es demasiado y presentar soluciones que no son todas las soluciones para el problema. El problema es: ¿cuál es la manera adecuada de tratar con una variable global y el uso de la palabra clave global? Para que hacer primero tenemos que analizar y describir lo que es un mundial.

Echa un vistazo a este código de Zend - y por favor comprendan que no estoy sugiriendo que los Zend está mal escrita:

class DecoratorPluginManager extends AbstractPluginManager
{
/**
 * Default set of decorators
 *
 * @var array
 */
protected $invokableClasses = array(
    'htmlcloud' => 'Zend\Tag\Cloud\Decorator\HtmlCloud',
    'htmltag'   => 'Zend\Tag\Cloud\Decorator\HtmlTag',
    'tag'       => 'Zend\Tag\Cloud\Decorator\HtmlTag',
   );

Hay un montón de invisible dependencias de aquí. Los constantes son en realidad clases. También puede ver require_once en algunas páginas de este marco. Require_once es un global de dependencia, de ahí la creación de dependencias externas. Eso es inevitable en un marco. ¿Cómo se puede crear una clase como DecoratorPluginManager sin un montón de código externo del que depende? No puede funcionar sin un montón de extras. Con el Zend framework, has cambiado la implementación de una interfaz? Una interfaz es de hecho un mundial.

Otra utilizado a nivel mundial de la aplicación es Drupal. Están muy preocupados acerca de un diseño adecuado, pero al igual que toda gran marco, que tiene un montón de dependencias externas. Echa un vistazo a los globales en esta página:

/**
 * @file
 * Initiates a browser-based installation of Drupal.
 */

/**
 * Root directory of Drupal installation.
 */
define('DRUPAL_ROOT', getcwd());

/**
 * Global flag to indicate that site is in installation mode.
 */
define('MAINTENANCE_MODE', 'install');

// Exit early if running an incompatible PHP version to avoid fatal errors.
if (version_compare(PHP_VERSION, '5.2.4') < 0) {
  print 'Your PHP installation is too old. Drupal requires at least PHP 5.2.4. See the     <a     href="http://drupal.org/requirements">system requirements</a> page for more     information.';
  exit;
}

// Start the installer.
require_once DRUPAL_ROOT . '/includes/install.core.inc';
install_drupal();

Escrito jamás una redirección a la página de inicio de sesión? Que es el cambio de un valor global. (Y entonces no estás diciendo: 'WTF', que considero como una buena reacción a la mala documentación de su solicitud). El problema con las globales, no es que sean globales, usted necesita de ellos para tener una significativa aplicación. El problema es la complejidad de la aplicación general que se puede hacer en una pesadilla para manejar. Las sesiones son globales, $_POST es un mundial, DRUPAL_ROOT es global, la includes/instalar.núcleo.inc' es un inmodificable global. Hay un gran mundo fuera de cualquier función que se requiere para permitir que la función de hacer su trabajo.

La respuesta de Gordon es incorrecta, porque él overrates de la independencia de la función y llamar a una función de un mentiroso es simplificar demasiado la situación. Funciones no mienten y cuando usted echa un vistazo a su ejemplo, la función está diseñada mal su ejemplo es un error. (Por cierto, estoy de acuerdo con esta conclusión, que uno debe separar el código.) La respuesta de deceze no es realmente una definición adecuada de la situación. Funciones siempre funcionan dentro de un ámbito más amplio, y su ejemplo es demasiado simplista. Vamos a estar todos de acuerdo con él en que esa función es completamente inútil, porque vuelve una constante. Esa función es de todos modos un mal diseño. Si desea mostrar que la práctica es mala, por favor venga con un ejemplo relevante. El cambio de nombre de variables a través de una aplicación no es la gran cosa tener un buen IDE (o una herramienta). La pregunta es sobre el alcance de la variable, no la diferencia en el alcance de la función. Hay un tiempo apropiado para una función a desempeñar su papel en el proceso (es por eso que se creó en el primer lugar) y en que momento adecuado puede influir en el funcionamiento de la aplicación como un todo, de ahí que también trabajan en variables globales. La respuesta de xzyfer es una declaración sin argumentación. Globals son tan presente en una aplicación si usted tiene procesal de las funciones o la programación orientada a objetos de diseño. Los próximos dos maneras de cambiar el valor de un mundial son esencialmente los mismos:

function xzy($var){
 global $z;
 $z = $var;
}

function setZ($var){
 $this->z = $var;
}

En ambos casos, es el valor de $z cambiado dentro de una función específica. En ambos sentidos de la programación se puede hacer esos cambios en un montón de otros lugares del código. Se podría decir que el uso global podría llamar a $z en cualquier lugar y cambiar allí. Sí, usted puede. Pero ¿lo hará usted? Y cuando se hace de inepto lugares, en caso de que no se la llama de un error?

Bob Fanger comentarios sobre xzyfer.

Nadie debe, a continuación, sólo el uso de cualquier cosa y especialmente de la palabra clave 'global'? No, pero al igual que cualquier tipo de diseño, a tratar de analizar en lo que depende y lo que de él depende. Trate de averiguar cuando cambia y cómo cambia. El cambio de valores globales sólo debería ocurrir con las variables que se pueden cambiar con cada petición/respuesta. Es decir, sólo a aquellas variables que son pertenecen a la funcional de flujo de un proceso, y no a su aplicación técnica. La redirección de una URL a la página de inicio de sesión pertenece a la funcional de flujo de un proceso, la implementación de la clase que se usa para una interfaz para la implementación técnica. Usted puede cambiar el último durante las distintas versiones de la aplicación, pero no debe cambiar aquellos con cada petición/respuesta.

Para entender más aún cuando es un problema de trabajar con variables globales y la palabra clave global y cuando no puedo introducir la siguiente frase, que viene de Wim de Bie al escribir acerca de los blogs: Personal de sí, privado no'. Cuando una función es cambiar el valor de una variable global en aras de su propio funcionamiento, a continuación, voy a llamar que el uso privado de una variable global y un error. Pero cuando el cambio de la variable global está hecho para el correcto funcionamiento de la aplicación como un todo, como la redirección del usuario a la página de inicio de sesión, entonces es que, en mi opinión, posiblemente, un buen diseño, no por definición mala, y ciertamente no es un anti-patrón.

En retrospectiva, las respuestas de Gordon, deceze y xzyfer: todos ellos han privado de sí " (y errores) como ejemplos. Es por eso que se oponen al uso de variables globales. Yo lo haría también. Ellos, sin embargo, no cuentan con personal de sí, en privado no, ejemplos como he hecho en esta respuesta varias veces.

12voto

xzyfer Puntos 6465

Simplemente ponga rara vez hay una razón para global y nunca una buena en PHP moderno código IMHO. Especialmente si estás usando PHP 5. Y más especialmente si es desarrollar código orientado a objetos.

GLOBALS afectan negativamente la mantenibilidad, legibilidad y Testabilidad del código. Muchos usos de la global puede y debe ser sustituido con la inyección de dependencia o simplemente pasando el objeto global como un parámetro.

function getCustomer($db, $id) {
    $row = $db->fetchRow('SELECT * FROM customer WHERE id = '.$db->quote($id));
    return $row;
}

3voto

Bob Fanger Puntos 9547

No tiene sentido hacer una función concat utilizando la palabra clave global.

Se utiliza para acceder a las variables globales como un objeto de base de datos.

Ejemplo:

function getCustomer($id) {
  global $db;
  $row = $db->fetchRow('SELECT * FROM customer WHERE id = '.$db->quote($id));
  return $row;
}

Puede ser utilizado como una variación en el patrón Singleton

Iteramos.com

Iteramos es una comunidad de desarrolladores que busca expandir el conocimiento de la programación mas allá del inglés.
Tenemos una gran cantidad de contenido, y también puedes hacer tus propias preguntas o resolver las de los demás.

Powered by:

X