Uzyskaj dostęp do zmiennej globalnej w funkcji PHP


84

Zgodnie z większością reguł zakresu języków programowania, mogę uzyskać dostęp do zmiennych, które są zdefiniowane poza funkcjami wewnątrz nich, ale dlaczego ten kod nie działa?

<?php
    $data = 'My data';

    function menugen() {
        echo "[" . $data . "]";
    }

    menugen();
?>

Wynik jest [].


3
Nie traktuj go jako globalnego, przekaż go do funkcji jako argument
Mark Baker

2
Gdzie instrukcja mówi takie rzeczy?
deceze

Powiązana lektura: PHP globalnie w funkcjach
Jocelyn

Sprawdź drugi przykład na tej stronie: php.net/manual/en/language.variables.scope.php
Amin Gholibeigian

afaik możemy uzyskać dostęp za pomocą $ GLOBALS ['varname'], gdzie indeks "varname" to $ varname poza funkcją. W rzeczywistości możemy użyć print_r ($ GLOBALS) do przeglądania wszystkich globalnych zmiennych.
Ahmad,

Odpowiedzi:


165

To nie działa, ponieważ mają zadeklarować zmienne globalne, które będziesz dostępu:

$data = 'My data';

function menugen() {
    global $data; // <-- Add this line

    echo "[" . $data . "]";
}

menugen();

W przeciwnym razie możesz uzyskać do niego dostęp jako $GLOBALS['data']. Zobacz zakres zmienny .

Nawet jeśli jest to trochę nie na temat, sugerowałbym unikanie używania globali i preferowanie przekazywania jako parametrów.


Dzięki, masz rację, ale nie użyli tej linii w drugim przykładzie instrukcji: php.net/manual/en/language.variables.scope.php
Amin Gholibeigian

6
W rzeczywistości ten drugi przykład miał pokazać czytelnikom, czego nie robić:This script will not produce any output because the echo statement refers to a local version of the $a variable, and it has not been assigned a value within this scope.
Matteo Tassinari

2
Cholera! Musiałem się zalogować, aby zagłosować za tą odpowiedzią, tylko dlatego, że strasznie zapomniałem zakresu zmiennych php.
Milche Patern

20

Możesz wykonać jedną z następujących czynności:

<?php
    $data = 'My data';

    function menugen() {
        global $data;
        echo "[" . $data . "]";
    }

    menugen();

Lub

<?php
    $data = 'My data';

    function menugen() {
        echo "[" . $GLOBALS['data'] . "]";
    }

    menugen();

To powiedziawszy, nadużywanie globalnych może prowadzić do słabego kodu. Zwykle lepiej jest przekazać to, czego potrzebujesz. Na przykład, zamiast odwoływać się do obiektu globalnej bazy danych, należy przekazać uchwyt do bazy danych i działać na jego podstawie. Nazywa się to iniekcją zależności . Wdrażanie testów automatycznych (co powinieneś) znacznie ułatwia życie.


13

To kwestia zakresu. Krótko mówiąc, należy unikać zmiennych globalnych, więc :

Musisz albo przekazać go jako parametr:

$data = 'My data';

function menugen($data)
{
    echo $data;
}

Możesz też mieć to na zajęciach i uzyskać do niego dostęp

class MyClass
{
    private $data = "";

    function menugen()
    {
        echo this->data;
    }

}

Zobacz również odpowiedź @MatteoTassinari, ponieważ możesz oznaczyć ją jako globalną, aby uzyskać do niej dostęp, ale zmienne globalne generalnie nie są wymagane, więc rozsądnie byłoby ponownie przemyśleć kodowanie.


a innym sposobem jest użycie słowa kluczowego global (oczywiście nie jest to najlepszy sposób).
Jocelyn

1
„Powinien” nie odpowiada na pytanie i może nie być najlepszym podejściem w każdym przypadku. W przypadku prostych skryptów zmiana parametrów i dodawanie klas jest niewygodne. Podobnie jak JavaScript, w PHP nie wszystko musi być zorientowane obiektowo i mieć przestrzeń nazw w wazoo.
Beejor

@Beejor Biorąc pod uwagę, że OP ma funkcję o nazwie menugen(), oznacza to, że będzie więcej niż tylko generowanie menu. Na przykład, co z rozszerzeniem tego menu, aby dodać więcej elementów z innego źródła, co z wyborem aktualnie wybranej strony, która jest w menu. Posiadanie losowych globalnych zmiennych i logiki w całym miejscu wymaga projektowania OOP. Fakt, że PHP / JS nie musi mieć struktury, jest jednym z największych powodów, dla których znajdujesz dużo niechlujnego, niezgrabnego kodu. Można to zrobić bardzo dobrze, ale pozwala ludziom nie myśleć o możliwościach utrzymania w przyszłości.
webnoob,

