How do I pass a registered service singleton into another registered service's constructor in Laravel 7?

Viewed 433

I have recently been learning about the AppServiceProvider. I have registered a service in the AppServiceProvider which creates a singleton - an instantiated GuzzleHttp Client, like so:

$this->app->singleton('GuzzleHttp\Client', function($api) {
    return new Client([
        'base_uri' =>  env('ELASTICSEARCH_HOST'),
        'auth' => [
            env('ELASTICSEARCH_USER'), 
            env('ELASTICSEARCH_PASS')
        ],
    ]);
});

This is connecting to an ElasticSearch API, and that currently works:

$response = app('GuzzleHttp\Client')->request('GET');

I have set up a facade called ElasticSearchFacade, which contains only the getFacadeAccessor():

protected static function getFacadeAccessor()
{
    return 'elasticSearch';
}

I have also registered elasticSearch in my AppServiceProvider, like so:

$this->app->bind('elasticSearch', function() {
    return new ElasticSearch();
});

This creates a new ElasticSearch instance. However, I would love to pass the GuzzleHttp\Client into the elasticSearch service. So I have tried adding the following to my ElasticSearch.php file:

use GuzzleHttp\Client;

class ElasticSearch
{
    protected $client;

    public function __contruct(Client $client)
    {
        $this->client = $client;
    }

    public function handle()
    {
        $response = $this->client->request('GET');
        die($response->getBody()->getContents());
    }
}

I have now changed the registered service to pass through the GuzzleHttp Client like so:

$this->app->bind('elasticSearch', function() {
    return new ElasticSearch(app('GuzzleHttp\Client'));
});

However I am getting the error:

PHP Error: Call to a member function request() on null

1 Answers

The constructor method is __construct not __contruct. You have not defined a custom constructor for your ElasticSearch class. So that member variable is null.

Side Note: do not call env outside of the configuration files.

To avoid having to make these env calls outside of configuration files you can just add configuration files as needed or add to current configuration files. Something like Elastic Search credentials can probably get added to the services.php configuration file:

<?php

return [
    ...

    'elasticsearch' => [
        'host' => env('ELASTICSEARCH_HOST'),
        'user' => env('ELASTICSEARCH_USER'),
        'password' => env('ELASTICSEARCH_PASS'),
    ],

    ...
];

Now that you have these in the configuration you can use the configuration system to pull these values:

config('services.elasticsearch'); // that whole array of values
config('services.elasticsearch.host'); // just that host value

Config::get('services.elasticsearch');
app('config')->get(...);

There are multiple ways to access the configuration system.

Related