2008-10-03 7 views
5

J'ai une fonction qui inclut un fichier basé sur la chaîne qui lui est transmise, c'est-à-dire la variable d'action de la chaîne de requête. J'utilise ceci pour des buts de filtrage etc. ainsi les gens ne peuvent pas inclure des dossiers qu'ils ne devraient pas pouvoir et si le dossier n'existe pas un dossier par défaut est chargé à la place. Le problème est que lorsque la fonction s'exécute et inclut la portée du fichier, elle est perdue car l'inclusion s'exécute dans une fonction. Cela devient un problème car j'utilise un fichier de configuration global, puis j'utilise des fichiers de configuration spécifiques pour chaque module sur le site. La façon dont je le fais en ce moment est de définir les variables que je veux pouvoir utiliser comme globales, puis de les ajouter au sommet de la fonction de filtrage.PHP Conserve la portée lors de l'appel d'une fonction

Existe-t-il un moyen plus simple de le faire, c'est-à-dire en préservant la portée lors d'un appel de fonction ou existe-t-il des macros PHP?

Modifier: Serait-il préférable d'utiliser extract ($ _ GLOBALS); à l'intérieur de mon appel de fonction à la place?

Éditer 2: Pour tous ceux qui s'en soucient. Je me suis rendu compte que j'étais complètement en train de penser au problème et qu'au lieu d'utiliser une fonction, je devrais utiliser un include, duh! De cette façon, je peux garder ma portée et avoir mon gâteau aussi.

+0

Dans mon cas, le recours à votre « Edit 2 » et en utilisant simplement un include ne fonctionne pas parce que j'ai Il y a beaucoup plus de choses qui se passent. Essentiellement penser à une classe "View" qui nécessite un viewscript.php qui, parce que nous sommes dans une portée de plugin, je veux passer dans la portée "globale" au viewscript sans avoir besoin de déclarer chaque variable comme globale dans le " doInclude "fonction. –

Répondre

5

Edit: D'accord, je l'ai relu votre question et je pense que je reçois ce que vous parlez maintenant:
vous voulez quelque chose comme cela fonctionne:

// myInclude.php 
$x = "abc"; 

// ----------------------- 
// myRegularFile.php 

function doInclude() { 
    include 'myInclude.php'; 
} 
$x = "A default value"; 
doInclude(); 
echo $x; // should be "abc", but actually prints "A default value" 

Si vous ne modifient que quelques variables, et vous savez à l'avance quelles variables vont être définies dans l'include, déclarez-les comme global dans la fonction doInclude().

Alternativement, si chacun de vos comprend peut définir un certain nombre de variables, vous pouvez les mettre tous dans un seul tableau:

// myInclude.php 
$includedVars['x'] = "abc"; 
$includedVars['y'] = "def"; 

// ------------------ 
// myRegularFile.php 
function doInclude() { 
    global $includedVars; 
    include 'myInclude.php'; 
    // perhaps filter out any "unexpected" variables here if you want 
} 

doInclude(); 
extract($includedVars); 
echo $x;  // "abc" 
echo $y;  // "def" 

réponse originale:

ce genre de chose est connu sous le nom de «fermetures» et sont introduits dans PHP 5.3

http://steike.com/code/php-closures/

Serait-il préférable d'utiliser extract ($ _ GLOBALS); à l'intérieur de mon appel de fonction à la place?

cher seigneur, no. Si vous voulez accéder à une variable globale à partir d'une fonction, utilisez simplement le mot-clé global. par exemple:

$x = "foo"; 
function wrong() { 
    echo $x; 
} 
function right() { 
    global $x; 
    echo $x; 
} 

wrong();  // undefined variable $x 
right();  // "foo" 
+0

C'est exactement le problème que j'ai rencontré. J'essaye de développer un plugin pour un script, mais malheureusement ce script fait des choses étranges avec les globals. C'est difficile de suivre tous les globals dont j'ai besoin et de les déclarer dans la fonction "doInclude". Eh bien ... je pensais que $ GLOBALS fonctionnerait, mais ça ne marche pas à cause de l'ordre des fonctions et des inclusions. Telle est la vie d'un développeur de plugin, je suppose. –

0

Quand il vient je les définir généralement juste les options de configuration (fichier en particulier les chemins et autres) avec des chemins absolus à l'aide d'un define(). Quelque chose comme:

define('MY_CONFIG_PATH', '/home/jschmoe/myfiles/config.inc.php'); 

De cette façon, ils sont toujours globalement accessibles indépendamment des changements de portée et à moins que je migrer vers une structure de fichier, il est toujours en mesure de trouver tout.

+0

J'ai la plupart des variables de configuration configurées de cette manière, mais j'ai un tableau de codes de pays, un objet de base de données, etc. qui ne peut pas être défini de cette manière. – Joshua

0

Si je comprends bien, vous avez un code le long des lignes de:

function do_include($foo) { 
    if (is_valid($foo)) 
    include $foo; 
} 

do_include(@$_GET['foo']); 

Une solution (qui peut ou peut ne pas être simple, selon le code de base) est de déplacer les inclure dans le monde portée:

if (is_valid(@$_GET['foo'])) 
    include $_GET['foo']; 

Autres solutions de contournement existe (comme vous l'avez mentionné: déclarer globals, en collaboration avec le tableau _globals $ directement, etc.), mais l'avantage de cette solution est que vous ne devez pas se rappeler ces conventions dans tous les les fichiers inclus.

0

Pourquoi ne pas retourner une valeur de votre inclure puis définissez la valeur de l'appel à inclure une variable:

config.php

return array(
    'foo'=>'bar', 
    'x'=>23, 
    'y'=>12 
); 

script.php

$config = require('config.php'); 
var_dump($config); 

Non besoin de gâcher l'endroit avec des variables globales

0

Est-il possible de le faire, plus facile à savoir en préservant la portée lorsqu'un appel de fonction est faite

Vous pouvez utiliser:

function doInclude($file, $args = array()) { 
    extract($args); 
    include($file); 
} 

Si vous ne voulez pas passer explicitement les variables, vous pourrait appeler doInclude avec get_defined_vars comme argument, par exemple .:

doInclude('test.template.php', get_defined_vars()); 

Personnellement, je préférerais passer un tableau explicite, plutôt que d'utiliser, mais cela fonctionnerait.

+0

Cela ne répond pas à la question, mais plutôt de dire "vous le faites mal". Merci Steve. Parfois, il y a des situations où * serait * bien d'exécuter une fonction en utilisant une portée désirée (ie globale) 'call_user_func_array_with_scope ('function', $ args, $ this)' serait utile si elle existait ... null "ou global pour le rebondir sur la portée globale.Il serait utile lors de la construction d'un plugin pour travailler à l'intérieur de certaines contraintes bien définies. –

0

Vous pouvez déclarer des variables dans le fichier inclus comme global, assurant qu'ils ont une portée mondiale:

//inc.php 
global $cfg; 
$cfg['foo'] = bar; 

//index.php 
function get_cfg($cfgFile) { 
    if (valid_cfg_file($cfgFile)) { 
     include_once($cfgFile); 
    } 
} 
... 
get_cfg('inc.php'); 
echo "cfg[foo]: $cfg[foo]\n"; 
Questions connexes