我已经定义了一个 Doctrine Entity,它映射到我的数据库中的一个视图。一切正常,实体关系按预期正常工作。
现在的问题是,当orm:schema-manager:update
在 CLI 上运行时,会为此实体创建一个表,这是我想要阻止的。这个实体已经有一个视图,不需要为它创建一个表。
我可以对实体进行注释,这样就不会创建表,同时仍然可以访问所有与实体相关的功能(关联,...)?
我已经定义了一个 Doctrine Entity,它映射到我的数据库中的一个视图。一切正常,实体关系按预期正常工作。
现在的问题是,当orm:schema-manager:update
在 CLI 上运行时,会为此实体创建一个表,这是我想要阻止的。这个实体已经有一个视图,不需要为它创建一个表。
我可以对实体进行注释,这样就不会创建表,同时仍然可以访问所有与实体相关的功能(关联,...)?
基于在 Marco Pivetta 的帖子中启发的 ChrisR 的原始 alswer,如果您使用 Symfony2,我将在此处添加解决方案:
看起来 Symfony2 不使用原始 Doctrine 命令:\Doctrine\ORM\Tools\Console\Command\SchemaTool\UpdateCommand
相反,它使用捆绑包中的一个:\Doctrine\Bundle\DoctrineBundle\Command\Proxy\UpdateSchemaDoctrineCommand
所以基本上这是必须扩展的类,最终有:
src/Acme/CoreBundle/Command/DoctrineUpdateCommand.php:
<?php
namespace Acme\CoreBundle\Command;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Doctrine\ORM\Tools\SchemaTool;
class DoctrineUpdateCommand extends \Doctrine\Bundle\DoctrineBundle\Command\Proxy\UpdateSchemaDoctrineCommand {
protected $ignoredEntities = array(
'Acme\CoreBundle\Entity\EntityToIgnore'
);
protected function executeSchemaCommand(InputInterface $input, OutputInterface $output, SchemaTool $schemaTool, array $metadatas) {
/** @var $metadata \Doctrine\ORM\Mapping\ClassMetadata */
$newMetadatas = array();
foreach ($metadatas as $metadata) {
if (!in_array($metadata->getName(), $this->ignoredEntities)) {
array_push($newMetadatas, $metadata);
}
}
parent::executeSchemaCommand($input, $output, $schemaTool, $newMetadatas);
}
}
最终它变得相当简单,我只需将其子类\Doctrine\ORM\Tools\Console\Command\SchemaTool\UpdateCommand
化为我自己的 CLI 命令。在该子类中过滤$metadatas
要传递给的数组,executeSchemaCommand()
然后将其传递给父函数。
只需将此新的子类命令附加到您在教义 cli 脚本中使用的 ConsoleApplication 即可!
下面是扩展命令,在生产中你可能想$ignoredEntities
从你的配置或其他东西中获取属性,这应该会让你上路。
<?php
use Symfony\Component\Console\Input\InputArgument,
Symfony\Component\Console\Input\InputOption,
Symfony\Component\Console\Input\InputInterface,
Symfony\Component\Console\Output\OutputInterface,
Doctrine\ORM\Tools\SchemaTool;
class My_Doctrine_Tools_UpdateCommand extends \Doctrine\ORM\Tools\Console\Command\SchemaTool\UpdateCommand
{
protected $name = 'orm:schema-tool:myupdate';
protected $ignoredEntities = array(
'Entity\Asset\Name'
);
protected function executeSchemaCommand(InputInterface $input, OutputInterface $output, SchemaTool $schemaTool, array $metadatas)
{
/** @var $metadata \Doctrine\ORM\Mapping\ClassMetadata */
$newMetadatas = array();
foreach($metadatas as $metadata) {
if(!in_array($metadata->getName(), $this->ignoredEntities)){
array_push($newMetadatas, $metadata);
}
}
return parent::executeSchemaCommand($input, $output, $schemaTool, $newMetadatas);
}
}
PS:感谢 Marco Pivetta 让我走上了正轨。https://groups.google.com/forum/?fromgroups=#!topic/doctrine-user/rwWXZ7faPsA
相当老的一个,但使用事件监听器也没有任何价值的解决方案Doctrine2
-postGenerateSchema
对我来说,它比覆盖
Doctrine
类更好:
namespace AppBundle\EventListener;
use Doctrine\ORM\Tools\Event\GenerateSchemaEventArgs;
/**
* IgnoreTablesListener class
*/
class IgnoreTablesListener
{
private $ignoredTables = [
'table_name_to_ignore',
];
public function postGenerateSchema(GenerateSchemaEventArgs $args)
{
$schema = $args->getSchema();
$tableNames = $schema->getTableNames();
foreach ($tableNames as $tableName) {
if (in_array($tableName, $this->ignoredTables)) {
// remove table from schema
$schema->dropTable($tableName);
}
}
}
}
同时注册监听器:
ignore_tables_listener:
class: AppBundle\EventListener\IgnoreTablesListener
tags:
- {name: doctrine.event_listener, event: postGenerateSchema }
不需要额外的钩子。
$schema->getTableNames()
没有工作(我不知道为什么)。
所以:
namespace AppBundle\EventListener;
use Doctrine\Bundle\DoctrineBundle\Command\Proxy\UpdateSchemaDoctrineCommand;
use Doctrine\ORM\Tools\Event\GenerateSchemaEventArgs;
class IgnoreTablesListener extends UpdateSchemaDoctrineCommand
{
private $ignoredEntities = [
'YourBundle\Entity\EntityYouWantToIgnore',
];
/**
* Remove ignored tables /entities from Schema
*
* @param GenerateSchemaEventArgs $args
*/
public function postGenerateSchema(GenerateSchemaEventArgs $args)
{
$schema = $args->getSchema();
$em = $args->getEntityManager();
$ignoredTables = [];
foreach ($this->ignoredEntities as $entityName) {
$ignoredTables[] = $em->getClassMetadata($entityName)->getTableName();
}
foreach ($schema->getTables() as $table) {
if (in_array($table->getName(), $ignoredTables)) {
// remove table from schema
$schema->dropTable($table->getName());
}
}
}
}
并注册服务
#services.yml
ignore_tables_listener:
class: AppBundle\EventListener\IgnoreTablesListener
tags:
- {name: doctrine.event_listener, event: postGenerateSchema }
工作得很好!;)
如果问题仅在于在 db_view 中产生错误,那么在调用 dictionary:schema:update 命令时,为什么不是最简单的方法:
;-)