PHPUnitのBootstrapでは変数が自動で$GLOBALSに追加されない

# <i class="fa fa-cubes"></i> 概要

通常、グローバルスコープで定義された変数`$foo`は、同時に`$GLOBALS['foo']`でも[参照できます。]

しかし、PHPUnitのBootstrapに指定したファイルで定義されるグローバル変数は、Bootstrap中では`$GLOBALS`に追加されません。
ただし、テスト中[^1]の`$GLOBALS`には、Bootstrapで定義された変数も参照できます。
また、`$GLOBALS['foo'] = 'foo'`と直接代入した場合でも、Bootstrap内で使用できるようです。

[参照できます。]:http://php.net/manual/ja/reserved.variables.globals.php

# <i class="fa fa-code"></i> コード

## 構成

```
.
|-- run.php
|-- src
|   |-- bootstrap.php
|   `-- hoge.php
`-- tests
    `-- hogeTest.php

```

## bootstrap.php

グローバル変数を定義するファイルです。

```php:bootstrap.php

<?php

require 'hoge.php';

$global = 'global';
var_dump($GLOBALS['global']); // PHPunitではNotice

$GLOBALS['direct'] = 'direct';
var_dump($GLOBALS['direct']); // どちらでも正常

```

## hoge.php

グローバル変数を参照するクラスです。
`static`なのは、問題を見つけたときのメソッドが`static`だったからです。

```php:hoge.php

<?php


class Hoge
{

        static function huga()
        {
                echo $GLOBALS['global'];
        }

        static function direct()
        {
                echo $GLOBALS['direct'];
        }
}

```

## run.php

普通に呼び出す場合のファイルです。

```php:run.php

<?php

include 'src/bootstrap.php';

Hoge::huga();
Hoge::direct();


```

## hogeTest.php

PHPUnitのテストケースです。

```php:hogeTest.php

<?php

class HogeTest extends PHPUnit_Framework_TestCase
{
        public function testHuga()
        {
                Hoge::huga(); // テスト内では定義されている
                $this->expectoutPutString('global');
        }

        public function testDirect()
        {
                Hoge::direct();
                $this->expectoutPutString('direct');
        }
}



```


# <i class="fa fa-play"></i> 実行結果

## run.php

```shell-session

# php run.php
string(6) "global"
string(6) "direct"
globaldirect#

```

Bootstrap内で`$GLOBALS['global']`が定義されていますし、`class Hoge`も問題なしです。

## PHPUnit

```shell-session

# phpunit --bootstrap src/bootstrap.php  tests
PHP Notice:  Undefined index: global in /tmp/phpunittest/src/bootstrap.php on line 6
NULL
string(6) "direct"
PHPUnit 3.7.38 by Sebastian Bergmann.

..

Time: 330 ms, Memory: 2.50Mb

OK (2 tests, 2 assertions)
#


```

Bootstrap内では`$GLOBALS['global']`が未定義となり、エラーと`Null`になっています。
直接代入した`$GLOBALS['direct']`は表示されますし、
テストでは両方共正常に定義されて、テストをパスしています。

`--no-globals-backup`オプションも関係無いようです。

# 何が困るか

Laravelの動作環境を判定して、開発中にしか動作しないロガーを`start.php`で呼び出しているのですが
(Bootstrap内で`Hoge::huga()`を呼び出す感じ)
PHPUnitで毎回Noticeエラーとなる。
開発中しか意味が無い機能なので、エラーで正しく動いていなくても問題ないのですが、
今後、(Laravel由来の)`$GLOBALS`要素を参照する機能をBootstrapに追加したときに、テストで正しく動かない可能性がある。
また、テストでのエラーを回避することのためだけに、通常では必ず定義されている変数の定義チェックを追加しなければならないのは、ちょっと敗北気分。

何より、なぜこうなるかが不明なので、今後の開発がすこし不安になります…

***

# Laravel3での動作環境取得改善策(PHPUnit無関係)

ここからは完全に自分用です。

[Laravel３の動作環境モード]

>ちなみに、Laravelによって判断された環境はグローバル変数の`environment`として参照できます。

とあったので、今まで`$GLOBALS['environment']`を参照していました。
`$environment`の定義元は`core.php`

```php:core.php

if (Request::cli())
{
	$environment = get_cli_option('env', getenv('LARAVEL_ENV'));

	if (empty($environment))
	{
		$environment = Request::detect_env($environments, gethostname());
	}
}
else
{
	$root = Request::foundation()->getRootUrl();

	$environment = Request::detect_env($environments, $root);
}

/*
|--------------------------------------------------------------------------
| Set The Application Environment
|--------------------------------------------------------------------------
|
| Once we have determined the application environment, we will set it on
| the global server array of the HttpFoundation request. This makes it
| available throughout the application, though it is mainly only
| used to determine which configuration files to merge in.
|
*/

if (isset($environment))
{
	Request::set_env($environment);
}

```

で、定義されています。
今回の問題が起きてから初めてしっかり読んだのですが。

よく読むと、`Request`に`$environment`がセットされていることがわかります。
PHPUnit時の問題は、`$environment`がちゃんと定義されているのに、`$GLOBALS`には定義されない、です。
なので、`Request`にも本来`$GLOBALS`に入るハズだった値が格納されていることになります。
なので、`$GLOBALS['environment']`としていたところを、`Request::env()`とすることで、PHPUnitでのテスト中でも、動作環境を取得できました。
また、目的の動作環境かの判定も、`$GLOBALS['environment'] == 'dev'`ではなく`Request::is_env('dev')`で`bool`が取得できることが判明しました。



[Laravel３の動作環境モード]:http://kore1server.com/15/Laravel%EF%BC%93%E3%81%AE%E5%8B%95%E4%BD%9C%E7%92%B0%E5%A2%83%E3%83%A2%E3%83%BC%E3%83%89
[^1]: テストで使用するクラスが使う