I tried to implement the Repository pattern for my project:
MemberController.php -- this one is a bit too long and has repetitive code
<?php
class MemberController extends \BaseController {
private $repo;
public function __construct(MemberRepository $repo)
{
$this->repo = $repo;
}
//////////////////////
// 'Simple' pages //
//////////////////////
public function index()
{
$yourId = Auth::user()->id;
$data = $this->repo->getChildren($yourId);
return View::make('members.index', $data);
}
public function view($id)
{
$yourId = Auth::user()->id;
if ($this->repo->canView($yourId, $id)) {
$data = $this->repo->getDetails($id);
return View::make('members.view', $data);
} else {
return Response::make('Unauthorized', 401);
}
}
public function ledger($id)
{
$yourId = Auth::user()->id;
if ($this->repo->canView($yourId, $id)) {
$data = $this->repo->getLedger($id);
return View::make('members.ledger', $data);
} else {
return Response::make('Unauthorized', 401);
}
}
public function log($id)
{
$yourId = Auth::user()->id;
if ($this->repo->canView($yourId, $id)) {
$data = $this->repo->getLog($id);
return View::make('members.log', $data);
} else {
return Response::make('Unauthorized', 401);
}
}
//////////////////////
// Show Forms (GET) //
//////////////////////
public function showCreate()
{
return View::make('members.create');
}
public function showEdit($id)
{
$yourId = Auth::user()->id;
if ($this->repo->canModify($yourId, $id)) {
$data = $this->repo->getInfo($id);
return View::make('members.edit', $data);
} else {
return Response::make('Unauthorized', 401);
}
}
public function showBan($id)
{
$yourId = Auth::user()->id;
if ($this->repo->canModify($yourId, $id)) {
$data = $this->repo->getInfo($id);
return View::make('members.ban', $data);
} else {
return Response::make('Unauthorized', 401);
}
}
public function showUnBan($id)
{
$yourId = Auth::user()->id;
if ($this->repo->canModify($yourId, $id)) {
$data = $this->repo->getInfo($id);
return View::make('members.unban', $data);
} else {
return Response::make('Unauthorized', 401);
}
}
public function showDelete($id)
{
$yourId = Auth::user()->id;
if ($this->repo->canModify($yourId, $id)) {
$data = $this->repo->getInfo($id);
return View::make('members.delete', $data);
} else {
return Response::make('Unauthorized', 401);
}
}
public function showTopup($id)
{
$yourId = Auth::user()->id;
if ($this->repo->canModify($yourId, $id)) {
$data = $this->repo->getInfo($id);
return View::make('members.topup', $data);
} else {
return Response::make('Unauthorized', 401);
}
}
public function showWithdraw($id)
{
$yourId = Auth::user()->id;
if ($this->repo->canModify($yourId, $id)) {
$data = $this->repo->getInfo($id);
return View::make('members.withdraw', $data);
} else {
return Response::make('Unauthorized', 401);
}
}
public function showReset($id)
{
$yourId = Auth::user()->id;
if ($this->repo->canModify($yourId, $id)) {
$data = $this->repo->getInfo($id);
return View::make('members.reset', $data);
} else {
return Response::make('Unauthorized', 401);
}
}
///////////////////////
// Do Actions (POST) //
///////////////////////
public function doCreate()
{
$yourId = Auth::user()->id;
$result = $this->repo->create($yourId, Input::all());
if ($result->success) {
return Redirect::route('members.index')->with('message', $result->message);
} else {
return Redirect::back()->withErrors($result->message);
}
}
public function doEdit($id)
{
$yourId = Auth::user()->id;
if ($this->repo->canModify($yourId, $id)) {
$result = $this->repo->edit($id, Input::all());
if ($result->success) {
return Redirect::route('members.index')->with('message', $result->message);
} else {
return Redirect::back()->withErrors($result->message);
}
} else {
return Response::make('Unauthorized', 401);
}
}
public function doBan($id)
{
$yourId = Auth::user()->id;
if ($this->repo->canModify($yourId, $id)) {
$result = $this->repo->ban($id);
if ($result->success) {
return Redirect::route('members.index')->with('message', $result->message);
} else {
return Redirect::back()->withErrors($result->message);
}
} else {
return Response::make('Unauthorized', 401);
}
}
public function doUnBan($id)
{
$yourId = Auth::user()->id;
if ($this->repo->canModify($yourId, $id)) {
$result = $this->repo->unban($id);
if ($result->success) {
return Redirect::route('members.index')->with('message', $result->message);
} else {
return Redirect::back()->withErrors($result->message);
}
} else {
return Response::make('Unauthorized', 401);
}
}
public function doDelete($id)
{
$yourId = Auth::user()->id;
if ($this->repo->canModify($yourId, $id)) {
$result = $this->repo->delete($id);
if ($result->success) {
return Redirect::route('members.index')->with('message', $result->message);
} else {
return Redirect::back()->withErrors($result->message);
}
} else {
return Response::make('Unauthorized', 401);
}
}
public function doTopUp($id)
{
$yourId = Auth::user()->id;
if ($this->repo->canModify($yourId, $id)) {
$result = $this->repo->topUp($id, Input::only('amount'));
if ($result->success) {
return Redirect::route('members.index')->with('message', $result->message);
} else {
return Redirect::back()->withErrors($result->message);
}
} else {
return Response::make('Unauthorized', 401);
}
}
public function doWithdraw($id)
{
$yourId = Auth::user()->id;
if ($this->repo->canModify($yourId, $id)) {
$result = $this->repo->withdraw($id, Input::only('amount'));
if ($result) {
return Redirect::route('members.index')->with('message', $result->message);
} else {
return Redirect::back()->withErrors($result->message);
}
} else {
return Response::make('Unauthorized', 401);
}
}
public function doReset($id)
{
$yourId = Auth::user()->id;
if ($this->repo->canModify($yourId, $id)) {
$result = $this->repo->resetPasswordAndPin($yourId, $id, Input::all());
if ($result) {
return Redirect::route('members.index')->with('message', $result->message);
} else {
return Redirect::back()->withErrors($result->message);
}
} else {
return Response::make('Unauthorized', 401);
}
}
}
MemberRepository.php -- this one becomes a large class, with all code removed except for the function names; just wanted to show that it has many functions
<?php class MemberRepository { ///////////////// // Permissions // ///////////////// public function canView($viewerId, $memberId) { return true; } public function canModify($viewerId, $memberId) { return true; } ////////////////// // Getting Data // ////////////////// public function getChildren($memberId) { return []; } public function getDetails($memberId) { return []; } public function getLedger($memberId) { return []; } public function getLog($memberId) { return []; } public function getInfo($memberId) { return []; } ///////////// // Actions // ///////////// public function create($parentId, $data) { // Validate $data // Save to Database return new Result(true); } public function edit($memberId, $data) { // Validate $data // Update Database return new Result(true); } public function ban($memberId) { // Update Database return new Result(true); } public function unban($memberId) { // Update Database return new Result(true); } public function delete($memberId) { // Update Database return new Result(true); } public function topUp($memberId, $amount) { // Validate $amount // Update Database return new Result(true); } public function withdraw($memberId, $amount) { // Validate $amount // Update Database return new Result(true); } public function resetPasswordAndPin($memberId, $data) { // Validate $data // Update Database return new Result(true); } }
In MemberController.php, I do a lot of tedious copy-and-paste, so I think it violates the DRY principle.
I think that, by using this approach, what I basically do is just moving all sequential tasks (check permission, validate input, save to database) from Controller to Repository. I think that my MemberRepository.php class is still ugly.
I created a MemberValidator
class to help shorten the MemberRepository
, but I think it only helps a little.
I will have other entities, like Post
, Transaction
, Report
. I am not sure if I could use this approach again for them.
Is there any way to make my code shorter and cleaner?