100 votes

PHP fonction utilise une variable de l'extérieur

fonction parties($partie) { 
    $structure = 'http://' . $site_url . 'contenu/'; 
    echo($structure . $partie . '.php'); 
}

Cette fonction utilise une variable $site_url qui a été définie en haut de cette page, mais cette variable n'est pas passée dans la fonction.

Comment pouvons-nous la faire retourner dans la fonction?

182voto

walkhard Points 16756

Ajouter un deuxième paramètre

Vous devez passer un paramètre supplémentaire à votre fonction :

function parts($site_url, $part) { 
    $structure = 'http://' . $site_url . 'content/'; 
    echo $structure . $part . '.php'; 
}

En cas de fermetures

Si vous préférez utiliser des fermetures, vous pouvez importer une variable dans la portée actuelle (le mot-clé use) :

$parts = function($part) use ($site_url) { 
    $structure = 'http://' . $site_url . 'content/'; 
    echo $structure . $part . '.php'; 
};

global - une mauvaise pratique

Ce post est souvent lu, donc quelque chose doit être clarifié à propos de global. Son utilisation est considérée comme une mauvaise pratique (voir ici et ici).

Pour compléter voici la solution utilisant global :

function parts($part) { 
    global $site_url;
    $structure = 'http://' . $site_url . 'content/'; 
    echo($structure . $part . '.php'); 
}

Cela fonctionne car vous devez indiquer à l'interpréteur que vous voulez utiliser une variable globale, maintenant il pense que c'est une variable locale (à l'intérieur de votre fonction).

Lecture suggérée :

49voto

Joe Green Points 1029

Alternativement, vous pouvez apporter des variables de l'extérieur en utilisant des fermetures avec le mot-clé use.

$myVar = "foo";
$myFunction = function($arg1, $arg2) use ($myVar)
{
 return $arg1 . $myVar . $arg2;
};

14voto

bob-12345 Points 66

N'oubliez pas que vous pouvez aussi passer ces variables use par référence.

Les cas d'utilisation sont lorsque vous avez besoin de modifier la variable use à partir de l'intérieur de votre rappel (par exemple, produire le nouvel ensemble d'objets différents à partir d'un tableau source d'objets).

$sourcearray = [ (object) ['a' => 1], (object) ['a' => 2]];
$newarray = [];
array_walk($sourcearray, function ($item) use (&$newarray) {
    $newarray[] = (object) ['times2' => $item->a * 2];
});
var_dump($newarray);

Maintenant, $newarray comprendra (pseudocode ici pour la brièveté) [{times2:2},{times2:4}].

En revanche, utiliser $newarray sans le modificateur & rendrait la variable externe $newarray en lecture seule accessible depuis la portée de la fermeture. Mais $newarray dans la portée de la fermeture serait une variable nouvelle complètement différente vivant uniquement dans la portée de la fermeture.

Malgré que les noms des deux variables soient les mêmes, il s'agirait de deux variables différentes. La variable extérieure $newarray comprendrait [] dans ce cas après que le code ait fini.

NB : N'oubliez pas qu'il est préférable d'utiliser les structures de données immuables (contrairement à ce qui précède) dans votre projet web habituel. Cela représenterait 99% des cas d'utilisation. Donc l'approche ci-dessus, en utilisant la mutabilité, est réservée à un type de cas d'utilisation très rare de "niveau bas".

2voto

Leon Williams Points 466

Je suppose que cela dépend de votre architecture et de tout ce que vous pourriez avoir besoin de considérer, mais vous pourriez aussi adopter l'approche orientée objet et utiliser une classe.

class ClassName {

    private $site_url;

    function __construct( $url ) {
        $this->site_url = $url;
    }

    public function parts( string $part ) {
        echo 'http://' . $this->site_url . 'content/' . $part . '.php';
    }

    # Vous pourriez construire plein d'autres choses ici
    # et toujours avoir accès à $this->site_url.
}

Ensuite, vous pouvez créer et utiliser l'objet où vous le souhaitez.

$obj = new ClassName($site_url);
$obj->parts('part_argument');

Cela pourrait être exagéré pour ce que l'OP essayait spécifiquement de réaliser, mais c'est au moins une option que je voulais mettre sur la table pour les novices car personne ne l'a encore mentionnée.

L'avantage ici est la scalabilité et la contenance. Par exemple, si vous vous retrouvez à devoir passer les mêmes variables en référence à plusieurs fonctions pour une tâche commune, cela pourrait être un indicateur qu'une classe est nécessaire.

0voto

Grigory Points 40

J'avais une question similaire. Réponse: utiliser global. Et il y a d'autres options. Mais si vous avez besoin d'une fonction nommée avec l'utilisation de la portée externe, voici ce que j'ai:

global $myNamedFunctionWidelyAccessibleCallableWithScope;
$myNamedFunctionWidelyAccessibleCallableWithScope =
    function ($argument) use ($part, $orWhatYouWant) {
        echo($argument . $part . '.php');
        // faire quelque chose ici
        return $orWhatYouWant;
    };
function myNamedFunctionWidelyAccessible(string $argument)
{
    global $myNamedFunctionWidelyAccessibleCallableWithScope;
    return $myNamedFunctionWidelyAccessibleCallableWithScope($argument);
}

Cela est utile pour rendre la fonction myNamedFunctionWidelyAccessible accessible partout, mais la lie également à la portée. Et j'ai délibérément donné un nom très long, les choses globales sont mauvaises :(

Voici la documentation avec un bon exemple

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