【问题标题】:Laravel - Override parent constructor from extended classLaravel - 从扩展类覆盖父构造函数
【发布时间】:2014-10-29 18:02:32
【问题描述】:

我正在从包中扩展控制器,以便在使用 composer 更新时可以对其进行编辑并避免丢失更改。到目前为止一切正常,但构造函数有问题。

我原来的班级有这个:

class UserRegisterService
{


    public function __construct(UserSignupValidator $v = null)
    {
        //unrelated stuff here
        Event::listen('service.activated',
                      'Jacopo\Authentication\Services\UserRegisterService@sendActivationEmailToClient');
    }
}

扩展控制器是:

use Jacopo\Authentication\Services\UserRegisterService;
use Jacopo\Authentication\Validators\UserSignupValidator;


class CustomUserRegisterService extends UserRegisterService
{

    public function __construct(UserSignupValidator $v = null)
    {
        //unrelated stuff here
        Event::listen('service.activated',
                      'CustomUserRegisterService@sendActivationEmailToClient');
    }

我有基本相同的东西,我扩展类的更改在 CustomUserRegisterService@sendActivationEmailToClient 内部(基本上我想使用 mandrill 和自定义模板发送与原始控制器不同的电子邮件)。

事件正在触发并且两个函数都被调用,所以当用户被激活时我收到一封重复的电子邮件(在这种情况下就是事件)。我只想调用我的自定义类的构造函数,而另一个需要忽略。

这可能吗?

编辑: 正如 cmets 中所建议的,我在原始构造中评论了 Event::listen 并解决了问题,只发送了一封电子邮件。但这当然不能解决我一更新就会取消注释的问题。

添加return false;在 CustomUserRegisterService@sendActivationEmailToClient 的末尾也不起作用,只在构造函数中注释了事件就可以了。

【问题讨论】:

  • 假设您在子类中不是 callent parent::__constructor,则不应解雇父级的侦听器。父类UserRegisterService 是否有可能在您的代码中的其他地方被实例化?你确定是父监听器触发了,而不是子监听器触发了两次? (删除其中一个进行检查。)最后,您可以从侦听器中return false 停止事件传播(尽管最好弄清楚它发生的原因并解决它)。
  • 电子邮件是不同的(拥有自定义控制器的全部意义在于),所以我知道一个来自旧控制器,也许它不是来自构造函数,我会进一步测试并评论,感谢您的意见
  • 在您的父构造函数中,将事件侦听器更改为包含 throw new Exception(); 的闭包,然后查看堆栈跟踪以查看触发事件的位置。
  • 我对父构造函数所做的任何更改都将在我更新作曲家后被删除。这是这个问题的主要问题。
  • 不,这只是为了调试。这样您就可以准确地看到父构造函数中的侦听器是从哪里调用的,并隔离是否可能在您的代码中某处创建了父类 UserRegisterService 的实例。

标签: php laravel laravel-4


【解决方案1】:

只要您不在 CustomUserRegisterService 类 UserRegisterService 中调用 parent::__construct(),__construct 就不会被执行。但是您必须在 CustomUserRegisterService 类 __constructor 中的 UserRegisterService 中实现“不相关的东西”。

class A {
	public function __construct($v = "")
	{
		echo "A's constructor";
	}
}


class B extends A{
	public function __construct()
	{
        //parent::__construct();

		echo "B's constructor";
	}
}


$b = new B();

输出:B的构造函数

至于你的例子

好的,这是一个想法,但首先请检查您是否在代码中的某处实例化了 UserRegisterService。如果是这样,那么您必须使其成为单例。在 UserRegisterService 类 Event::listent 中,它说当它触发“service.activated”时运行 UserRegisterService 的 sendActivationEmailToClient。因此,每当它触发“service.activated”时,系统都会实例化一个 UserRegisterService 对象,然后运行 ​​sendActivationEmailToClient 函数。现在的问题是,当系统创建 UserRegisterService 实例时,它会运行构造函数。这意味着它将另一个侦听器添加到事件池中。 IMO 你需要做的是让用户 laravel 不会多次加载(实例化)UserRegisterService 或 CustomUserRegisterService。

例如:

//AClass.php in model folder

class AClass
{

    public function __construct($v = "")
    {
        echo "A's constructor <br />";
        
        Event::listen('a.run', 'A@hi');
    }

    public static function hi()
    {
         echo "Its me, A's event <br />";
    }
    

}

//BClass.php in model folder

class BClass extends AClass
{

    public function __construct()
    {
        //parent::__construct();
        echo "B's constructor <br />";
        
        Event::listen('a.run', 'BClass@hi');
        
    }

    public static function hi()
    {
        echo "Its me, B's event <br />";
    }

}




//in app/routes.php or in your service provider

App::singleton('ObjB', function(){
    return new BClass();
});

APP::bind('BClass', function(){
    return App::make('ObjB');
});


//test the events
Route::get('/',  function(){
    $b = App::make('ObjB');
    
    echo "1st event trigger ------------ <br/>";
    Event::fire('a.run');
    
    echo "2nd event trigger ------------ <br/>";
    Event::fire('a.run');
    
    echo "3rd event trigger ------------ <br/>";
    Event::fire('a.run');
});

我希望这会对你有所帮助。我正在 laravel 4.2 中对此进行测试,它对我有用。让我知道你的结果。谢谢

【讨论】:

  • 我没有在 CustomUserRegisterService 中调用父构造函数,“不相关的东西”是变量,它们都在构造函数中。所以如果我理解正确的话,不应该执行父构造函数吗?也许我在课堂的其余部分遗漏了其他东西,但我会说该事件正在启动这两个函数
  • 好吧,如果 CustomUserRegisterService 没有调用父构造函数,那么它应该是别的东西。尝试评论父类 Event::listen 并查看它是否仍在向您发送两封电子邮件。
  • 我在原始 event::listen 中评论了该事件,但我只收到一封电子邮件,所以我很困惑。两个构造函数都在这里执行。返回假; damiani 建议的那个也没有用。
猜你喜欢
  • 1970-01-01
  • 2022-11-24
  • 2011-07-28
  • 1970-01-01
  • 1970-01-01
  • 2011-05-01
  • 1970-01-01
  • 2015-02-01
  • 1970-01-01
相关资源
最近更新 更多