Доступ до глобальної змінної у функції PHP


84

Згідно з найбільш правилами обсягу мов програмування, я можу отримати доступ до змінних, які визначені поза функціями всередині них, але чому цей код не працює?

<?php
    $data = 'My data';

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

    menugen();
?>

Вихідний результат [].


3
Не сприймайте це як глобальне, передайте його функції як аргумент
Марк Бейкер

2
Де в посібнику говориться про такі речі?
обдурити


Перевірте другий приклад на цій сторінці: php.net/manual/en/language.variables.scope.php
Amin Gholibeigian

afaik ми можемо отримати доступ за допомогою $ GLOBALS ['varname'], де індексом "varname" є $ varname поза функцією. Фактично ми можемо використовувати print_r ($ GLOBALS) для перегляду всіх глобальних змінних.
Ахмад

Відповіді:


165

Це не працює, оскільки вам потрібно оголосити, до яких глобальних змінних ви будете отримувати доступ:

$data = 'My data';

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

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

menugen();

В іншому випадку ви можете отримати до нього доступ як $GLOBALS['data']. Див області видимості змінних .

Навіть якщо це трохи не в темі, я б запропонував вам взагалі уникати використання глобалів і віддавати перевагу передаванню як параметрам.


Дякую, Ви маєте рацію, але вони не використовували цей рядок у другому прикладі посібника: php.net/manual/en/language.variables.scope.php
Амін Голібейгій

6
Насправді той другий приклад був там, щоб показати читачам, чого не можна робити: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.
Маттео Тассінарі,

2
Боже! Мені довелося увійти в систему, щоб проголосувати за цю відповідь лише тому, що я моторошно забув обсяг змінних php.
Milche Patern

20

Ви можете зробити одне з наступного:

<?php
    $data = 'My data';

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

    menugen();

Або

<?php
    $data = 'My data';

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

    menugen();

Зважаючи на це, надмірне використання глобалів може призвести до поганого коду. Зазвичай краще передати те, що вам потрібно. Наприклад, замість посилання на глобальний об'єкт бази даних ви повинні передати дескриптор до бази даних і діяти відповідно до цього. Це називається введенням залежності . Це значно полегшує вам життя, коли ви впроваджуєте автоматизоване тестування (що і слід).


13

Це питання сфери застосування. Коротше кажучи, слід уникати глобальних змінних так :

Вам або потрібно передати його як параметр:

$data = 'My data';

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

Або мати його в класі та отримати до нього доступ

class MyClass
{
    private $data = "";

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

}

Дивіться також відповідь @MatteoTassinari, оскільки ви можете позначити її як глобальну, щоб отримати до неї доступ, але загальнозмінні змінні, як правило, не потрібні, тому було б розумно переглянути своє кодування.


а інший спосіб - використовувати ключове слово global (це не найкращий спосіб).
Джоселін

1
"Повинен" не відповідає на запитання, і це може бути не найкращим підходом для кожного випадку. Для простих сценаріїв зміна параметрів навколо та додавання класів є незграбним. Подібно до JavaScript, у PHP не все повинно бути об'єктно-орієнтованим та розміщеним у wazoo.
Беджор

@Beejor Враховуючи, що OP має функцію, яка називається, menugen()це означає, що буде більше, ніж просто створення меню. Наприклад, як щодо розширення цього меню, щоб додати більше елементів з іншого джерела, що щодо вибору поточної вибраної сторінки, яка знаходиться в меню. Наявність випадкових глобальних варіацій та логіки всюди кричить про дизайн ООП. Той факт, що PHP / JS не потребує структурування, є однією з найбільших причин, через яку ви виявляєте багато безладного незграбного коду. Це можна зробити дуже добре, але дозволяє людям не думати про ремонтопридатність у майбутньому.
webnoob

ps голосування вниз, відповідь також трохи відхилена. Відповідь дає рішення проблеми OP, лише тому, що вона вам не подобається, не робить її неправильною.
webnoob

1
@Beejor - Проблема цього аргументу полягає в тому, що люди можуть думати, що їм потрібна глобальна змінна, оскільки вони не знають кращого і не знатимуть кращого, якщо їм не скажуть.
webnoob

11

Ще один спосіб зробити це:

<?php

$data = 'My data';

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

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

$menugen();

ОНОВЛЕННЯ 2020-01-13: запит Пітера Мортенсена

Починаючи з PHP 5.3.0, ми маємо підтримку анонімних функцій, які можуть створювати закриття. Закриття може отримати доступ до змінної, яка створена поза її сферою дії.

У прикладі закриття може отримати доступ, $dataоскільки це було оголошено в useпункті.


Це було єдине робоче рішення в моєму випадку, коли у мене була функція, визначена як змінна всередині іншої функції. Глобал там не працював.
Kar.ma

Пояснення буде в порядку. Наприклад, що робить цей "вживаний" річ? Які версії PHP підтримуються цим "використанням"? (Будь ласка, дайте відповідь, відредагувавши свою відповідь , а не тут у коментарях (за потреби). Заздалегідь дякую.)
Пітер Мортенсен,

Не знаю, чому затверджений ans не відображає жодних результатів на сторінці плагіна для адміністрування Wordpress, але цей ans працює добре.
Наймур Хасан

3

Протягом багатьох років я завжди використовував такий формат:

<?php
    $data = "Hello";

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

    sayHello();
?>

Я вважаю, що це просто і легко дотримуватися. $ GLOBALS - це те, як PHP дозволяє посилатися на глобальну змінну. Якщо ви використовували такі речі, як $ _SERVER, $ _POST тощо, тоді у вас є посилання на глобальну змінну, не знаючи про це.


Який? $GLOBAL(текст) або $GLOBALS(зразок коду)? (Будь ласка, дайте відповідь, відредагувавши свою відповідь , а не тут, у коментарях (за потреби).)
Пітер Мортенсен,

це $ GLOBALS, а не $ GLOBAL. Має бути "S". Потім посилайтеся на ім’я змінної як на ключ до асоціативного масиву.
Psalms Kalu

Будь ласка, оновіть свою відповідь, відредагувавши її (щоб розпочати редагування , натисніть " редагувати " , між "поділитися" та "прапором" . Ці три знаходяться ліворуч - зліва від "відредаговано" та "відповіли" , після відповіді над цим коментарем і над усіма трьома коментарями тут). Інформація в коментарях може зникнути в будь-який момент. Це не форум - тут можна (і потрібно) оновлювати інформацію . Щиро дякую заздалегідь.
Пітер Мортенсен


0
<?php

    $data = 'My data';

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

        echo "[ $data ]";
    };

    $menugen();
?>

Ви також можете спростити

echo "[" . $data . "]"

до

echo "[$data]"

echo "[" . $data . "]"і echo "[ $data ]"не однакові (два зайвих пробіли у вихідних даних для останнього).
Пітер Мортенсен

0

З цієї причини PHP може розчарувати. Наведені вище відповіді globalдля мене не працювали, і мені знадобився деякий час, щоб з’ясувати правильне використання use.

Це вірно:

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

Це неправильно:

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

На вашому конкретному прикладі:

    $data = 'My data';

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

    $menugen();

-1

Якщо ви хочете, ви можете використовувати функцію "визначити", але ця функція створює константу, яку неможливо змінити після визначення.

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

    function myTest() {
        echo GREETING;
    }

    myTest();
?>

Константи PHP


Це визначає глобальну константу, а не змінну.
Беджор

3
Після визначення константи не можна змінювати.
Беджор
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.