【发布时间】:2017-03-10 17:01:42
【问题描述】:
我已将 Symfony 的 EntityType 扩展为 UserChooserType,以便与我的 User 实体和 Select2 一起使用。 UserChooserType 的选择列表来自 ldap 查询(通过 ajax 调用),而不是 Doctrine 查询。所以该字段开始为空白。
User 实体与我的应用程序中的许多不同实体相关。但是,如果我希望 UserChooserType 加载 a current 选定的用户,我必须为使用它的每个表单添加一个侦听器。例如:
class SiteType extends AbstractType
{
/**
* @param FormBuilderInterface $builder
* @param array $options
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$siteAdminOpts = array('label' => 'entity.site.admin', 'required'=>false);
//opts for the UserChooserType
$builder
->add('siteName', FT\TextType::class, array('label' => 'entity.site.name'))
->add('siteAdmin', UserChooserType::class, $siteAdminOpts )
//must be added to every form type that uses UserChooserType with mod for the datatype that $event->getData() returns
->addEventListener(FormEvents::PRE_SET_DATA, function(FormEvent $event){
$site = $event->getData();
$form = $event->getForm(); //SiteType
if($user = $site->getSiteAdmin()) $siteAdminOpts['choices'] = array($user);
$form->add('siteAdmin', UserChooserType::class, $siteAdminOpts);
});
}
//etc.
tldr;
我愿意:
- 将
UserChooserType的choices选项设置为UserChooserType::configureOptions()中的选定用户,或者 - 将
->addEventListener(...)移动到UserChooserType::buildForm()。
知道怎么做吗?
这里是 UserChooserType:
class UserChooserType extends AbstractType
{
/**
* @var UserManager
*/
protected $um;
/**
* UserChooserType constructor.
* @param UserManager $um
*/
public function __construct(UserManager $um){
$this->um = $um; //used to find and decorate User entities. It is not a Doctrine entity manager, but it uses one.
}
/**
* @inheritDoc
*/
public function buildForm(FormBuilderInterface $builder, array $options) {
$builder->addEventListener(FormEvents::PRE_SUBMIT, function (FormEvent $event) {
$data = $event->getData();
if (!$data) return;
$user = $this->um->getUserByUserName($data);
if(!$user->getId()) $this->um->saveUser($user); //create User in db, if it's not there yet.
});
$builder->resetViewTransformers(); //so new choices aren't discarded
$builder->addModelTransformer(new CallbackTransformer(
function ($user) { //internal storage format to display format
return ($user instanceof User) ? $user->getUserName() : '';
},
function ($username) { //display format to storage format
return ($username) ? $this->um->getUserByUserName($username) : null;
}
));
}
/**
* {@inheritdoc}
*/
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(array(
'class' => 'ACRDUserBundle:User',
'label' => 'ldap.user.name',
'choice_label' => function($user, $key, $index){
$this->um->decorateUser($user);
$label = $user->getDetail('displayName');
return $label ? $label : $user->getUserName();
},
'choice_value' => 'userName',
'choices' => [],
'attr' => array(
'class' => 'userchooser',
'placeholder' => 'form.placeholder.userchooser'
)
));
}
/**
* {@inheritdoc}
*/
public function getBlockPrefix()
{
return 'my_userchooser';
}
/**
* @inheritDoc
*/
public function getParent() {
return EntityType::class;
}
}
【问题讨论】:
-
快速问:您希望将选择限制为仅登录用户?还是让它们成为默认选择?
-
@CameronHurd:我想将选择限制为只有已经附加到实体的用户(如果有的话)。登录的用户很可能完全是其他人。例如
$site1:siteAdmin = $user1。所以UserChooserType选择 opt 应该只包含$user1,并且它应该被标记为“已选择”。但是$office2:coordinator = null,所以它的UserChooserType选项应该是空的。当有人键入搜索字符串时,其他选项通过 Ajax 填充。