這是clean architecture的第十篇惋砂,也是具體案例的第二篇绳锅,本篇會通過使用laravel框架,來開發(fā)我們的應(yīng)用眷柔。
本文為系列文章的第十篇原朝,完成的目錄請查看Clean Architecture。
laravel的建立
composer create-project laravel/laravel --prefer-dist cleanphp-laravel
配置數(shù)據(jù)庫采用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
我們啊來建立我們的數(shù)據(jù)庫sqlite3 database/database.sqlite
御板,建表,插入數(shù)據(jù)怠肋。
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
來設(shè)置路由
Route::get('/',"DashboardController@index");
而控制器文件里面的內(nèi)容是:
namespace App\Http\Controllers;
class DashboardController extends Controller
{
public function index()
{
return view("dashboard");
}
}
此處我們再新建resources/views/dashboard.blade.php钉答,填充好內(nèi)容后杈抢,我們就可以通過php artisan serve
來訪問了
具體代碼查看
git clone https://github.com/zhuanxuhit/php-clean-code.git
git checkout 15-laravel-dashboard
Customer管理
我們接著設(shè)置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
的實現(xiàn),需要在文件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的實現(xiàn)淘这,Eloquent是Active Record的ORM巩剖,具體介紹可以看eloquent佳魔。
下面我們來實現(xiàn)具體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
此處我們需要根據(jù)/customers/new
是get還是post方法來判斷是新建一個customer還是進行修改筹陵。
此處我們需要幾個功能
- form filter镊尺,我們需要對post的表單進行驗證
- Hydrator并思,我們需要將輸入的表單方便的賦值到我們的Entity的屬性上
此處表單驗證上,我們使用laravel的表單驗證弄砍,不再自己開發(fā)了输涕,通過命令php artisan make:request NewCustomerPost
新建。
public function rules()
{
return [
'name' => 'required',
'email' => 'required|email',
];
}
然后去controller中實現(xiàn)方法衣式,
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的關(guān)系是1對1叹阔,這在實現(xiàn)OrderRepository
需要注意了,里面從數(shù)據(jù)庫轉(zhuǎn)換后要進行轉(zhuǎn)換忠荞,看代碼:
/**
* @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的作用是將數(shù)據(jù)庫里的數(shù)據(jù)正確設(shè)置到Order對象$entity上帅掘。
具體代碼查看
git clone https://github.com/zhuanxuhit/php-clean-code.git
git checkout 17-laravel-orders
invoice管理
invoice和之前的customer和order類似修档,需要注意的是invoice會有一個領(lǐng)域服務(wù)InvoicingService
,實現(xiàn)未出賬單的出賬操作讥邻。
/**
* @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的全部。
總結(jié)
The Clean Architecture in PHP讀書筆記寫到這全部結(jié)束了发魄,在這最后一篇中俩垃,我們以laravel為框架給出了示例,最核心的領(lǐng)域邏輯是純的php class苹粟,不依賴于任何的框架跃闹,我們可以快速的進行切換。
但是在使用laravel過程中辣卒,特別是repository這塊,由于沒有直接使用laravel的Eloquent模塊荣茫,實現(xiàn)上確實比較麻煩,在實現(xiàn)CleanPhp\Invoicer\Persistence\Eloquent\Repository
下的類的時候港准,很多方法都比較tricky,而且可以想象的是轨帜,隨著項目負責(zé)度的提升衩椒,這一塊會成為程序員的夢靨,所以下一個系列我會去帶領(lǐng)大家看看php中幾大主流orm的實現(xiàn)原理苟弛,包括laravel阁将,doctrine2,盡情期待缤削。
這是The Clean Architecture in PHP的第十篇吹榴,你的鼓勵是我繼續(xù)寫下去的動力,期待我們共同進步吨拗。