代码之家  ›  专栏  ›  技术社区  ›  user1032531

实体类的用途和好处是什么?

  •  0
  • user1032531  · 技术社区  · 7 年前

    我经常遇到如下代码(参考 Slim tutorial github )

    ticketmapper.php文件

    class TicketMapper extends Mapper
    {
        public function getTickets() {
            $sql = "SELECT t.id, t.title, t.description, c.component
                from tickets t
                join components c on (c.id = t.component_id)";
            $stmt = $this->db->query($sql);
            $results = [];
            while($row = $stmt->fetch()) {
                $results[] = new TicketEntity($row);
            }
            return $results;
        }
        /**
         * Get one ticket by its ID
         *
         * @param int $ticket_id The ID of the ticket
         * @return TicketEntity  The ticket
         */
        public function getTicketById($ticket_id) {
            $sql = "SELECT t.id, t.title, t.description, c.component
                from tickets t
                join components c on (c.id = t.component_id)
                where t.id = :ticket_id";
            $stmt = $this->db->prepare($sql);
            $result = $stmt->execute(["ticket_id" => $ticket_id]);
            if($result) {
                return new TicketEntity($stmt->fetch());
            }
        }
        public function save(TicketEntity $ticket) {
            $sql = "insert into tickets
                (title, description, component_id) values
                (:title, :description, 
                (select id from components where component = :component))";
            $stmt = $this->db->prepare($sql);
            $result = $stmt->execute([
                "title" => $ticket->getTitle(),
                "description" => $ticket->getDescription(),
                "component" => $ticket->getComponent(),
            ]);
            if(!$result) {
                throw new Exception("could not save record");
            }
        }
    }
    

    票务.php

    class TicketEntity
    {
        protected $id;
        protected $title;
        protected $description;
        protected $component;
        /**
         * Accept an array of data matching properties of this class
         * and create the class
         *
         * @param array $data The data to use to create
         */
        public function __construct(array $data) {
            // no id if we're creating
            if(isset($data['id'])) {
                $this->id = $data['id'];
            }
            $this->title = $data['title'];
            $this->description = $data['description'];
            $this->component = $data['component'];
        }
        public function getId() {
            return $this->id;
        }
        public function getTitle() {
            return $this->title;
        }
        public function getDescription() {
            return $this->description;
        }
        public function getShortDescription() {
            return substr($this->description, 0, 20);
        }
        public function getComponent() {
            return $this->component;
        }
    }
    

    我当前的实践不使用实体类,而我的映射器方法只返回如下所示的stdclass:

    class TicketMapper extends Mapper
    {
        public function getTickets() {
            $sql = "...";
            $stmt = $this->db->query($sql);
            return $stmt->fetchAll(PDO::FETCH_OBJ);
        }
        public function getTicketById($ticket_id) {
            $sql = "...";
            $stmt = $this->db->prepare($sql);
            $result = $stmt->execute(["ticket_id" => $ticket_id]);
            return $stmt->fetch();  //Assuming my PDO is configured to return an object only
        }
        public function save($ticket) {/* no change */}
    }
    

    为什么数据库结果经常包装在某个实体类中?有什么标准可以决定是否这样做吗?

    2 回复  |  直到 7 年前
        1
  •  1
  •   tereÅ¡ko    7 年前

    重点 data mapper 是作为业务逻辑和存储之间的持久层。它在实体对象中填充或存储数据。

    这些实体有几个目标:

    • 封装:您可以跟踪和控制实体所包含的数据如何被访问和更改。

    • 验证:确保实体的状态与业务规则和检测能力相匹配,如果实体已进入(或即将进入)无效状态

    • 契约:您可以使用类型提示来定义其他模块(类、函数)可以使用这个实体,以及它可以接受哪些类型的东西作为参数。您还可以使用一个选项来定义此实体的替代项必须实现的接口

    • 行为:一个实体通常会有相关的行为(或业务逻辑),例如: $article->markAsApproved() 操作将不是一个简单的setter,而是进行原子状态更改。

    至于标准……嗯……”你用的是OOP还是不是“最接近的”。这个 stdClass 只是一个没有任何行为的光荣数组。

    你可能应该看看 this lecture .

        2
  •  0
  •   gmbc    7 年前

    封装:类是一个有用的包,它将代码和相关数据放在一起,与其他东西隔离开来。这使得在不搜索精确变量、不与现有代码/数据冲突的情况下更容易移动它。

    当然,类还有其他用途,但是在像PHP这样的脚本环境中,我认为最大的优势是它。

    代码重用

    继承

    更容易维护