• 技术文章 >后端开发 >php教程

    PHP领域模型和数据映射器详解

    小云云小云云2018-02-12 10:44:19原创903
    本文主要和大家分享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);
    
    
    //结束

    相关推荐:

    业务逻辑层之事务脚本与领域模型

    php入门到就业线上直播课:查看学习

    以上就是PHP领域模型和数据映射器详解的详细内容,更多请关注php中文网其它相关文章!

    声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn核实处理。

    前端(VUE)零基础到就业课程:点击学习

    清晰的学习路线+老师随时辅导答疑

    自己动手写 PHP MVC 框架:点击学习

    快速了解MVC架构、了解框架底层运行原理

    专题推荐:php 详解 映射
    上一篇:SQLite实现分页功能php代码分享 下一篇:自己动手写 PHP MVC 框架(40节精讲/巨细/新人进阶必看)

    相关文章推荐

    • ❤️‍🔥共22门课程,总价3725元,会员免费学• ❤️‍🔥接口自动化测试不想写代码?• 你知道如何用PHP实现多进程吗• PHP与MySQL连接的方法总结• 工具包分享:PHP实现滑块验证图片• 求解:phpcms模板怎样转码?该怎么解决• php 之 cookie 跟 session 简单解读(笔记)
    1/1

    PHP中文网