Last active
September 15, 2017 15:42
-
-
Save sebastiaanluca/4e834a24db7214ff3ae6 to your computer and use it in GitHub Desktop.
Simple example of returning a generic object in a repository using Laravel.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php namespace App\Repositories; | |
use App; | |
use Illuminate\Database\Eloquent\ModelNotFoundException; | |
use Illuminate\Support\Collection; | |
use Illuminate\Support\Contracts\ArrayableInterface; | |
abstract class AbstractRepository | |
{ | |
protected $model; | |
public function __construct($model) | |
{ | |
$this->model = $model; | |
} | |
/** | |
* Parses a value in a nested way as deep as possible, in an | |
* effort to normalize itself and its contents. | |
* | |
* Mainly converts (Eloquent, etc) objects to standardized RespitoryObjects. | |
* | |
* @param mixed $value | |
* | |
* @return RepositoryObject|Collection|mixed | |
*/ | |
protected function normalize($value) | |
{ | |
$isCollection = false; | |
// TODO: extensively test with various values! | |
// If it's an array | |
if (is_array($value) || $value instanceof Collection) { | |
$isCollection = true; | |
if ($value instanceof Collection) { | |
$value = $value->toArray(); | |
} | |
foreach ($value as &$item) { | |
// We're not there yet! | |
// Some nesting to get every object normalized | |
$item = $this->normalize($item); | |
} | |
// Some conversion because we want collections and not arrays | |
// (collections are way more powerful) | |
if (is_array($value)) { | |
$value = App::make('Illuminate\Support\Collection', [$value]); | |
} | |
} | |
// An object that implements ArrayableInterface (e.g. Eloquent) | |
// needs to be converted to array so its values represent | |
// whatever is visible or hidden | |
elseif (is_object($value) && $value instanceof ArrayableInterface) { | |
$value = $value->toArray(); | |
} | |
// A regular object that we just cast | |
// to an array | |
elseif (is_object($value)) { | |
$value = (array)$value; | |
} | |
// Fill the custom repository object, but only | |
// if it's an array (otherwise making it a | |
// repository object would be too much normalization) | |
// Also don't do this for collections | |
if (is_array($value) && !$isCollection) { | |
$object = App::make('App\Repositories\RepositoryObject'); | |
$object->fill($value); | |
} | |
// Return either the normalised object | |
// or the original value (not an array or object, or a nested call) | |
return isset($object) ? $object : $value; | |
} | |
/** | |
* Perform some content validation on the provided value. | |
* | |
* @param mixed $value | |
* | |
* @throws ModelNotFoundException | |
*/ | |
protected function validate($value) | |
{ | |
// Is it a Collection? | |
if ($value instanceof Collection) { | |
// Does it have any content? | |
if (count($value) <= 0) { | |
throw (new ModelNotFoundException())->setModel($this->model); | |
} | |
} | |
} | |
/** | |
* Wrapper to normalize and validate a result. | |
* | |
* @param mixed $result | |
* | |
* @return \App\Repositories\RepositoryObject|\Illuminate\Support\Collection|mixed | |
*/ | |
protected function enhance($result) | |
{ | |
$result = $this->normalize($result); | |
$this->validate($result); | |
return $result; | |
} | |
/** | |
* Handle every public call that's not overridden and reroute it to the model. | |
* | |
* @param $name | |
* @param $arguments | |
* | |
* @return \App\Repositories\RepositoryObject|\Illuminate\Support\Collection|mixed | |
*/ | |
public function __call($name, $arguments) | |
{ | |
// TODO: might need some more review and work | |
return $this->enhance(call_user_func_array([$this->model, $name], $arguments)); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php namespace App\Repositories\Items; | |
use App; | |
use App\Models\Item; | |
use App\Repositories\AbstractRepository; | |
class ItemDBRepository extends AbstractRepository | |
{ | |
public function __construct(Item $model) | |
{ | |
parent::__construct($model); | |
} | |
public function findOrFail($id) | |
{ | |
return $this->enhance($this->model->findOrFail($id)); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php namespace App\Repositories; | |
use Illuminate\Support\Contracts\ArrayableInterface; | |
use Illuminate\Support\Contracts\JsonableInterface; | |
class RepositoryObject implements ArrayableInterface, JsonableInterface | |
{ | |
public function fill(array $attributes) | |
{ | |
foreach ($attributes as $key => $value) { | |
$this->$key = $value; | |
} | |
} | |
/** | |
* Get the instance as an array. | |
* | |
* @return array | |
*/ | |
public function toArray() | |
{ | |
return (array)$this; | |
} | |
/** | |
* Convert the object to its JSON representation. | |
* | |
* @param int $options | |
* | |
* @return string | |
*/ | |
public function toJson($options = 0) | |
{ | |
return json_encode($this->toArray()); | |
} | |
/** | |
* Convert the object to a JSON string. | |
* | |
* @return string | |
*/ | |
public function __toString() | |
{ | |
return $this->toJson(); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment