我正在开发一个保存IP地址和IP范围的项目。目前,我的Range实体引用了两个IP地址实体(网络和广播实体),并且与主机具有OneToMany关系。 IP地址实体与IP范围具有ManyToOne关系,这是可选的。
这是我的IP地址实体:
class IPAddress {
/**
* @var int
*
* @ORM\Column(name="id", type="integer")
* @ORM\Id
* @ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
// relations to other tables
/**
* @var IPRange
* @ORM\ManyToOne(targetEntity="AppBundle\Entity\IPRange", inversedBy="hosts", cascade={"persist", "remove"})
* @ORM\JoinColumn(name="ip_range_id", referencedColumnName="id", nullable=true)
*/
private $ipRangeId;
// entity variables
/**
* @var mixed
* @ORM\Column(name="ip_address", type="binary", length=16, nullable=false, unique=true)
* @SIAssert\IpPacked(version="all")
*/
private $ipAddress;
/**
* @var string
* @ORM\Column(name="ip_address_text", type="string", length=50, nullable=false)
*/
private $ipAddressText;
/**
* @var int
* @ORM\Column(name="cidr", type="smallint", nullable=false, options={"unsigned"=true})
*/
private $cidr;
/**
* @var mixed
* @ORM\Column(name="gateway", type="binary", length=16, nullable=false)
*/
private $gateway;
/**
* @var string
* @ORM\Column(name="gateway_text", type="string", length=50, nullable=false)
*/
private $gatewayText;
/**
* @var int
* @ORM\Column(name="type", type="smallint", options={"unsigned"=true})
*/
private $type;
/**
* @var string
* @ORM\Column(name="description", type="string", length=50)
*/
private $description;
// getters and setters not shown
}
我的IP范围实体:
class IPRange {
/**
* @var int
* @ORM\Column(name="id", type="integer")
* @ORM\Id
* @ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
// relations to other tables
/**
* @var IPAddress
* @ORM\OneToOne(targetEntity="AppBundle\Entity\IPAddress", cascade={"persist", "remove"}, orphanRemoval=true)
* @ORM\JoinColumn(name="network", referencedColumnName="id", nullable=false)
*/
private $network;
/**
* @var IPAddress
* @ORM\OneToOne(targetEntity="AppBundle\Entity\IPAddress", cascade={"persist", "remove"}, orphanRemoval=true)
* @ORM\JoinColumn(name="broadcast", referencedColumnName="id", nullable=false)
*/
private $broadcast;
/**
* @var array
* @ORM\OneToMany(targetEntity="AppBundle\Entity\IPAddress", mappedBy="ipRangeId")
*/
private $hosts;
// entity variables
/**
* @var string
* @ORM\Column(name="description", type="string", length=50, nullable=false)
*/
private $description;
/**
* @var int
* @ORM\Column(name="cidr", type="smallint", nullable=false, options={"unsigned"=true})
*/
private $cidr;
/**
* @var string
* @ORM\Column(name="notes", type="text", length=65535, nullable=true)
*/
private $notes;
// getters and setters not shown
}
创建新IP范围时的当前流程:
我必须遗漏一些东西,因为编程创建实体似乎有很多步骤。
有没有更好更有效的方法呢?
已编辑...添加了我的表单类型...
我的IPRangeType:
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('description', TextType::class, array(
'required' => true,
'label' => 'Description:',
'label_attr' => array(
'class' => 'text-right middle',
),
))
->add('notes', TextareaType::class, array(
'required' => false,
'label' => 'Notes:',
'label_attr' => array(
'class' => 'text-right middle',
),
))
->add('cidr', ChoiceType::class, array(
'required' => true,
'multiple' => false,
'expanded' => false,
'choices' => array (
'IPv4' => [
'/30 (255.255.255.252)' => 30,
'/29 (255.255.255.248)' => 29,
'/28 (255.255.255.240)' => 28,
'/27 (255.255.255.224)' => 27,
'/26 (255.255.255.192)' => 26,
'/25 (255.255.255.128)' => 25,
'/24 (255.255.255.0)' => 24,
'/23 (255.255.254.0)' => 23,
'/22 (255.255.252.0)' => 22,
'/21 (255.255.248.0)' => 21,
'/20 (255.255.240.0)' => 20,
],
'IPv6' => [
'/64 network' => 64,
]
),
'label' => 'CIDR (subnet):',
'label_attr' => array(
'class' => 'text-right middle',
),
))
->add('network', IPAddressType::class, array(
'required' => true,
))
->add('gateway_select', ChoiceType::class, array(
'mapped' => false,
'required' => true,
'multiple' => false,
'expanded' => false,
'choices' => array (
'- enter in valid IP and CIDR -' => 0,
),
'label' => 'Gateway:',
'label_attr' => array(
'class' => 'text-right middle',
),
))
->add('json_data', HiddenType::class, array(
'mapped' => false,
))
;
}
我的IPAddressType:
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('ipAddress', TextType::class, array(
'required' => true,
'label' => 'IP Address:',
'label_attr' => array(
'class' => 'text-right middle',
),
))
->add('cidr', ChoiceType::class, array(
'required' => true,
'multiple' => false,
'expanded' => false,
'choices' => array (
'IPv4' => [
'/30 (255.255.255.252)' => 30,
'/29 (255.255.255.248)' => 29,
'/28 (255.255.255.240)' => 28,
'/27 (255.255.255.224)' => 27,
'/26 (255.255.255.192)' => 26,
'/25 (255.255.255.128)' => 25,
'/24 (255.255.255.0)' => 24,
'/23 (255.255.254.0)' => 23,
'/22 (255.255.252.0)' => 22,
'/21 (255.255.248.0)' => 21,
'/20 (255.255.240.0)' => 20,
],
'IPv6' => [
'/64 network' => 64,
]
),
'label' => 'CIDR (subnet):',
'label_attr' => array(
'class' => 'text-right middle',
),
))
->add('gateway', TextType::class, array(
'required' => true,
'label' => 'Gateway:',
'label_attr' => array(
'class' => 'text-right middle',
),
))
->add('type', ChoiceType::class, array(
'required' => true,
'multiple' => false,
'expanded' => false,
'choices' => IPAddress::TYPE,
'label' => 'Address Type:',
'label_attr' => array(
'class' => 'text-right middle',
),
))
->add('description', TextType::class, array(
'required' => true,
'label' => 'Description:',
'label_attr' => array(
'class' => 'text-right middle',
),
))
;
$builder->get('ipAddress')
->addModelTransformer(new IPToStringTransformer());
$builder->get('gateway')
->addModelTransformer(new IPToStringTransformer());
}
答案 0 :(得分:0)
听起来非常迂回。我将详细介绍一下我将采取的一般做法。
我会创建两个表单类型,调用一个IpAddressType和另一个IpRangeType。由于您在IpAddress中进行共享,因此您只需要一种类型,它就是所有相同的数据。
因此,您的表单类型将类似于:
(这是symfony 2.3语法 - 如果你有更新的版本会有一些差异 - 但方法是相同的)
class IpRangeType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add('description');
$builder->add('cidr'); // and other single fields
$builder->add('network', new IpAddressType());
$builder->add('broadcast', new IpAddressType());
$builder->add('hosts', 'collection', ['type' => new IpAddressType()]);
}
public function getName()
{
return 'ip_range';
}
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'YourBundle\Entity\IpRange',
));
}
}
子表单类型。
class IpAddressType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add('ipAddress');
$builder->add('ipAddressText'); // etc etc
}
public function getName()
{
return 'ip_address';
}
public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(array(
'data_class' => 'YourBundle\Entity\IpAddress',
));
}
}
然后在你的控制器中:
$ipRange = new IpRange();
$em = $this->getDoctrine()->getManager();
$form = $this->createForm(new IpRangeType(), $ipRange);
$form->handleRequest($request);
if ($form->isValid()) {
$em->persist($ipRange);
$em->flush();
return $this->redirect($this->generateUrl('your_success_route'));
}
应该那么简单。
注意:您需要在IpRange $ hosts属性上至少设置cascade = persist,否则它不会保留添加到集合中的IpAddress项。
由于IpRange网络上的级联持续存在,广播和主机属性不需要保留单个项目,因此ipAddress实体将自动与父实体相关联。
您需要按照此方法添加主机条目:
http://symfony.com/doc/current/form/form_collections.html
另外请一般查看表单文档,您永远不需要生成'表格是否正确完成的实体(非常特殊情况除外)。
正确实施表单应该返回您的完整实体,并在表单中添加数据,您只需验证&持续。
处理表单提交的文档:http://symfony.com/doc/current/forms.html#handling-form-submissions