Как $ this-> app-> singleton () работает в laravel? - PullRequest
2 голосов
/ 13 июля 2020

В моем проекте laravel у меня есть следующие интерфейс, репозиторий и контроллер.

Это интерфейс

interface TrainingClassTypeInterfaces
{
    public function updateTrainingClassType($id, $request);
} 

Это репозиторий

use App\Models\Trainings\AppTrainingClassType;
class TrainingClassTypeEloquent implements TrainingClassTypeInterfaces
    {
        protected $model;
    
        public function __construct(AppTrainingClassType $appTrainingClassType)
        {
            $this->model = $appTrainingClassType;
        }
    
        public  function updateTrainingClassType($id, $request)
        {
            $response = false;
            $isUpdated = $this->model::where('training_class_id',$id)->update([
                'app_id' => $request->app_id
            ]);
            .... 
        }
    
    }

Это контроллер

class TrainingClassTypesController extends \TCG\Voyager\Http\Controllers\VoyagerBaseController
{
    protected  $trainingService;
    public function __construct(TrainingClassTypeEloquent $trainingClassTypeInterfaces) {
        $this->trainingService = $trainingClassTypeInterfaces;
    }

    public function insertOrUpdate()
    {
        ...
        $this->trainingService->updateTrainingClassType($id, $request);
        ..
    }

}

Здесь все работает нормально

Как видите, я использую метод TrainingClassTypeEloquent внутри TrainingClassTypesController. Но он возвращал ошибку вроде

Argument 1 passed to ...::__construct() must be an instance of

В основном он просил меня поместить экземпляр модели в класс TrainingClassTypeEloquent. Затем я сделал следующее

$TCTypes = new AppTrainingClassType();
$TCT = new TrainingClassTypeEloquent($TCTypes);
$TCT->updateTrainingClassType($id, $request);

, который работал нормально, но я был смущен тем, что этот подход неправильный, должен быть какой-то правильный способ.

После поиска в Google я нашел другое решение, которое является одноэлементная привязка, а затем я попытался выполнить в AppServiceProvider

$this->app->singleton(
            \App\Services\Voyager\Eloquent\TrainingClassType\TrainingClassTypeInterfaces::class,
            \App\Services\Voyager\Eloquent\TrainingClassType\TrainingClassTypeEloquent::class
        );

После добавления этой одноэлементной привязки я заметил, что скрипт работал без предоставления экземпляра модели в класс TrainingClassTypeEloquent.

Я хотел бы знаю, как работает $this->app->singleton(), так что таким образом моя концепция будет прояснена. Если кто-то знает, пожалуйста, расскажите мне об этом.

Большое спасибо

Ответы [ 3 ]

1 голос
/ 13 июля 2020

Это все о ПРИВЯЗКА услуги к сервисному контейнеру .

Что делает метод $this->app->singleton();?

Одноэлементный метод связывает класс или интерфейс с сервисным контейнером , чтобы Laravel мог поддерживать зависимость (при использовании интерфейса в качестве параметра конструктора).

(На самом деле Singleton - это шаблон проектирования. Реализация Singleton всегда возвращает тот же объект при последующих вызовах вместо нового экземпляра). Итак, метод $this->app->singleton(); снова и снова возвращает один и тот же объект.

Следует отметить , что Laravel do c говорит:

не нужно привязывать классы к контейнеру, если они не зависят от каких-либо интерфейсов . Контейнер не нужно инструктировать о том, как создавать эти объекты, поскольку он может автоматически разрешать эти объекты с помощью отражения.

Но ваш класс контроллера зависит от интерфейса, поэтому контейнер должен быть проинформирован и для этого вам нужно использовать этот метод $this->app->singleton();, но есть и другие способы.

Опять же, в то же время, этот TrainingClassTypeEloquent::class имеет зависимость от AppTrainingClassType::class. Но в этом случае нам не нужно об этом беспокоиться, потому что Laravel использует Reflection API для поддержания своей зависимости, поскольку этот класс не использует интерфейс, как класс TrainingClassTypesController::class.

Как только вы закончите привязку службы к контейнеру, Laravel автоматически поместит службу в метод конструктора в качестве аргумента, в котором используется интерфейс.

Надеюсь, это поможет вам. Вы можете найти дополнительную помощь в этом ответе .

0 голосов
/ 13 июля 2020

Связывание синглтона

Метод singleton связывает класс или интерфейс с контейнером, который должен быть разрешен только один раз. После разрешения одноэлементной привязки тот же экземпляр объекта будет возвращен при последующих вызовах в контейнер:

$this->app->singleton('HelpSpot\API', function ($app) {
    return new \HelpSpot\API($app->make('HttpClient'));
});

Для большего количества go до ЗДЕСЬ

0 голосов
/ 13 июля 2020

Вам необходимо зарегистрировать TrainingClassTypeEloquent

$this->app->singleton(TrainingClassTypeInterfaces::class, static function ($app) {
    return new TrainingClassTypeEloquent(new AppTrainingClassType());
});

Затем вы можете ввести его в свой контроллер

public function insertOrUpdate(TrainingClassTypeInterfaces $trainingService, $id)
{
    $trainingService->updateTrainingClassType($id, request());
}

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...