当我有一组带有Doctrine Discriminator Map的实体时,我无法添加过滤器来获取所有映射实体的一种类型,因为SonataAdminBundle
和/或SonataDoctrineORMAdminBundle
会引发错误。
具有Doctrine Discriminator Map的实体
/**
* @ORM\Table(name="activities")
* @ORM\Entity()
* @ORM\InheritanceType("SINGLE_TABLE")
* @ORM\DiscriminatorColumn(name="type", type="string")
* @ORM\DiscriminatorMap({
* "joined" = "...\JoinedActivity",
* "other" = "...\OtherActivity"
* })
*/
abstract class Activity()
{
abstract public function getType();
}
/**
* @ORM\Entity()
*/
class JoinActivity extends Activity()
{
const TYPE = 'joined';
public function getType()
{
return self::type;
}
}
/**
* @ORM\Entity()
*/
class OtherActivity extends Activity()
{
const TYPE = 'other';
public function getType()
{
return self::type;
}
}
然后我添加了Sonata Admin过滤器:
protected function configureDatagridFilters(DatagridMapper $filter)
{
$filter->add(
'type',
null,
[
'label' => 'Activity Type',
],
'choice',
[
'choices' => [
JoinActivity::TYPE => ucfirst(JoinActivity::TYPE),
OtherActivity::TYPE => ucfirst(OtherActivity::TYPE),
],
]
);
}
获取新的过滤条件,仅选择joined
或other
个活动。
Notice: Undefined index: type
500 Internal Server Error - ContextErrorException
根据greg0ire
的要求,这是Symfony / Sonata返回的Stack Trace:
[1] Symfony\Component\Debug\Exception\ContextErrorException: Notice: Undefined index: type
at n/a
in /path/to/symfony/project/vendor/sonata-project/doctrine-orm-admin-bundle/Guesser/FilterTypeGuesser.php line 69
at Symfony\Component\Debug\ErrorHandler->handleError('8', 'Undefined index: type', '/path/to/symfony/project/vendor/sonata-project/doctrine-orm-admin-bundle/Guesser/FilterTypeGuesser.php', '69', array('class' => 'AppBundle\EntityBundle\Entity\Activity', 'property' => 'type', 'modelManager' => object(ModelManager), 'ret' => array(object(ClassMetadata), 'type', array()), 'options' => array('field_type' => null, 'field_options' => array(), 'options' => array(), 'parent_association_mappings' => array()), 'metadata' => object(ClassMetadata), 'propertyName' => 'type', 'parentAssociationMappings' => array()))
in /path/to/symfony/project/vendor/sonata-project/doctrine-orm-admin-bundle/Guesser/FilterTypeGuesser.php line 69
at Sonata\DoctrineORMAdminBundle\Guesser\FilterTypeGuesser->guessType('AppBundle\EntityBundle\Entity\Activity', 'type', object(ModelManager))
in /path/to/symfony/project/app/cache/dev/classes.php line 15104
at Sonata\AdminBundle\Guesser\TypeGuesserChain->Sonata\AdminBundle\Guesser\{closure}(object(FilterTypeGuesser))
in /path/to/symfony/project/app/cache/dev/classes.php line 15111
at Sonata\AdminBundle\Guesser\TypeGuesserChain->guess(object(Closure))
in /path/to/symfony/project/app/cache/dev/classes.php line 15105
at Sonata\AdminBundle\Guesser\TypeGuesserChain->guessType('AppBundle\EntityBundle\Entity\Activity', 'type', object(ModelManager))
in /path/to/symfony/project/vendor/sonata-project/doctrine-orm-admin-bundle/Builder/DatagridBuilder.php line 105
at Sonata\DoctrineORMAdminBundle\Builder\DatagridBuilder->addFilter(object(Datagrid), null, object(FieldDescription), object(ActivityAdmin))
in /path/to/symfony/project/app/cache/dev/classes.php line 13069
at Sonata\AdminBundle\Datagrid\DatagridMapper->add('type', null, array('label' => 'Activity Type', 'field_options' => array('choices' => array('joined' => 'Joined')), 'field_type' => 'choice', 'field_name' => 'type'), 'choice', array('choices' => array('joined' => 'Joined')))
in /path/to/symfony/project/src/AppBundle/SonAdminBundle/Admin/ActivityAdmin.php line 64
at AppBundle\SonAdminBundle\Admin\ActivityAdmin->configureDatagridFilters(object(DatagridMapper))
in /path/to/symfony/project/app/cache/dev/classes.php line 10609
at Sonata\AdminBundle\Admin\AbstractAdmin->buildDatagrid()
in /path/to/symfony/project/app/cache/dev/classes.php line 10910
at Sonata\AdminBundle\Admin\AbstractAdmin->getDatagrid()
in /path/to/symfony/project/vendor/sonata-project/admin-bundle/Controller/CRUDController.php line 104
at Sonata\AdminBundle\Controller\CRUDController->listAction()
in line
at call_user_func_array(array(object(CRUDController), 'listAction'), array())
in /path/to/symfony/project/app/bootstrap.php.cache line 3222
at Symfony\Component\HttpKernel\HttpKernel->handleRaw(object(Request), '1')
in /path/to/symfony/project/app/bootstrap.php.cache line 3181
at Symfony\Component\HttpKernel\HttpKernel->handle(object(Request), '1', true)
in /path/to/symfony/project/app/bootstrap.php.cache line 3335
at Symfony\Component\HttpKernel\DependencyInjection\ContainerAwareHttpKernel->handle(object(Request), '1', true)
in /path/to/symfony/project/app/bootstrap.php.cache line 2540
at Symfony\Component\HttpKernel\Kernel->handle(object(Request))
in /path/to/symfony/project/web/app_dev.php line 15
at require('/path/to/symfony/project/web/app_dev.php')
in /path/to/symfony/project/vendor/symfony/symfony/src/Symfony/Bundle/FrameworkBundle/Resources/config/router_dev.php line 40
知道如何解决它吗?
谢谢,
答案 0 :(得分:2)
我面临同样的问题。我做了一个解决方法 - 我使用 doctrine_orm_callback 类型与doctrine INSTANCE OF 运算符。
代码如下所示:
var db = 'telegraf'
var rp = 'autogen'
var measurement = 'procstat'
var groupBy = []
var whereFilter = lambda: ("process_name" == 'dnsmasq')
var period = 1m
var name = 'Dnsmasq Deadman'
var idVar = name + ':{{.Group}}'
var message = 'Dnsmasq not responding. {{.Time}} Restarting dnsmasq. {{ index .Tags "host"}}'
var idTag = 'alertID'
var levelTag = 'level'
var messageField = 'message'
var durationField = 'duration'
它正在发挥作用。也许它可以帮助你。
答案 1 :(得分:0)
我认为Sonata很困惑b / c它希望toArray()
出现在你的Doctrine映射的字段中。我不认为$response = $paginated->toArray();
$response['filters'] = [];
的过滤是支持的,但我记得对单继承有一些支持,特别是在创建新对象时。但是找不到它。
答案 2 :(得分:0)
在创建继承实体及其父类之后,不建议修改它之间的链接。如果需要,则应考虑改用合成。
这就是为什么Doctrine不允许直接管理区分项字段的原因。
以下所有文本均从此very useful response复制而来,这对于全面和更好地理解是宝贵的。
当对象实例的类型需要随时间变化时,这不是一个好兆头。我在这里不是在谈论向下转换/向上转换,而是关于需要更改对象的实际类型。
首先,让我告诉您为什么这是一个坏主意:
这就是大多数语言不允许您在执行过程中更改对象的真实类类型的原因的一部分(当然,还有内存,但我不想详细介绍)。有些人可以让您做到这一点(有时以多种方式使用,例如JVM),但这确实不是一个好习惯!
通常,这样做的需要在于糟糕的面向对象设计决策。
由于这些原因,Doctrine不允许您更改实体对象的类型。当然,您仍然可以编写普通的SQL(在本文结尾-但请通读!)来进行更改,但是我建议您使用以下两个“干净”选项:
我意识到您已经说过第一个选项不是一个选项,但是我花了一段时间写下这篇文章,所以我觉得我应该使其尽可能完整以供将来参考。
Person
更改为Employee
时,请创建一个新的Employee实例,然后将要复制的数据从旧的Person对象复制到Employee对象。不要忘记删除旧实体并保留新实体。现在,这是我之前提到的简单的SQL方法-希望您不需要使用它!
确保对查询进行了清理(因为查询将在不进行任何验证的情况下执行)。
$query = "UPDATE TABLE_NAME_HERE SET discr = 'employee' WHERE id = ".$entity->getId();
$entity_manager->getConnection()->exec( $query );
这是DBAL\Connection
类中的exec方法的文档和代码(供您参考):
/**
* Execute an SQL statement and return the number of affected rows.
*
* @param string $statement
* @return integer The number of affected rows.
*/
public function exec($statement)
{
$this->connect();
return $this->_conn->exec($statement);
}