PHP面向对象之领域模型+数据映射器实例(分析)
这里要说明一下因为本人比较懒博客中相关文章的内容更多的是对<深入PHP面向对象、模式与实践>一书中代码的整理和简单注解方便自己日后复习和参考,
对相关内容感兴趣的初学的朋友建议请先阅读原文。此处的内容只能当成一种学习的补充和参考。谢谢!
因原书中领域模型+数据映射器的示例代码是连贯在一起的所以这里就整理在一起了。
简单介绍一下我的看法,从数据库操作的角度看领域模型主要是操作数据表中的单条记录的而数据映射器是操作整个数据表的数据的。
按原文的解释数据映射器是一个负责将数据库数据映射到对象的类,而领域模型象征着真实世界里项目中的各个参与者,它在数据中通常表现为一条记录。
废话不多说,代码和注解如下:
与领域模型相关的三个数据表结构分别为venue(场所)、space(空间)、event(事件)。
createtable'venue'(
'id'int(11)notnullauto_increment,
'name'text,
primarykey('id')
)
createtable'space'(
'id'int(11)notnullauto_increment,
'venue'int(11)defaultnull,
'name'text,
primarykey('id')
)
createtable'event'(
'id'int(11)notnullauto_increment,
'space'int(11)defaultnull,
'start'mediumtext,
'duration'int(11)defaultnull,
'name'text,
primarykey('id')
)
//领域模型(这里只建了一个Venue类用于理解)
namespacewoo\domain;
abstractclassDomainObject{//抽象基类
private$id;
function__construct($id=null){
$this->id=$id;
}
functiongetId(){
return$this->id;
}
//原书没有具体实现,应该是用于获取对象的从属对象的,比如venue(场所)相关的space(空间)对象
//具体的代码实现中应该从数据库中查询了相关数据并调用了Collection类,下面看到这个类的时候会有一个了解
//而且这个方法的实现应该放在子类中才对
staticfunctiongetCollection($type){
returnarray();
}
functioncollection(){
returnself::getCollection(get_class($this));
}
}
classVenueextendsDomainObject{
private$name;
private$spaces;
function__construct($id=null,$name=null){
$this->name=$name;
$this->spaces=self::getCollection('\\woo\\domain\\space');//这里应该证明了我上述的猜测
parent::__construct($id);
}
functionsetSpaces(SpaceCollection$spaces){
$this->spaces=$spaces;
}
functionaddSpace(Space$space){
$this->spaces->add($space);
$space->setVenue($this);
}
functionsetName($name_s){
$this->name=$name_s;
$this->markDirty();
}
functiongetName(){
return$this->name;
}
}
//数据映射器(正如原文的解释数据映射器是一个负责将数据库数据映射到对象的类)
namespacewoo\mapper;
abstractclassMapper{//抽象基类
abstractstatic$PDO;//操作数据库的pdo对象
function__construct(){
if(!isset(self::$PDO){
$dsn=\woo\base\ApplicationRegistry::getDSN();
if(is_null($dsn)){
thrownew\woo\base\AppException("nodns");
}
self::$PDO=new\PDO($dsn);
self::$PDO->setAttribute(\PDO::ATTR_ERRMODE,\PDO::ERRMODE_EXCEPTION);
}
}
functioncreateObject($array){//将数组创建为上述领域模型中的对象
$obj=$this->doCreateObject($array);//在子类中实现
return$obj;
}
functionfind($id){//通过ID从数据库中获取一条数据并创建为对象
$this->selectStmt()->execute(array($id));
$array=$this->selectStmt()->fetch();
$this->selectStmt()->closeCursor();
if(!is_array($array)){
returnnull;
}
if(!isset($array['id'])){
returnnull;
}
$object=$this->createObject($array);
return$object;
}
functioninsert(\woo\domain\DomainObject$obj){//将对象数据插入数据库
$this->doInsert($obj);
}
//需要在子类中实现的各抽象方法
abstractfunctionupdate(\woo\domain\DomainObject$objet);
protectedabstractfunctiondoCreateObject(array$array);
protectedabstractfunctionselectStmt();
protectedabstractfunctiondoInsert(\woo\domain\DomainObject$object);
}
//这里只建立一个VenueMapper类用于理解
classVenueMapperextendsMapper{
function__construct(){
parent::__construct();//各种sql语句对象
$this->selectStmt=self::$PDO->prepare("select*fromvenuewhereid=?");
$this->updateStmt=self::$PDO->prepare("updatevenuesetname=?,id=?whereid=?");
$this->insertStmt=self::$PDO->prepare("insertintovenue(name)values(?)");
}
protectedfunctiongetCollection(array$raw){//将Space数组转换成对象
returnnewSpaceCollection($raw,$this);//这个类的基类在下面
}
protectedfunctiondoCreateObject(array$array){//创建对象
$obj=new\woo\domain\Venue($array['id']);
$obj->setname($array['name']);
return$obj;
}
protectedfunctiondoInsert(\woo\domain\DomainObject$object){//将对象插入数据库
print'inserting';
debug_print_backtrace();
$values=array($object->getName());
$this->insertStmt->execute($values);
$id=self::$PDO->lastInsertId();
$object->setId($id);
}
functionupdate(\woo\domain\DomainObject$object){//修改数据库数据
print"updation\n";
$values=array($object->getName(),$object->getId(),$object->getId());
$this->updateStmt->execute($values);
}
functionselectStmt(){//返回一个sql语句对象
return$this->selectStmt;
}
}
Iterator接口定义的方法:
rewind() 指向列表开头
current() 返回当前指针处的元素
key() 返回当前的键(比如,指针的指)
next()
valid()
下面这个类是处理多行记录的,传递数据库中取出的原始数据和映射器进去,然后通过数据映射器在获取数据时将其创建成对象
abstractclassCollectionimplements\Iterator{
protected$mapper;//数据映射器
protected$total=0;//集合元素总数量
protected$raw=array();//原始数据
private$result;
private$pointer=0;//指针
private$objects=array();//对象集合
function__construct(array$raw=null,Mapper$mapper=null){
if(!is_null($raw)&&!is_null($mapper)){
$this->raw=$raw;
$this->total=count($raw);
}
$this->mapper=$mapper;
}
functionadd(\woo\domain\DmainObject$object){//这里是直接添加对象
$class=$this->targetClass();
if(!($objectinstanceof$class)){
thrownewException("Thisisa{$class}collection");
}
$this->notifyAccess();
$this->objects[$this->total]=$object;
$this->total++;
}
abstractfunctiontargetClass();//子类中实现用来在插入对象时检查类型的
protectedfunctionnotifyAccess(){//不知道干嘛的
}
privatefunctiongetRow($num){//获取集合中的单条数据,就是这里通过数据映射器将数据创建成对象
$this->notifyAccess();
if($num>=$this->total||$num<0){
returnnull;
}
if(isset($this->objects[$num]){
return$this->objects[$num];
}
if(isset($this->raw[$num]){
$this->objects[$num]=$this->mapper->createObject($this->raw[$num]);
return$this->objects[$num];
}
}
publicfunctionrewind(){//重置指针
$this->pointer=0;
}
publicfunctioncurrent(){//获取当前指针对象
return$this->getRow($this->pointer);
}
publicfunctionkey(){//获取当前指针
return$this->pointer;
}
publicfunctionnext(){//获取当前指针对象,并将指针下移
$row=$this->getRow($this->pointer);
if($row){$this->pointer++}
return$row;
}
publicfunctionvalid(){//验证
return(!is_null($this->current()));
}
}
//子类
classVenueColletionextendsCollectionimplements\woo\domain\VenueCollection{
functiontargetClass(){
return"\woo\domain\Venue";
}
}
//客户端
$mapper=new\woo\mapper\VenueMapper();
$venue=$mapper->find(12);
print_r($venue);
$venue=new\woo\domain\Venue();
$venue->setName("thelikeylounge-yy");
//插入对象到数据库
$mapper->insert($venue);
//从数据库中读出刚才插入的对象
$venue=$mapper->find($venue->getId());
print_r($venue);
//修改对象
$venue->setName("thebibblebeerlikeylounge-yy");
//调用update来更新记录
$mapper->update($venue);
//再次读出对象数据
$venue=$mapper->find($venue->getId());
print_r($venue);
//结束
以上这篇PHP面向对象之领域模型+数据映射器实例(分析)就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持毛票票。