Перетворювач Даних (англ. Data Mapper ) — це шаблон, який виступає в ролі посередника для
двоспрямованої передачі між постійним сховищем даних (часто, реляційної бази даних)
і подання даних у пам’яті (шар домену, що вже завантажено і використовується для логічної обробки).
Мета шаблону в тому, щоб тримати подання даних у пам’яті та постійне сховище даних незалежними один від одного та від самого перетворювача даних. Шар складається з одного або більше mapper ‘а (або об’єктів доступу до даних),
відровідальних за передачу даних. Реалізації mapper ‘ів різняться за призначенням. Загальні mapper ‘и можуть
обробляти різні типи сутностей доменів, а виділені mapper ‘и будуть обробляти один або кілька
конкретних типів.
Storage.php
<?php
namespace DesignPatterns\Structural\DataMapper ;
/**
* Class Storage
* @package DesignPatterns\Structural\DataMapper
*/
class Storage
{
/**
* @var array
*/
private $data = [];
/**
* Storage constructor.
*
* @param array $data
*/
public function __construct ( array $data )
{
$this -> data = $data ;
}
/**
* @param int $id
*
* @return array|null
*/
public function find ( int $id )
{
if ( isset ( $this -> data [ $id ])) {
return $this -> data [ $id ];
}
return null ;
}
}
User.php
<?php
namespace DesignPatterns\Structural\DataMapper ;
/**
* Class User
* @package DesignPatterns\Structural\DataMapper
*/
class User
{
/**
* @var string
*/
private $username ;
/**
* @var string
*/
private $email ;
/**
* @param array $state
*
* @return User
*/
public static function fromState ( array $state ): User
{
return new self (
$state [ 'username' ],
$state [ 'email' ]
);
}
/**
* User constructor.
*
* @param string $username
* @param string $email
*/
public function __construct ( string $username , string $email )
{
$this -> username = $username ;
$this -> email = $email ;
}
/**
* @return string
*/
public function getUsername ()
{
return $this -> username ;
}
/**
* @return string
*/
public function getEmail ()
{
return $this -> email ;
}
}
UserMapper.php
<?php
namespace DesignPatterns\Structural\DataMapper ;
use InvalidArgumentException ;
/**
* Class UserMapper
* @package DesignPatterns\Structural\DataMapper
*/
class UserMapper
{
/**
* @var Storage
*/
private $storage ;
/**
* UserMapper constructor.
*
* @param Storage $storage
*/
public function __construct ( Storage $storage )
{
$this -> storage = $storage ;
}
/**
* @param int $id
*
* @return User
*/
public function findById ( int $id ): User
{
$result = $this -> storage -> find ( $id );
if ( $result === null ) {
throw new InvalidArgumentException ( 'User #' . $id . ' not found' );
}
return $this -> mapRowToUser ( $result );
}
/**
* @param array $row
*
* @return User
*/
private function mapRowToUser ( array $row ): User
{
return User :: fromState ( $row );
}
}
Test case:
UserMapperTest.php
<?php
namespace DesignPatterns\Tests\Structural\DataMapper ;
use DesignPatterns\Structural\DataMapper\Storage ;
use DesignPatterns\Structural\DataMapper\UserMapper ;
use InvalidArgumentException ;
use PHPUnit_Framework_TestCase ;
class DataMapperTest extends PHPUnit_Framework_TestCase
{
public function testCanMapUserFromStorage ()
{
$storage = new Storage (
[
1 => [
'username' => 'zyuzka' ,
'email' => 'zyuzka@mail.com' ,
],
]
);
$mapper = new UserMapper ( $storage );
$user = $mapper -> findById ( 1 );
$this -> assertInstanceOf ( 'DesignPatterns\Structural\DataMapper\User' , $user );
}
public function testWillNotMapInvalidData ()
{
$this -> expectException ( InvalidArgumentException :: class );
$storage = new Storage ([]);
$mapper = new UserMapper ( $storage );
$mapper -> findById ( 1 );
}
}