0

So I have a BaseValuation abstract class and it's implementations example FooValuation and BarValuation.

I want to instantiate Foo or Bar implementations depending on use input. So I created a simple class myself called Valuation which simply does this:

<?php

namespace App\Valuation;

class Valuation
{
    public $class;

    public function __construct($id, $type = 'basic')
    {
        $class = 'App\Valuation\Models\\' . ucfirst($type) . 'Valuation';

        $this->class = new $class($id);
    }

    public function make()
    {
        return $this->class;
    }
}

Using this I can simply do (new App\Valuation\Valuation($id, $type))->make() and I will get the desired implementation according to what the use asked for.

But I know that laravel's container is powerful and must allow me to do this somehow but I cannot understand how this will be done. Any ideas anyone?

Rohan
  • 13,308
  • 21
  • 81
  • 154
  • Not sure if this answers your question, and I like your approach more, but PHP seems to be able to do this without any fancy coding: https://3v4l.org/3bS97 – Loek Apr 25 '18 at 12:20

1 Answers1

5

You can bind a class to any string, normally this is done in a service provider.

$this->app->bind('string', SomethingValuation::class);

Then you can instantiate this with App::make('string').

I think this has more value when you're binding a single implementation (concrete) to an interface (abstract) rather than binding multiple classes.

You can also just allow Laravel to instantiate the class for you by calling App::make(\Full\Path::class).

Both would allow you to inject a mock into the container with the same name for testing purposes.

Devon Bessemer
  • 34,461
  • 9
  • 69
  • 95