O
O
Oleg Pravdin2018-12-27 17:10:10
Laravel
Oleg Pravdin, 2018-12-27 17:10:10

Where is the best place to initialize a library in Laravel?

Good afternoon. As part of the Laravel project, the library is being used to work with the API. At the moment, I use a "layer": a service of two methods: _construct and getInstance.

class ApiClient
{
    protected $api;
    public function __construct() {
        $this->api = new VeryUsefulApi([
            '1' => env('1', false),
            '2' => env('2', false),
            '3' => env('3', false),
            '4' => env('4', false),
        ]);
    }

    public function getInstance() {
        return $this->api;
    }
}

In the first one, automatically according to the parameters from the ENV file, the library is initialized and written to the protected field of the class, in the second, an already initialized object is simply issued outside. This service is registered as singletone. In other services that need to use this library, I use constructor dependency injection and do something like
public function __construct(ApiClient $api) {
        $this->api= $api;
}

and then I use it at the destination.
Question: how do you solve such a problem and / or how should it be solved correctly?

Answer the question

In order to leave comments, you need to log in

2 answer(s)
R
Roman Sokharev, 2018-12-27
@greabock

use Illuminate\Support\ServiceProvider;

class ApiClientServiceProvider extends ServiceProvider 
{
    /** @var boolean  Отложенный, потому не при каждом запросе нам нужно дергать это апи */
    public $deffered = true;

    public function register ( ) 
    {
        
        $this->app->singleton(VeryUsefulApi::class, function($app) {
             // Не очень хорошо дергать env из провайдера, поэтому поместим-ка настройки в конфиг
            // А уж из конфига будем дергать env
            new VeryUsefulApi([$app['config']['services.verify_user']); 
        });

        $this->app->singleton(ApiClient::class); // Ну это если нужен именно синглтон
    }

     /** @return array | string[]  Сообщаем контейнеру, что если вдруг нужны эти ключи, то они тут */
    public function provides() {
        return [VeryUsefulApi::class, ApiClient::class];
    }
}

class ApiClient 
{
    /** @var VeryUsefulApi */
    protected $api;

    public function __construct (VeryUsefulApi $api)  
    {
        $this->api = $api;
    }
    #...
}

class SomeController {

    /** @var ApiClient */
    protected $client;

    public fuction __construct(ApiClient  $client)
    {
          $this->clien = $client;
    }
}

Well, this is literally what you asked for.
On the other hand, it is not very clear why this wrapper is needed at all.
Why not pull VeryUsefulApi directly, bypassing the ApiClient wrapper.
Well, it is, thinking out loud ... "You know better from the well" (c))

V
Vitaliy Orlov, 2018-12-27
@orlov0562

That's pretty much how it's done. Only it is better to implement VeryUsefulApi into the adapter via DI, otherwise ApiClient is tightly coupled to VeryUsefulApi. But, I guess there are reasons why this is done.
If there are no reasons, then look here how it's done: Laravel's Dependency Injection Container in Depth .

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question