>我定义了一个映射到数据库中视图的教义实体。一切正常,实体关系按预期工作正常。
现在的问题是,在 CLI 上运行orm:schema-manager:update
时,会为此实体创建一个表,这是我想防止的。此实体已有一个视图,无需为其创建表。
我是否可以对实体进行批注,以便在仍保留对所有实体相关功能(关联等)的访问权限的同时不创建表?
基于Marco Pivetta帖子中受启发的ChrisR的原始算法,如果您使用的是Symfony2,我将在此处添加解决方案:
看起来Symfony2没有在以下位置使用原始的Doctrine命令:\Doctrine\ORM\Tools\Console\Command\SchemaTool\UpdateCommand
相反,它使用捆绑包中的那个:\Doctrine\Bundle\DoctrineBundle\Command\Proxy\UpdateSchemaDoctrineCommand
所以基本上这是必须扩展的类,最终拥有:
src/Acme/CoreBundle/Command/DoctrineUpdateCommand.php
:
<?php
namespace AppCommand;
use DoctrineBundleDoctrineBundleCommandProxyUpdateSchemaDoctrineCommand;
use DoctrineORMMappingClassMetadata;
use DoctrineORMToolsSchemaTool;
use SymfonyComponentConsoleInputInputInterface;
use SymfonyComponentConsoleOutputOutputInterface;
use SymfonyComponentConsoleStyleSymfonyStyle;
class DoctrineUpdateCommand extends UpdateSchemaDoctrineCommand
{
protected function executeSchemaCommand(InputInterface $input, OutputInterface $output, SchemaTool $schemaTool, array $metadatas, SymfonyStyle $ui): ?int
{
$ignoredEntities = [
'AppEntityEntityToIgnore',
];
$metadatas = array_filter($metadatas, static function (ClassMetadata $classMetadata) use ($ignoredEntities) {
return !in_array($classMetadata->getName(), $ignoredEntities, true);
});
return parent::executeSchemaCommand($input, $output, $schemaTool, $metadatas, $ui);
}
}
最终它相当简单,我只需要将DoctrineORMToolsConsoleCommandSchemaToolUpdateCommand
子类化到我自己的 CLI 命令中。在该子类中,筛选传递给executeSchemaCommand()
的$metadatas
数组,然后将其传递给父函数。
只需将这个新的子类化命令附加到您在 doctrine cli 脚本中使用的控制台应用程序即可完成!
下面是扩展命令,在生产中,您可能希望从配置或其他东西中获取$ignoredEntities
属性,这应该会让您上路。
<?php
use DoctrineORMToolsConsoleCommandSchemaToolUpdateCommand;
use DoctrineORMToolsSchemaTool;
use SymfonyComponentConsoleInputInputInterface;
use SymfonyComponentConsoleOutputOutputInterface;
use SymfonyComponentConsoleStyleSymfonyStyle;
class My_Doctrine_Tools_UpdateCommand extends UpdateCommand
{
protected $name = 'orm:schema-tool:myupdate';
protected $ignoredEntities = array(
'EntityAssetName'
);
protected function executeSchemaCommand(InputInterface $input, OutputInterface $output, SchemaTool $schemaTool, array $metadatas, SymfonyStyle $ui)
{
/** @var $metadata DoctrineORMMappingClassMetadata */
$newMetadata = [];
foreach ($metadatas as $metadata) {
if (!in_array($metadata->getName(), $this->ignoredEntities)) {
$newMetadata[] = $metadata;
}
}
return parent::executeSchemaCommand($input, $output, $schemaTool, $newMetadata, $ui);
}
}
PS:感谢马可·皮维塔让我走上了正确的轨道。 https://groups.google.com/forum/?fromgroups=#!topic/doctrine-user/rwWXZ7faPsA
相当古老的,但使用Doctrine2
也没有任何价值的解决方案:postGenerateSchema
事件侦听器 - 对我来说,这比覆盖要好 Doctrine
类:
namespace AppDoctrineListener;
use DoctrineORMToolsEventGenerateSchemaEventArgs;
/**
* 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);
}
}
}
}
同时注册侦听器:
# config/services.yaml
services:
ignore_tables_listener:
class: AppDoctrineListenerIgnoreTablesListener
tags:
- {name: doctrine.event_listener, event: postGenerateSchema }
不需要额外的钩子。
在 Doctrine 2.7.0 中引入了新的 SchemaIgnoreClasses
实体管理器配置选项,该选项基本上忽略了任何架构操作中配置的类。
要将其与Symfony一起使用,我们只需要在Doctrine实体管理器配置中添加schema_ignore_classes
键,如下所示:
doctrine:
dbal:
# your dbal configuration
orm:
default_entity_manager: default
entity_managers:
default:
connection: default
mappings:
Main:
is_bundle: false
type: annotation
dir: '%kernel.project_dir%/src/Entity/Main'
prefix: 'AppEntityMain'
alias: Main
schema_ignore_classes:
- ReferenceToMyClass
- ReferenceToMyOtherClass
$schema->getTableNames()
不起作用(我不知道为什么)。
所以:
<?php
namespace AppBundleEventListener;
use DoctrineBundleDoctrineBundleCommandProxyUpdateSchemaDoctrineCommand;
use DoctrineORMToolsEventGenerateSchemaEventArgs;
class IgnoreTablesListener extends UpdateSchemaDoctrineCommand
{
private $ignoredEntities = [
'YourBundleEntityEntityYouWantToIgnore',
];
/**
* 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, true)) {
// remove table from schema
$schema->dropTable($table->getName());
}
}
}
}
并注册一项服务
# config/services.yaml
services:
ignore_tables_listener:
class: AppBundleEventListenerIgnoreTablesListener
tags:
- {name: doctrine.event_listener, event: postGenerateSchema }
工作正常! ;)
如果问题只是在db_view中产生错误,那么在调用doctrine:schema:update命令时,为什么不是最简单的方法:
- 从@ORM\实体注释中删除 @
- 执行策略:架构:更新
- 将 @ 添加到 ORM\实体注释
;-)