Динамическое использование классов в PHP - PullRequest
0 голосов
/ 02 января 2019

Я пишу программу, которая обрабатывает географические координаты города, и я хочу случайным образом выбирать свой город в каждом прогоне;процесс для всех городов одинаков.

У меня есть класс PHP для каждого города, который содержит его географические координаты;например:

<?php
namespace Utility\Locations;
class Tehran
{
    const MIN_LAT = 35.325;
    const MAX_LAT = 35.390;
    const MIN_LNG = 51.165;
    const MAX_LNG = 51.230;
}

В другом PHP-файле я использую класс как:

use Utility\Locations\Tehran;
use Utility\Locations\Karaj;
...
protected function MyProcessingMethod () {
    ...
    $city =  Faker::create()->randomElement(array("Tehran", "Karaj"));
    echo $city::MIN_LAT;
    ...
}
...

Если это поможет, вышеупомянутый файл представляет собой CodeCeption Cest и MyProcessingMethod используется как DataProvider.Когда я запускаю свои тесты, используя codecept run scenarios/MyCest.php, я получаю эту ошибку:

PHP Fatal error:  Uncaught Error: Class 'Tehran' not found in /home/zeinab/PhpstormProjects/test/scenarios/MyCest.php:190
Stack trace:
#0 [internal function]: MyCest->MyProcessingMethod()
#1 /home/zeinab/PhpstormProjects/test/vendor/codeception/codeception/src/Codeception/Util/ReflectionHelper.php(47): ReflectionMethod->invokeArgs(Object(MyCest), Array)
#2 /home/zeinab/PhpstormProjects/test/vendor/codeception/codeception/src/Codeception/Test/Loader/Cest.php(65): Codeception\Util\ReflectionHelper::invokePrivateMethod(Object(MyCest), Object(ReflectionMethod))
#3 /home/zeinab/PhpstormProjects/test/vendor/codeception/codeception/src/Codeception/Test/Loader.php(109): Codeception\Test\Loader\Cest->loadTests('/home/zeinab/Ph...')
#4 /home/zeinab/PhpstormPro in /home/zeinab/PhpstormProjects/test/scenarios/MyCest.php on line 190

Я прочитал официальную документацию PHP по этому типу использования , но все примеры с использованиемклассы, которые определены в файле назначения.

Я также попробовал это:

$city =  Faker::create()->randomElement(array(Tehran::class, Karaj::class));
echo $city::MIN_LAT;

Но я получил ту же ошибку.

Есть ли в любом случае делать то, что я хочу?

РЕДАКТИРОВАТЬ 1: Я указал путь к классам в теге psr-4 моего composer.json:

"autoload": {
    "psr-4": {
        "Utility\\": "Utility/"
    }
}

Кажется, что нет никаких проблемв загрузке классов, так как их использование напрямую работает нормально.Например, следующий код работает отлично:

echo Tehran::MIN_LAT;

Ответы [ 2 ]

0 голосов
/ 02 января 2019

Я создал этот фрагмент кода в качестве примера - поэтому он может не полностью отражать ваши методы, но ответом является принцип:)

<?php
    # create our city classes
    class Brighton
    {
        const X = 1;
        const Y = 2;
    }

    class London
    {
        const X = 3;
        const Y = 4;
    }

    # create our get city class
    class Foo
    {
        public function getCity()
        {
            $possibleCities = ['Brighton', 'London', 'Birmingham']; # add a city that's not a class for testing
            $city = rand(0, count($possibleCities) -1);

            return $possibleCities[$city];
        }
    }

    # init foo
    $foo = new Foo();
    $city = $foo->getCity(); # get city

    # check if class exists, if it does, init it
    $cityClass = (class_exists($city) ? new $city() : null);

    # check if class is empty - if it isn't echo CONST X
    echo (!empty($cityClass) ? $cityClass::X : $city. ' class not found');

Как включить классы (если они находятся в отдельных файлах)):

Представьте, что дерево выглядит так:

|-app
|-----core
|---------city
|-------------Brighton.php
|-------------London.php
|-----Foo.php

В Foo.php

<?php
    require_once 'city/Brighton.php';
    require_once 'city/London.php';

    use City\Brighton;
    use City\London;

    # etc. etc

А затем у Brighton.php и London.php есть пространство имен City:

<?php
    namespace City;

    class Brighton
    {} # etc
0 голосов
/ 02 января 2019

добавить загрузчик в первую строку вашего кода:

function loader($className)
{
    $fileName = str_replace('\\', '/', $className) . '.php';
    require_once $fileName;
}
spl_autoload_register('loader');

затем используйте пространства имен, такие как структуры каталогов:

Ahvaz.php в каталоге app / core / city

namespace app\core\city;
class Ahvaz
{
//...
}

при загрузке класса Ahvaz.php вот так

$var = new Ahvaz();

нужно добавить use app\core\city;

тогда у вас есть:

use app\core\city;
$var = new Ahvaz();

будет включать Ahvaz.php из каталога app / core / city

...