我为每个联系人(姓名,电子邮件)实体提供了一组PhoneNumber实体。 PhoneNumber分为区域代码,交换,后缀,扩展名,然后是类型选择器(工作,家庭,移动)。我想使用DataTransformer,以便数字可以显示在单个表单字段而不是4个不同的文本框中。这些语音在数据库中并不是唯一的。
更新:如何在从字符串版本转换回实体时访问完整实体?我之前遇到过这个问题并最终将实体的ID放在文本字段中的括号内,然后在变换中将它们重新出现,以便我可以进行查询以获取实体。
phonenumber_combined是一个引用我的PhoneNumberCombinedType类的自定义表单类型服务。
我在联系人中收集电话的添加方法:
->add('phones', 'collection', array(
'label' => 'Phones',
'type' => new PhoneNumberType(),
'allow_add' => true,
'allow_delete' => true
))
;
PhoneNumberType buildForm函数:
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('phone', 'phonenumber_combined')
->add('type', 'entity',
array('class' => 'Test\Bundle\SystemBundle\Entity\Type',
'property' => 'name',
'query_builder' => function(EntityRepository $er){
return $er->createQueryBuilder('type')
->where('type.type = :t')
->orderBy('type.name', 'ASC')
->setParameter('t', 'PhoneNumber');
}))
;
}
PhoneNumberCombinedType服务:
public function buildForm(FormBuilderInterface $builder, array $options)
{
$transformer = new PhoneNumberToStringTransformer($this->om);
$builder->addViewTransformer($transformer);
}
PhoneNumberToStringTransformer:
public function transform($phonenumber)
{
if (null === $phonenumber) {
return null;
}
return $phonenumber->__toString();
}
public function reverseTransform($phonenumber)
{
if (!$phonenumber) {
return null;
}
// PHONE NUMBER IS JUST A STRING AT THIS POINT, HOW DO I GET THE ENTITY?
}
答案 0 :(得分:3)
你必须通过构造函数注入传递一个对象管理器,然后像往常那样对它进行操作。
class PhoneNumberTransformer implements DataTransformerInterface
{
/**
* @var ObjectManager
*/
private $om;
/**
* @param ObjectManager $om
*/
public function __construct(ObjectManager $om)
{
$this->om = $om;
}
public function transform($phonenumber)
{
if ($phonenumber === null) {
return null;
}
return $phonenumber->__toString();
}
public function reverseTransform($phonenumber)
{
if (!$this->phonenumber) {
return null;
}
$phoneEntity = $this->om
->getRepository('{REFERENCE_TO_THE_ENTITY}')
->findOneBy(array('phonenumber' => $phonenumber));
if ($phoneEntity === null) {
throw new TransformationFailedException();
}
return $phoneEntity;
}
}
答案 1 :(得分:0)
很抱歉没有更新,但我找到了解决此问题的合适解决方案。我向PhoneNumber实体添加了一个 setPhone方法,该实体似乎在反向转换后自动调用。在我的变压器中,我添加了一个正则表达式,将我的电话号码分成各自的部分,然后将每个部分添加到一个数组中。该数组由变换器返回,然后由setPhone用于更新PhoneNumber对象。
我的PhoneNumber实体中的setPhone方法:
/**
* Used by PhoneNumberToStringTransformer to set Entity data
* @param array $phone_data
*/
public function setPhone($phone_data)
{
if($phone_data == null) {
$this->setAreaCode(null);
$this->setExchange(null);
$this->setSuffix(null);
$this->setExtension(null);
return $this;
}
$this->setAreaCode($phone_data['AreaCode']);
$this->setExchange($phone_data['Exchange']);
$this->setSuffix($phone_data['Suffix']);
$this->setExtension($phone_data['Extension']);
return $this;
}
我的PhoneNumberToStringTransformer中的reverseTransform:
/**
* Transforms a phonenumber string to an array that will be passed to setPhone
* which will handle setting each entity field.
*
* @param string $string Phone number string
* @return (array) areaCode, exchange, suffix and extension
*/
public function reverseTransform($string)
{
if (!$string || strlen($string) == 0) {
return null;
}
// Split phone number into array for areaCode, exchange, suffix, and extension
$pattern = '/(\d{3})?-?(\d{3})?-?(\d{4})?( x(\d+))?/';
preg_match_all($pattern, $string, $matches, PREG_PATTERN_ORDER);
$phone_data = array('AreaCode'=>null, 'Exchange'=>null, 'Suffix'=>null, 'Extension'=>null);
$counter = 1;
foreach($phone_data as $key => $value) {
if($counter == 4)
$counter = 5;
if(isset($matches[$counter][0]) && $matches[$counter][0] !== '') {
$phone_data[$key] = $matches[$counter][0];
} else {
$phone_data[$key] = null;
}
$counter++;
}
return $phone_data;
}