Skip to main content

SubMapper

SubMapper is a highly simplified mapper used in places where you might need to delegate the mapping of another object to the main mapper. It is designed so that you don't have to deal with the complexity of managing types.

In SubMapper, passing the Context is optional. SubMapper automatically passes the Context from the caller if you don't specifically do it.

map() Method

The map() method maps an object to the class or object you specified.

use Rekalogika\Mapper\SubMapper\SubMapperInterface;

/** @var SubMapperInterface $subMapper */

// using class-string as the target type
$postDto = $subMapper->map($source, PostDto::class);

// the target can also be an existing object
$postDto = new PostDto();
$subMapper->map($source, $postDto);

mapForProperty() Method

With the mapForProperty(), you specify the property name of the variable that will contain the result of the mapping. SubMapper will detect the type of the property in $containing::$propertyName and use it as the target type for the mapping.

This is useful if the property is an array or an array-like object, as PHP doesn't have generics and it is not simple to specify the type of the array elements.

use Rekalogika\Mapper\SubMapper\SubMapperInterface;

class Post {
/** @var list<Comment> */
public array $comments;
}

class Comment {}

class PostDto {
/** @var list<CommentDto> */
public array $comments;
}

class CommentDto {}

/** @var Post $post */
/** @var SubMapperInterface $subMapper */

$postDto = new PostDto();
$subMapper->cache($postDto);

$commentsDto = $subMapper->mapForProperty($post->comments, PostDto::class, 'comments');
$postDto->comments = $commentsDto;

$containing can be a class string or an existing object. If it is an existing object, SubMapper will attempt to retrieve the current object from the property and map the source to it.

cache() Method

To reduce the possibility of infinite recursion due to circular references, you can use the cache() method to store the object that is being mapped. You should call cache() after you instantiate the object and before you delegate the mapping of its properties by calling map() or mapForProperty().

use Rekalogika\Mapper\SubMapper\SubMapperInterface;

/** @var SubMapperInterface $subMapper */

$postDto = new PostDto();
$subMapper->cache($postDto);
$postDto->author = $subMapper->map($source->author, AuthorDto::class);

return $postDto;

createProxy() Method

You can use the createProxy() method to create a proxy object that will be initialized only after you first access its properties.

use Rekalogika\Mapper\SubMapper\SubMapperInterface;

/** @var SubMapperInterface $subMapper */
/** @var Post $source */

// this is the function that will be used to initialize the proxy object
$initializer = static function (
PostDto $target
) use ($source): void {
$target->__construct();
$target->name = $source->getName();
};

$postDto = $subMapper->createProxy(
PostDto::class, // real target class
$initializer, // will be executed when the proxy is first accessed
['id'] // eager properties, accessing these will not trigger the
// hydration of the proxy object
);

// id is eager, so this will not cause the initializer to be called.
$postDto->id = $post->getId();

// this will trigger the initializer
$name = $postDto->name;