Data Mapper

Purpose:

A Data Mapper, is a Data Access Layer that performs bidirectional transfer of data between a persistent data store (ofen a relational database) and an in memory data representation (the domain layer). The goal of the pattern is to keep the in memory representation and the persistent data store independent of each other and the data mapper itself. The layer is composed of one or more mappers (or Data Access Objects), performing the data transfer. Mapper implementations vary in scope. Generic mappers will handle many different domain entity types, dedicated mappers will handle one or a few.

The key point of this pattern is, unlike Active Record pattern, the data model follows Single Responsibility Principle.

User.php

<?php 

namespace DesignPatterns\Structural\DataMapper;

/**
 * User Model
 */
class User
{
    /**
        * Email
        *
        * @var string
    */
    private $email;

    /**
        * username
        *
        * @var String
    */
    private $username;

    /**
        * @param array
        *
        * @return User
    */
    public static function fromState(array $state): User
    {
        return new self(
            $username = $state['username'],
            $email = $state['email']
        );
    }
    
    function __construct(string $username, string $email)
    {
        $this->email = $email;
        $this->$username = $username;
    }

    /**
        * Return Username 
        *
        * @return string
    */
    public function getUsername(): string
    {
        return $this->username;
    }

    /**
        * Return Email Address
        *
        * @return string
    */
    public function getEmail()
    {
        return $this->email;
    }
}
?>

  

StorageAdapter.php

<?php 

namespace DesignPatterns\Structural\DataMapper;

class StorageAdapter
{
    /**
        * data array
        *
        * @var array
    */
    private $data;

    /**
        * Constructor
        *
        * @return Void
    */
    public function __construct(array $data)
    {
        $this->data = $data;
    }

    /**
        * Load the value by id
        *
        * @return string
    */
    public function find(int $id)
    {
        return $this->data[$id] ?? null;
    }
}

?>

  

UserMapper.php

<?php 

namespace DesignPatterns\Structural\DataMapper;

class UserMapper
{
    /**
        * Varibles Description
        *
        * @var StorageAdapter
    */
    private $adapter;

    /**
        * Constructor
        *
        * @return Void
    */
    public function __construct(StorageAdapter $adapter)
    {
        $this->adapter = $adapter;
    }

    /**
        * finds a user from storage based on ID and returns a User object located
        * in memory. Normally this kind of logic will be implemented using the Repository pattern.
        * However the important part is in mapRowToUser() below, that will create a business object from the
        * data fetched from storage
        *
        * @param int
        *
        * @return User
    */
    public function findById(int $id): User
    {
        $result = $adapter->find($id);

        if ($result === null) {
            throw new \InvalidArgumentException("User #$id not found");
        }

        return $this->mapRowToUser($result);
    }

    /**
        * @param array
        *
        * @return User
    */
    private function mapRowToUser(array $row): User
    {
        return User::fromState($row);
    }
}
?>

  

Tests/DataMapperTest.php

<?php

namespace DesignPatterns\Structural\DataMapper\Tests;

use DesignPatterns\Structural\DataMapper\StorageAdapter;
use DesignPatterns\Structural\DataMapper\User;
use DesignPatterns\Structural\DataMapper\UserMapper;
use PHPUnit\Framework\TestCase;

class DataMapperTest extends TestCase
{
    public function testCanMapUserFromStorage()
    {
        $storage = new StorageAdapter([1 => ['username' => 'domnikl', 'email' => 'liebler.dominik@gmail.com']]);
        $mapper = new UserMapper($storage);

        $user = $mapper->findById(1);

        $this->assertInstanceOf(User::class, $user);
    }

    /**
     * @expectedException \InvalidArgumentException
     */
    public function testWillNotMapInvalidData()
    {
        $storage = new StorageAdapter([]);
        $mapper = new UserMapper($storage);

        $mapper->findById(1);
    }
}

  

 

posted @ 2019-05-09 17:37  Victor!!!!  阅读(230)  评论(0)    收藏  举报