Symfony 2.8 为EntityType设置session存储默认值失败问题
问题根因
- 方案1报错核心原因:session中存储的Etude实体是脱管状态,从你提供的调试信息可看到实体关联集合的
em属性均为null,说明该实体未被当前请求的EntityManager托管,直接赋值给EntityType的data参数会触发托管校验错误。 - 方案2失效原因:你混淆了参数用法,
data参数不支持接收返回QueryBuilder的匿名函数,该写法是query_builder参数的使用规则,传入的回调不会被正确解析为默认值。 - 方案3失效原因:
choice_value参数的作用是指定下拉选项对应的值字段,并非用来设置当前选中的默认值,用法完全不符合参数设计。
解决方案
方案A:合并脱管实体到EntityManager(改动最小)
在表单类中注入EntityManager,对从session取出的实体对象执行merge操作,将其转为托管状态即可正常赋值:
// 表单类中新增EntityManager注入 private $em; public function __construct(\Doctrine\ORM\EntityManagerInterface $em) { $this->em = $em; } // 修改getDataFromFilters方法 private function getDataFromFilters(array $options, string $field) { if (!isset($options['filters'][$field]) || null === $value = $options['filters'][$field]) { return null; } // 仅对实体对象执行合并操作 if (is_object($value) && $this->em->getMetadataFactory()->hasMetadataFor(get_class($value))) { return $this->em->merge($value); } return $value; }
修改完成后保留你原来方案1的EntityType配置即可正常生效,不会再报托管错误。
方案B:Session仅存实体主键(更规范的写法)
建议不要把整个实体对象存入session,仅存储主键值,取默认值时再从数据库查询获取托管状态的实体:
// 存session的逻辑修改为仅存etude的id,不要存整个Etude对象 private function getDataFromFilters(array $options, string $field) { if (!isset($options['filters'][$field]) || null === $value = $options['filters'][$field]) { return null; } if ($field === 'etude') { return $this->em->getRepository(Etude::class)->find($value); } // DateType默认值处理:如果存的是时间字符串转成DateTime对象 if ($field === '你对应的DateType字段名' && is_string($value)) { return new \DateTime($value); } return $value; }
DateType默认值失效补充处理
如果DateType默认值不生效,优先检查两点:
- 传入的默认值是否为
\DateTime对象,字符串格式的时间不会被自动识别 - 如果DateType配置
widget为choice,确认DateTime对象的年月日值合法
内容的提问来源于stack exchange,提问作者nboulfroy
相关产品推荐
相关产品推荐

