简体   繁体   English

方法链与可变变量

[英]Method chaining with variable variables

The API that I'm using (ConnectPHP of Oracle Service Cloud) follows the chaining approach. 我正在使用的API(Oracle Service Cloud的ConnectPHP)遵循链接方法。 For example: 例如:

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

How would I go about achieving the same if the subsequent properties of the $incident object are generated dynamically? 如果$incident对象的后续属性是动态生成的,我将如何实现相同的目标? For example: 例如:

$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();

What I tried 我尝试了什么

$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();

If there is no risk of user input , you can create string of all object keys and use eval like this 如果没有用户输入的风险 ,则可以创建所有对象键的字符串,并使用eval这样

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

Live demo : https://eval.in/923232 现场演示: https : //eval.in/923232

OUTPUT is as 输出为

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

        )

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

        )

)

and now you can easily access like $incident->CustomFields->c->make 现在您可以轻松地访问$incident->CustomFields->c->make

@kranthi is technically right( in the comment ), I given the implementation. @kranthi在技术上是正确的( 在注释中 ),我给出了实现。

So, kranthi was on the right track. 因此,kranthi走在正确的道路上。

$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);
   }
}

The trick was to pass the whole $incident object as a function argument (I think that's called as dependency injection if I'm not wrong) and using -> as a literal instead of a string that resided inside a variable. 诀窍是将整个$incident对象作为函数参数传递(如果我没记错的话,我认为这称为依赖项注入),然后使用->作为文字而不是驻留在变量内的字符串。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM