在以下项目中实现SOLID域对象模型

sam*_*ayo 15 php oop design-patterns model domain-object

我有以下示例,其中我倾向于使用几个类来创建一个简单的Web应用程序.

文件层次结构如下所示.

> cupid 
    - libs 
        - request
        - router 
        - database
        - view 
    - bootstrap.php 
  - index.php 
Run Code Online (Sandbox Code Playgroud)

index.php刚刚调用bootstrap.php又包含这样的事情:

// bootstrap.php
namespace cupid
use request, router, database, view; 

spl_autoload_register(function($class){ /* autoload */ });

$request  = new view; 
$response = new response; 
$router   = new router; 
$database = new database; 

$router->get('/blog/{id}', function($id) use ($database, $view) {

    $article = $database->select("SELECT blog, content FROM foo WHERE id = ?",[$id]); 

    $view->layout('blogPage', ['article'=>$article]);
}); 
Run Code Online (Sandbox Code Playgroud)

你可能会说,我的问题是这一行:

$article = $database->select("SELECT blog, content FROM foo WHERE id = ?", [$id]); 
Run Code Online (Sandbox Code Playgroud)

我不想使用,而是尝试"域对象模型"方法.

现在,鉴于我将添加另一个名为domain的文件夹 blog.php

> cupid 
    - domain
       - Blog.php
    - libs 
        ...
Run Code Online (Sandbox Code Playgroud)

并填充blog.php属性映射表行,以及getter和setter ..

namespace App\Domain; 

class Blog {

    private $id, $title, $content, $author; 

    public function getTitle(){
        return $this->title; 
    }           

    public function setTitle($title){
        $this->title = $title; 
    }

    ...
}
Run Code Online (Sandbox Code Playgroud)

我的问题是:假设我对DOM的理解到目前为止是正确的,并且我有一个CRUD/ORM类,或者一个PDO包装器来查询数据库;

"我如何联系在一起,即博客模型与PDO包装器在我的引导文件中获取博客?" ..

Ora*_*ill 14

至于域对象,你基本上已经写了一个,你的博客对象.要获得域模型的资格,所有类必须提供表示以及问题空间中概念的任何功能.

这里更有趣的问题和你似乎正在努力解决的问题是如何坚持域模型.遵循单一责任原则的宗旨,您的Blog类应该处理博客文章和博客文章可以做的事情,而不是存储一个.为此,您将介绍博客文章存储库的概念,该存储库将处理存储和检索此类对象的问题.以下是如何完成此操作的简单实现.

class BlogRepository  {
    public function __construct(\cupid\database $db){
        $this->db = $db;
    }

    public function findById($id){
        $blogData = $this->db->select("select * from blog where id = ?", [$id]);
        if ($blogData){
            return $this->createBlogFromArray($blogData);
        }
        return null;
    }
    public function findAllByTag($tag){...}
    public function save(Blog $blog) {...}
    private function createBlogFromArray(array $array){
        $blog = new Blog();
        $blog->setId($blogData["id"]);
        $blog->setTitle($blogData["title"]);
        $blog->setContent($blogData["content"]);
        $blog->setAuthor($blogData["author"]);
        return $blog;
    }
}
Run Code Online (Sandbox Code Playgroud)

然后你的控制器应该看起来像这样.

$router->get('/blog/{id}', function($id) use ($blogRepository, $view) {
    $article = $blogRepository->findById($id);
    if ($article) {
        $view->layout('blogPage', ['article'=>$article]);
    } else {
        $view->setError("404");
    }
}); 
Run Code Online (Sandbox Code Playgroud)

要真正成为SOLID,上面的类应该是一个特定于数据库的BlogRepository接口实现,以遵守IoC.还应该向BlogRepository提供工厂,以便从存储中检索的数据中实际创建博客对象.

在我看来,这样做的一个好处就是您可以在一个地方实现和维护与数据库相关的所有博客相关交互.

该方法的其他优点

  • 为您的域对象实现缓存是微不足道的
  • 可以轻松切换到不同的数据源(来自平面文件,博客api,文档数据库服务器,PostgresSQL等).

您也可以使用类型识别ORM来解决同一问题.基本上,这个Repository类只不过是单个类的ORM.

这里重要的是你不是直接与数据库交谈,而是将sql分散在整个代码中.这会造成维护噩梦,并将您的代码与数据库的架构相结合.