Home arrow PHP arrow Page 2 - Building the Data Mapper Classes for the Data Mapper Design Pattern

Review: a quick look at some previous sample classes - PHP

In this third part of a five-part series on the data mapper design pattern, I start developing a basic user mapper class. This class allows you to map user domain objects to their associated database table in a fairly easy way.

TABLE OF CONTENTS:
  1. Building the Data Mapper Classes for the Data Mapper Design Pattern
  2. Review: a quick look at some previous sample classes
  3. Building an abstract data mapper class
  4. Mapping concrete user domain objects with a user mapper class
By: Alejandro Gervasio
Rating: starstarstarstarstar / 2
March 24, 2010

print this article
SEARCH DEV SHED

TOOLS YOU CAN USE

advertisement

Just in case you haven’t read the two previous articles, where I explained in detail how to create two sample domain and data access layers, below I listed the definitions of the classes that compose the layers. This will allow you to take a close  look at them and quickly understand how they work.

First, here is the source code of the classes that comprise the domain layer, along with an example that shows how to use it for modeling some simple user objects. Here are the corresponding sample files:

(DomainObjectAbstract.php)

 

 

<?php

 

 

abstract class DomainObjectAbstract

{

    protected $_data = array();

   

    public function __construct(array $data = NULL)

    {

        if ($data !== NULL)

        {

            // populate domain object with an array of data

            foreach ($data as $property => $value)

            {

                if (!empty($property))

                {

                   $this->$property = $value;

                }

            }

        }

    }

   

    // set domain object property

    public function __set($property, $value)

    {

        if (!array_key_exists($property, $this->_data))

        {

            throw new ModelObjectException('The specified property is not valid for this domain object.'); 

        }

        if (strtolower($property) === 'id' AND $this->_data['id'] !== NULL)

        {

            throw new DomainObjectException('ID for this domain object is immutable.');

        }

        $this->_data[$property] = $value;

    }

   

    // get domain object property

    public function __get($property)

    {

        if (!array_key_exists($property, $this->_data))

        {

            throw new DomainObjectException('The property requested is not valid for this domain object.');

        }

        return $this->_data[$property];

    } 

   

    // check if given domain object property has been set

    public function __isset($property)

    {

        return isset($this->_data[$property]);

    }

   

    // unset domain object property

    public function __unset($property)

    {

        if (isset($this->_data[$property]))

        {

            unset($this->_data[$property]);

        }

    }

}

 

 

 

 

(DomainObjectException.php)

 

 

<?php

 

 

class DomainObjectException extends Exception{}

As its name implies, the above “DomainObjectAbstract” class defines the behavior and structure of generic domain objects, whose properties can be added and removed on the fly, thanks to the implementation of the “__set()”, __get()” and “__unset()” PHP magic functions. With this class seated on top of the hierarchy, creating a sub class that spawns concrete user objects is reduced to doing something as simple as this: 

(User.php)

 

 

<?php

 

 

class User extends DomainObjectAbstract

{

    protected $_data = array('id' => NULL, 'fname' => '', 'lname' => '', 'email' => '');

}

That was easy to code and read, wasn’t it? Now, if you ever want to employ the previous “User” class to create a concrete user object, it could be done in a snap, in the following way:

$user = new User();

$user->fname = 'Julie';

$user->lname = 'Smith';

$user->email = 'julie@domain.com';

If you analyze the two earlier classes, you’ll realize that they’re the building blocks of a domain layer composed of objects that are nothing but basic data containers with a predictable behavior. This approach is very useful and efficient, as the objects are easy to test, and completely ignorant of the persistent storage mechanism.

With the domain layer already set, it’s time to show the structure of the data access layer. Disappointingly, it is made up of only a trivial MySQL abstraction class called “MySQLAdapter,” whose definition is as follows:

(MySQLAdapter.php)

 

 

<?php

 

 

class MySQLAdapter

{

    private $_config = array();

    private static $_instance = NULL;

    private static $_connected = FALSE;

    private $_link = NULL;

