【问题标题】:PHP - Make 'new' of a Class and Arguments set in a stringPHP - 在字符串中设置类和参数的“新”
【发布时间】:2020-12-10 08:20:45
【问题描述】:

我在一个变量中设置了一个类和参数,如下所示:

$myVar = '\Api\MyClass(\DateTimeInterface::RFC3339_EXTENDED)';

我需要为这个变量创建一个new

我尝试了多种解决方案,最后解决了 Class 的 new 但我无法通过参数。

我的代码是:

<?php

$myVar = '\Api\MyClass(\DateTimeInterface::RFC3339_EXTENDED)';
$className = substr($myVar, 0, strpos($myVar, "(")); // $className will be: \Api\MyClass
if (class_exists($className)) {
    preg_match('/\((.*?)\)/', $myVar, $classArguments); $classArguments will be: \DateTimeInterface::RFC3339_EXTENDED
    $obj = new $className($classArguments[1]); // it doesn't work
}

问题是$classArguments[1] 作为string 传递给我的班级。下面的区别:

// It works
$p = \DateTimeInterface::RFC3339_EXTENDED;
var_dump($p);

// and return
string(15) "Y-m-d\TH:i:s.vP"
// It doesn't work
$p = "\DateTimeInterface::RFC3339_EXTENDED";
var_dump($p);

// return
string(36) "\DateTimeInterface::RFC3339_EXTENDED"

你能帮帮我吗?

谢谢。

【问题讨论】:

  • 我能问一下你的用例吗?我想不出任何有效的用例可能最终得到这种字符串。

标签: php class variables


【解决方案1】:

New 只能用于创建实例。使您的构造函数期望该日期格式为默认格式,因此您不需要传递它。

class MyClass {
    public function __construct(string $dateFormat = DateTimeInterface::RFC3339_EXTENDED)
    {
    }
}

$var = 'MyClass';

$instance = new $var;
$p = "\DateTimeInterface::RFC3339_EXTENDED";

将不起作用,因为它现在是一个字符串而不是常量值。

你也可以传递类似的东西

class MyClass {
    public function __construct(string $something = '')
    {
        echo $something;
    }
}

$var = 'MyClass';
$text = 'Hello world';
$instance = new $var($text);

世界你好

如果您需要解析完整的字符串,请尝试eval()但不推荐

$var = 'new MyClass("hello world");';
$instance = eval($var);

世界你好

或者,但不推荐

$var = 'MyClass("hello world")';
$instance = eval("new {$var};");

世界你好

【讨论】:

    【解决方案2】:

    您可以使用constant 函数来获取常量的值。

    一个简单的示例类,初始化时只输出参数值。

    class MyClass
    {
        function __construct($arg) {
            echo "$arg\n";
        }
    }
    
    new MyClass('anything'); // outputs "anything"
    

    这只是一个帮助器,它从像您的 $myVar 这样的字符串中获取类名和参数字符串。

    function parseClassAndArgument(string $str): array {
        preg_match('/(.*)\((.*)\)/', $str, $matches);
        [, $className, $argument] = $matches;
        return [$className, $argument];
    }
    

    此帮助程序允许您传递字符串值或常量名称,并根据字符串名称中是否有:: 来猜测它是哪一个。如果您知道 $myVar 将始终包含一个常量名称,则可以仅将其替换为 constant($argument) 部分。

    function parseArgValue(string $argument): string {
        return strpos($argument, '::') ? constant($argument) : $argument;
    }
    

    这会识别出$argument 引用一个常量并输出Y-m-d\TH:i:s.vP

    $myVar = 'MyClass(\DateTimeInterface::RFC3339_EXTENDED)';
    [$className, $argument] = parseClassAndArgument($myVar);
    new $className(parseArgValue($argument));
    

    这会按原样输出字符串foo

    $myVar = 'MyClass(foo)';
    [$className, $argument] = parseClassAndArgument($myVar);
    new $className(parseArgValue($argument));
    

    这是一个仅处理类构造函数的一个参数的简化示例,但希望对您有所帮助!

    【讨论】:

    • 你当然可以在类构造函数中包含参数字符串解析;不需要在课外做。
    猜你喜欢
    • 1970-01-01
    • 2014-09-22
    • 1970-01-01
    • 1970-01-01
    • 2016-09-28
    • 2018-09-04
    • 2013-10-29
    • 1970-01-01
    • 2011-12-06
    相关资源
    最近更新 更多