7

I have registered a singleton in a service provider like so:

$this->app->singleton(MyClass::class);

This can normally be accessed by simply stating it in the parameters like so:

class FooController extends Controller
{
    public function index(MyClass $myClass)
    {
        //...
    }
}

However I cannot seem to be able to access this singleton in other custom classes (i.e. non controller classes). (https://laravel.com/docs/5.2/container#resolving)

For example like here:

class Bar {
   private $myClass;
   private $a;
   private $b;

   public function __construct($a, $b) {
      $this->a = $a;
      $this->b = $b;
      $this->myClass = ... // TODO: get singleton
   }
}

How do I do this?

Note that I will be creating multiple instances of Bar.

Yahya Uddin
  • 26,997
  • 35
  • 140
  • 231

3 Answers3

10

Type-hint the class/interface in your constructor and in most cases Laravel will automatically resolve and inject it into you class.

See the Service Provider documentation for some examples and alternatives.

To go with your example:

class Bar {
    private $myClass;

    public function __construct(MyClass $myClass) {
       $this->myClass = $myClass;
    }
}

In cases where Bar::__construct takes other parameters that can not be per-defined in a service provider you will have to use a service locator:

/* $this->app is an instance of Illuminate\Foundation\Application */
$bar = new Bar($this->app->make(MyClass::class), /* other parameters */);

Alternatively, move the service location into the constructor it self:

use  Illuminate\Support\Facades\App;

class Bar {
    private $myClass;

    public function __construct() {
       $this->myClass = App::make(MyClass::class);
    }
}
nCrazed
  • 1,025
  • 6
  • 20
  • The problem with this approach is how will I create multiple instances of Bar (especially if I have more parameters on the constructor). i.e. `$bar = new Bar(5, 10);`. Updated question to show what I mean – Yahya Uddin Feb 28 '16 at 16:46
7

In later Laravel versions 6 and higher there are even more helpers to solve this:

resolve(MyClass::class);
app(MyClass::class);

& all the methods provided by the other answers

class Bar {
   private $myClass;
   private $a;
   private $b;

   public function __construct($a, $b) {
      $this->a = $a;
      $this->b = $b;
      $this->myClass = app(MyClass::class);
   }
}
Christophvh
  • 12,586
  • 7
  • 48
  • 70
2

You can use singleton running make method of Application this way:

use Illuminate\Contracts\Foundation\Application;

class Bar {
   private $myClass;
   private $a;
   private $b;

   public function __construct($a, $b, Application $app) {
      $this->a = $a;
      $this->b = $b;
      $this->myClass = $app->make(MyClass::class);
   }
}

You can read more about this in Container resolving documentation.

Marcin Nabiałek
  • 109,655
  • 42
  • 258
  • 291
  • How would I create multiple different instances of `Bar`? – Yahya Uddin Feb 29 '16 at 00:59
  • Also is there a way to access the `$app` variable in a static context – Yahya Uddin Feb 29 '16 at 01:28
  • 1
    @YahyaUddin We were not talking about `Bar`. You can create instances of it using again `App::make(Bar::class)`. Instead of injecting `Application` you can use anywhere `App` facade, so you can run anywhere `App::make(SomeClass::class)` to create object (it will be either new instance or same instance depending whether it's defined as singleton or not). – Marcin Nabiałek Feb 29 '16 at 05:38