    private $_result = NULL;

   

    // return Singleton instance of MySQLAdapter class

    public static function getInstance(array $config = array())

    {

        if (self::$_instance === NULL)

        {

            self::$_instance = new self($config);

        }

        return self::$_instance;

    }

   

    // private constructor

    private function __construct(array $config)

    {

        if (count($config) < 4)

        {

            throw new MySQLAdapterException('Invalid number of connection parameters');  

        }

        $this->_config = $config;

    }

   

    // prevent cloning class instance

    private function __clone(){}

   

    // connect to MySQL

    private function connect()

    {

        // connect only once

        if (self::$_connected === FALSE)

        {

            list($host, $user, $password, $database) = $this->_config;

            if ((!$this->_link = mysqli_connect($host, $user, $password, $database)))

            {

                throw new MySQLAdapterException('Error connecting to MySQL : ' . mysqli_connect_error());

            }

            self::$_connected = TRUE;

            unset($host, $user, $password, $database);      

        }

    }

 

 

    // perform query

    public function query($query)

    {

        if (is_string($query) and !empty($query))

        {

            // lazy connect to MySQL

            $this->connect();

            if ((!$this->_result = mysqli_query($this->_link, $query)))

            {

                throw new MySQLAdapterException('Error performing query ' . $query . ' Error : ' . mysqli_error($this->_link));

            }

        }

    }

   

    // fetch row from result set

    public function fetch()

    {

        if ((!$row = mysqli_fetch_object($this->_result)))

        {

            mysqli_free_result($this->_result);

            return FALSE;

        }

        return $row;

    }

 

 

    // get insertion ID

    public function getInsertID()

    {

        if ($this->_link !== NUlL)

        {

            return mysqli_insert_id($this->_link); 

        }

        return NULL;  

    }

   

    // count rows in result set

    public function countRows()

    {

        if ($this->_result !== NULL)

        {

           return mysqli_num_rows($this->_result);

        }

        return 0;

    }

    

    // close the database connection

    function __destruct()

    {

        is_resource($this->_link) AND mysqli_close($this->_link);

    }

}

 

 

 

 

 

 

(MySQLAdapterException.php)

 

 

<?php

 

 

class MySQLAdapterException extends Exception{}

Since all that the “MySQLAdapter” class does is perform some common database operations, such as connecting to the server, running hard-coded queries and fetching rows in result sets, I’m not going to spend more time explaining its driving logic. It’s valid to notice, though, that this class is the only element that comprises the data access layer.

Naturally, if you’re like me, at this point you want an answer to the following question: if an application needs to save a user object (or any other kind of domain object) to the database via the previous “MySQLAdapter” class, how can this be done without breaking the rules of the persistence ignorance paradigm?

Well, here’s where data mappers come in. Their mission is to keep those domain objects isolated from the data access layer. But this is theory that needs to be backed up with some functional code. Therefore, in the following segment I’m going to start coding a data mapper class, so you’ll be able to understand its underlying logic.

Now, click on the link below and read the section to come.         



 
 
>>> More PHP Articles          >>> More By Alejandro Gervasio
 

blog comments powered by Disqus
escort Bursa Bursa escort Antalya eskort
   

PHP ARTICLES

- Hackers Compromise PHP Sites to Launch Attac...
- Red Hat, Zend Form OpenShift PaaS Alliance
- PHP IDE News
- BCD, Zend Extend PHP Partnership
- PHP FAQ Highlight
- PHP Creator Didn't Set Out to Create a Langu...
- PHP Trends Revealed in Zend Study
- PHP: Best Methods for Running Scheduled Jobs
- PHP Array Functions: array_change_key_case
- PHP array_combine Function
- PHP array_chunk Function
- PHP Closures as View Helpers: Lazy-Loading F...
- Using PHP Closures as View Helpers
- PHP File and Operating System Program Execut...
- PHP: Effects of Wrapping Code in Class Const...

Developer Shed Affiliates

 


Dev Shed Tutorial Topics: