This is part 10 of Clean Architecture, and part 2 of a concrete case study, in which we will develop our application using the Laravel framework.
This is the tenth article in the series, and for the completed table of contents, see Clean Architecture.
The establishment of the laravel
composer create-project laravel/laravel --prefer-dist cleanphp-laravelCopy the code
To configure the database using SQLite, modify the. Env file
DB_CONNECTION=sqlite
DB_DATABASE=/Users/zhuanxu/workspace/cleanphp-laravel/database/database.sqliteCopy the code
DB_DATABASE here in for your own path, and build the 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', '[email protected]'); INSERT INTO customers(name, email) VALUES('ABC Company', '[email protected]');Copy the code
Establish a Dashboard
And we do it by command
php artisan make:controller DashboardControllerCopy the code
Create a new controller and change routes/web.php to set the route
Route::get('/',"DashboardController@index");Copy the code
The contents of the controller file are:
namespace App\Http\Controllers; class DashboardController extends Controller { public function index() { return view("dashboard"); }}Copy the code
Here we will have a new resources/views/dashboard blade. PHP, fill after good content, we can through the PHP artisan serve
To access the
Specific code view
git clone https://github.com/zhuanxuhit/php-clean-code.git
git checkout 15-laravel-dashboardCopy the code
The Customer management
We then set up the route for 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');Copy the code
Then the controller CustomersController inject 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; }}Copy the code
Through Laravel service container, can easily into came in, we need to declare CustomerRepositoryInterface implementation here, Need in the file app/will/AppServiceProvider PHP feature:
use CleanPhp\Invoicer\Persistence\Eloquent\Repository\CustomerRepository;
use CleanPhp\Invoicer\Domain\Repository\CustomerRepositoryInterface;
public function register()
{
$this->app->bind(CustomerRepositoryInterface::class,
CustomerRepository::class);
}Copy the code
CustomerRepository is the Eloquent implementation of the persistence layer, Eloquent for Active Record.
Let’s implement the specific Customer operation.
Customer Listing
Add index method to CustomersController
public function index( )
{
$customers = $this->customerRepository->getAll();
return view('customers/index', ['customers' => $customers]);
}Copy the code
And new file resources/views/customers/index. The blade. The PHP
Adding and Editing Customers
Here we need to decide whether to create a new customer or modify it according to whether /customers/new is a get or a post method.
Here we need several functions
- Form filter, we need to validate the POST form
- Hydrator, we need to easily assign the input form to our Entity properties
For form validation, we will use Laravel’s form validation instead of developing it ourselves, creating it by using PHP artisan make: Request NewCustomerPost.
public function rules()
{
return [
'name' => 'required',
'email' => 'required|email',
];
}Copy the code
And then I’m going to implement the method in 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);
}Copy the code
We can see that the methods in controller are very thin, and the specific operations are done through the domain layer.
Specific code view
git clone https://github.com/zhuanxuhit/php-clean-code.git
git checkout 16-laravel-customersCopy the code
The Order management
In order, there is an attribute named Customer, and the relationship between order and Customer is 1 to 1. This should be paid attention to in order Repository.
/**
* @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);
}Copy the code
The purpose of this hydrate is to set the data in the database correctly on the Order object $Entity.
Specific code view
git clone https://github.com/zhuanxuhit/php-clean-code.git
git checkout 17-laravel-ordersCopy the code
Invoice management
Invoice is similar to the previous customer and order. What needs to be noted is that invoice has a domain service InvoicingService to realize the billing operation of the unissued bill.
/**
* @return array
*/
public function generateInvoices()
{
$orders = $this->orderRepository->getUninvoicedOrders();
$invoices = [];
foreach ($orders as $order){
$invoices[] = $this->factory->createFromOrder($order);
}
return $invoices;
}Copy the code
There’s not much else to notice.
Specific code view
git clone https://github.com/zhuanxuhit/php-clean-code.git
git checkout 18-laravel-invoicesCopy the code
That’s all for PHP-Clean-Architecture.
conclusion
This is The end of The Clean Architecture in PHP book notes. In this last article, we use Laravel as The framework to give examples. The core domain logic is pure PHP class, independent of any framework, and we can quickly switch.
However, using Laravel, especially repository, is tricky, as it lacks the Eloquent laravel module, Many of the methods used to implement a class under CleanPhp/Invoicer/Persistence/Eloquent/Repository are tricky, and as you can imagine, as the project becomes more responsible, it can become a nightmare for programmers. So in the next series I will take you through the implementation of some of the major ORMs in PHP, including Laravel, Doctrine2.
This is The tenth chapter of The Clean Architecture in PHP. Your encouragement is The motivation for me to continue writing. I look forward to our common progress.