【问题标题】:Method chaining with variable variables带有可变变量的方法链
【发布时间】:2017-12-21 07:00:43
【问题描述】:

我使用的 API(Oracle 服务云的 ConnectPHP)遵循链接方法。例如:

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

【问题讨论】:

  • $incident->CustomFields->c->make 和 $incident->StatusWithType->Status->ID 是静态键,但您想用动态值更新它们吗??
  • 键也可能会改变...我只是以其中两个键为例。但是配对是固定的,即StatusWithType 后面总是跟Status->ID
  • so array('CustomFields', 'c', 'make') 应该是 CustomFields->c->make........ array('StatusWithType', 'Status', 'ID') 应该是StatusWithType->Status->ID........ array('1', '2', '3') => 1->2->3 。 .....像这样......你期待吗??
  • 是的,你是对的@kranthi
  • 请试试这个 foreach($data as $array) { $incident->{$array['parts'][0]}->{$array['parts'][1]} ->{$array['parts'][2]} = $array['value']; }

标签: php oop rightnow-crm oracle-service-cloud


【解决方案1】:

如果没有用户输入的风险,您可以创建所有对象键的字符串并像这样使用 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 在技术上是正确的(在评论中),我给出了实现。

【讨论】:

  • 谢谢。不幸的是,这确实包含用户输入。所以我不希望这样使用 go 。无论如何都赞成。我已经找到了解决方案,将发布一点以供参考。
【解决方案2】:

所以,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);
   }
}

诀窍是将整个 $incident 对象作为函数参数传递(如果我没记错的话,我认为这称为依赖注入)并使用 -> 作为文字而不是驻留在变量中的字符串.

【讨论】:

  • 如果数组中有 2 或 4 个元素,如 array('CustomFields', 'c');array('CustomFields', 'c', 'make','extra'); 怎么办?
  • @user2486 : 检查这个条件 if(is_array($parts) && count($parts) == 3) ????
  • @kranthi : 请分享你的答案
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-08-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-11-04
  • 2013-05-13
相关资源
最近更新 更多