让我说我有一个视图表。我希望从中获取数据到实体。我可以(以及如何)创建实体类来做到这一点。 (不需要保存操作)。我只想展示它们。
答案 0 :(得分:26)
接受的答案是正确的,但我想提供一些您可能需要考虑的其他建议:
将您的实体标记为只读。
将构造函数设为私有,以便只有Doctrine可以创建实例。
/**
* @ORM\Entity(readOnly=true)
* @ORM\Table(name="your_view_table")
*/
class YourEntity {
private function __construct() {}
}
答案 1 :(得分:18)
之前的答案都是正确的,但是如果您使用学说迁移工具并执行schema:update
它将失败...
所以,除了将实体标记为只读并将构造函数设为私有之外(在Ian Phillips的回答中解释):
/**
* @ORM\Entity(readOnly=true)
* @ORM\Table(name="your_view_table")
*/
class YourEntity {
private function __construct() {}
}
您需要将架构工具设置为在执行架构时忽略实体:update ...
为了做到这一点,你只需要在你的包中创建这个命令,并在ignoredEntity列表中设置你的实体:
的src / Acme公司/ CoreBundle /命令/ 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);
}
}
(归功于Alexandru Trandafir Catalin:从这里获得:https://stackoverflow.com/a/25948910/1442457)
顺便说一下,这是我发现使用教条中的观点的唯一方法......我知道这是一种解决方法......如果有更好的方式我是开放的或建议的话)答案 2 :(得分:17)
查询视图没有什么特别之处 - 它只是一个虚拟表。以这种方式设置您的实体表并享受:
/**
* @ORM\Entity
* @ORM\Table(name="your_view_table")
*/
class YourEntity {
// ...
}
答案 3 :(得分:9)
除了上面的anwers之外,如果您使用doctrine迁移进行架构更新,则以下配置可以正常运行。
/**
* @ORM\Entity(readOnly=true)
* @ORM\Table(name="view_table_name")
*/
class YourEntity {
private function __construct() {}
}
直到这里与上述答案相同。在这里,您需要配置doctrine不绑定模式;
doctrine:
dbal:
schema_filter: ~^(?!view_)~
上面的过滤器定义过滤了所有'view_'前缀表以及可以使用正则表达式扩展的视图。只需确保使用“view_”前缀命名您的观看次数。
但是学说:schema:update --dump-sql仍然显示视图,我希望他们也会将相同的过滤器集成到模式更新中。
我希望这个解决方案可以帮助其他人。
来源:http://symfony.com/doc/current/bundles/DoctrineMigrationsBundle/index.html#manual-tables
答案 4 :(得分:1)
除上述答案外,我还混合了一些示例代码来扩展DoctrineUpdateCommand
这是我的DoctrineUpdateCommand:
class DoctrineUpdateCommand extends UpdateSchemaDoctrineCommand{
protected function executeSchemaCommand(InputInterface $input, OutputInterface $output, SchemaTool $schemaTool, array $metadatas) {
$container = $this->getApplication()->getKernel()->getContainer();
$filterExpr = $container->get('doctrine')->getEntityManager()->getConnection()->getConfiguration()->getFilterSchemaAssetsExpression();
$emptyFilterExpression = empty($filterExpr);
/** @var $newMetadatas \Doctrine\ORM\Mapping\ClassMetadata */
$newMetadatas = array();
foreach ($metadatas as $metadata) {
if(($emptyFilterExpression||preg_match($filterExpr, $metadata->getTableName()))){
array_push($newMetadatas, $metadata);
}
}
parent::executeSchemaCommand($input, $output, $schemaTool, $newMetadatas);
}
}
感谢正确的方式
答案 5 :(得分:0)
除了以上答案外,您还必须具有视图实体和虚拟表的命名策略,例如:view_your_table,然后必须将以下代码添加到doctrine.yaml中,以禁止创建新的迁移文件到视图:
schema_filter: ~^(?!view_)~
答案 6 :(得分:0)
由于需要在我的数据库中引入一个关于 Zend 实现的视图,我花了一天的时间。
如前所述,您应该创建一个实体,并且该实体必须具有 Id()
注释:
/**
* @Doctrine\ORM\Mapping\Table(name="your_view")
* @Doctrine\ORM\Mapping\Entity(readOnly=true)
*/
class YourViewEntity
{
/**
* @var SomeEntityInterface
* @Doctrine\ORM\Mapping\Id()
* @Doctrine\ORM\Mapping\OneToOne(targetEntity="SomeMainEntity", fetch="LAZY")
* @Doctrine\ORM\Mapping\JoinColumn(nullable=false, referencedColumnName="id")
*/
protected $some;
/**
* @var AnotherEntityInterface
* @Doctrine\ORM\Mapping\ManyToOne(targetEntity="AnotherEntity", fetch="LAZY")
* @Doctrine\ORM\Mapping\JoinColumn(nullable=false, referencedColumnName="id")
*/
protected $another;
// Make the constructor private so that only Doctrine can create instances.
private function __construct() {}
}
还带有私有构造函数,如Ian Phillips answer 中所述。但这并不能阻止 orm:schema-tool:update
基于新实体创建表,试图覆盖我们的视图......尽管在生产中应该避免使用 orm:schema-tool:update
以支持迁移脚本,用于开发目的这非常有用。
由于 schema_filter: ~^(?!view_)~
似乎都不起作用,也已弃用,我设法在 Kamil Adryjanek page 上找到了一个技巧,它提供了向实体添加 EventListener
或 Subscriber
的选项经理,这将阻止为我们创建表。我的实现如下:
class SkipAutogenerateTableSubscriber implements EventSubscriber
{
public const CONFIG_KEY = "skip_autogenerate_entities";
private $ignoredEntities = [];
public function __construct($config)
{
if (array_key_exists(self::CONFIG_KEY, $config)) {
$this->ignoredEntities = (array) $config[self::CONFIG_KEY];
}
}
public function getSubscribedEvents()
{
return [
ToolEvents::postGenerateSchema
];
}
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)) {
$schema->dropTable($table->getName());
}
}
}
}
这不仅解决了 orm:schema-tool
的问题,还解决了 migrations:diff
模块的 doctrine/migrations
。