-
-
Save JeffreyWay/4652702 to your computer and use it in GitHub Desktop.
<?php | |
class DogsController extends BaseController { | |
protected $db; | |
// Let the db-layer be injected. Don't worry... | |
// Laravel will automatically inject the dependencies for you. | |
function __construct(DogInterface $db) { | |
$this->db = $db; | |
} | |
public function index() | |
{ | |
var_dump($this->db->getAll()); | |
} | |
} |
<?php | |
// When you need an instance of DogInterface, | |
// use the Eloquent implementation. Easy to switch out. | |
App::bind('DogInterface', 'EloquentDog'); | |
// Let's define a contract for what any implementation | |
// of DogInterface should offer. | |
interface DogInterface { | |
public function getAll(); | |
} | |
// Here's our first implementation: an Eloquent one. | |
class EloquentDog extends Eloquent implements DogInterface { | |
public $table = 'dogs'; | |
public function getAll() | |
{ | |
return static::all(); | |
} | |
} | |
// And our second implementation, perhaps for a simple Array "DB" | |
class ArrayDog implements DogInterface { | |
public function getAll() | |
{ | |
return ['sparky', 'trash', 'ham']; | |
} | |
} | |
route::get('/', function() { | |
// Laravel is smart enough to inject the necessary | |
// dependencies for, using reflection. | |
$dog = App::make('DogInterface'); | |
// Try changing line 5 to the second implementation, ArrayDog | |
// Instance switch! | |
$dog->getAll(); | |
}); |
I think Jeff's example is OK as long as your repository doesn't have any dependencies. However, if your repositories start to have dependencies you would need to split the repository from the eloquent model itself, with something like:
interface DogRepositoryInterface {}
class EloquentDogRepository implements DogRepository {}
class Dog extends Eloquent {}
Then you would inject an implementation of DogRepositoryInterface
into your controllers.
I believe the IoC container will throw an exception when it tries to resolve the dependency in the constructor for DogController. It should complain that it cannot resolve type Array in the Eloquent constructor.
I ran into this issue when I trying my own approach: https://gist.github.com/4367545
John - Yeah, exactly what Taylor said. I was trying to keep it somewhat simple for this Gist, but yeah, I'd imagine that in most projects, you'd want a base Dog class, and then have Laravel automatically inject the dependency.
I'll update this Gist in a sec.
Thank you very much to all of you for taking time to respond to my question. I now understand why sometimes its better to separate it depending on the situation. Thanks again. Cheers everyone!
Evan - Hmm - I checked this code before posting the Gist, and didn't notice any exceptions being thrown...
@eoconnell - You should update your repo to the latest one. do composer update
That issue is already solved here - laravel/framework#80
Yeah, the IoC container will resolve default arguments now, so shouldn't get any exceptions here.
The idea of a Dog being an extension of Eloquent makes little sense. A dog is not a type of database abstraction.
Great to hear. Thanks.
Hi Jeffrey, thanks for sharing this gist. Anyway I got a question. Is it better to extend eloquent and implement the interface at the same time like your code above like this:
class EloquentDog extends Eloquent implements DogInterface {}
Or it would be better to create 1 class that implements the interface and 1 class that extends eloquent like this:
class EloquentDog implements DogInterface {
public function all() {
return Dog::all();
}
}
class Dog extends Eloquent {}
Because I'm confused, some said the second option is better. My question is related to this one - laravel/framework#139 (comment)
Wanna know your thoughts about it. Thanks.