101 votes

Global dans les fonctions PHP

Quel est l'utilité de le mot clé global?

Existe-il des raisons de préférer une méthode à l'autre?

  • De sécurité?
  • La Performance?
  • Quelque chose d'autre?

Méthode 1:

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

Méthode 2:

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

Quand est-il judicieux d'utiliser global?

Pour moi, il semble être dangereux... mais c'est peut être juste un manque de connaissance. Je suis intéressé par documentées (par exemple avec un exemple de code, lien vers la documentation...) des raisons techniques.

Merci à l'avance!


Bounty

C'est une bonne question générale sur le sujet, j' (@Gordon) cherche à offrir une prime pour obtenir d'autres réponses. Si votre réponse est en accord avec la mienne ou donne un point de vue différent n'a pas d'importance. Depuis l' global rubrique vient chaque maintenant et puis, on pourrait utiliser un bon "canonique" réponse à un lien.

166voto

Gordon Points 156415

Globales sont mal

C'est vrai pour l' global mot-clé ainsi que tout ce qui atteint une portée locale à la portée globale (statique, les singletons, les registres, les constantes). Vous ne voulez pas les utiliser. Un appel de fonction ne devrait pas avoir à s'appuyer sur quelque chose d'extérieur, par exemple

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
}

Tous ces éléments vont rendre votre code dépend de l'extérieur. Ce qui signifie, vous devez connaître l'état global de votre application avant de vous pouvez appeler l'un de ces. La fonction ne peut pas exister sans que l'environnement.

À l'aide de la superglobales pourrait ne pas être un défaut évident, mais si vous appelez votre code à partir d'une Ligne de Commande, vous n'avez pas d' $_GET ou $_POST. Si votre code s'appuie sur les commentaires de ces, vous limiter vous-même à un environnement web. Juste résumé de la demande dans un objet et l'utiliser à la place.

En cas de couplage codé en dur les noms de classe (statique, constantes), votre fonction ne peut exister sans que la classe qui est disponible. C'est moins un problème lorsque c'est les classes du même espace de noms, mais quand vous commencez à mélanger à partir des espaces de noms différents, vous êtes la création d'un emmêlés.

La réutilisation est sévèrement entravée par l'ensemble de la ci-dessus. Est donc de tests unitaires.

Aussi, vos signatures de fonction sont couchés quand vous vous attaquez à la portée globale

function fn()

est un menteur, parce qu'il prétend que je peux appeler cette fonction sans passer quoi que ce soit. C'est seulement quand je regarde le corps de la fonction que j'apprends, je dois mettre de l'environnement dans un certain état.

Si votre fonction requiert des arguments à terme, de les rendre explicites et de les transmettre à:

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

traduit clairement à partir de la signature de ce qu'elle exige d'être appelé. Il ne dépend pas de l'environnement à être dans un état spécifique. Vous n'avez pas à le faire

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

C'est une question de tirant (mot clé global) vs poussant dans (arguments). Lorsque vous appuyez sur/injecter des dépendances, la fonction ne dépend pas de l'extérieur plus. Lorsque vous effectuez fn(1) vous n'avez pas à avoir une variable contenant 1 à l'extérieur. Mais quand vous tirez dans global $one à l'intérieur de la fonction, vous vous attaquez à la portée globale et s'attendre à avoir une variable de que défini quelque part. La fonction n'est plus indépendants.

Pire encore, lorsque vous modifiez les variables globales à l'intérieur de votre fonction, votre code sera vite complètement incompréhensible, parce que vos fonctions sont avoir des effets secondaires tous sur la place.

En l'absence d'un meilleur exemple, envisager de

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

Et puis vous n'

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

Il n'y a pas moyen de voir qu' $foo a été changé à partir de ces trois lignes. Pourquoi appeler la même fonction avec les mêmes arguments, tout d'un coup changer de sortie ou de modifier une valeur dans l'état global? Une fonction doit faire X pour une entrée définis par Y. Toujours.

Cela devient encore plus grave lors de l'utilisation de la programmation orientée objet, parce que la programmation orientée objet est à propos de l'encapsulation et en allant à la portée globale, vous êtes en rupture de l'encapsulation. Tous ces Singletons et des Registres de vous voir dans des cadres sont des odeurs de code qui devrait être supprimé en faveur de l'Injection de Dépendance. Découpler votre code.

Plus De Ressources:

38voto

Loek Bergman Points 1072

Globales sont inévitables.

C'est un vieux débat, mais je tiens encore à ajouter quelques réflexions parce que je m'ennuie d'eux dans les réponses. Ces réponses simplifier ce mondial, c'est trop et de présenter des solutions qui ne sont pas toutes les solutions à ce problème. Le problème est: quelle est la bonne façon de traiter avec une variable globale et l'utilisation du mot-clé global? Pour ce faire, nous devons d'abord examiner et de décrire ce mondial.

Jetez un oeil à ce code de Zend - et s'il vous plaît comprendre que je ne suggérons pas que Zend est mal écrit:

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',
   );

