【问题标题】:PHP Object, set multiple propertiesPHP Object,设置多个属性
【发布时间】:2012-05-13 04:07:16
【问题描述】:

是否可以在 php 中一次为一个对象设置多个属性? 而不是这样做:

$object->prop1 = $something;
$object->prop2 = $otherthing;
$object->prop3 = $morethings;

做一些类似的事情:

$object = (object) array(
    'prop1' => $something,
    'prop2' => $otherthing,
    'prop3' => $morethings
);

不覆盖对象

【问题讨论】:

  • 为什么要以这种方式混淆代码的作用?在未来的某个时候,某人(也许是你)将需要阅读这段代码,而这样做只会使其更难理解。
  • 为什么不把它粘贴到一个 php 文件中并运行它呢?与其在这里问是否可行,不如自己尝试一下。
  • 只需创建一个辅助函数来为您完成。传入对象和数组。
  • 它看起来很糟糕而且代码更多,你为什么需要它?

标签: php oop object


【解决方案1】:

不像你想要的那样。但这可以通过使用循环来完成。

$map =  array(
    'prop1' => $something,
    'prop2' => $otherthing,
    'prop3' => $morethings
);

foreach($map as $k => $v)
    $object->$k = $v;

只看到额外的 2 行。

【讨论】:

  • 不是多 2 行,而是 50% 多行;更糟糕的是,如果只有两个属性要设置。实际上,如果我们不作弊并使用 bug-preventors {},这只是 3 行。
  • @Pacerier 我希望你在拖钓。在实际用例中,这样的数组可以保存数百个值。当然,如果你只提交 2 个值,那就是额外的工作,因为它是三行。但是,如果您使用具有 358 个值的数组,则此解决方案将停留在三行。
  • @Holonaut,这是一个严肃的评论,而不是巨魔评论。当然,肯定会有数百个值的用例,但许多用例只有两个、三个或四个值。
  • @Pacerier 您无法判断哪个用例出现的频率更高。 OP 的问题是关于设置多个属性,答案是有效的。他的示例数组有 3 个值这一事实只是偶然的,应该被视为从 2 到 * 的任何值。实现这一目标的答案是正确的,您只是没有看到大局。
【解决方案2】:

你应该看看Object Oriented PHP Best Practices

“由于 setter 函数返回 $this,你可以像这样链接它们:”

 $object->setName('Bob')
        ->setHairColor('green')
        ->setAddress('someplace');

顺便说一句,这被称为fluent interface

【讨论】:

  • 这是完全不同的事情。他正在谈论创建变量属性的快捷方式,这与您的答案无关。
  • 如果你一直在谈论使用public function __set($k, $v){ $this->$k=$v; return $this;},那么它仍然不起作用,因为(($obj->k="v")->k2)="v2"; 是语法错误。
  • 为什么会有 8 个赞?它与被问到的问题无关......?
【解决方案3】:

我建议你不要这样做。说真的,不要

您的代码在第一种方式中要干净得多,它更清楚您的意图,并且您不会将代码的注意力集中到将来某个时候有人会看到您的代码并认为“到底是什么白痴思考”?

如果你坚持做一些显然是错误的事情,你总是可以创建一个数组,迭代它并在一个循环中设置所有属性。不过我不会给你代码。这是邪恶的。

【讨论】:

  • 不正确。其他语言也有这种语法,它们被誉为干净的代码。这取决于您如何使用它。
【解决方案4】:

您可以为返回对象的对象编写一些设置器:

public function setSomething($something)
{
 $this->something = $something;
 return $this; //this will return the current object
}

你可以这样做:

$object->setSomething("something")
       ->setSomethingelse("somethingelse")
       ->setMoreThings("some more things");

您需要为每个属性编写一个 setter,因为 __set 函数无法返回值。

或者,设置一个函数来接受一组属性 => 值并设置所有内容?

public function setProperties($array)
{
  foreach($array as $property => $value)
  {
    $this->{$property} = $value;
  }
  return $this;
}

并传入数组:

$object->setProperties(array('something' => 'someText', 'somethingElse' => 'more text', 'moreThings'=>'a lot more text'));

【讨论】:

  • “需要为每个属性编写一个设置器,因为 __set 函数无法返回值”。请参阅我的答案以了解解决方法。
【解决方案5】:

我意识到这是一个老问题,但为了其他遇到它的人的利益,我最近自己解决了这个问题并想分享结果

<?php
    //Just some setup
    header('Content-Type: text/plain');
    $account = (object) array(
        'email' => 'foo',
        'dob'=>((object)array(
            'day'=>1,
            'month'=>1,
            'year'=>((object)array('century'=>1900,'decade'=>0))
        ))
    );
    var_dump($account);
    echo "\n\n==============\n\n";

    //The functions
    function &getObjRef(&$obj,$prop) {
        return $obj->{$prop};
    }

    function updateObjFromArray(&$obj,$array){
        foreach ($array as $key=>$value) {
            if(!is_array($value))
                $obj->{$key} = $value;
            else{
                $ref = getObjRef($obj,$key);
                updateObjFromArray($ref,$value);
            }
        }
    }

    //Test
    updateObjFromArray($account,array(
        'id' => '123',
        'email' => 'user@domain.com',
        'dob'=>array(
            'day'=>19,
            'month'=>11,
            'year'=>array('century'=>1900,'decade'=>80)
        )
    ));
    var_dump($account);

显然没有内置保护措施。主要的警告是updateObjFromArray 函数假定对于$array 中的任何嵌套数组,$obj 中的对应键已经存在并且是一个对象,这必须是真的或将其视为对象会引发错误。

希望这会有所帮助! :)

【讨论】:

    【解决方案6】:

    我实际上不会这样做....但为了好玩我会

    $object = (object) ($props + (array) $object);
    

    你最终得到一个由 $objects 公共属性组成的 stdClass,所以它失去了它的类型。

    【讨论】:

    • 这会覆盖不符合问题要求的对象。 $object === $old_object 不再正确。
    【解决方案7】:

    方法objectThis() 到transtypage 类数组属性或数组到stdClass。使用直接transtypage(对象)会删除数字索引,但使用这种方法会保留数字索引。

    public function objectThis($array = null) {
        if (!$array) {
            foreach ($this as $property_name => $property_values) {
                if (is_array($property_values) && !empty($property_values)) {
                    $this->{$property_name} = $this->objectThis($property_values);
                } else if (is_array($property_values) && empty($property_values)) {
                    $this->{$property_name} = new stdClass();
                }
            }
        } else {
            $object = new stdClass();
            foreach ($array as $index => $values) {
                if (is_array($values) && empty($values)) {
                    $object->{$index} = new stdClass();
                } else if (is_array($values)) {
                    $object->{$index} = $this->objectThis($values);
                } else if (is_object($values)) {
                    $object->{$index} = $this->objectThis($values);
                } else {
                    $object->{$index} = $values;
                }
            }
            return $object;
        }
    }
    

    【讨论】:

    • 代码示例前面的解释可能需要一些改进
    • 什么是transtypage?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-02-03
    • 2014-10-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多