我需要用Symphony的事件发送者替换我的notifyService
。
这是原始服务:
<?php
class VmService
{
/**
* @var VmManager|null
*/
protected $vmManager = null;
/**
* @var ProvisionerInterface[]
*/
protected $provisionners = array();
/**
* @var NotifyService|null
*/
protected $notifyService = null;
public function setVmManager(VmManager $vmManager)
{
$this->vmManager = $vmManager;
}
public function getVmManager()
{
return $this->vmManager;
}
/**
* @param $type
* @param ProvisionerInterface $provisionner
*/
public function setProvisionner($type, ProvisionerInterface $provisionner)
{
$this->provisionners[$type] = $provisionner;
}
/**
* @param $type
* @return ProvisionerInterface
*/
public function getProvisionner(Vm $vm)
{
return $this->provisionners[$vm->getType()];
}
/**
* @param NotifyService $notifyService
*/
public function setNotifyService(NotifyService $notifyService)
{
$this->notifyService = $notifyService;
}
/**
* @return NotifyService|null
*/
public function getNotifyService()
{
return $this->notifyService;
}
public function initialise(Vm $vm)
{
$vmManager = $this->getVmManager();
$provisioner = $this->getProvisionner($vm);
$provisioner->initialise($vm);
$vm->setStatus(VM::STOPPED);
$vmManager->flush($vm);
}
public function delete(Vm $vm, $force = false)
{
$now = new \DateTime();
$day = $now->format('w');
if ( ($day == 0 || $day == 6) && ! $force) {
throw new \Exception('Cannot delete a VM on weekend unless you force it');
}
$vmManager = $this->getVmManager();
$provisioner = $this->getProvisionner($vm);
$provisioner->delete($vm);
$vm->setStatus(Vm::STOPPED);
$vmManager->flush($vm);
}
private function deleteLogFile(Vm $vm)
{
$filename = VmLogger::getLogFile($vm->getIdVm());
if (file_exists($filename)) {
@unlink("$filename");
}
}
public function prepare(Vm $vm)
{
/**
* @var VM $vm
*/
$provisionner = $this->getProvisionner($vm);
//$provisionner->start($vm, true, 'integ.lafourchette.local');
$provisionner->stop($vm);
}
public function start(Vm $vm, $provisionEnable = true)
{
$vmManager = $this->getVmManager();
$notify = $this->getNotifyService();
/**
* @var VM $vm
*/
$provisionner = $this->getProvisionner($vm);
$vm->setStatus(VM::STARTED);
$vmManager->flush($vm);
try {
$provisionner->start($vm, $provisionEnable);
$vm->setStatus(VM::RUNNING);
$vmManager->flush($vm);
$notify->send('ready', $vm);
} catch (UnableToStartException $e) {
$vm->setStatus(VM::STOPPED);
$vmManager->flush($vm);
$notify->send('unable_to_start', $vm);
throw $e;
}
}
public function getStatus(Vm $vm)
{
return $this->getProvisionner($vm)->getStatus($vm);
}
public function stop(Vm $vm)
{
$vmManager = $this->getVmManager();
/**
* @var VM $vm
*/
$provisionner = $this->getProvisionner($vm);
$vm->setStatus(Vm::STOPPED);
$vmManager->flush($vm);
$provisionner->stop($vm);
}
public function archived(Vm $vm)
{
$vmManager = $this->getVmManager();
$this->delete($vm);
$vm->setStatus(VM::EXPIRED);
$this->deleteLogFile($vm);
$vmManager->flush($vm);
$this->prepare($vm);
}
}
以下是我改变的内容:
<?php
class VmService
{
/**
* @var VmManager|null
*/
protected $vmManager = null;
/**
* @var ProvisionerInterface[]
*/
protected $provisionners = array();
/**
* @var NotifyService|null
*/
protected $notifyService = null;
public function setVmManager(VmManager $vmManager)
{
$this->vmManager = $vmManager;
}
public function getVmManager()
{
return $this->vmManager;
}
/**
* @param $type
* @param ProvisionerInterface $provisionner
*/
public function setProvisionner($type, ProvisionerInterface $provisionner)
{
$this->provisionners[$type] = $provisionner;
}
/**
* @param $type
* @return ProvisionerInterface
*/
public function getProvisionner(Vm $vm)
{
return $this->provisionners[$vm->getType()];
}
/**
* @param NotifyService $notifyService
*/
public function setNotifyService(NotifyService $notifyService)
{
$this->notifyService = $notifyService;
}
/**
* @return NotifyService|null
*/
public function getNotifyService()
{
return $this->notifyService;
}
public function initialise(Vm $vm)
{
$vmManager = $this->getVmManager();
$provisioner = $this->getProvisionner($vm);
$provisioner->initialise($vm);
$vm->setStatus(VM::STOPPED);
$vmManager->flush($vm);
}
public function delete(Vm $vm, $force = false)
{
$now = new \DateTime();
$day = $now->format('w');
if ( ($day == 0 || $day == 6) && ! $force) {
throw new \Exception('Cannot delete a VM on weekend unless you force it');
}
$vmManager = $this->getVmManager();
$provisioner = $this->getProvisionner($vm);
$provisioner->delete($vm);
$vm->setStatus(Vm::STOPPED);
$vmManager->flush($vm);
}
private function deleteLogFile(Vm $vm)
{
$filename = VmLogger::getLogFile($vm->getIdVm());
if (file_exists($filename)) {
@unlink("$filename");
}
}
public function prepare(Vm $vm)
{
/**
* @var VM $vm
*/
$provisionner = $this->getProvisionner($vm);
//$provisionner->start($vm, true, 'integ.lafourchette.local');
$provisionner->stop($vm);
}
public function start(Vm $vm, $provisionEnable = true)
{
$vmManager = $this->getVmManager();
$dispatcher = new EventDispatcher();
/**
* @var VM $vm
*/
$provisionner = $this->getProvisionner($vm);
$vm->setStatus(VM::STARTED);
$vmManager->flush($vm);
try {
$provisionner->start($vm, $provisionEnable);
$vm->setStatus(VM::RUNNING);
$vmManager->flush($vm);
$event = new NotifyEvent($vm);
$dispatcher->addListener('notify.action', $event);
$dispatcher->dispatch('notify.action');
} catch (UnableToStartException $e) {
$vm->setStatus(VM::STOPPED);
$vmManager->flush($vm);
$event = new NotifyEvent($vm);
$dispatcher->addListener('notify.action', $event);
$dispatcher->dispatch('notify.action');
throw $e;
}
}
public function getStatus(Vm $vm)
{
return $this->getProvisionner($vm)->getStatus($vm);
}
public function stop(Vm $vm)
{
$vmManager = $this->getVmManager();
/**
* @var VM $vm
*/
$provisionner = $this->getProvisionner($vm);
$vm->setStatus(Vm::STOPPED);
$vmManager->flush($vm);
$provisionner->stop($vm);
}
public function archived(Vm $vm)
{
$vmManager = $this->getVmManager();
$this->delete($vm);
$vm->setStatus(VM::EXPIRED);
$this->deleteLogFile($vm);
$vmManager->flush($vm);
$this->prepare($vm);
}
}
然而,正如我在文档中看到的那样,我需要一个监听器,但我无法弄清楚如何关联它,以及如何使它工作。
答案 0 :(得分:5)
您需要重构代码。 As stated in the documentation,为了分派事件,您必须创建事件并在 EventDispatcher 实例上调用dispatch
方法,因此在代码中而不是您正在执行的操作目前:
<?php
// this is the start method of your service
// ...
$event = new NotifyEvent($vm);
$dispatcher->addListener('notify.action', $event);
$dispatcher->dispatch('notify.action');
// ...
您必须创建活动并直接发送:
<?php
// this is the start method of your service
// ...
$event = new NotifyEvent($vm);
$dispatcher->dispatch('notify.action', $event);
// ...
您现在也发送相同的活动(&#39; notify.action&#39;),但之前您有2个不同的活动:&#39;准备好&#39;并且&#39; unable_to_start&#39;,因此您必须为2个不同的事件创建2个侦听器(&#39; notify.success&#39;以及&#39; notify.unable_to_start&#39;例如)。
现在你还有两个问题:
start
方法时都要创建调度程序,因此每次都必须配置它(配置意味着添加监听器)如果通过基于Symfony EventDispatcher创建另一个服务来重构一点,你可以解决这两个问题:
<?php
// somewhere in your config file
// ...
$app['notifyService'] = $app->share(function() use ($app) {
$dispatcher = new Symfony\Component\EventDispatcher\EventDispatcher();
$dispatcher->addListener('notify.success', $callable1);
$dispatcher->addListener('notify.unable_to_start', $callable2);
return $dispatcher;
});
请注意,$callable1
和$callable2
可以为您提供一个想法,请再次检查documentation以了解如何正确添加侦听器(您可以创建一个clousure或方法)处理事件的类,完全取决于你)。
现在,您已根据事件调度程序定义了一个notifyService(另一个与Silex使用的EventDispatcher完全不同,因此您的域事件有一个干净的事件调度程序),您可以将其用作通知服务你的班。您可以像以前一样:使用setNotifyService
方法,在代码中您只需要创建事件并调用调度方法(假设您已经调用了setNotifyService):
<?php
// class VmService
// method start
// when you've to dispatch the success event
$event = new NotifySuccessEvent($vm);
$this->notifyService->dispatch('notify.success', $event);
// if you have to dispatch the notify.unable_to_start event
$event = new NotifyUnableToStartEvent($vm);
$this->notifyService->dispatch('notify.unable_to_start', $event);
我希望这会让你走上正轨。
PS:您必须自己编写2个事件类的代码,再次查看文档以获取详细信息。