#php #class #variables
#php #класс #переменные
Вопрос:
У меня есть класс и аргументы, установленные в переменной, подобной этой:
$myVar = 'ApiMyClass(DateTimeInterface::RFC3339_EXTENDED)';
Мне нужно сделать new
из этой переменной.
Я пробовал несколько решений, и в конце new
класс был решен, но я не могу передать аргумент.
Мой код:
<?php
$myVar = 'ApiMyClass(DateTimeInterface::RFC3339_EXTENDED)';
$className = substr($myVar, 0, strpos($myVar, "(")); // $className will be: ApiMyClass
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-dTH:i:s.vP"
// It doesn't work
$p = "DateTimeInterface::RFC3339_EXTENDED";
var_dump($p);
// return
string(36) "DateTimeInterface::RFC3339_EXTENDED"
вы можете мне помочь?
Спасибо.
Комментарии:
1. Могу я спросить ваш вариант использования? Я не могу придумать ни одного допустимого варианта использования, в котором вы могли бы получить такую строку.
Ответ №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 "$argn";
}
}
new MyClass('anything'); // outputs "anything"
Это просто помощник, который получает имя класса и строку аргумента из строки, подобной вашей $myVar
.
function parseClassAndArgument(string $str): array {
preg_match('/(.*)((.*))/', $str, $matches);
[, $className, $argument] = $matches;
return [$className, $argument];
}
Этот помощник позволяет вам передавать либо строковое значение, либо имя константы, и угадывает, какое из них основано на том, есть ли a ::
в имени строки. Вы можете заменить это только constant($argument)
частью, если вы знаете $myVar
, что она всегда будет содержать постоянное имя.
function parseArgValue(string $argument): string {
return strpos($argument, '::') ? constant($argument) : $argument;
}
Это распознает, что $argument
ссылается на константу, и выводит Y-m-dTH: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));
Это упрощенный пример, который обрабатывает только один параметр для конструктора класса, но я надеюсь, что это поможет вам!
Комментарии:
1. Конечно, вы могли бы включить синтаксический анализ строки аргумента внутри конструктора класса; нет необходимости делать это вне класса.