PHP面向对象之领域模型+数据映射器

/*
这里要说明一下 因为本人比较懒 博客中相关文章的内容更多的是对<深入PHP面向对象、模式与实践>一书中代码的整理和简单注解方便自己日后复习和参考,
对相关内容感兴趣的初学的朋友建议请先阅读原文。此处的内容只能当成一种学习的补充和参考。谢谢!
因原书中领域模型+数据映射器的示例代码是连贯在一起的 所以这里就整理在一起了。
简单介绍一下我的看法,从数据库操作的角度看领域模型主要是操作数据表中的单条记录的而数据映射器是操作整个数据表的数据的。
按原文的解释数据映射器是一个负责将数据库数据映射到对象的类,而领域模型象征着真实世界里项目中的各个参与者,它在数据中通常表现为一条记录。
废话不多说,代码和注解如下:

与领域模型相关的三个数据表结构分别为venue(场所)、space(空间)、event(事件)。
create table  ‘venue‘ (
     ‘id‘ int(11) not null auto_increment,
     ‘name‘ text,
     primary key (‘id‘)
)
create table  ‘space‘ (
     ‘id‘ int(11) not null auto_increment,
     ‘venue‘ int(11) default null,
     ‘name‘ text,
     primary key (‘id‘)
)
create table  ‘event‘ (
     ‘id‘ int(11) not null auto_increment,
     ‘space‘ int(11) default null,
     ‘start‘ mediumtext,
     ‘duration‘ int(11) default null,
     ‘name‘ text,
     primary key (‘id‘)
)

*/

//领域模型(这里只建了一个Venue类用于理解)
namespace woo\domain;

abstract class DomainObject{            //抽象基类

    private $id;

    function __construct ($id=null){
        $this->id = $id;
    }

    function getId(){
        return $this->id;
    }

    //原书没有具体实现,应该是用于获取对象的从属对象的,比如venue(场所)相关的space(空间)对象
    //具体的代码实现中应该从数据库中查询了相关数据并调用了Collection类,下面看到这个类的时候会有一个了解
    //而且这个方法的实现应该放在子类中才对
    static function getCollection($type){
        return array();
    }

    function collection(){
        return self::getCollection(get_class($this));
    }

}

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;
    }

    function addSpace(Space $space){
        $this->spaces->add($space);
        $space->setVenue($this);
    }

    function setName($name_s){
        $this->name = $name_s;
        $this->markDirty();
    }

    function getName(){
        return $this->name;
    }
}

//数据映射器(正如原文的解释数据映射器是一个负责将数据库数据映射到对象的类)
namespace  woo\mapper;

abstract class Mapper{            //抽象基类
    abstract static $PDO;        //操作数据库的pdo对象
    function __construct (){
        if(!isset(self::$PDO){
            $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);
        }
    }

    function createObject($array){                    //将数组创建为上述领域模型中的对象
        $obj = $this->doCreateObject($array);        //在子类中实现
        return $obj;
    }

    function find($id){                                //通过ID从数据库中获取一条数据并创建为对象
        $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);
        return $object;
    }

    function insert(\woo\domain\DomainObject $obj){            //将对象数据插入数据库
        $this->doInsert($obj);
    }

    //需要在子类中实现的各抽象方法
    abstract function update(\woo\domain\DomainObject $objet);
    protected abstract function doCreateObject(array $array);
    protected abstract function selectStmt();
    protected abstract function doInsert(\woo\domain\DomainObject $object);
}

//这里只建立一个VenueMapper类用于理解
class VenueMapper extends Mapper {
    function __construct (){
        parent::__construct();    //各种sql语句对象
        $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){        //将Space数组转换成对象
        return new SpaceCollection($raw,$this);            //这个类的基类在下面
    }

    protected function doCreateObject (array $array){    //创建对象
        $obj = new \woo\domain\Venue($array[‘id‘]);
        $obj->setname($array[‘name‘]);
        return $obj;
    }

    protected function doInsert(\woo\domain\DomainObject $object){  //将对象插入数据库
        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){        //修改数据库数据
        print "updation\n";
        $values = array($object->getName(),$object->getId(),$object->getId());
        $this->updateStmt->execute($values);
    }

    function selectStmt(){                    //返回一个sql语句对象
        return $this->selectStmt;
    }

}

/*
Iterator接口定义的方法:
rewind()            指向列表开头
current()            返回当前指针处的元素
key()                返回当前的键(比如,指针的指)
next()
valid()

下面这个类是处理多行记录的,传递数据库中取出的原始数据和映射器进去,然后通过数据映射器在获取数据时将其创建成对象

*/
abstract class Collection implements \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;
    }

    function add(\woo\domain\DmainObject $object){    //这里是直接添加对象
        $class = $this->targetClass();
        if(!($object instanceof $class)){
            throw new Exception("This is a {$class} collection");
        }
        $this->notifyAccess();
        $this->objects[$this->total] = $object;
        $this->total ++;
    }

    abstract function targetClass();    //子类中实现用来在插入对象时检查类型的

    protected function notifyAccess(){    //不知道干嘛的

    }

    private function getRow($num){        //获取集合中的单条数据,就是这里通过数据映射器将数据创建成对象
        $this->notifyAccess();
        if($num >= $this->total || $num < 0){
            return null;
        }
        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];
        }
    }

    public function rewind(){            //重置指针
        $this->pointer = 0;
    }

    public function current(){            //获取当前指针对象
        return $this->getRow($this->pointer);
    }

    public function key(){                //获取当前指针
        return $this->pointer;
    }

    public function next(){            //获取当前指针对象,并将指针下移
        $row = $this->getRow($this->pointer);
        if($row){$this->pointer ++}
        return $row;
    }

    public function valid(){        //验证
        return (!is_null($this->current()));
    }

}

