2010-08-22 5 views
2

Maintenant, avant de sauter à la façon dont vous ne devriez pas mélanger les étendues: Je le sais. Cependant, il s'agit d'un cas où le mélange de portée doit se produire ou si une duplication de code majeure doit avoir lieu, rien autour de cela. Et je préférerais le mixage.exporter la variable vers la portée précédente dans PHP

Cela dit, je voudrais ce code:

function a() { 
    $a = "a"; 
    $b = "b"; 
    $c = "c"; 
} 
function b() { 
    a(); 
    echo $a . $b . $c; 
} 
b(); // Output: abc 
echo $a; // Should raise a notice that $a is undefined 

pour pouvoir travailler comme commenté. Je sais que ce n'est pas possible dans la plupart des langues - j'ai pu le faire dans Ruby, cependant; et je me demande si vous pouvez le faire avec PHP.

Les noms des variables ne sont pas connus à l'avance dans la situation réelle.

Encore une fois, c'est la duplication de code ou ceci - absolument pas moyen de contourner cela.

En outre, ce serait bien si a devait être quelque chose comme a('b') ou quelque chose.


En réalité, le code est la suivante:

static function renderError($what, $vararray) { 
    foreach($vararray as $key => $val) { /* this foreach is the code we want to decouple */ 
     $key = 'e_'.$key; 
     $$key = htmlspecialchars($val); 
    } 
    ob_clean(); 
    exit(eval('?>'.file_get_contents(ROOT."/templates/$what.php"))); 
} 

Avec un appel comme E_Render::renderError('NotFound', array('requested_url' => '/notfound', 'misspelling' => '/reallynotfound'));

Puis, dans les modèles/NotFound.php, vous auriez quelque chose comme:

<html> 
<body> 
<?php echo $e_requested_url; ?> could not be found. Did you mean <?php echo $e_misspelling: ?>? 
</body> 
</html> 

Nous préférerions vraiment que nos auteurs de gabarits ne fassent rien de plus que cela ... bien que $e['requested_url'] pourrait être fait si rien de mieux n'était disponible. Pourquoi ne pouvez-vous pas renvoyer $ a d'un()?

Répondre

6

C'est pourquoi nous avons OO:

class Foo { 

    function a() { 
     $this->a = "a"; 
     $this->b = "b"; 
     $this->c = "c"; 
    } 

    function b() { 
     $this->a(); 
     echo $this->a . $this->b . $this->c; 
    } 
} 

$f = new Foo; 
$f->b(); // Output: abc 
echo $a; // Should raise a notice that $a is undefined 

Autre possibilité:

function a() { 
    $a = "a"; 
    $b = "b"; 
    $c = "c"; 

    return compact('a', 'b', 'c'); 
} 

function b() { 
    extract(a()); 
    echo $a . $b . $c; 
} 

Voir: compact(), extract()

Sinon, je ne vois pas une façon de faire cela sans changer radicalement la la langue. PS: Si vous pensez que cette fonctionnalité est si importante, pourquoi n'utilisez-vous pas simplement Ruby?

+0

Garder les noms de variables $ a, $ b, $ c est critique. Tant pis. –

+0

+1 Vous l'avez eu en premier. Vous n'avez pas déclaré $ a, $ band $ c comme membres du cours? – NAVEED

+0

@NAVEED Ne pas avoir à. PHP peut ajouter des membres de classe à l'exécution – NullUserException

0

Pourquoi?

function a() { 
    $a = "a"; 
    return $a; 
} 
function b() { 
    $a = a(); 
    echo $a; 
} 
b(); // Output: a 
echo $a; // Should raise a notice that $a is undefined 

cela ne casse pas la portée.

+0

Voir la question éditée. Je dois être capable de déclarer plusieurs variables et de les avoir dans un tableau. Aussi, je ne connaîtrai pas les noms des variables avant main dans la situation réelle. –

+0

