在奏鸣曲中定义扩展实体
Defining extended entities in sonata
我有一些基本实体,它定义了所有(或至少大多数)其他实体应该具有的一些字段。看起来像:
namespace App\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* @ORM\Entity()
* @ORM\MappedSuperclass
* @ORM\HasLifecycleCallbacks()
*/
abstract class BaseEntity {
/**
* @var integer
*
* @ORM\Column(name="id", type="integer")
* @ORM\Id
* @ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* @ORM\Column(type="boolean")
*/
protected $published;
/**
* @ORM\Column(type="datetime")
*/
protected $createdAt;
/**
* @ORM\Column(type="datetime")
*/
protected $updatedAt;
public function getId(): ?int
{
return $this->id;
}
等等...getter 和 setter。
然后我有实体,即 ArticleCategory 扩展了 BaseEntity:
namespace App\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* @ORM\Entity(repositoryClass="App\Repository\ArticleCategoryRepository")
*/
class ArticleCategory extends BaseEntity
{
/**
* @ORM\Column(type="string", length=255)
*/
private $title;
public function getTitle(): ?string
{
return $this->title;
}
public function setTitle(string $title): self
{
$this->title = $title;
return $this;
}
}
所以,它只是添加了一个额外的字段 - 标题。
然后,我有基础管理员 class:
namespace App\Admin;
use Sonata\AdminBundle\Admin\AbstractAdmin;
use Sonata\AdminBundle\Datagrid\ListMapper;
use Sonata\AdminBundle\Datagrid\DatagridMapper;
use Sonata\AdminBundle\Form\FormMapper;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use App\Entity\BaseEntity;
class BaseAdmin extends AbstractAdmin
{
/**
* @param BaseEntity $entity
*/
public function prePersist($entity)
{
$now = new \DateTime();
$entity->setCreatedAt($now);
$entity->setUpdatedAt($now);
$entity->setPublished(true);
}
}
然后是该 ArticleCategory 实体的管理员 class:
namespace App\Admin;
use Sonata\AdminBundle\Datagrid\ListMapper;
use Sonata\AdminBundle\Datagrid\DatagridMapper;
use Sonata\AdminBundle\Form\FormMapper;
use Symfony\Component\Form\Extension\Core\Type\TextType;
final class ArticleCategoryAdmin extends BaseAdmin
{
protected function configureFormFields(FormMapper $formMapper)
{
$formMapper
->add('title', TextType::class);
}
protected function configureDatagridFilters(DatagridMapper $datagridMapper)
{
$datagridMapper
->add('title');
}
protected function configureListFields(ListMapper $listMapper)
{
$listMapper
->addIdentifier('title');
}
}
问题是当我转到奏鸣曲列表页面而不是显示 ArticleCategory 类型中的所有实体时,我收到 sql 错误:
'field list'
中的未知列 'b0_.id'
查询如下所示:
SELECT b0_.id AS id_0, b0_.published AS published_1, b0_.created_at AS created_at_2, b0_.updated_at AS updated_at_3, a1_.title AS title_4
FROM article_category a1_
WHERE a1_.id IN (?, ?)
ORDER BY a1_.id ASC' with params [2, 3]
So sonata 正在从正确的 table (article_category) 获取数据并为其创建别名 "a1_" 并且所有直接在 ArticleCategory(标题)中的字段都被很好地收集,使用该别名。
但是属于基础 class (BaseEntity) sonata 的所有其他字段都试图通过一些 un-existing 别名 "b0_" 获取,当然查询失败。
知道如何解决这个问题吗?如何告诉奏鸣曲所有字段都属于同一个 table 即使它们属于 2 个实体 classes?
找到问题了。在定义基础实体的开始我有:
/**
* @ORM\Entity()
* @ORM\MappedSuperclass
* @ORM\HasLifecycleCallbacks()
*/
这是不正确的,因为 "Entity()" 行。那必须被删除。它不能同时是实体和映射晚餐 class。
/**
* @ORM\MappedSuperclass
* @ORM\HasLifecycleCallbacks()
*/
我有一些基本实体,它定义了所有(或至少大多数)其他实体应该具有的一些字段。看起来像:
namespace App\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* @ORM\Entity()
* @ORM\MappedSuperclass
* @ORM\HasLifecycleCallbacks()
*/
abstract class BaseEntity {
/**
* @var integer
*
* @ORM\Column(name="id", type="integer")
* @ORM\Id
* @ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* @ORM\Column(type="boolean")
*/
protected $published;
/**
* @ORM\Column(type="datetime")
*/
protected $createdAt;
/**
* @ORM\Column(type="datetime")
*/
protected $updatedAt;
public function getId(): ?int
{
return $this->id;
}
等等...getter 和 setter。
然后我有实体,即 ArticleCategory 扩展了 BaseEntity:
namespace App\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* @ORM\Entity(repositoryClass="App\Repository\ArticleCategoryRepository")
*/
class ArticleCategory extends BaseEntity
{
/**
* @ORM\Column(type="string", length=255)
*/
private $title;
public function getTitle(): ?string
{
return $this->title;
}
public function setTitle(string $title): self
{
$this->title = $title;
return $this;
}
}
所以,它只是添加了一个额外的字段 - 标题。
然后,我有基础管理员 class:
namespace App\Admin;
use Sonata\AdminBundle\Admin\AbstractAdmin;
use Sonata\AdminBundle\Datagrid\ListMapper;
use Sonata\AdminBundle\Datagrid\DatagridMapper;
use Sonata\AdminBundle\Form\FormMapper;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use App\Entity\BaseEntity;
class BaseAdmin extends AbstractAdmin
{
/**
* @param BaseEntity $entity
*/
public function prePersist($entity)
{
$now = new \DateTime();
$entity->setCreatedAt($now);
$entity->setUpdatedAt($now);
$entity->setPublished(true);
}
}
然后是该 ArticleCategory 实体的管理员 class:
namespace App\Admin;
use Sonata\AdminBundle\Datagrid\ListMapper;
use Sonata\AdminBundle\Datagrid\DatagridMapper;
use Sonata\AdminBundle\Form\FormMapper;
use Symfony\Component\Form\Extension\Core\Type\TextType;
final class ArticleCategoryAdmin extends BaseAdmin
{
protected function configureFormFields(FormMapper $formMapper)
{
$formMapper
->add('title', TextType::class);
}
protected function configureDatagridFilters(DatagridMapper $datagridMapper)
{
$datagridMapper
->add('title');
}
protected function configureListFields(ListMapper $listMapper)
{
$listMapper
->addIdentifier('title');
}
}
问题是当我转到奏鸣曲列表页面而不是显示 ArticleCategory 类型中的所有实体时,我收到 sql 错误:
'field list'
中的未知列 'b0_.id'查询如下所示:
SELECT b0_.id AS id_0, b0_.published AS published_1, b0_.created_at AS created_at_2, b0_.updated_at AS updated_at_3, a1_.title AS title_4
FROM article_category a1_
WHERE a1_.id IN (?, ?)
ORDER BY a1_.id ASC' with params [2, 3]
So sonata 正在从正确的 table (article_category) 获取数据并为其创建别名 "a1_" 并且所有直接在 ArticleCategory(标题)中的字段都被很好地收集,使用该别名。 但是属于基础 class (BaseEntity) sonata 的所有其他字段都试图通过一些 un-existing 别名 "b0_" 获取,当然查询失败。
知道如何解决这个问题吗?如何告诉奏鸣曲所有字段都属于同一个 table 即使它们属于 2 个实体 classes?
找到问题了。在定义基础实体的开始我有:
/**
* @ORM\Entity()
* @ORM\MappedSuperclass
* @ORM\HasLifecycleCallbacks()
*/
这是不正确的,因为 "Entity()" 行。那必须被删除。它不能同时是实体和映射晚餐 class。
/**
* @ORM\MappedSuperclass
* @ORM\HasLifecycleCallbacks()
*/