我们有监控服务,我们的监控单元会关注某些机器。
我正在创建一个表单来在Symfony2中注册一台新机器。
所以我们有机器实体:
监控实体:
对于新机器,客户需要填写表单:
现在,如果我用一个机器实体作为数据支持来制作一个表单,我没有要求序列号的“字段”。 Symfony不允许它,因为后台实体没有名为“序列号”的字段。
我怎么能:
我想我可以:
我希望我能解释这一点。我想很多人都必须解决这个问题。我想我只是在查看一些非常标准的Symfony功能,因为我不确定它叫什么: - )
答案 0 :(得分:5)
首先,你应使用关系 - 即机器有一个监控。我认为人们对此有疑问,因为当你习惯于用“id”和外键来思考事物时,以完全面向对象的方式思考关系是新的:)。
因此,假设您的计算机与Monitor相关,您现在可以创建一个嵌入MonitorType的MachineType(它将是一个包含serialnumber字段的表单)。然后,在提交复合表单时,将使用Monitor类上的serialnumber约束。
默认情况下,绑定所有这些内容时,它将创建一个新的Machine对象,并通过$ machine-> getMonitor()提供新的Monitor对象。如果你坚持,这将是两个插入。但是,我猜你宁愿用它的序列号查找监视器并使用现有的监视器,对吗?这样做很简单,只需在绑定表单后短路即可。
$form = new MachineType();
$form->bindRequest($request);
if ($form->isValid()) {
$em = $this->getDoctrine()->getEntityManager();
$machine = $form->getData();
$serialNumber = $machine->getMonitor->getSerialNumber();
$existingMonitor = $em
->getRepository('YourBundle:Monitor')
->findOneBy(array('serialNumber' => $serialNumber));
if ($existingMonitory) {
$machine->setMonitor($existingMonitor);
}
$em->persist($machine);
$em->persist($machine->getMonitor());
$em->flush();
// ...
}
所以,这就是主意。最重要的是,通过不使用关系,你会让自己处于劣势。你看,通过将这两个表单嵌入到一起,你真的做可以自然地访问序列号字段。
祝你好运!答案 1 :(得分:4)
我最近解决了这个问题,创建了一个自定义表单类型(在我的情况下称为“选择器”),它附有一个datatransformer,它通过serial返回监视器:
机器类型:
class MachineType extends AbstractType {
public function buildForm(FormBuilder $builder, array $options) {
$builder->add('name');
$builder->add('monitor', 'monitor_selector_type');
}
public function getName() {
return 'machine;
}
}
监视器选择器类型(最终这将只是一个文本字段(默认类型为父“text”),您将在其中输入监视器序列。如果输入了非现有序列,该字段将显示错误。
class MonitorSelectorType extends AbstractType {
private $doctrine
public function __construct(Registry $doctrine) {
$this->doctrine = $doctrine;
}
public function buildForm(FormBuilder $builder, array $options) {
$transformer = new MonitorToSerialTransformer($this->doctrine->getEntityManager());
$builder->appendClientTransformer($transformer);
}
public function getDefaultOptions(array $options) {
return array(
'invalid_message'=>'The selected monitor does not exist',
'error_bubbling'=>false
);
}
public function getName() {
return 'machine;
}
}
此类将串行转换为实际监视器,将实际监视器转换为串行
class MonitorToSerialTransformer {
private $em
public function __construct(EntityManager $em) {
$this->em = $em;
}
public function transform($val) {
if (null === $val) {
return '';
}
return $val->getSerial();
}
public function reverseTransform($val) {
if (!$val) {
return null;
}
$monitor = $this->em->getRepository('xBundle:Monitor')->findOneBy(array('serial' => $val));
if (null === $monitor) {
throw new TransformationFailedException('A monitor with serial '.$val.' does not exist!');
}
return $monitor;
}
}
最后,在服务容器中注册MonitorSelectorType,其id为“monitor_selector_type”,并标记为“form.type”,并为其注入了学说。
现在,您可以在应用程序的任何随机位置轻松使用此选择器类型按ID选择监视器。根本不需要将逻辑添加到控制器中。
如果您希望在输入未知序列时创建新监视器,则可以实例化它而不是抛出TransformationFailedException,如果计算机没有监视器的附加选项,甚至可以将其保留到实体管理器。
此致 巴特