如何阻止 symfony 尝试为我在学说迁移中创建的视图创建表?
/**
* Class TenancyPendingInspection
* @ORM\Entity(repositoryClass="DJABundle\PropertyVisit\Repository\TenancyPendingInspectionRepository", readOnly=true)
* @ORM\Table(name="view_tenancies_pending_inspections")
*/
class TenancyPendingInspection
{
我还有学说迁移文件。
doctrine:
dbal:
default_connection: default
connections:
default:
[...]
charset: UTF8
server_version: 5.6
schema_filter: ~^(?!view_)~
php app/console doc:sch:val
[Mapping] OK - The mapping files are correct.
[Database] FAIL - The database schema is not in sync with the current mapping file.
php app/console doc:sch:update --dump-sql
CREATE TABLE view_tenancies_pending_inspections ...
简短回答:这是不可能的。
发生这种情况是因为
MysqlPlatform
忽略了视图。
//vendor/doctrine/dbal/lib/Doctrine/DBAL/Platforms/MySqlPlatform.php
class MySqlPlatform extends AbstractPlatform
[...]
public function getListTablesSQL()
{
return "SHOW FULL TABLES WHERE Table_type = 'BASE TABLE'";
}
[...]
解决方案:创建一个不忽略视图的新MysqlPlatform:
class MysqlViewsPlatform extends \Doctrine\DBAL\Platforms\MySqlPlatform
{
public function getListTablesSQL()
{
return "SHOW FULL TABLES";
}
}
使用您的平台创建服务:
services:
doctrine.dbal.mysql_views_platform:
class: albertsola\DoctrineViews\MysqlViewsPlatform
arguments: []
通过您的连接使用该平台:
doctrine:
dbal:
default_connection: default
connections:
default:
driver: "%database_driver%"
host: "database_host%"
port: "database_port%"
dbname: "database_name%"
user: "database_user%"
password: "database_password%"
charset: UTF8
platform_service: "doctrine.dbal.mysql_views_platform"
应用程序/控制台学说:架构:验证 此命令验证实体和视图实体是否同步。
副作用: 应用程序/控制台学说:架构:更新--dump-sql 如果视图和实体不同步,这将生成不应执行的 SQL!您必须手动更新数据库中的视图。
我使用学说迁移来解决这个问题。尽管doctrine:schema:update --dump-sql对于检查它在您的视图/实体中不匹配的内容非常有用。
注意:此黑客停止创建表,但学说模式差异仍然尝试更新添加外键的“表”。
这对我来说很有效;
class DiffCommandWrapper extends DiffCommand
{
private $views = [];
public function __construct(\PDO $db, SchemaProviderInterface $schemaProvider = null)
{
parent::__construct($schemaProvider);
$name = $db->query('select database()')->fetchColumn();
$stm = $db->query("SHOW FULL TABLES IN {$name} WHERE TABLE_TYPE LIKE 'VIEW';");
foreach ($stm->fetchAll(\PDO::FETCH_ASSOC) as $row) {
$this->views[] = $row["Tables_in_{$name}"];
}
}
public function execute(InputInterface $input, OutputInterface $output)
{
$input->setOption('filter-expression', '/!(' . implode('|', $this->views) . ')/');
parent::execute($input, $output);
}
}
然后使用包装器代替 cli-config.php 中的 DiffCommand
ConsoleRunner::addCommands($cli);
$cli->addCommands([
new something\DiffCommandWrapper($connection),
new Command\ExecuteCommand(),
new Command\GenerateCommand(),
new Command\MigrateCommand(),
new Command\StatusCommand(),
new Command\VersionCommand(),
]);
您应该能够使用 setFilterSchemaAssetsExpression。
http://www.doctrine-project.org/api/dbal/2.4/source-class-Doctrine.DBAL.Configuration.html#87-99
如果做不到这一点,如果您想做更少的编程和更多的配置,您可以将视图放入另一个实体管理器中。但这不是最好的方式......
https://symfony.com/doc/3.3/doctrine/multiple_entity_managers.html
自doctrine-orm 2.11起,可以忽略选定的实体,请参阅此处。
在doctrine yaml配置中你可以指定如下:
doctrine:
orm:
# ....
schema_ignore_classes:
- 'App\Entity\TenancyPendingInspection'
- 'App\Entity\ViewToBeIngored'