DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

Zones

Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks

Curious about the future of data-driven systems? Join our Data Engineering roundtable and learn how to build scalable data platforms.

Data Engineering: The industry has come a long way from organizing unstructured data to adopting today's modern data pipelines. See how.

Threat Detection: Learn core practices for managing security risks and vulnerabilities in your organization — don't regret those threats!

Managing API integrations: Assess your use case and needs — plus learn patterns for the design, build, and maintenance of your integrations.

Related

  • The Blue Elephant in the Room: Why PHP Should Not Be Ignored Now or Ever
  • Laravel for Beginners: An Overview of the PHP Framework
  • Is PHP Still the Best Language in 2024?
  • These 37 Items Are Required for Magento 2 Launch

Trending

  • Java Is Greener on Arm
  • How to Read JSON Files in Java Using the Google Gson Library
  • Jakarta WebSocket Essentials: A Guide to Full-Duplex Communication in Java
  • Monitoring Kubernetes Service Topology Changes in Real Time
  1. DZone
  2. Coding
  3. Languages
  4. Practical PHP Patterns: Mapper

Practical PHP Patterns: Mapper

By 
Giorgio Sironi user avatar
Giorgio Sironi
·
Sep. 13, 10 · Interview
Likes (0)
Comment
Save
Tweet
Share
5.1K Views

Join the DZone community and get the full member experience.

Join For Free

The Mapper pattern is used to establish a communication between two subsystems, when the integration must be managed in a way to avoid creating mutual dependencies or even one-way dependencies between them.

The classic example of this pattern is its specialization for data storage, the Data Mapper, which as you can see from the relative article translates data between an object graph and an external storage such as a relational database (most advanced ORMs like Doctrine 2 are Data Mappers), but also a document-oriented database or any other kind of persistent storage.

The Mapper component is naturally dependent on both the subsystems it connect, but they are not aware at all of its existence. No additional hard dependencies are introduced from the subsystems towards other components.

Following our example, Doctrine 2 borrows the Hibernate's approach to mapping: it parses annotations or unobtrusive XML files for specifying metadata on the object-oriented side, and uses a wrapped version of PDO (with ordinary database drivers) on the database side. Neither the database tables are aware of the existence of an object model, nor the objects are ideally aware of them being persisted into a tabular form.

Client code

The main issue in wiriting a Mapper, in all its specializations, is how to invoke it, since the connected subsystems do not know anything about it, nor they can instance it without a dependency being created.

The most common solution is to use an higher-level layer that drives the three components at the same time. In PHP applications, this is usually a controller layer, which by default starts a transaction and commit it following the lifecycle of the served HTTP request. The domain objects are then passed to the Data Mapper's Facade or they depend on a set of Repository interfaces implemented with the aid of the Data Mapper.

Another possible solution is to implement an Observer pattern, so that interfaces or abstractions in the two subsystems break the dependency. The Mapper implementation classes would realize these interfaces, but there is a trade-off produced by the introduction of interfaces in the subsystems.

Mapper vs. Gateway

In comparison, a Gateway is simpler to implement than a Mapper, although your mileage may vary depending on the domain and your requirements.

Basically, a Mapper is more complex but by definition it has the benefit that neither of the two components depend on it. Thus the Mapper is even more decoupled than one of the two subsystems dependent on an interface or abstraction of a Gateway: in fact, you can simply throw it out the Mapper and the two subsystems will work as long as they can to fulfill their own responsibilities. Whereas, you can't remove a Gateway from an application without specifying an alternate implementation.

This pattern is also different from a Mediator: no one of the objects at the same or at a lower layer of the Mapper is aware of it.

Example

The code sample is a simple Data Mapper that shuffles data between database and Twitter, just to shake the notion that all Data Mappers are ORMs.

The code presented here is only a one-way implementation, since a bidirectional one would involve authentication and would increase too much the size of this article.
The first side of the Mapper is a domain model built over the database (not represented here). The second side is Twitter's own web services instead, which we can be sure does not depend on our little in-memory database.

<?php
class TwitterMapper
{
    private $connection;

    /**
     * The Mapper composes one side of the computation (the database)
     * in the form of its Facade (the connection).
     * The other side is Twitter's web service, so it isn't injected
     * for simplicity.
     */
    public function __construct(PDO $connection)
    {
        $this->connection = $connection;
    }

    /**
     * the only functionality I need from the feed
     */
    public function synchronizeLastTweets(array $usernames)
    {
        foreach ($usernames as $username) {
            $endPoint = "http://twitter.com/statuses/user_timeline/{$username}.xml?count=1";
            $buffer = file_get_contents($endPoint);
            $xml = new SimpleXMLElement($buffer);
            $this->_addTweet($xml->id, $username, $xml->status->text);
        }
    }

    public function _addTweet($id, $username, $text)
    {
        $stmt = $this->connection->prepare('INSERT INTO tweets (id, username, text) VALUES (:id, :username, :text)');
        $stmt->bindValue(':id', $id, PDO::PARAM_STR);
        $stmt->bindValue(':username', $username, PDO::PARAM_STR);
        $stmt->bindValue(':text', $text, PDO::PARAM_STR);
        return $stmt->execute();
    }
}

$pdo = new PDO('sqlite::memory:');
$pdo->exec('CREATE TABLE tweets (id INT NOT NULL, username VARCHAR(255) NOT NULL, text VARCHAR(255) NOT NULL, PRIMARY KEY(id))');

$mapper = new TwitterMapper($pdo);
// higher-level layer
$mapper->synchronizeLastTweets(array('giorgiosironi')); 
PHP

Opinions expressed by DZone contributors are their own.

Related

  • The Blue Elephant in the Room: Why PHP Should Not Be Ignored Now or Ever
  • Laravel for Beginners: An Overview of the PHP Framework
  • Is PHP Still the Best Language in 2024?
  • These 37 Items Are Required for Magento 2 Launch

Partner Resources


Comments

The likes didn't load as expected. Please refresh the page and try again.

ABOUT US

  • About DZone
  • Support and feedback
  • Community research
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Core Program
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 100
  • Nashville, TN 37211
  • support@dzone.com

Let's be friends: