【问题标题】:Laravel model observer repository injectionLaravel 模型观察者仓库注入
【发布时间】:2015-01-11 00:55:15
【问题描述】:

我正在努力思考如何为 Laravel 的模型观察者注入存储库。 目前,我有这个设置。

UserPetServiceProvider.php

<?php namespace Bunny\Providers;

use Illuminate\Support\ServiceProvider;
use Bunny\Observers\Pet\UserPetObserver;

class UserPetServiceProvider extends ServiceProvider {

    public function register()
    {
        // User pets
        $this->app->bind('Bunny\Repos\Pet\IUserPetRepo', 'Bunny\Repos\Pet\UserPetRepo');

        // User pet layers
        $this->app->bind('Bunny\Repos\Pet\IUserPetLayerRepo', 'Bunny\Repos\Pet\UserPetLayerRepo');

        // User pet markings
        $this->app->bind('Bunny\Repos\Pet\IUserPetMarkingRepo', 'Bunny\Repos\Pet\UserPetMarkingRepo');

        $this->app->events->subscribe(new UserPetObserver());
    }

}

它可以很好地绑定所有接口和存储库,并且可以与观察者绑定,但我需要在构造函数中执行的存储库注入。构造函数中没有传递任何内容,因此它可以解释失败的原因。

UserPetRepo.php

<?php namespace Bunny\Repos\Pet;

use Bunny\Repos\BaseRepo;
use Bunny\Models\Pet\UserPet;
use Bunny\Repos\User\IUserRepo;
use Bunny\Repos\Breed\IStageRepo;
use Bunny\Repos\Breed\IBreedLayerRepo;

use Illuminate\Config\Repository as Config;
use Illuminate\Support\Str as String;
use Illuminate\Session\SessionManager as Session;
use Illuminate\Events\Dispatcher;

class UserPetRepo extends BaseRepo implements IUserPetRepo {

    public function __construct(UserPet $pet, IUserRepo $user, IStageRepo $stage, IBreedLayerRepo $layer, Config $config, String $string, Session $session, Dispatcher $events)
    {
        $this->model = $pet;
        $this->user = $user;
        $this->stage = $stage;
        $this->layer = $layer;
        $this->config = $config;
        $this->string = $string;
        $this->session = $session;
        $this->events = $events;

        $this->directory = $this->config->get('pathurl.userpets');
        $this->url       = $this->config->get('pathurl.userpets_url');
    }

    /**
     * Create new user pet
     * @param attributes     Attributes
     */
    public function createWithImage( array $attributes, array $colors, $domMarkings = null, $domMarkingColors = null, $recMarkings = null, $recMarkingColors = null )
    {
        $this->model->name = $attributes['name'];
        $this->model->breed_id = $attributes['breed_id'];
        $this->model->user_id = $this->user->getId();
        $this->model->stage_id = $this->stage->getBaby()->id;

        // Get image
        $image = $this->layer->compile(
            $attributes['breed_id'],
            'baby',
            $colors,
            $domMarkings,
            $domMarkingColors
        );

        // Write image and set
        $file = $this->writeImage( $image );
        if( ! $file )
        {
            return false;
        }

        $this->model->base_image = $file;
        $this->model->image = $file;

        if( ! $this->model->save() )
        {
            return false;
        }

        $this->events->fire('userpet.create', array($this->model));

        return $this->model;
    }

    /**
     * Write image
     * @param image      Imagick Object
     */
    protected function writeImage( $image )
    {
        $fileName = $this->string->random(50) . '.png';

        if( $image->writeImage( $this->directory . $fileName ) )
        {
            return $fileName;
        }

        $this->model->errors()->add('writeImage', 'There was an error writing your image. Please contact an administrator');
        return false;
    }

}

UserPetObserver.php

use Bunny\Repos\Pet\IUserPetLayerRepo;
use Bunny\Repos\Pet\IUserPetMarkingRepo;
use Bunny\Observers\BaseObserver;

class UserPetObserver extends BaseObserver {

    public function __construct(IUserPetLayerRepo $layers, IUserPetMarkingRepo $markings)
    {
        $this->layers = $layers;
        $this->markings = $markings;
    }

    /**
     * After create
     */
    public function onCreate( $model )
    {
        $this->layers->user_pet_id = $model->id;
        dd(Input::all());
        $this->layers->breed_layer_id = $model->id;
    }

    public function subscribe( $event )
    {
        $event->listen('userpet.create', 'UserPetObserver@onCreate');
    }

}

它抛出这个错误:

参数 1 传递给 Bunny\Observers\Pet\UserPetObserver::__construct() 必须是一个实例 Bunny\Repos\Pet\IUserPetLayerRepo 的,没有给出,在 H:\WD 中调用 SmartWare.swstor\HALEY-HP\Source2\bunny-meadows\app\Bunny\Providers\UserPetServiceProvider.php 在第 22 行并定义

这是有道理的,因为我没有在构造函数中传递任何东西。所以我尝试手动传递我的存储库。

$this->app->events->subscribe(new UserPetObserver(new UserPetLayerRepo, new UserPetMarkingRepo));

但随后它会引发 UserPetLayerRepo 需要注入的错误......而且它只是不断地循环。是不是我想多了?

谢谢。

编辑::: 这是我唯一能想到的。不过,这似乎是一种非常丑陋/糟糕的做法:

$this->app->events->subscribe(new UserPetObserver($this->app->make('Bunny\Repos\Pet\UserPetLayerRepo'), $this->app->make('Bunny\Repos\Pet\UserPetMarkingRepo')));

还有其他想法吗?

【问题讨论】:

    标签: php laravel dependency-injection repository


    【解决方案1】:

    试试吧:

    $this->app->events->subscribe($this->app->make('UserPetObserver'));
    

    当 Laravel 生成 UserPetObserver 对象时,它会在构造函数中读取类型提示的依赖项并自动生成它们。

    【讨论】:

    • 谢谢!我不知道为什么我在传入 $this->app->make() 作为构造函数的参数后没有想到这一点 D:一天编码太多了哈哈
    • 你知道为什么每当我尝试注入一个不在同一个 register() 方法中的存储库时,它就会给我这个:类 cache.store 不存在。 ?我的构造函数中有这个:public function __construct(IUserPetLayerRepo $layers, IUserPetMarkingRepo $markings, IBreedLayerRepo $breedLayers) 如果我删除 IBredLayerRepo,它工作正常。它不在同一个 register() 中,因为它在另一个服务提供商中。
    • 我想在这种情况下是因为 IBredLayerRepo 依赖于缓存存储,并且您的服务提供商的注册函数在缓存存储加载之前被调用。实际上,不应在 register 方法中调用您的事件侦听器。您应该覆盖 boot 方法并在那里添加您的事件侦听器。文档here.
    • 每当我将它移到那里时,我都会收到一条错误消息。 public function boot(Dispatcher $events) { $events-&gt;subscribe($this-&gt;app-&gt;make('Bunny\Observers\Pet\UserPetObserver')); } 它说启动方法必须与 Illuminate/Support 中的 ServiceProvider::boot() 兼容。我查看了他们的代码,在 boot() 中没有传递任何内容,那么如何在其中构建依赖项?
    • $this->app->events 成功了。但是当它们在文档中显示时,您不能将东西注入 boot() 中,这很奇怪。哦,好吧(:非常感谢!这解决了 cache.store 问题。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-02-20
    • 2023-04-10
    • 2021-02-13
    • 2020-10-11
    相关资源
    最近更新 更多