<?php
$me = [
'name' => 'Damiano',
'surname' => 'Petrungaro',
'job' => 'Software Developer',
'company' => [
'name' => 'Car Match',
'url' => 'https://carmatch.mx/'
],
'github' => 'https://github.com/damianopetrungaro',
'twitter' => '@damiano_dev',
'buzzwords' => [
'food', 'php', 'code', 'perfectionist', 'DDD', 'never stop learning'
]
];
- Laravel documentation
An object that wraps a row
in a database table or view,
encapsulates the database access,
and adds domain logic on that data.
- Martin Fowler, PoEAA
BUSINESS LOGIC
PERSISTENCE
USER
PRODUCT
CART
<?php
namespace App\Http\Controllers;
//...
class UserController extends Controller
{
public function show(Request $request)
{
$name = $request->get('name', 'Damiano');
return UserEloquent::where('name', $name)->first() ?: "No $name was found";
}
}
How eloquent models are usually used
Read
<?php
namespace App\Http\Controllers;
class UserController extends Controller
{
public function create(Request $request)
{
// Some validation logic here
$user = new UserEloquent();
$user->name = $request->name;
// Some domain logic here
$user->save();
return $user
}
}
How eloquent models are usually used
Write
A class should have only a single responsibility
Changes to only one part of the software's specification should be able to affect the specification of the class
One to one mapping between table structure and entity
One property of an Entity will be a column in a table or a field in a document
Our domain model depends on ORM behavior by design
Our model can't exist without the ORM and exposes behavior not needed by the domain
Mediates between the domain
and data mapping layers
using a collection-like interface
for accessing domain objects.
- Edward Hieatt and Rob Mee, PoEAA
BUSINESS LOGIC
PERSISTENCE
USER
REPOSITORY
PRODUCT
REPOSITORY
CART
REPOSITORY
USER
PRODUCT
CART
<?php
namespace App\Repository;
// ...
class UserRepository
{
public function __construct(UserEloquent $userModel)
{
$this->userModel = $userModel;
}
public function findByName(string $name):? UserEloquent
{
return $this->userModel->where('name', $name)->first();
}
}
<?php
namespace App\Http\Controllers;
//...
class UserController extends Controller
{
public function __construct(UserRepository $userRepository)
{
$this->userRepository = $userRepository;
}
public function show(Request $request)
{
$name = $request->get('name', 'Damiano');
return $this->userRepository->findByName($name) ?: "No $name were found";
}
}
<?php
namespace App\Http\Controllers;
class UserController extends Controller
{
public function __construct(UserRepository $userRepository)
{
$this->userRepository = $userRepository;
}
public function show(Request $request)
{
$name = $request->get('name', 'Damiano');
if ($user = $this->userRepository->findByName($name)) {
// We do not want this
// $user->delete();
}
return $user ?: "No $name were found";
}
}
<?php
namespace App\Model;
interface User
{
public function id(): int;
public function name(): string;
}
<?php
namespace App\Model;
// ...
class UserEloquent extends Model implements User
{
// ...
public function id(): int
{
return $this->id;
}
public function name(): string
{
return $this->name;
}
}
<?php
namespace App\Model;
// ...
class UserEloquent extends Model implements User
{
// ...
public function scopeFindByName(string $name)
{
// ...
}
public function scopeBannedLastWeek()
{
// ...
}
}
<?php
namespace App\Repository;
// ...
class UserRepository
{
// ...
public function findByName(string $name):? User
{
// ...
}
public function bannedLastWeek(): UserCollection
{
// ...
}
}
<?php
namespace App\Repository;
// ...
class UserRepository
{
// ...
public function add(User $user): void
{
// ...
}
public function update(User $user): void
{
// ...
}
public function delete(int $id): void
{
// ...
}
// ...
}
<?php
namespace App\Repository;
use App\Model\User;
interface UserRepository
{
public function findByName(string $name):? User;
public function add(User $user): void;
public function update(User $user): void;
public function delete(int $id): void;
}
<?php
namespace App\Repository;
// ...
final class UserEloquentRepository implements UserRepository
{
// ...
public function findByName(string $name):? User
{
// ...
}
public function add(User $user): void
{
// ...
}
public function update(User $user): void
{
// ...
}
public function delete(int $id): void
{
// ...
}
}
<?php
namespace App\Model;
interface User
{
public static fromName(string $name): self;
// ...
}
<?php
namespace App\Model;
// ...
class UserEloquent implements User
{
private function __construct()
{
// Ah! You can't use me!
}
public static function fromName(string $name): self
{
if(strlen($name) <= 5) {
throw new InvalidNameException($name);
}
$user = new self;
$user->name = $name;
return $user;
}
}
<?php
namespace App\ValueObject;
final class Name
{
// ...
public function __construct(string $name)
{
// All validation rules here
$this->name = $name;
}
}
<?php
namespace App\Model;
// ...
class UserEloquent implements User
{
// ...
private function __construct()
{
// Ah! You can't use me!
}
public static function fromName(Name $name): self
{
$user = new self;
$user->name = $name;
return $user;
}
// ...
}
<?php
namespace App\Repository;
// ...
interface UserRepository
{
public function findByEmail(Email $email):? User;
public function findByName(Name $name):? User;
public function getById(UserId $id): User;
public function add(User $user): void;
public function update(User $user): void;
public function delete(UserId $id): void;
}
twitter: @damiano_dev
slides: http://bit.ly/dp-eloquent
joind: https://joind.in/talk/c94e6