PHP関数でグローバル変数にアクセスする


84

ほとんどのプログラミング言語のスコープルールに従って、関数内の関数の外部で定義されている変数にアクセスできますが、このコードが機能しないのはなぜですか?

<?php
    $data = 'My data';

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

    menugen();
?>

出力は[]です。


3
グローバルとして扱わず、引数として関数に渡します
Mark Ba​​ker

2
マニュアルはどこにそのようなことを言っていますか?
–deceze


このページの2番目の例を確認してください:php.net/manual/en/language.variables.scope.php
Amin Gholibeigian 2013年

afaik $ GLOBALS ['varname']を使用してアクセスできます。ここで、インデックス "varname"は関数外の$ varnameです。実際、print_r($ GLOBALS)を使用してすべてのグローバル変数を表示できます。
アフマド

回答:


165

アクセスするグローバル変数を宣言する必要があるため、機能しいません。

$data = 'My data';

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

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

menugen();

それ以外の場合は、としてアクセスできます$GLOBALS['data']可変スコープを参照してください。

少し話題から外れたとしても、グローバルをまったく使用せず、パラメーターとして渡すことをお勧めします。


ありがとう、あなたは正しいですが、マニュアルの2番目の例ではこの行を使用していませんでした: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.
マッテオTassinari

2
ダン!php変数のスコープを不気味に忘れたという理由だけで、この回答に賛成するためにログインする必要がありました。
Milche Patern 2015

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の回答も参照してください。アクセスするにはグローバルとしてマークできますが、グローバル変数は通常必要ないため、コーディングを再考することをお勧めします。


もう1つの方法は、キーワードglobalを使用することです(もちろん、これは最善の方法ではありません)。
Jocelyn 2013年

1
「すべき」は質問に答えるものではなく、これがすべての場合に最適なアプローチであるとは限りません。単純なスクリプトの場合、パラメータを変更してクラスを追加するのは不格好です。JavaScriptと同じように、PHPでは、すべてがオブジェクト指向であり、wazooの名前空間である必要はありません。
Beejor 2016

@Beejor OPに呼び出される関数があることを考えると、menugen()単にメニューを生成するだけではなく、さらに多くのことが行われることを意味します。たとえば、そのメニューを拡張して別のソースからアイテムを追加する場合や、メニューにある現在選択されているページを選択する場合はどうでしょうか。ランダムなグローバル変数とロジックがいたるところにあると、OOP設計が叫ばれます。PHP / JSを構造化する必要がないという事実は、厄介な不格好なコードがたくさんある最大の理由の1つです。それは非常にうまく行うことができますが、人々は将来の保守性について考えることができません。
webnoob 2016

ps答えに反対票を投じることも少しずれています。答えは、OPの問題に対する解決策を提供します。それが気に入らないからといって、間違いを犯すことはありません。
webnoob 2016

1
@ Beejor-その議論の問題は、人々がグローバル変数が必要だと思うかもしれないということです。なぜなら、彼らはそれ以上のことを知らず、言われない限りそれ以上のことを知らないからです。
webnoob 2016

11

それを行う別の方法:

<?php

$data = 'My data';

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

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

$menugen();

更新2020-01-13:PeterMortensenからのリクエスト

PHP 5.3.0以降、クロージャを作成できる無名関数がサポートされています。クロージャは、そのスコープ外で作成された変数にアクセスできます。

この例では、クロージャは句で$data宣言されているため、アクセスできますuse


これは私の場合、別の関数内の変数として定義された関数を持っていた唯一の実用的な解決策でした。グローバルはそこでは機能しませんでした。
Kar.ma

説明が必要です。たとえば、この「使用」は何をするのでしょうか。この「使用」はどのPHPバージョンでサポートされていますか?(コメントではなく、回答を編集して返信してください(必要に応じて)。よろしく
PeterMortensen19年

承認されたansがWordpress管理プラグインページに出力を表示しない理由はわかりませんが、このansはうまく機能します。
NaimurHasan20年

3

何年もの間、私は常にこのフォーマットを使用してきました:

<?php
    $data = "Hello";

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

    sayHello();
?>

私はそれが簡単でわかりやすいと思います。$ GLOBALSは、PHPでグローバル変数を参照する方法です。$ _SERVER、$ _ POSTなどを使用したことがある場合は、それを知らなくてもグローバル変数を参照しています。


どれ?$GLOBAL(テキスト)または$GLOBALS(サンプルコード)?(コメントではなく、回答を編集して返信してください(必要に応じて))
PeterMortensen19年

$ GLOBALではなく$ GLOBALSです。「S」があるはずです。次に、連想配列へのキーのように変数名を参照します。
詩篇カル

回答を編集して更新してください(編集を開始するに編集」をクリックし、「共有」「フラグ」の間にあります。これら3つは左側、つまり「編集済み」「回答済み」の左側、回答後です。それ自体、このコメントの上、そしてここにある3つのコメントすべての上)。コメント内の情報はいつでも消えることがあります。これはフォーラムではありません。情報ここで更新できます(更新する必要があります)。よろしくお願いします。
PeterMortensen20年


0
<?php

    $data = 'My data';

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

        echo "[ $data ]";
    };

    $menugen();
?>

簡略化することもできます

echo "[" . $data . "]"

echo "[$data]"

echo "[" . $data . "]"echo "[ $data ]"は同じではありません(後者の出力には2つの余分なスペースがあります)。
ピーターモーテンセン

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

必要に応じて、「define」関数を使用できますが、この関数は、一度定義すると変更できない定数を作成します。

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

    function myTest() {
        echo GREETING;
    }

    myTest();
?>

PHP定数


これは、変数ではなく、グローバル定数を定義します。
Beejor 2016

3
一度定義した定数は変更できません。
Beejor 2016
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.