The Clean Architecture in PHP 讀書筆記(十)

laravel

這是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還是進行修改筹陵。

此處我們需要幾個功能

  1. form filter镊尺,我們需要對post的表單進行驗證
  2. 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ù)寫下去的動力,期待我們共同進步吨拗。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末婿斥,一起剝皮案震驚了整個濱河市哨鸭,隨后出現(xiàn)的幾起案子像鸡,更是在濱河造成了極大的恐慌,老刑警劉巖只估,帶你破解...
    沈念sama閱讀 212,383評論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件蛔钙,死亡現(xiàn)場離奇詭異,居然都是意外死亡桑涎,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,522評論 3 385
  • 文/潘曉璐 我一進店門娃胆,熙熙樓的掌柜王于貴愁眉苦臉地迎上來等曼,“玉大人,你說我怎么就攤上這事胁黑〖衔罚” “怎么了?”我有些...
    開封第一講書人閱讀 157,852評論 0 348
  • 文/不壞的土叔 我叫張陵触趴,是天一觀的道長渴肉。 經(jīng)常有香客問我,道長披蕉,這世上最難降的妖魔是什么乌奇? 我笑而不...
    開封第一講書人閱讀 56,621評論 1 284
  • 正文 為了忘掉前任礁苗,我火速辦了婚禮,結(jié)果婚禮上试伙,老公的妹妹穿的比我還像新娘疏叨。我一直安慰自己,他們只是感情好蚤蔓,可當我...
    茶點故事閱讀 65,741評論 6 386
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著既绕,像睡著了一般凄贩。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上疲扎,一...
    開封第一講書人閱讀 49,929評論 1 290
  • 那天椒丧,我揣著相機與錄音,去河邊找鬼句柠。 笑死棒假,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的帽哑。 我是一名探鬼主播,決...
    沈念sama閱讀 39,076評論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼僻族,長吁一口氣:“原來是場噩夢啊……” “哼屡谐!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起碉输,我...
    開封第一講書人閱讀 37,803評論 0 268
  • 序言:老撾萬榮一對情侶失蹤亭珍,失蹤者是張志新(化名)和其女友劉穎枝哄,沒想到半個月后挠锥,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,265評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡粱侣,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,582評論 2 327
  • 正文 我和宋清朗相戀三年齐婴,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片柠偶。...
    茶點故事閱讀 38,716評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡诱担,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出蔫仙,到底是詐尸還是另有隱情摇邦,我是刑警寧澤,帶...
    沈念sama閱讀 34,395評論 4 333
  • 正文 年R本政府宣布阱州,位于F島的核電站法梯,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏夜惭。R本人自食惡果不足惜铛绰,卻給世界環(huán)境...
    茶點故事閱讀 40,039評論 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望敢会。 院中可真熱鬧这嚣,春花似錦、人聲如沸姐帚。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,798評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽遗嗽。三九已至,卻和暖如春媳谁,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背柔纵。 一陣腳步聲響...
    開封第一講書人閱讀 32,027評論 1 266
  • 我被黑心中介騙來泰國打工搁料, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留系羞,地道東北人。 一個月前我還...
    沈念sama閱讀 46,488評論 2 361
  • 正文 我出身青樓椒振,卻偏偏與公主長得像昭伸,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子澎迎,可洞房花燭夜當晚...
    茶點故事閱讀 43,612評論 2 350

推薦閱讀更多精彩內(nèi)容