Skip to content

Instantly share code, notes, and snippets.

@Meroje
Created November 18, 2012 20:53
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Meroje/4107359 to your computer and use it in GitHub Desktop.
Save Meroje/4107359 to your computer and use it in GitHub Desktop.
Entity Repository in Laravel4

Some Key points

[21:35:16] 1. Controllers call out to a repository to answer questions (like give me comments for a post, or are there any active users)
[21:35:27] so the repositories contain those business rules
[21:35:37] the entities (orm models) contain the application agnostic business rules
[21:35:42] like what makes a valid person
[21:36:09] 2. The repository interacts with the ORM to get the entities
[21:36:42] 3. The controller is merely responsible for processing the request, calling out to the appropriate repositories, and constructing the response
[21:36:52] All of the interactions are injected of course
[21:37:17] Just FYI

The Entity-Repository-Controller pattern

[21:39:32] GDmac: Controllers contain application specific business logic that needs to be tested without the DB
[21:39:48] GDmac: Entities contain application agnostic business logic that also needs to be tested without the DB
[21:40:26] GDmac: So I inject the repository into the controller and the entities know nothing of databases

About the database agnostic repository

[21:45:33] Meroje: Notice the repo, it's MySQLAccount
[21:46:00] if I wanted to switch to Mongo, I just write a new derivative of AccountRepository called MongoAccount
[21:46:24] that also allows me to mock the repo in my tests so that I don't need the DB
[21:47:47] Meroje: I'll probably make it responsible for saving too, but I'm not sure yet.

<?php
namespace DiamondAPI\Controller;
use Symfony\Component\HttpFoundation\Request;
use DiamondAPI\Model\Contact;
use DiamondAPI\Model\ContactRole;
use DiamondAPI\Repository\AccountRepository;
use DiamondAPI\Controller\Response\ResourceCreated;
use DiamondAPI\Controller\Response\ResourceUpdated;
use DiamondAPI\Controller\Response\ResourceDeleted;
use DiamondAPI\Controller\Response\ResourceNotFoundError;
use DiamondAPI\Controller\Response\ResourceList;
class Contacts extends Base
{
/**
* @var \DiamondAPI\Repository\AccountRepository
*/
protected $accountRepository;
/**
* @param \DiamondAPI\Repository\AccountRepository $accountRepository
*/
function __construct(AccountRepository $accountRepository)
{
$this->accountRepository = $accountRepository;
}
/**
* @param int $accountId
* @return Response\ResourceList
*/
public function index($accountId)
{
$contacts = $this->accountRepository->getContactsInAccount($accountId);
return new ResourceList($contacts->toArray());
}
/**
* @param int $accountId
* @return Response\ResourceCreated|Response\ResourceNotFoundError
*/
public function store($accountId)
{
$account = $this->accountRepository->findById($accountId);
$contact = new Contact();
if (!$account)
return new ResourceNotFoundError();
$role = ContactRole::find(ContactRole::$ROLE_ACCOUNT_ADMIN);
$contact->setFillable(array('firstName', 'lastName', 'email'));
$contact->fill($this->getRequestParams(null, array()));
$contact->password = \Hash::make($this->getRequestParams('password'));
$contact->role_id = $role->id;
$contact->save();
$contact->accounts()->attach($account->id);
return new ResourceCreated($contact->toArray());
}
/**
* @param int $accountId
* @param int $contactId
* @return Response\ResourceNotFoundError|Response\ResourceUpdated
*/
public function update($accountId, $contactId)
{
$account = $this->accountRepository->findById($accountId);
$contact = $this->accountRepository->getContactInAccount($accountId, $contactId);
if (!$contact || !$account)
return new ResourceNotFoundError();
$contact->setFillable(array('firstName', 'lastName', 'email', 'password'));
$contact->fill($this->getRequestParams(null, array()));
$contact->save();
return new ResourceUpdated($contact->toArray());
}
/**
* @param int $accountId
* @param int $contactId
* @return Response\ResourceDeleted|Response\ResourceNotFoundError
*/
public function destroy($accountId, $contactId)
{
$contact = $this->accountRepository->getContactInAccount($accountId, $contactId);
if (!$contact)
return new ResourceNotFoundError();
$contact->delete();
return new ResourceDeleted($contact->toArray());
}
}
<?php
namespace DiamondAPI\Model;
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
class Contact extends Base
{
/**
* @var bool
*/
public $timestamps = true;
/**
* @var string
*/
protected $table = 'contacts';
/**
* @var array
*/
protected $hidden = array('password');
/**
* @return BelongsToMany
*/
public function accounts()
{
return $this->belongsToMany('DiamondAPI\Model\Account');
}
public function role()
{
return $this->hasOne('DiamondAPI\Model\ContactRole');
}
}
<?php
namespace DiamondAPI\Repository;
use DiamondAPI\Model\Account;
use DiamondAPI\Model\Contact;
class MySQLAccount implements AccountRepository
{
/**
* @return array
*/
public function getLast25Accounts()
{
return Account::take(25)->get();
}
/**
* @param int $id
* @return \DiamondAPI\Model\Account
*/
public function findById($id)
{
return Account::find($id);
}
/**
* @param int $accountId
* @param int $limit
* @return array|null
*/
public function getContactsInAccount($accountId, $limit = 25)
{
$account = Account::with(array('contacts' => function ($query) use ($limit) {
$query->take($limit);
}))->where('accounts.id', $accountId)->first();
if ($account)
return $account->contacts;
else
return null;
}
/**
* @param int $accountId
* @param int $contactId
* @return Contact|null
*/
public function getContactInAccount($accountId, $contactId)
{
$account = Account::with(array('contacts' => function ($query) use ($contactId) {
$query->where('contacts.id', $contactId)->take(1);
}))->where('accounts.id', $accountId)->first();
if (count($account->contacts))
return $account->contacts[0];
else
return null;
}
}
App::bind('DiamondAPI\Repository\AccountRepository', function () {
return new \DiamondAPI\Repository\MySQLAccount();
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment