/* Work cell This pattern involves a domain model, a data mapper, and an identity map, which are collated and reviewed in a unified way. $venue = new \woo\domain\venue (null, "The Green Tree"); \woo\domain\objectwatcher::instance ()->performoperations () Now, let's take a look at the above two lines of client code as a pointcut about how this pattern works. The first sentence when you use a domain model object to create an object, it calls the identity map Objectwatcher class to mark itself as a new object that needs to be added. The Performoperations method of the second sentence inserts the object that is stored in the identity Mapper's properties $new into the database. Note that it internally calls the $obj->finder () method to generate a corresponding data mapper class from the Helperfactory factory class in the realm pattern and return it. Helperfactory This class does not have a specific implementation (the original is not implemented), in fact, according to the type of the class passed by the parameter to create the corresponding data mapper using the conditional branch. Read the code and comments directly below to understand. */namespace woo\domain;//Identity Map class objectwatcher{Private $all = Array (); Store object's small warehouse private $dirty = Array (); Store objects that need to be modified in the database private $new = Array (); Store objects that need to be added to the database private $delete = Array (); Store objects that need to be deleted in the database private static $instance; Singleton private Function __construct () {} static function instance () {if (!self:: $instance) { Self:: $instance = new Objectwatcher (); } return Self:: $instance; } Gets a unique identity, where the domain class class name +id is used to create a unique identity that avoids duplicate ID problems when multiple database tables call this class Globalkey (DomainObject $obj) {$key = get_ Class ($obj). "." . $obj->getid (); return $key; }//Add object static function Add (DomainObject $obj) {$inst = Self::instance (); $inst->all[$inst->globalkey ($obj)] = $obj; }//Gets the object static function exists ($classname, $id) {$inst = Self::instance (); $key = "$classname. $id"; if (Isset ($inst->all[$key]) {return $inst->all[$key]; } return null; }//marked as the object that needs to be deleted static function Adddelete (DomainObject $obj) {$self = Self::instance (); $self->delete[$self->globalkey ($obj)] = $obj; }//marked as the object that needs to be modified static function Adddirty (DomainObject $obj) {$inst = Self::instance (); if (!in_array ($obj, $inst->new,true)) {$inst->dirty[$inst->globalkey ($obj)] = $obj; }}//marked as requiring new object static function adDnew (DomainObject $obj) {$inst = Self::instance (); $inst->new[] = $obj; }//marked as Clean object static function Addclean (DomainObject $obj) {$self = Self::instance (); unset ($self->delete[$self->globalkey ($obj)]); unset ($self->dirty[$self->globalkey ($obj)]); $self->new = Array_filter ($self->new,function ($a) use ($obj) {return! ( $a = = = $obj);}); }//Change the above required additions and deletions of objects to the database interaction with the function performoperations () {foreach ($this->dirty as $key = $obj) {$obj->finder ()->update ($obj); $obj->finder () Gets a data mapper} foreach ($this->new as $key + = $obj) {$obj->finder ()->ins ERT ($obj); } $this->dirty = Array (); $this->new = Array (); }}//domain Model abstract class domainobject{//abstract base class Private $id =-1; function __construct ($id =null) {if (Is_null ($id)) {$this->marknew (); is marked when initializedFor objects that need to be added} else {$this->id = $id; }}//called method function Marknew () {objectwatcher::addnew ($this) that identifies the mapped tag object; } function markdeleted () {objectwatcher::adddelete ($this); } function Markdirty () {objectwatcher::adddirty ($this); } function Markclean () {Objectwatcher::addclean ($this); } function SetId ($id) {$this->id = $id; } function GetId () {return $this->id; } function Finder () {return Self::getfinder (Get_class ($this)); }//Use a factory class to instantiate a particular type of data mapper object, such as Venuemapper//This object will be used by the Performoperations method call in the identity mapper to modify and delete the database interaction static Functio n Getfinder ($type) {return helperfactory::getfinder ($type); }}class Venue extends DomainObject {private $name; Private $spaces; function __construct ($id = null, $name =null) {$this->name= $name; $this->spaces = self::getcollection (' \\woo\\domaiN\\space '); Parent::__construct ($id); } function Setspaces (Spacecollection $spaces) {$this->spaces = $spaces; $this->markdirty (); The object marked as needing modification} function Addspace (Space $space) {$this->spaces->add ($space); $space->setvenue ($this); $this->markdirty (); The object marked as needing modification} function SetName ($name _s) {$this->name = $name _s; $this->markdirty (); Object marked as needing to be modified} function GetName () {return $this->name; }}//domain Model class Space extends domainobject{//... function setName ($name _s) {$this->name = $name _s; $this->markdirty (); } function Setvenue (Venue $venue) {$this->venue = $venue; $this->markdirty (); }}//Data Mapper abstract class mapper{abstract static $PDO; The PDO object function __construct () {if (!isset self:: $PDO) of the operating database { $DSN = \woo\base\applicationregistry::getdsn (); if (Is_null ($DSN)) {throw new \woo\base\appexception ("No DNS"); } self:: $PDO = new \pdo ($DSN); Self:: $PDO->setattribute (\pdo::attr_errmode,\pdo::errmode_exception); }}//Gets the Tagged object private function getfromap ($id) {return \woo\domain\objectwatcher::exists ($this->targ Etclass (), $id); }//New Tagged object private function addtomap (\woo\domain\domainobject $obj) {//////return \woo\domain\object Watcher::add ($obj); }//Map database data to Object function CreateObject ($array) {$old = $this->getfrommap ($array [' id ']); if ($old) {return $old;} $obj = $this->docreateobject ($array); $this->addtomap ($obj); $obj->markclean (); return $obj; The function find ($id) {//Gets a piece of data from the database by ID and creates it as an object $old = $this->getfrommap ($id); IF ($old) {return $old} $this->selectstmt ()->execute (Array ($id)); $array = $this->selectstmt ()->fetch (); $this->selectstmt ()->closecursor (); if (!is_array ($array)) {return null; } if (!isset ($array [' ID '])) {return null; } $object = $this->createobject ($array); $this->addtomap ($object); return $object; } function Insert (\woo\domain\domainobject $obj) {//Inserts the object data into the database $this->doinsert ($obj); $this->addtomap ($obj); }//Abstract function Targetclass (), which needs to be implemented in subclasses; Gets the type of the class, abstract function update (\woo\domain\domainobject $objet); Modify Operation protected abstract function Docreateobject (array $array); Create object protected abstract function selectstmt (); Query operation protected abstract function Doinsert (\woo\domain\domainobject $object); Insert Operation}class Venuemapper extends Mapper {function __construct () {parent::__construct (); Preprocessing object $this->selectstmt = self:: $PDO->prepare ("select * from venue where id=?"); $this->updatestmt = self:: $PDO->prepare ("Update venue set name=?,id=?") where id=? "); $this->insertstmt = self:: $PDO->prepare ("INSERT into venue (name) VALUES (?)"); } protected function GetCollection (array $raw) {//Convert space array to object collection return new Spacecollection ($raw, $th IS); } protected function Docreateobject (array $array) {//create object $obj = new \woo\domain\venue ($array [' id ']); $obj->setname ($array [' name ']); return $obj; } protected function Doinsert (\woo\domain\domainobject $object) {//Inserts the object into the database print ' inserting '; Debug_print_backtrace (); $values = Array ($objeCt->getname ()); $this->insertstmt->execute ($values); $id = self:: $PDO->lastinsertid (); $object->setid ($id); } function Update (\woo\domain\domainobject $object) {//Modify database Data print "updation\n"; $values = Array ($object->getname (), $object->getid (), $object->getid ()); $this->updatestmt->execute ($values); } function Selectstmt () {//Returns a Preprocessed object return $this->selectstmt; }}//Client $venue = new \woo\domain\venue (null, "The Green Tree"); is marked as a new object at initialization $venue->addspace (new \woo\domain\space (null, "The Space Upstairs")); This two-line Addspace method is not marked as a modification object because venue has been marked new, but Space is marked as a new object $venue->addspace when initialized (the new \woo\domain\space (null , "the Bar Stage"); \woo\domain\objectwatcher::instance ()->performoperations (); Interact with database add a venue data, and two space data