PHP中动态类的用法

时间:2019-01-02 09:03:04

标签: php class codeception

我正在编写一个处理城市地理坐标的程序,我想在每次运行中随机选择我的城市;所有城市的过程都相同。

每个城市都有一个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 official documentations on this type of usage,但是所有示例都使用了目标文件中定义的类。

我也尝试过:

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

但是我遇到了同样的错误。

反正有做我想做的事吗?

编辑1: 我在psr-4的{​​{1}}标签中放置了类的路径:

composer.json

加载类似乎没有问题,因为直接使用它们可以正常工作。例如,以下代码非常有用:

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

2 个答案:

答案 0 :(得分:0)

将加载程序添加到代码的第一行:

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

然后使用名称空间,例如目录结构:

  

app / core / city目录中的Ahvaz.php

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

当您加载这样的类 Ahvaz.php

$var = new Ahvaz();

您需要添加use app\core\city;

那么您就有了:

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

它将包含来自app / core / city目录的Ahvaz.php

答案 1 :(得分:0)

我出于示例目的创建了此代码段-因此它可能无法完全反映您的方法,但答案是原理:)

<?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具有城市名称空间:

<?php
    namespace City;

    class Brighton
    {} # etc