ok pouvez-vous expliquer a) pourquoi il ne peut pas être un tableau, parce que vous pouvez simplement retourner un tableau et vraiment quelle est la différence entre $ a et $ array ['a'] et b) donner plus de contexte à votre problème Je n'ai pas encore vu une raison pour laquelle la portée doit être brisée. –

+0

aussi si vous ne connaissez pas les noms de variables avant main, comment sauriez-vous quoi utiliser dans b()? Encore une fois, s'il vous plaît donner plus de contexte à la question –

0

Je ne comprends pas pourquoi vous ne pouvez pas les retourner en tant que tableau. En plus de la suggestion @NullUserException, je suggérerais l'approche suivante (si vous ne prenez pas la route OOP).

function a() { 
    $a = "a"; 
    $b = "b"; 
    $c = "c"; 

    return array($a, $b, $c); 
} 

function b() { 
    list($a, $b, $c) = a(); 
    echo $a . $b . $c; 
} 
1

Il n'y a aucun moyen de faire ce que vous demandez étant donné les restrictions que vous imposez. Il n'y aura jamais de bonne raison de faire exactement ce que vous essayez de faire. Il y a beaucoup de meilleures solutions.

Quoi qu'il en soit, le plus proche, vous aurez passe par référence:

<?php 
function a(&$a, &$b, &$c) 
{ 
    $a = 1; 
    $b = 2; 
    $c = 3; 
} 

function b() 
{ 
    a($a, $b, $c); 
} 
?> 
1

J'ai juste couru ce code

- var1.php

<?php 

function a($vars) { 
    foreach ($vars as $var => $val) { 
     $$var = $val; 
    } 

    echo eval('?>' . file_get_contents('var2.php') . '<?php '); 
}; 


a(array('a' => 'foo', 'b' => 'bar', 'c' => 'baz')); 

- var2.php

<html> 
    <body> 
     <div><?= '$a = "' . $a . '"' ?></div> 
     <div><?= '$b = "' . $b . '"' ?></div> 
     <div><?= '$c = "' . $c . '"' ?></div> 
    </body> 
</html> 

Et il sort:

$a = "foo" 
$b = "bar" 
$c = "baz" 

La raison étant que depuis eval() garde la portée actuelle, toute variable déclarée localement dans la fonction sera également disponible sur place à l'intérieur de la chaîne eval'ed. Même chose avec $ this.

** MISE A JOUR **

Depuis eval() est mal et doit être évitée (comme suggéré de bien vouloir), voici une ré-écriture à l'aide templating simple. De cette façon, votre concepteur n'a qu'à connaître le nom de la variable disponible (dans les spécifications):

- var1.php

<?php 

function showError($error, $vars) { 

    $template = file_get_contents("{$error}.php"); 
    $keys = array(); 
    $values = array(); 
    foreach ($vars as $var => $val) { 
     $keys[] = '@{e_'.$var.'}'; 
     $values[] = $val; 
    } 

    echo str_replace($keys, $values, $template); 
}; 

showError('template1', array('value' => 300, 'message' => 'Something foo')); 

- template1.php

<html> 
    <body> 
     <div>Error <span style="font-weight: bold; color: red;">@{e_value}</span></div> 
     <div>The message was : <em>@{e_message}</em></div> 
    </body> 
</html> 
+0

-1 Pour suggérer 'eval()' et des balises courtes. – NullUserException

+0

... bien, assez juste à propos de l'eval. En ce qui concerne les étiquettes courtes, c'est votre opinion. Je mets à jour la réponse, donc il n'y a pas eval() du tout. Content? –

+1

Les étiquettes courtes sont un cauchemar. Beaucoup de serveurs les ont désactivé et laisser les gens sans connaissance, ce qui conduit à des questions comme [http://stackoverflow.com/questions/2476072/tags-not-working-in-php-5-3-1] et [this] (http://stackoverflow.com/questions/2476072/tags-not-working-in-php-5-3-1). Et ils ne sont pas non plus conformes aux normes. C'est une "fonctionnalité" stupide qui n'aurait pas dû être ajoutée en premier lieu. – NullUserException