mark-gerarts / automapper-plus

An AutoMapper for PHP
MIT License
551 stars 30 forks source link

Is Automapper-plus able to convert array of object to object #55

Closed krabouilleur closed 4 years ago

krabouilleur commented 4 years ago

Hi, Example : the array $array =

array (2) {
  [0]=> 
    object(App\Foo) {
      id => 1
    }
  [1]=>
    object(App\Foo) {
      id => 2
    }
}

Is automapper able to convert this array to an object like this ?

object(FooList) (2) {
  [0]=> 
    object(App\Foo) {
      id => 1
    }
  [1]=>
    object(App\Foo) {
      id => 2
    }
}
krabouilleur commented 4 years ago

Here a full example without automapper:

<?php

class Foo {
  public $id;
  public function __construct($id){
    $this->id=$id;
  }
}

class FooList {
}

// custom function to show is possible to convert an array to object
function arrayToObject(array $array, $className) {
  return unserialize(sprintf(
      'O:%d:"%s"%s',
      strlen($className),
      $className,
      strstr(serialize($array), ':')
  ));
}

$first = new Foo(1);
$second = new Foo(2);
$array=[];
$array[]=$first;
$array[]=$second;

// variable to show it's possible to convert an array to object
$arrayToObject=arrayToObject($array, 'FooList');

echo'<pre>';var_dump('array ==>', $array, 'convertedToObject ==>', $arrayToObject);
die();
?>

THE RESULT without automapper:

array (size=2)
  0 => 
    object(Foo)[1]
      public 'id' => int 1
  1 => 
    object(Foo)[2]
      public 'id' => int 2

------------------------------

object(FooList)[3]
  public '0' => 
    object(Foo)[4]
      public 'id' => int 1
  public '1' => 
    object(Foo)[5]
      public 'id' => int 2
mark-gerarts commented 4 years ago

Hi @krabouilleur. The easiest solution would be to use object crates. This essentially tells the mapper to map all properties of the source object as public properties of the destination object. This works because the source array's property keys are its indices. As an example:

<?php

$config = new AutoMapperConfig();
// Register the list class as an object crate, meaning it will be
// treated the same as \stdClass.
$config->getOptions()->registerObjectCrate(FooList::class);
// Allow mapping from array.
$config->registerMapping(DataType::ARRAY, FooList::class);
$mapper = new AutoMapper($config);

$first = new Foo(1);
$second = new Foo(2);

$result = $mapper->map([$first, $second], FooList::class);

dump($result);
// The result:
// FooList {#16
//   +"0": Foo {#13
//     +id: 1
//   }
//   +"1": Foo {#14
//     +id: 2
//   }
// }

dump($result->{0}->id);
// 1

The alternative is using a custom mapper, leaving you in full control.

mark-gerarts commented 4 years ago

I'll assume this issue is solved. If you have any more questions, feel free to open a new issue or reopen this one!