在PHP函数中访问全局变量


82

根据大多数编程语言的作用域规则,我可以访问在函数内部定义的变量,但是为什么此代码不起作用?

<?php
    $data = 'My data';

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

    menugen();
?>

输出为[]


3
不要将其视为全局变量
Mark Ba​​ker

2
手册在哪里说这样的话?
deceze

相关阅读:PHP全局函数
Jocelyn


afaik我们可以使用$ GLOBALS ['varname']进行访问,其中索引“ varname”是函数外部的$ varname。事实上,我们可以使用print_r($ GLOBALS)查看所有全局变量。
艾哈迈德(Ahmad)

Answers:


162

它不起作用,因为您必须声明要访问的全局变量:

$data = 'My data';

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

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

menugen();

否则,您可以通过访问它$GLOBALS['data']。请参阅可变范围

即使有些偏离主题,我还是建议您完全避免使用全局变量,而更希望将其作为参数传递。


谢谢,您是对的,但是他们没有在手册的第二个示例中使用此行:php.net/manual/en/language.variables.scope.php
Amin Gholibeigian 2013年

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.
Matteo Tassinari

2
ang!我不得不登录以投票赞成这个答案,只是因为我令人毛骨悚然地忘记了php变量作用域。
Milche Patern

19

您可以执行以下操作之一:

<?php
    $data = 'My data';

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

    menugen();

要么

<?php
    $data = 'My data';

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

    menugen();

话虽这么说,过度使用全局变量可能会导致某些不良代码。通常最好传递您的需求。例如,应该引用数据库的句柄并对其执行操作,而不是引用全局数据库对象。这称为依赖注入。实施自动化测试(应该这样做)会使您的生活变得更加轻松。


12

这是范围的问题。简而言之,应避免使用全局变量,因此

您要么需要将其作为参数传递:

$data = 'My data';

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

或者将其放在班级中并访问

class MyClass
{
    private $data = "";

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

}

也可以参见@MatteoTassinari答案,因为您可以将其标记为全局访问,但通常不需要全局变量,因此重新考虑编码是明智的。


另一种方法是使用关键字global(当然,这不是最好的方法)。
乔斯林

1
“应该”不能回答问题,这可能不是每种情况的最佳方法。对于简单的脚本,更改参数和添加类比较麻烦。就像JavaScript一样,在PHP中,并非所有事物都需要面向对象并在wazoo中进行命名空间。
Beejor

@Beejor鉴于OP具有一个称为menugen()它的功能,这意味着要完成的工作不仅仅是生成菜单。例如,如何扩展菜单以从其他来源添加更多项目,以及如何选择菜单中当前选定的页面。到处都是随机的全局变量和逻辑,这为OOP设计大声疾呼。不需要构造PHP / JS的事实是您发现许多混乱的笨拙代码的最大原因之一。它可以做得很好,但是却使人们不必考虑未来的可维护性。
webnoob

ps不赞成投票的答案也有些偏离。答案确实为OP的问题提供了解决方案,只是因为您不喜欢它,并没有使它出错。
webnoob

1
@Beejor-该论点的问题在于人们可能认为他们需要一个全局变量,因为他们不了解任何东西,除非被告知,否则他们不会知道任何更好的东西。
webnoob

10

另一种方法是:

<?php

$data = 'My data';

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

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

$menugen();

2020年1月13日更新:彼得·莫滕森的要求

从PHP 5.3.0开始,我们提供了可以创建闭包的匿名函数支持。闭包可以访问在其范围之外创建的变量。

在示例中,闭包能够访问,$data因为它是在use子句中声明的。


在我的案例中,这是唯一可行的解​​决方案,其中我将一个函数定义为另一个函数中的变量。Global在那里没有工作。
Kar.ma

一个解释将是有条理的。例如,这种“使用”方式有什么用?此“使用”功能支持哪些PHP版本?(请通过编辑您的回答来回答,而不是在注释中(适当时在此处提供。提前致谢。)
Peter Mortensen

不知道为什么批准的ans在Wordpress管理插件页面中不显示任何输出,但是此ans确实可以很好地工作。
Naimur Hasan

3

多年以来,我一直使用这种格式:

<?php
    $data = "Hello";

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

    sayHello();
?>

我发现它简单易懂。$ GLOBALS是PHP允许您引用全局变量的方式。如果您使用过$ _SERVER,$ _ POST等,那么您将引用全局变量而不知道它。


哪一个?$GLOBAL(文本)还是$GLOBALS(示例代码)?(请通过编辑您的回答来回答,而不是在注释中(适当时在此处)。)
Peter Mortensen

是$ GLOBALS而不是$ GLOBAL。应该有一个“ S”。然后,将您的变量名引用为关联数组的键。
诗篇卡卢

通过编辑来更新您的答案(要开始编辑,请在共享”“标记”之间单击编辑。这三个位于答案的左侧- “已编辑”“已回答”的左侧)本身,在此评论上方以及此处的所有三个评论上方)。评论中的信息随时可能消失。这不是论坛-可以(并且应该)在此处更新信息。确实非常感谢您。
Peter Mortensen

0

您需要将变量传递给函数:

$data = 'My data';

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

0
<?php

    $data = 'My data';

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

        echo "[ $data ]";
    };

    $menugen();
?>

您也可以简化

echo "[" . $data . "]"

echo "[$data]"

echo "[" . $data . "]"echo "[ $data ]"不相同(后者的输出中有两个额外的空格)。
彼得·莫滕森

-1

如果需要,可以使用“定义”功能,但是此功能会创建一个常量,一旦定义就无法更改。

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

    function myTest() {
        echo GREETING;
    }

    myTest();
?>

PHP常量


这定义了全局常量,而不是变量。
Beejor

3
常量一旦定义就无法更改。
Beejor
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.