A very common practice among PHP developers is to create classes that represent database tables. Such classes are often referred to as entity classes, and form the core of the domain model software design pattern.
Application\Entity\Base class. All future entity classes will then extend Base.$mapping (discussed later), and $id (with its corresponding getter and setter):namespace Application\Entity;
class Base
{
protected $id = 0;
protected $mapping = ['id' => 'id'];
public function getId() : int
{
return $this->id;
}
public function setId($id)
{
$this->id = (int) $id;
}
}arrayToEntity() method, which converts an array to an instance of the entity class, and vice versa (entityToArray()). These methods implement a process often referred to as hydration. As these methods should be generic, they are best placed in the Base class.$mapping property is used to translate between database column names and object property names. arrayToEntity() populates values of this object instance from an array. We can define this method as static in case we need to call it outside of an active instance:public static function arrayToEntity($data, Base $instance)
{
if ($data && is_array($data)) {
foreach ($instance->mapping as $dbColumn => $propertyName) {
$method = 'set' . ucfirst($propertyName);
$instance->$method($data[$dbColumn]);
}
return $instance;
}
return FALSE;
}entityToArray() produces an array from current instance property values:public function entityToArray()
{
$data = array();
foreach ($this->mapping as $dbColumn => $propertyName) {
$method = 'get' . ucfirst($propertyName);
$data[$dbColumn] = $this->$method() ?? NULL;
}
return $data;
}customer table. Here is the CREATE statement from a MySQL data dump, which illustrates its data structure:CREATE TABLE 'customer' (
'id' int(11) NOT NULL AUTO_INCREMENT,
'name' varchar(256) CHARACTER SET latin1 COLLATE latin1_general_cs NOT NULL,
'balance' decimal(10,2) NOT NULL,
'email' varchar(250) NOT NULL,
'password' char(16) NOT NULL,
'status' int(10) unsigned NOT NULL DEFAULT '0',
'security_question' varchar(250) DEFAULT NULL,
'confirm_code' varchar(32) DEFAULT NULL,
'profile_id' int(11) DEFAULT NULL,
'level' char(3) NOT NULL,
PRIMARY KEY ('id'),
UNIQUE KEY 'UNIQ_81398E09E7927C74' ('email')
);TABLE_NAME class constant:namespace Application\Entity;
class Customer extends Base
{
const TABLE_NAME = 'customer';
protected $name = '';
protected $balance = 0.0;
protected $email = '';
protected $password = '';
protected $status = '';
protected $securityQuestion = '';
protected $confirmCode = '';
protected $profileId = 0;
protected $level = '';
}protected. In order to access these properties, you will need to design public methods that get and set the properties. Here is a good place to put to use the PHP 7 ability to data-type to the return value.$name and $balance. You can imagine how the remainder of these methods will be defined: public function getName() : string
{
return $this->name;
}
public function setName($name)
{
$this->name = $name;
}
public function getBalance() : float
{
return $this->balance;
}
public function setBalance($balance)
{
$this->balance = (float) $balance;
}
}mapping property, an array of key/value pairs where the key represents the database column name and the value the property name.$securityQuestion, $confirmCode, and $profileId, do not correspond to their equivalent column names, security_question, confirm_code, and profile_id. The $mapping property will ensure that the appropriate translation takes place:protected $mapping = [ 'id' => 'id', 'name' => 'name', 'balance' => 'balance', 'email' => 'email', 'password' => 'password', 'status' => 'status', 'security_question' => 'securityQuestion', 'confirm_code' => 'confirmCode', 'profile_id' => 'profileId', 'level' => 'level' ];
Copy the code from steps 2, 4, and 5 into a Base.php file in the Application/Entity folder. Copy the code from steps 8 through 12 into a Customer.php file, also in the Application/Entity folder. You will then need to create getters and setters for the remaining properties not shown in step 10: email, password, status, securityQuestion, confirmCode, profileId, and level.
You can then create a chap_05_matching_entity_to_table.php calling program, which initializes the autoloader defined in Chapter 1, Building a Foundation, uses the Application\Database\Connection, and the newly created Application\Entity\Customer classes:
<?php
define('DB_CONFIG_FILE', '/../config/db.config.php');
require __DIR__ . '/../Application/Autoload/Loader.php';
Application\Autoload\Loader::init(__DIR__ . '/..');
use Application\Database\Connection;
use Application\Entity\Customer;Next, get a database connection, and use the connection to acquire an associative array of data for one customer at random:
$conn = new Connection(include __DIR__ . DB_CONFIG_FILE); $id = rand(1,79); $stmt = $conn->pdo->prepare( 'SELECT * FROM customer WHERE id = :id'); $stmt->execute(['id' => $id]); $result = $stmt->fetch(PDO::FETCH_ASSOC);
Finally, you can create a new Customer entity instance from the array and use var_dump() to view the result:
$cust = Customer::arrayToEntity($result, new Customer()); var_dump($cust);
Here is the output of the preceding code:

There are many good works that describe the domain model. Probably the most influential is Patterns of Enterprise Application Architecture by Martin Fowler (see http://martinfowler.com/books/eaa.html). There is also a nice study, also available as a free download, entitled Domain Driven Design Quickly by InfoQ (see http://www.infoq.com/minibooks/domain-driven-design-quickly).