Edited at

再認識しておくPHPスコープ

More than 3 years have passed since last update.

どうもこんにちは

今回はPHPスコープの事について書きたいと思います

特別な事が書いているわけではないので上級PHPerの皆さんはスルーしましょう :bird:

今回の参照はもちろん公式です

変数のスコープ


スコープの種類

PHPのスコープの種類は3種類しかありません


  1. ローカルスコープ

  2. グローバルスコープ

  3. スーパーグローバル


ローカルスコープ

これは関数内スコープのことです

<?php

function func1()
{
$val = 'ローカルスコープ';
return $val;
}

echo $val;
echo func1();

これは以下のように出力されます

>                 // echo $val;

>ローカルスコープ // echo func1();

関数内で定義した変数$valが出力されないのでローカル変数として扱われていることが分かります

基本的にアプリケーションを作成していくときはローカルスコープを意識してプログラミングしていきましょう


グローバルスコープ

これは関数内で定義されていない変数のスコープになります

ただグローバルと付いていますが、関数内で直接使用する事は出来ません

<?php

$val = 'グローバルスコープ';

function func2()
{
return $val;
}

echo $val;
echo func2();

これを実行すると

echo $val;グローバルスコープという文字が出力されますが

echo func2();Undefined Variable: valと言われて$val変数を認識出来ません

これを認識できるようにする場合は

    function func2()

{
global $val; // globalキーワードを使用
return $val;
}

globalキーワードを使う事によって関数外の値を使用します

ただこのように外部の値を関数内で使用したい場合は、globalキーワードを使用するのではなく引数に追加しましょう

globalはプログラムを追うことを難しくしテストも書きにくくなってしまいます


スーパーグローバル

全てのスコープで使用できる組み込みの変数と書いてあります

これらがそうです


  • $GLOBALS

  • $_SERVER

  • $_GET

  • $_POST

  • $_FILES

  • $_COOKIE

  • $_SESSION

  • $_REQUEST

  • $_ENV

よく使いますね

ただ、どこでも使いたい変数を$GLOBALSに無闇に突っ込むのはやめましょう

これもグローバル変数と同じく追いづらいコードの素になります

特にglobal変数の値をバンバン変更している場合かなり危険です


関数以外の括弧でのスコープの検証

僕が長らくPHPを使っていながら気を遣っていなかったのがfor文を使う時に宣言する変数です

Scalaの場合

var num = 10

println(num)

for ( n <- (1 to 3) ) {
var num = n*3
println(num)
}

println(num)

出力結果

3

6
9
10

Scalaでvar使うんかいというのは置いておいて

for内で宣言した変数はその括弧内で完結します

最初に宣言したvar num = 10は、括弧内で同じ変数名numを宣言していても最後のprintln(num)で10を出力します

これを基準だと思い込んでいると罠にはまります

$i = 10;

println($i);

for ($i=1; $i<=3; $i++)
{
println($i);
}

println($i);

※printlnは自作の改行echo

出力結果

10

1
2
3
4

最後の出力で僕は10を期待していたのですが4が出力されてしまいました

for文は括弧内で完結するだろうと思っていたら上書きされてしまうので注意が必要です

if式でもただの括弧内でもScalaはスコープがありますが、PHPは関数内かそれ以外という分け方になっています

何となく書けてしまったままPHPをやっていたので普段はまらないようなところで期待した動作にならないことがありました

なんという事でしょう…変数名を被らせないようたゆまぬ努力が必要です


所感

Scala最高

関数をしっかり作ってスコープを意識すれば悲劇は起きずに済むとは思います、基本ですね

以上です