So I am a laravel developer and even though I have worked with it for a while now, and I love how the magic happens beneath the surface, how it automatically binds implementations when instantiating classes via the IoC container, right now I am trying to go to the basics of design patters and learn how things actually work.
So I started with the Animal example:
abstract class Animal
{
    abstract function makeSound();
}
class Dog extends Animal
{
    public function makeSound()
    {
        echo "Bark!\n";
    }
}
class Cat extends Animal
{
    public function makeSound()
    {
        echo "Bark!\n";
    }
}
So I am reading Head First Design Patterns and I am trying to make the most of the book. At this point every time I create a new Animal, I will have to implement the make sound method which will differ in most cases.
So the book tells me that I should code a Soundable interface and then have implementations of that interface in the Animal extended classes.
I finally came up with something like this:
interface Soundable
{
    function sound();
}
class Bark implements Soundable
{
    public function sound()
    {
        return "Bark!\n";
    }
}
class Meow implements Soundable
{
    public function sound()
    {
        return "Meow!\n";
    }
}
class Animal
{
    public $soundable;
    public function __construct(Soundable $soundable)
    {
        $this->soundable = $soundable;
    }
    public function makeSound()
    {
        echo $this->soundable->sound();
    }
}
class Dog extends Animal
{
}
class Cat extends Animal
{
}
function makeAnimal(Animal $animal){
    return $animal; 
}
// Making a dog
$animal = makeAnimal(new Dog(new Bark()));
$animal->makeSound();
// Making a cat
$animal = makeAnimal(new Cat(new Meow()));
$animal->makeSound();
So now when I have another animal that barks or meows, I can simple instantiate that implementation while making an animal.
Now my question is how do I tell PHP to automatically pass the new Bark() while instantiating the Dog class since it will bark and I don't want to write it every time I instantiate a new Dog object.
So how do I use a similar magic that Laravel uses to pass the Bark object automatically while instantiating Dog.
PS: I am still learning so I might be going in the wrong direction altogether while understanding these principles. Please guide me if you know better.
First of all, a small note: the book is wrong. The interface should be called Audible or Vocal. "Soundable" is not a real word an the author should be embarrassed. Also, calling a variable in the same name as an interface is kinda bad.  
Another thing is: the Laravel's IoC is actually just a glorified service locator, so it wouldn't really help you here.
Usually, you would have two options:
I tend to recommend Auryn in these case. Though, if you are willing to jump few additional hoops and suffer through limited configuration, you can also use Symfony's DIC.
If you were using Auryn, initialization of your dog and cat would be just:
$injector = new Auryn\Injector;
$dog = $injector->make('Dog'); 
$cat = $injector->make('Cat'); 
The library would on its own look up the reflection of the constructor for Dog and detect that it will also need to create a new Bark instance.
You can create simply animal factory (sounds strange) with factory methods.
Factory classes are often implemented because they allow the project to follow the SOLID principles more closely. In particular, the interface segregation and dependency inversion principles.
For more information look here https://www.sitepoint.com/understanding-the-factory-method-design-pattern/ Just remember if you want to write down some unit test don't use static methods, just instantiate factory, there may be need in future to create factory with some dependencies.
<?php
class AnimalFactory
{
    public function createDog() : Dog
    {
        return new Dog(new Bark());
    }
}
$factory = new AnimalFactory();
$dog = $factory->createDog();
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With