我应该使用什么模式将PHP关联数组转换为复杂的对象图


What pattern should I use to convert PHP associative arrays to/from complex Object graphs?

我的数据以关联数组的形式到达。这是可行的,但我的代码是一堆嵌套数组,我想开始使用适当的OO/对象,使这些数据更容易处理。我无法更改接收这些数据的方式,所以我想找到一种干净的方法,将关联数组转换为下面类的实例。

我有这些类来为我的应用程序中的人员建模:

class Person {
  /**
   * @var string
   */
  private $_name;
  /**
   * @var array[Dog]
   */
  private $_dogs = array();
  /**
   * @var array[Hobby]
   */
  private $_hobbies = array();
}
class Dog {
  /**
   * @var string
   */
  private $_color;
  /**
   * @var string
   */
  private $_breed;
}
class Hobby {
  /**
   * @var string
   */
  private $_description;
  /**
   * @var int
   */
  private $_cost;
}

我的数据(JSON)如下所示:

'person': {
  'name': 'Joe',
  'dogs': [
     {'breed': 'Husky', 'color': 'Black'},
     {'breed': 'Poodle', 'color': 'Yellow'}
   ]
  'hobbies': [
     {'description': 'Skiing', 'cost': 500},
     {'description': 'Running', 'cost': 0}
   ]
}

我可以使用json_decode轻松地将此JSON转换为关联数组,但困难在于将嵌套的HobbyPet对象中的每一个转换为适当的类,然后当我想要回关联数组时,再次将这些对象转换为关联阵列。

我可以通过在每个类中编写一个to/from数组函数来完成这一切,但这看起来相当混乱,而且容易出错。有没有一种更简单的方法可以让这些物体快速水合/脱水?

将此添加到Hobby

public function fromArray($array){
if(isset($array['description'])){
    $this->_description = $array['description'];
}
if(isset($array['cost'])){
    $this->_cost = $array['cost'];
}
}
public function toArray(){
$array = array();
$array['description'] = $this->_description;
$array['cost'] = $this->_cost;
return $array;
}

这是给小狗的:

public function fromArray($array){
if(isset($array['breed'])){
    $this->_breed = $array['breed'];
}
if(isset($array['cost'])){
    $this->_cost = $array['color'];
}
}
public function toArray(){
$array = array();
$array['breed'] = $this->_breed;
$array['color'] = $this->_color;
return $array;
}

以及面授课程:

public function fromArray($array){
if(isset($array['name'])){
    $this->_name = $array['name'];
}
if(isset($array['dogs'])){
    foreach($array['dogs'] as $dogArray){
        $dog = new Dog();
        $dog->fromArray($dogArray);
        $this->_dogs[] = $dog;
    }
}
if(isset($array['hobbies'])){
    foreach($array['hobbies'] as $hobbyArray){
        $hobby = new Hobby();
        $hobby->fromArray($hobbyArray);
        $this->_hobbies[] = $hobby;
    }
}
}
public function toArray(){
$array = array();
$array['name'] = $this->_name;
foreach($this->_dogs as $dogObj){
    $array['dogs'][] = $dogObj->toarray();;
}
foreach($this->_hobbies as $hobbyObj){
    $array['hobbies'][] = $hobbyObj->toarray();;
}
return $array;
}

这可能不太好用(因为我现在还不能测试它),但可以尝试这样的方法:

$data = json_decode($jsonData, TRUE);
$myObj = new Object();
foreach($data as $key => $val) {
  $myObj->$key = $val;
}

我为第二个参数传递了TRUE,因为否则json_decode将返回stdClass对象。我想把它作为一个带有foreach的关联数组来处理。

我意识到我还没有给出一个设计模式的名字,但我无法自信地回答这个问题。下面是对类似问题的另一个回答:PHP设计模式

如果您使用JSON进行大量解码/编码(正如您所提到的,您需要在关联数组和对象之间来回切换),我会确保有正当的理由转换为自定义类。

示例:

$person = json_decode($json);
echo $person->name;
echo $person->dogs[0]->breed;
$person->name = "Jim";
$json = json_encode($person);

如果您想继续使用自定义类,这将需要一些工作。请参阅此问题。