Использование констант в пространствах имен

#php #namespaces #constants

#php #пространства имен #константы

Вопрос:

Я работаю с пространствами имен и PHP 5.3 в своем проекте framework. У меня есть основной App класс и Autoloader класс. В App классе я настроил несколько переменных среды:

 public static function setupEnv()
        {
            $os = 'UNIX';
            if (stristr(PHP_OS,'WIN'))
            {
                $os = 'WIN';
            }

            if (!defined('DIRECTORY_SEPARATOR'))
            {
                define('DIRECTORY_SEPARATOR',($os == 'UNIX') ? '/' : '\');

            }
            define('DS', DIRECTORY_SEPARATOR);

            if (!defined('PATH_SEPARATOR'))
            {
                define('PATH_SEPARATOR', ($os == 'UNIX') ? ':' : ';');
            }
            define('PS', PATH_SEPARATOR);

            if (!defined('APP_PATH'))
            {
                define('APP_PATH', dirname(dirname(__FILE__)));
                define('AP', APP_PATH);
            }
        }
  

Константы определяются правильно, и DIRECTORY_SEPARATOR и DS , и если я повторяю их здесь, они работают просто отлично. Пространство имен для этого — FeatherApp . В Autoloader классе я использую DS константу, и она просто отлично работает. Autoloader Класс находится в том же пространстве имен Feather App.

Я запускаю PHPUnit и создал этот тест — setupEnv() вызывается в setUp() функции PHPUnit:

 public function testAutoloadFunction()
    {
        $this->assertEquals(
            dirname(dirname(__FILE__)) . DS.'Components'.DS.'Collections'.DS.'Collection.php',
            FeatherAppAutoloader::Autoload('\Feather\Components\Collections\Collection')
        );
    }
  

Это не проходит тест, хотя путь возвращается правильно. В нем говорится:

Use of undefined constant DS - assumed 'DS'

Итак, это большая предыстория, чтобы ответить на мой вопрос — почему это ошибка? Я подумал, хорошо, может быть, мне нужно ссылаться на FeatherAppDS, но это приводит к следующему:

PHP Fatal error: Undefined constant 'FeatherAppDS' in /web/Feather/Tests/AutoloaderTest.php

Я думал, что константы были определены в глобальной области, так что разве это не должно работать? Если нет, то как мне заставить это работать, чтобы PHPUnit был доволен? Если я помещаю use FeatherApp вверху, он все равно завершается с той же assumed 'DS' ошибкой.

Кто-нибудь может это объяснить? Документация по PHP пока бесполезна!

Комментарии:

1. Одно из ваших наблюдений, должно быть, неверно. Константы не были определены, поэтому setupEnv() метод и / или App класс не были запущены до unittest .

2. Если я попытаюсь выполнить эхо DS перед setupEnv() командой, оно будет пустым / неопределенным. Если я повторяю его после setupEnv() , оно определено. Это не константа, определенная в другом месте. Итак, тот факт, что модульный тест использует правильное значение для DS , я бы сказал иначе.

3. Добавьте assert('defined("DS")'); в этот метод unittest, чтобы узнать больше. И добавьте print "setupEnv" в функцию инициализации для отладки.

4. Интересно, я только что протестировал на рабочей станции Windows с помощью WAMP, и это работает… но на моей рабочей станции Linux это не удается. Я еще немного покопаюсь в этом сегодня вечером.

5. ХОРОШО — я понятия не имею, что я сделал, но сейчас это работает. Я думаю, проблема в том, что я не проверял if (!defined('DS')) , и когда setUp() функция выполнялась в последующих тестах, это вызывало проблемы. Это мое лучшее предположение. Теперь код работает!

Ответ №1:

У меня была очень похожая проблема, и я запустил тесты со следующими шагами:

  1. Маркировка тестов @runInSeparateProcess аннотацией

  2. Переопределение run() в тестовом классе следующим образом:

    публичная функция run(PHPUnit_Framework_TestResult $result = NULL) { $this->setPreserveGlobalState(false); возвращает parent::run($result); }

  3. Ввод require_once() , который приводит к определению константы в тестовом файле, в setUp() :

    общедоступная функция setUp() { require_once DIR.’/SetUpEnv.php ‘; }

Возможно, это не идеальное решение, но оно, несомненно, лучше, чем отсутствие решения вообще.

Я вычеркнул фрагменты (или, может быть, все целиком) из других ответов на StackOverflow и / или в других местах, но прошло некоторое время, поэтому приношу извинения источникам, которые я здесь не цитирую.