Creating the Entities
These entity classes are all going to use a unique identifier that represents them. That
$id
attribute will require a
getId()
and a
setId()
method. To keep from repeating ourselves, and
as a way to identify all entities, let’s go ahead and create an abstract
AbstractEntity
that all of
these entities can inherit from:
// src/Domain/Entity/AbstractEntity.php
namespace
CleanPhp\Invoicer\Domain\Entity;
abstract class
AbstractEntity
{
protected
$id
;
public function
getId
() {
return
$this
->
id
;
}
public function
setId
(
$id
) {
$this
->
id
=
$id
;
return
$this
;
}
}
Now let’s define our
Customer
entity, which as a Name, Email Address, and Invoice Delivery
Method:
Building Our Domain
103
// src/Domain/Entity/Customer.php
namespace
CleanPhp\Invoicer\Domain\Entity;
class
Customer
extends
AbstractEntity {
protected
$name
;
protected
$email
;
public function
getName
() {
return
$this
->
name
;
}
public function
setName
(
$name
) {
$this
->
name
=
$name
;
return
$this
;
}
public function
getEmail
() {
return
$this
->
emailAddress
;
}
public function
setEmail
(
$email
) {
$this
->
email
=
$email
;
return
$this
;
}
}
Next, let’s define our Order entity, which has a Many to One relationship with
Customer
, as well
as an Order Number, Description, and Total Order Amount:
// src/Domain/Entity/Order.php
namespace
CleanPhp\Invoicer\Domain\Entity;
class
Order
{
protected
$customer
;
protected
$orderNumber
;
protected
$description
;
protected
$total
;
public function
getCustomer
() {
return
$this
->
customer
;
}
public function
setCustomer
(
$customer
) {
$this
->
customer
=
$customer
;
Building Our Domain
104
return
$this
;
}
public function
getOrderNumber
() {
return
$this
->
orderNumber
;
}
public function
setOrderNumber
(
$orderNumber
) {
$this
->
orderNumber
=
$orderNumber
;
return
$this
;
}
public function
getDescription
() {
return
$this
->
description
;
}
public function
setDescription
(
$description
) {
$this
->
description
=
$description
;
return
$this
;
}
public function
getTotal
() {
return
$this
->
total
;
}
public function
setTotal
(
$total
) {
$this
->
total
=
$total
;
return
$this
;
}
}
Finally, our
Invoice
entity, which has a Many to One relationship with an
Order
, as well as an
Invoice Date and Total Invoice Amount:
// src/Domain/Entity/Invoice.php
namespace
CleanPhp\Invoicer\Domain\Entity;
class
Invoice
{
protected
$order
;
protected
$invoiceDate
;
protected
$total
;
public function
getOrder
() {
return
$this
->
order
;
}
Building Our Domain
105
public function
setOrder
(Order
$order
) {
$this
->
order
=
$order
;
return
$this
;
}
public function
getInvoiceDate
() {
return
$this
->
invoiceDate
;
}
public function
setInvoiceDate
(\DateTime
$invoiceDate
) {
$this
->
invoiceDate
=
$invoiceDate
;
return
$this
;
}
public function
getTotal
() {
return
$this
->
total
;
}
public function
setTotal
(
$total
) {
$this
->
total
=
$total
;
return
$this
;
}
}
These three classes complete our small Domain Model layer.
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
01-domain-models:
git
clone
https
://
github
.
com
/
mrkrstphr
/
cleanphp
-
example
.
git
git checkout
01-
domain
-
models
Testing Our Domain Models
I’m going to make an executive decision at this point and decide not to write any tests for these
models as they stand right now. Writing tests for simple getter and setter methods is pretty
tedious, and if something is going to go wrong, it’s likely not going to happen here.
If you want to write these tests, go for it! You’ll likely be at least somewhat better off for doing
so.
We’ll start writing tests next when we start building out our domain services for this application.
Building Our Domain
106
Domain Services
Remember that the Domain Services layer was next as we move outward from the Domain
Model layer within the Onion/Clean Architecture. This layer will hold all the services and service
contracts that the application will use. As the only thing deeper in the onion is the Domain Model
layer, the Domain Services layer can only depend on the Domain Model layer (as well as PHP
itself).
Our domain services layer will comprise of: * Repository Interfaces These interfaces will
define how the real repositories will work. Since we can’t rely on any infrastructure at this
point, we can’t actually code any concrete repositories yet. * Factories These factories will be
responsible for creating domain objects based on our business rules. * Services These services
will be responsible for implementing the rest of our business rules. They may rely on both the
repositories and the factories to complete their work.
Let’s get started!
Setting up Repositories
We’re going to need to retrieve and persist data from our database, and we’ll do that by using
repositories. Repositories live in the infrastructure layer of our application, but we’ll define them
in the domain services layer. The infrastructure layer is meant to be highly swappable, so we’ll
want to define some contracts for that layer to follow within our domain services layer.
Normally, we’d start by writing some tests that define the functionality of these repositories, but
since we’re just going to have interfaces at this point, there would literally be nothing to test.
Generally, we’re going to want to be able to do the following operations for Customers, Orders
and Invoices:
• Get by ID
• Get All
• Persist (Save)
• Begin
• Commit
Since this is common functionality, let’s go ahead and create a base
RepositoryInterface
to
define this functionality:
Building Our Domain
107
// src/Domain/Repository/RepositoryInterface.php
Do'stlaringiz bilan baham: |