The Clean Architecture in PHP 读书

作者: 小聪明李良才 | 来源:发表于2016-11-23 18:52 被阅读609次
    laravel

    这是clean architecture的第十篇,也是具体案例的第二篇,本篇会通过使用laravel框架,来开发我们的应用。

    本文为系列文章的第十篇,完成的目录请查看Clean Architecture

    laravel的建立

    composer create-project laravel/laravel --prefer-dist cleanphp-laravel
    

    配置数据库采用sqlite,修改.env文件

    DB_CONNECTION=sqlite
    DB_DATABASE=/Users/zhuanxu/workspace/cleanphp-laravel/database/database.sqlite
    

    此处DB_DATABASE换为你自己的路径,并新建database.sqlite,touch /Users/zhuanxu/workspace/cleanphp-laravel/database/database.sqlite

    我们啊来建立我们的数据库sqlite3 database/database.sqlite,建表,插入数据。

    CREATE TABLE customers ( id integer PRIMARY KEY, name varchar(100) NOT NULL, email varchar(100) NOT NULL );
    
    CREATE TABLE orders ( id integer PRIMARY KEY, customer_id int REFERENCES customers(id) NOT NULL, order_number varchar(20) NOT NULL, description text NOT NULL, total float NOT NULL );
    
    CREATE TABLE invoices ( id integer PRIMARY KEY, order_id int REFERENCES orders(id) NOT NULL, invoice_date date NOT NULL, total float NOT NULL );
    
    INSERT INTO customers(name, email) VALUES('Acme Corp', 'ap@acme.com'); INSERT INTO customers(name, email) VALUES('ABC Company', 'invoices@abc.com');
    

    建立Dashboard

    我们通过命令

    php artisan make:controller DashboardController
    

    来新建控制器,并修改routes/web.php来设置路由

    Route::get('/',"DashboardController@index");
    

    而控制器文件里面的内容是:

    namespace App\Http\Controllers;
    
    class DashboardController extends Controller
    {
    
        public function index()
        {
            return view("dashboard");
        }
    }
    

    此处我们再新建resources/views/dashboard.blade.php,填充好内容后,我们就可以通过php artisan serve

    来访问了

    具体代码查看

    git clone https://github.com/zhuanxuhit/php-clean-code.git
    
    git checkout 15-laravel-dashboard
    

    Customer管理

    我们接着设置Customer的路由

    Route::get( '/customers', 'CustomersController@index' );
    Route::get( '/customers/new', 'CustomersController@edit' );
    Route::post('/customers/new','CustomersController@store');
    
    Route::get( '/customers/edit/{id}', 'CustomersController@edit' );
    Route::post('/customers/edit/{id}','CustomersController@store');
    

    然后控制器CustomersController中注入CustomerRepositoryInterface

    class CustomersController extends Controller
    {
    
        /**
         * @var \CleanPhp\Invoicer\Domain\Repository\CustomerRepositoryInterface
         */
        private $customerRepository;
    
        /**
         * CustomersController constructor.
         *
         * @param \CleanPhp\Invoicer\Domain\Repository\CustomerRepositoryInterface $customerRepository
         */
        public function __construct(CustomerRepositoryInterface $customerRepository)
        {
            $this->customerRepository = $customerRepository;
        }
    }
    

    通过Laravel的service container,能很方便的注入进来,此处我们需要声明CustomerRepositoryInterface的实现,需要在文件app/Providers/AppServiceProvider.php中新增:

    use CleanPhp\Invoicer\Persistence\Eloquent\Repository\CustomerRepository;
    use CleanPhp\Invoicer\Domain\Repository\CustomerRepositoryInterface;
    
    public function register()
    {
      $this->app->bind(CustomerRepositoryInterface::class,
                       CustomerRepository::class);
    }
    

    此处CustomerRepository是持久层的基于Laravel的Eloquent的实现,Eloquent是Active Record的ORM,具体介绍可以看eloquent

    下面我们来实现具体Customer的操作。

    Customer Listing

    在CustomersController中新增index方法

        public function index(  )
        {
            $customers = $this->customerRepository->getAll();
            return view('customers/index', ['customers' => $customers]);
        }
    

    并新增文件resources/views/customers/index.blade.php

    Adding and Editing Customers

    此处我们需要根据/customers/new是get还是post方法来判断是新建一个customer还是进行修改。

    此处我们需要几个功能

    1. form filter,我们需要对post的表单进行验证
    2. Hydrator,我们需要将输入的表单方便的赋值到我们的Entity的属性上

    此处表单验证上,我们使用laravel的表单验证,不再自己开发了,通过命令php artisan make:request NewCustomerPost新建。

        public function rules()
        {
            return [
                'name' => 'required',
                'email' => 'required|email',
            ];
        }
    

    然后去controller中实现方法,

    public function store(NewCustomerPost $request, $id = '')
    {
      $data = $request->all();
      $customer = $id ? $this->customerRepository->getById($id) : new Customer();
    
      $customer->setName($data['name'])->setEmail($data['email']);
      $this->customerRepository->persist($customer);
      return new RedirectResponse('/customers/edit/' . $customer->getId());
    }
    
    public function edit($id = '')
    {
      $customer = $id ? $this->customerRepository->getById($id) : new Customer();
      $viewModel['customer'] = $customer;
      return view('customers/new-or-edit', $viewModel);
    }
    

    我们可以看到controller里的方法都非常的薄,主要还是通过domain层来完成具体的操作。

    具体代码查看

    git clone https://github.com/zhuanxuhit/php-clean-code.git
    
    git checkout 16-laravel-customers
    

    Order管理

    order总的过程和Customer类似,一个不同的地方是,Order里面有个属性是Customer,Order和Customer的关系是1对1,这在实现OrderRepository需要注意了,里面从数据库转换后要进行转换,看代码:

        /**
         * @param $object
         * @param Order $entity
         */
        protected function hydrate( $object, $entity )
        {
            $customer = $this->customerRepository->getById($object->customer_id);
            $entity->setCustomer($customer)->setOrderNumber($object->order_number)
                ->setTotal($object->total)->setDescription($object->description);
        }
    

    此处hydrate的作用是将数据库里的数据正确设置到Order对象$entity上。

    具体代码查看

    git clone https://github.com/zhuanxuhit/php-clean-code.git
    
    git checkout 17-laravel-orders
    

    invoice管理

    invoice和之前的customer和order类似,需要注意的是invoice会有一个领域服务InvoicingService,实现未出账单的出账操作。

    /**
     * @return array
     */
    public function generateInvoices()
    {
        $orders = $this->orderRepository->getUninvoicedOrders();
        $invoices = [];
        foreach ($orders as $order){
          $invoices[] = $this->factory->createFromOrder($order);
        }
        return $invoices;
    }
    

    除此之外就没什么需要注意的。

    具体代码查看

    git clone https://github.com/zhuanxuhit/php-clean-code.git
    
    git checkout 18-laravel-invoices
    

    以上就是php-clean-architecture的全部。

    总结

    The Clean Architecture in PHP读书笔记写到这全部结束了,在这最后一篇中,我们以laravel为框架给出了示例,最核心的领域逻辑是纯的php class,不依赖于任何的框架,我们可以快速的进行切换。

    但是在使用laravel过程中,特别是repository这块,由于没有直接使用laravel的Eloquent模块,实现上确实比较麻烦,在实现CleanPhp\Invoicer\Persistence\Eloquent\Repository下的类的时候,很多方法都比较tricky,而且可以想象的是,随着项目负责度的提升,这一块会成为程序员的梦靥,所以下一个系列我会去带领大家看看php中几大主流orm的实现原理,包括laravel,doctrine2,尽情期待。

    这是The Clean Architecture in PHP的第十篇,你的鼓励是我继续写下去的动力,期待我们共同进步。

    相关文章

      网友评论

      • b855dcd71655:不错, 是一次DDD的实践,最近正好也在看关于DDD方面的东西,不过发现难以去实施,理论知识已经具备了,似乎难在了划分领域,如何与框架结合等问题上。。我用的是Yii2,按理说如果使用ddd的话我是直接可以将核心业务写成一个composer包的吧,然后结合框架来使用。。
      • 文木拭水:写的很好:+1:,学习了:pray:
        小聪明李良才: @文木拭水 谢谢鼓励的

      本文标题:The Clean Architecture in PHP 读书

      本文链接:https://www.haomeiwen.com/subject/asmvpttx.html