Bog'liq The-Clean-Architecture-in-PHP-Kristopher-Wilson
@stop
The new thing here is the select box for selecting the Customer for the Order. We simply loop
through the provided array of customers and output an
@stop
I’m running out of things to say after these code snippets.
Generating Invoices Our next step is generating new invoices. We’ll start with the
/invoices/new
route which
resolves to the
newAction()
:
// app/Http/Controllers/InvoicesController.php public function newAction
() {
return view(
'invoices/new'
, [
'orders'
=>
$this
->
orderRepository
->
getUninvoicedOrders
()
]);
}
This simple action just grabs all uninvoiced orders and supplies them to the view template:
endif ;
?> @stop
The view shows the uninvoiced orders, if any, and provides a button to generate invoices for
those orders.
So let’s work that action:
// app/Http/Controllers/InvoicesController.php public function generateAction
() {
$invoices
=
$this
->
invoicing
->
generateInvoices
();
$this
->
invoiceRepository
->
begin
();
foreach (
$invoices
as $invoice
) {
$this
->
invoiceRepository
->
persist
(
$invoice
);
}
$this
->
invoiceRepository
->
commit
();
return view(
'invoices/generate'
, [
'invoices'
=>
$invoices
]);
}
This, like all the code in this chapter, is stolen directly from the ZF2 project, and modified slightly
for Laravel. Let’s finish off with the view, which shows a list of the generated invoices:
resources
/
views
/
invoices
/
generate
.
blade
.
php
-->
@
extends (
'layouts.layout'
)
@
section(
'content'
)
<
div class
=
"page-header"
>
<
h2
>
Generated Invoices
h2
>
div
>
php
if (
empty (
$invoices
))
:
?> No invoices were generated. else :
?>
endif ;
?> @stop
And viola, invoice generation.
Viewing Invoices The last stop on our Laravel journey is to view an individual invoice. Let’s start with the
viewAction()
:
Switching to Laravel
240
// app/Http/Controllers/InvoicesController.php public function viewAction
(
$id
) {
$invoice
=
$this
->
invoiceRepository
->
getById
(
$id
);
if (
!
$invoice
) {
return new Response(
''
,
404
);
}
return view(
'invoices/view'
, [
'invoice'
=>
$invoice
,
'order'
=>
$invoice
->
getOrder
()
]);
}
Let’s make sure
Response
is part of the
use
statements:
use Illuminate\Http\Response;
And next, our view:
resources
/
views
/
invoices
/
view
.
blade
.
php
-->
@
extends (
'layouts.layout'
)
@
section(
'content'
)
<
div class
=
"page-header clearfix"
>
<
h2
>
Invoice
#{{{ $invoice->getId() }}}
table
>
@
stop
And viewing invoices, and all invoice functionality, is complete.
This would make a good place to commit your code to source control.
If you’re just reading, but want to see the code in action, you can checkout the tag
18-laravel-invoices:
git clone https://github.com/mrkrstphr/cleanphp-example.git
git checkout 18-laravel-invoices
Next Steps If this were a real project, I’d recommend a few things:
1. Test this application layer. Test it through and through. These will likely be integration
tests, or full system tests, as unit testing controllers in any framework, except maybe
something like Silex, is near impossible.
2. Ditch the ZF2 components and use the Laravel counterparts. ZF2 isn’t component based,
no matter how hard they try to pretend, and we were forced to bring along the kitchen
sink just to use two tiny little slivers of the framework.
3. Fully embrace Blade, or don’t. We kind of went half-and-half in the examples. I’d opt for
not using blade; it’s just weird.
Summary This was a lot of work. A lot of tedious work. If we were switching from ZF2 to Laravel in a real,
large application, this would have been a lot more work.
Switching to Laravel
242
Is this feasible? It definitely is, as we’ve seen here, but it’s a huge undertaking. One that most
certainly will lead to bugs and issues not present in the old system – especially since we didn’t
write any tests for this layer. As testing this layer can be quite complicated, I left it out of this
book. However, having a full suite of tests for each layer will aid greatly in detecting and fixing
issues early in the process.
Switching frameworks is incredibly laborious. Do so sparingly, and spend a lot of time evaluating
your framework choice up front, so that hopefully you’ll never have a need to switch. Further,
write code intelligently and favor highly decoupled components. It will only make your
application better in the long run.
Document Outline
Table of Contents
Introduction
Organization
The Author
A Word about Coding Style
The Problem With Code
Writing Good Code is Hard
Writing Bad Code is Easy
We Can't Test Anything
Change Breaks Everything
We Live or Die by the Framework
We Want to Use All the Libraries
Writing Good Code
What is Architecture?
What does Architecture Look Like?
Layers of Software
Examples of Poor Architecture
Costs of Poor Architecture
Coupling, The Enemy
Spaghetti Coupling
OOP Coupling
Why is Coupling the Enemy?
How do we Reduce Coupling?
Your Decoupling Toolbox
Design Patterns, A Primer
The Factory Patterns
Repository Pattern
Adapter Pattern
Strategy Pattern
Learning More Design Patterns
SOLID Design Principles
Single Responsibility Principle
Open/Closed Principle
Liskov Substitution Principle
Interface Segregation Principle
Dependency Inversion Principle
Applying SOLID Principles
Dependency Injection
Inversion of Control
When to use Dependency Injection
Handling Many Dependencies
Are we still coupling?
Defining a Contract with Interfaces
Interfaces in PHP
Using Interfaces as Type Hints
Using Interfaces as a Contract
Making Third Party Code Conform to Contracts
Abstracting with Adapters
Setting up the Adapter
How does this help?
The Clean Architecture
MVC, and its Limitations
MVC in a Diagram
The MVC Components
Routing
MVC Isn't Good Enough
Obese Models
More Layers for All of the Things!
The Clean Architecture
The Clean Architecture
The Onion Architecture
Framework Independence
The Problem with Frameworks
Framework Independence
This is a Lot of Work
Database Independence
Domain Models
Domain Services
Database Infrastructure / Persistence
Organizing the Code
Wrapping it Up
External Agency Independence
Using Interfaces, Adapters and Dependency Injection