ps Głosowanie w dół odpowiedź również jest trochę nieaktualne. Odpowiedź dostarcza rozwiązania problemu PO, tylko dlatego, że ci się nie podoba, nie oznacza, że ​​jest źle.
webnoob

1
@Beejor - Problem z tym argumentem polega na tym, że ludzie mogą pomyśleć, że potrzebują zmiennej globalnej, ponieważ nie wiedzą nic lepszego i nie będą wiedzieć nic lepszego, chyba że im powiedzą.
webnoob

11

Inny sposób na zrobienie tego:

<?php

$data = 'My data';

$menugen = function() use ($data) {

    echo "[".$data."]";
};

$menugen();

UPDATE 2020-01-13: na wniosek Petera Mortensena

Od PHP 5.3.0 mamy obsługę anonimowych funkcji, które mogą tworzyć domknięcia. Zamknięcie może uzyskać dostęp do zmiennej, która została utworzona poza jego zakresem.

W tym przykładzie zamknięcie ma dostęp, $dataponieważ zostało zadeklarowane w useklauzuli.


To było jedyne działające rozwiązanie w moim przypadku, w którym miałem funkcję zdefiniowaną jako zmienna wewnątrz innej funkcji. Globalny tam nie działał.
Kar.ma

Wytłumaczenie byłoby w porządku. Np. Do czego służy ta rzecz? W jakich wersjach PHP jest to obsługiwane? (Prosimy o odpowiedź, edytując swoją odpowiedź , a nie w komentarzach (jeśli dotyczy). Z góry dziękujemy.)
Peter Mortensen,

Nie wiem, dlaczego zatwierdzone odpowiedzi nie pokazują żadnych wyników na stronie wtyczki administratora Wordpress, ale te odpowiedzi działają dobrze.
Naimur Hasan

3

Od wielu lat używam tego formatu:

<?php
    $data = "Hello";

    function sayHello(){
        echo $GLOBALS["data"];
    }

    sayHello();
?>

Uważam to za proste i łatwe do naśladowania. $ GLOBALS to sposób, w jaki PHP umożliwia odwoływanie się do zmiennej globalnej. Jeśli używałeś takich rzeczy jak $ _SERVER, $ _POST, itp., To masz odwołanie do zmiennej globalnej, nie wiedząc o tym.


Który? $GLOBAL(tekst) czy $GLOBALS(przykładowy kod)? (Prosimy o odpowiedź, edytując swoją odpowiedź , a nie w komentarzach (jeśli dotyczy).)
Peter Mortensen,

to $ GLOBALS, a nie $ GLOBAL. Powinien pojawić się „S”. Następnie odwołaj się do nazwy zmiennej jak klucza do tablicy asocjacyjnej.
Psalms Kalu,

Proszę zaktualizować swoją odpowiedź edytując je (aby rozpocząć edycję , kliknij przycisk Edytuj , między „akcję” i „flagi” Te trzy są po lewej stronie. - na lewo od „edycja” i „odpowiedzi” , po odpowiedzi sama, nad tym komentarzem, a przede wszystkim trzy komentarze tutaj). Informacje w komentarzach mogą zniknąć w dowolnym momencie. To nie jest forum - informacje można (i należy) aktualizować tutaj. Z góry bardzo dziękuję.
Peter Mortensen


0
<?php

    $data = 'My data';

    $menugen = function() use ($data) {

        echo "[ $data ]";
    };

    $menugen();
?>

Możesz też uprościć

echo "[" . $data . "]"

do

echo "[$data]"

echo "[" . $data . "]"i echo "[ $data ]"nie są takie same (dwie dodatkowe spacje na wyjściu dla tego ostatniego).
Peter Mortensen

0

Z tego powodu PHP może być frustrujące. Powyższe odpowiedzi globalnie zadziałały w moim przypadku i zajęło mi trochę czasu, zanim wymyśliłem prawidłowe użycieuse .

To jest poprawne:

$functionName = function($stuff) use ($globalVar) {
 //do stuff
}
$output = $functionName($stuff);
$otherOutput = $functionName($otherStuff);

To jest niepoprawne:

function functionName($stuff) use ($globalVar) {
 //do stuff
}
$output = functionName($stuff);
$otherOutput = functionName($otherStuff);

Na podstawie twojego konkretnego przykładu:

    $data = 'My data';

    $menugen = function() use ($data) {
        echo "[" . $data . "]";
    }

    $menugen();

-1

Jeśli chcesz, możesz użyć funkcji „define”, ale ta funkcja tworzy stałą, której po zdefiniowaniu nie można zmienić.

<?php
    define("GREETING", "Welcome to W3Schools.com!");

    function myTest() {
        echo GREETING;
    }

    myTest();
?>

Stałe PHP


To definiuje stałą globalną, a nie zmienną.
Beejor

3
Po zdefiniowaniu stałych nie można zmienić.
Beejor
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.