Il y a beaucoup de invisible ici de dépendances. Ces constantes sont en fait des classes. Vous pouvez également voir require_once dans certaines pages de ce cadre. Require_once mondial de dépendance, d'où la création de dépendances externes. C'est inévitable pour un cadre. Comment pouvez-vous créer une classe comme DecoratorPluginManager sans beaucoup de code externe dont il dépend? Il ne peut pas fonctionner sans beaucoup d'extras. En utilisant le Zend framework, avez-vous déjà changé la mise en œuvre d'une interface? Une interface est en fait un mondial.

Un autre utilisé mondialement application est Drupal. Ils sont très préoccupés par la bonne conception, mais comme tout grand cadre, ils ont beaucoup de dépendances externes. Jetez un oeil à la globals dans cette page:

/**
 * @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();

Jamais écrit une redirection vers la page de connexion? C'est la modification d'une valeur globale. (Et puis, n'êtes-vous pas dire "WTF", qui je considère comme une bonne réaction de mauvaise documentation de votre application.) Le problème avec les variables globales est pas qu'ils sont globales, vous en avez besoin afin d'avoir un sens de l'application. Le problème est la complexité de l'ensemble de l'application qui peut en faire un cauchemar à gérer. Les Sessions sont globales, $_POST est un mondial, DRUPAL_ROOT est mondiale, les includes/installer.de base.inc " est une inmodifiable mondiale. Il y est grand monde en dehors de toute fonction qui est nécessaire afin de laisser la fonction de faire son travail.

La réponse de Gordon est incorrect, parce qu'il surfait à l'indépendance d'une fonction et l'appel d'une fonction un menteur est simplifier à l'extrême la situation. Fonctions de ne pas mentir et quand vous prenez un coup d'oeil à son exemple, la fonction est conçue mal son exemple est un bug. (En passant, je suis d'accord avec cette conclusion qu'il faut découpler le code). La réponse de deceze n'est pas vraiment une bonne définition de la situation. Les fonctions de toujours fonctionner au sein d'un champ d'application plus large et son exemple est beaucoup trop simpliste. Nous serons tous d'accord avec lui que la fonction est complètement inutile, parce qu'elle renvoie une constante. Cette fonction est de toute façon une mauvaise conception. Si vous voulez montrer que la pratique est mauvais, s'il vous plaît venez avec un exemple pertinent. Renommage de variables dans une application n'est pas grave d'avoir une bonne IDE (ou un outil). La question est à propos de la portée de la variable, pas la différence de champ d'application avec la fonction. Il y a un bon moment pour une fonction à exercer son rôle dans le processus (c'est pourquoi il est créé en premier lieu), et, à la bonne heure peut-il influencer le fonctionnement de l'application dans son ensemble, et donc également de travailler sur des variables globales. La réponse de xzyfer est une déclaration sans argumentation. Globales sont tout aussi présents dans une application si vous avez des fonctions de procédure ou de la programmation orientée objet design. Les deux façons de changer la valeur d'un mondial sont essentiellement les mêmes:

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

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

Dans les deux cas est la valeur de $z changé à l'intérieur d'une fonction spécifique. Dans les deux modes de programmation vous pouvez faire ces changements dans un tas d'autres endroits dans le code. On pourrait dire que l'aide globale, vous pourriez l'appeler $z n'importe où et à changer. Oui, vous le pouvez. Mais allez-vous? Et quand fait inapte, doit-il donc pas être appelé un bug?

Bob Fanger commentaires sur xzyfer.

Devrait-on alors simplement utiliser quoi que ce soit et surtout le mot-clé "global"? Non, mais juste comme n'importe quel type de conception, d'essayer d'analyser ce qu'il dépend et ce qui en dépend. Essayez de savoir quand il change et comment il change. Évolution des valeurs globales, ne devrait se produire avec les variables qui peuvent changer à chaque requête/réponse. C'est uniquement à ceux des variables qui font partie du flux fonctionnel d'un processus, et non pas à sa mise en œuvre technique. La redirection d'une URL vers la page de connexion appartient au flux fonctionnel d'un processus, la mise en œuvre de la classe utilisée pour une interface à la mise en œuvre technique. Vous pouvez modifier cette dernière durant les différentes versions de l'application, mais ne devrait pas modifier ceux-ci à chaque requête/réponse.

Afin de mieux comprendre quand c'est un problème de travailler avec des variables globales et le mot-clé global et quand ne pas vais-je introduire la phrase suivante, qui vient de Wim de Bie lors de l'écriture sur les blogs: Personnels oui, privés non". Lorsqu'une fonction est en train de changer la valeur d'une variable globale dans le souci de son propre fonctionnement, alors je les appel que l'usage privé d'une variable globale et un bug. Mais quand le changement de la variable globale est faite pour le bon traitement de la demande dans son ensemble, comme la redirection de l'utilisateur vers la page de connexion, alors c'est qu'à mon avis, éventuellement, un bon design, pas par définition mauvais et certainement pas un anti-modèle.

Rétrospectivement, les réponses de Gordon, deceze et xzyfer: ils ont tous des 'private oui" (et les bugs) en sont des exemples. C'est pourquoi ils se sont opposés à l'utilisation de variables globales. J'aimerais en faire trop. Cependant, ils ne viennent pas avec les personnels oui, privés n'-exemples comme j'ai fait dans cette réponse plusieurs fois.

36voto

deceze Points 200115

L'une des raisons pour laquelle l'encontre global , cela signifie que la fonction est dépendante d'une autre portée. Cela va dégénérer très rapidement.

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

vs

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

Exigeant $str1 et $str2 à être mis en place dans l'appel de la portée de la fonction de travail signifie que vous introduire des dépendances inutiles. Vous ne pouvez pas renommer ces variables dans le présent champ d'application, sans les renommer dans la fonction, et donc aussi dans tous les autres étendues que vous êtes à l'aide de cette fonction. Cette bientôt retombe dans le chaos que vous essayez de garder une trace de vos noms de variable.

global est un mauvais modèle, même pour les mondiaux de choses telles que $db des ressources. Il va venir le jour où vous souhaitez renommer $db , mais ne peut pas, parce que l'ensemble de votre demande dépend de ce nom.

La limitation et de la séparation de la portée des variables est indispensable pour l'écriture tout à mi-chemin d'applications complexes.

15voto

xzyfer Points 6465

Autrement dit, il y a rarement une raison pour `` et jamais un bon en PHP moderne coder mon humble avis. Surtout si vous utilisez PHP 5. Et plus spécialement si vous vous développez du code orienté objet.

Globals affecter négativement la maintenabilité, la lisibilité et la testabilité du code. Beaucoup d’utilisations de `` peut et devrait être remplacé par l’Injection de dépendance ou simplement en passant l’objet global en tant que paramètre.

6voto

mAsT3RpEE Points 449

Je pense que tout le monde a assez bien expliqué sur les aspects négatifs de variables globales. Je vais donc ajouter les points positifs ainsi que les instructions pour une bonne utilisation de variables globales:

  1. Le but principal de globals était de partager les informations entre les fonctions. en arrière quand il n'y a rien comme une classe, le code php se composait d'un tas de fonctions. Parfois vous auriez besoin de partager de l'information entre les fonctions. Généralement, le mondial a été utilisé pour faire cela avec le risque d'avoir des données corrompues en les rendant mondiale.

    Maintenant, avant de quelques happy go lucky niais commence un commentaire à propos de l'injection de dépendance, je voudrais vous demander comment l'utilisateur d'une fonction comme exemple get_post(1) savez toutes les dépendances de la fonction. Considérez également que les dépendances peuvent différer de
    une version à l'autre et d'un serveur à l'autre. Le principal problème avec l'injection de dépendance est la gestion des dépendances doivent être connus à l'avance. Dans une situation où ce n'est pas possible ou indésirables les variables globales ont été le seul moyen de parvenir à cet objectif.

    En raison de la création de la classe, maintenant commune fonctions peuvent être facilement regroupés dans une classe et de partager des données. Par implémentations comme Médiateurs, même sans rapport avec les objets peuvent partager de l'information. Ce n'est plus nécessaire.

  2. Une autre utilisation de variables globales est pour la configuration. Surtout au début d'un script avant tout des chargeurs automatiques ont été chargé, de connexions de base de données, etc ...

    Pendant le chargement des ressources, variables globales peuvent être utilisées pour configurer les données (c'est à dire qui base de données à utiliser où les fichiers de la bibliothèque sont situés, l'url du serveur, etc). Le meilleur façon de le faire est par l'utilisation de l' define() fonction depuis ces valeurs ne changeront pas souvent et peut facilement être placé dans un fichier de configuration.

  3. L'utilisation finale pour les variables globales est de détenir des données communes (c'est à dire CRLF, IMAGE_DIR, IMAGE_DIR_URL), lisible par l'homme indicateurs d'état (c'est à dire ITERATOR_IS_RECURSIVE). Ici globales sont utilisées pour stocker l'information qui est destinée à être utilisée application large leur permettant d'être changé et ces modifications apparaissent en application de large.

  4. Le pattern singleton est devenu populaire au cours de php php4 lors de chaque instance d'un objet pris de la mémoire. Le singleton a contribué à sauver de la ram en permettant seulement à une instance d'un objet à créer. Avant les références, même injection de dépendance aurait été une mauvaise idée.

    La nouvelle version de php de la mise en œuvre d'objets à partir de PHP 5.4+ prend soin de la plupart de ces problèmes vous pouvez passer des objets autour avec peu ou pas de peine plus. Ce n'est plus nécessaire.

    Une autre utilisation pour les singletons est le cas spécial où une seule instance d'un objet doivent exister à un moment, cette instance pourrait exister avant / après l'exécution du script et cet objet est partagé entre les différents scripts / serveurs / langues etc. Ici un le pattern singleton résout la solution tout à fait bien.

Donc, en conclusion, si vous êtes en position 1, 2 ou 3, puis en utilisant un mondial serait raisonnable. Cependant, dans d'autres situations Méthode 1 doit être utilisé.

Hésitez pas à mettre à jour d'autres cas où globals doit être utilisé.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X