Метод цепочки с переменными переменными

API, который я использую (ConnectPHP Oracle Service Cloud), использует подход цепочки. Например:

$incident = new Incident();
$incident->CustomFields->c->make = "Same value";
$incident->StatusWithType->Status->ID = 34;
$incident->save();

Как бы я пошел на достижение того же, если последующие свойства $incident объект генерируется динамически? Например:

$data = array();
$data[0]['parts'] = array('CustomFields', 'c', 'make');
$data[0]['value'] = "Some value";

$data[1]['parts'] = array('StatusWithType', 'Status', 'ID');
$data[1]['value'] = 34;

$incident = new Incident();
foreach($data as $array)
{
foreach($array['parts'] as $key)
{
// how will I generate
// (1) $incident->CustomFields->c->make = $array['value']
// (2) $incident->StatusWithType->Status->ID = $array['value']
}
}
$incident->save();

Что я пробовал

$incident = new Incident();
foreach($data as $array)
{
$parts = implode('->', $array['parts']);
$incident->{$parts} = $array['value']; // this doesn't work even though $parts is coming out with the expected pattern because I think it is converting it into a string representation
}
$incident->save();

0

Решение

Если нет риска ввода пользователя , Вы можете создать строку всех ключей объекта и использовать Eval как это

$incident = new stdClass();
foreach($data as $key=>$chain){
$str = "{'".implode("'}->{'",$chain['parts'])."'}";
eval("@\$incident->$str = '$chain[value]';");
}
print_r($incident);

Живая демоверсия: https://eval.in/923232

ВЫХОД как

stdClass Object
(
[CustomFields] => stdClass Object
(
[c] => stdClass Object
(
[make] => Some value
)

)

[StatusWithType] => stdClass Object
(
[Status] => stdClass Object
(
[ID] => 34
)

)

)

и теперь вы можете легко получить доступ, как $incident->CustomFields->c->make

@kranthi технически прав (в комментарии), Я дал реализацию.

1

Другие решения

Итак, Кранти был на правильном пути.

$incident = new Incident();
foreach($data as $array)
{
$this->setDynamicFields($incident, $array['parts'], $array['value']);
}
$incident->save();

function setDynamicFields($obj, $parts, $value)
{
if(is_array($parts) && count($parts) == 3)
{
$obj->{$parts[0]}->{$parts[1]}->{$parts[2]} = ($parts[0] == 'StatusWithType' ? (int) $value: $value);
}
}

Хитрость заключалась в том, чтобы пройти весь $incident объект в качестве аргумента функции (я думаю, это называется внедрением зависимости, если я не ошибаюсь) и использование -> как литерал вместо строки, находящейся внутри переменной.

0

По вопросам рекламы [email protected]