//子类
class VenueColletion extends Collection implements \woo\domain\VenueCollection{
    function targetClass(){
        return "\woo\domain\Venue";
    }
}

//客户端
$mapper = new \woo\mapper\VenueMapper();
$venue = $mapper->find(12);
print_r($venue);

$venue = new \woo\domain\Venue();
$venue->setName("the likey lounge-yy");
//插入对象到数据库
$mapper->insert($venue);
//从数据库中读出刚才插入的对象
$venue = $mapper->find($venue->getId());
print_r($venue);

//修改对象
$venue->setName("the bibble beer likey lounge-yy");
//调用update来更新记录
$mapper->update($venue);
//再次读出对象数据
$venue = $mapper->find($venue->getId());
print_r($venue);

//结束
时间: 2024-10-10 06:07:29

PHP面向对象之领域模型+数据映射器的相关文章

领域模型与数据映射器(理解)

领域模型根据业务逻辑编写,以及生成对象(对象安全,与数据层分离) 处理业务逻辑,根据业务逻辑编写,如果每个类与数据表相对应是最好不过,但是现实生产并不是这样.   主要功能是这样,如公交站会有很多公交车(公交车也是一个对象,它可能拥有乘客)以及车站的基本信息(名称等等),我们把车站声明为一个领域对象,构造方法可以传入ID已经车站的基本信息,每一条基本信息拥有自己的set get 方法,这里还会拥有公交车的get set (公交车的领域对象) 数据层 数据映射器可以很好的完成数据库操作,好处在于领

springmvc 前段控制器 处理器映射器 处理器适配器 视图视图解析器 配置

1. 前段控制器 新建项目在web.xml中配置前段控制器 <servlet> <servlet-name>springmvc</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <init-param> <param-name>contextConfigLocation</pa

Spring映射器、适配器、解析器

1 springmvc的映射器和适配器 1.1springmvc的映射器 根据客户端请求的url,找到处理本次请求的handler(处理器),将url和controller关联起来 1.2springmvc的适配器 对映射器查找到的controller中的方法进行调用. 第一种:Controller适配 第二种:HttpRequestHandler适配 第三种:注解适配 不同的处理器,对应不同的适配器,但是所有适配器最终都返回ModelAndView对象,springmvc通过对ModelAnd

springmvc03 非注解和注解处理器映射器和适配器

1其它非注解处理器映射器和适配器 1.1BeanNameUrlHandlerMapping(映射器) 根据请求url(XXXX.action)匹配spring容器bean的 name 找到对应的bean(程序编写的Handler) 1.2SimpleUrlHandlerMapping(映射器) <!--简单url映射, 集中配置bean的id对应 的url --> <bean class="org.springframework.web.servlet.handler.Simp

04SpringMvc_映射器_BeanNameUrlHanderMapping

这篇文章我们讲的是映射器,映射器的作用是什么样的请求交给Action,如果我们没有在xml配置文件中进行配置,默认的就是BeanNameUrlHanderMapping. 我们讲一个案例增加用户的案例. 案例结构图如下: 对上面的案例结构进行说明: 1. UserAction.java是增加用户的Action. 2.SpringMvc_002.xml是对应这个案例的配置文件. 3.Spirngmvc.xml是总的配置文件. 4.index.jsp是项目默认的访问页面. 5.succss.jsp是

非注解的处理器适配器和处理器映射器

一.非注解的处理器映射器 1,org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping 该bean 按照名称配置url,如下: <bean id="itemsController1" name="/queryItems_test.action" class="cn.itcast.ssm.controller.ItemsController1" /> 2,org.

注解的处理器映射器和适配器

1, 配置注解映射器和适配器. <!--注解映射器 --> <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping"/> <!--注解适配器 --> <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMa

【SpringMVC学习03】SpringMVC中注解和非注解方式下的映射器和适配器总结

从上一篇的springmvc入门中已经看到,springmvc.xml中的配置了映射器和适配器,是使用非注解的方式来配置的,这是非注解方式的一种,这里再复习一下: 1. 非注解方式 1.1 处理器适配器 上一节中使用的处理器适配器是:org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter.即: SimpleControllerHandlerAdapter适配器能执行实现了Controller接口的Handler,所以我

Java Persistence with MyBatis 3(中文版) 第四章 使用注解配置SQL映射器

在上一章,我们看到了我们是怎样在映射器Mapper XML配置文件中配置映射语句的.MyBatis也支持使用注解来配置映射语句.当我们使用基于注解的映射器接口时,我们不再需要在XML配置文件中配置了.如果你愿意,你也可以同时使用基于XML和基于注解的映射语句. 本章将涵盖以下话题: l 在映射器Mapper接口上使用注解 l 映射语句 @Insert,@Update,@Delete,@SeelctStatements l 结果映射 一对一映射 一对多映射 l 动态SQL @SelectProvi