Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/mysql/57.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Php 如何在Symfony 2中为数据库视图设置实体(原则)_Php_Mysql_Symfony_Doctrine Orm - Fatal编程技术网

Php 如何在Symfony 2中为数据库视图设置实体(原则)

Php 如何在Symfony 2中为数据库视图设置实体(原则),php,mysql,symfony,doctrine-orm,Php,Mysql,Symfony,Doctrine Orm,假设我有一个视图表。我想从中获取数据到一个实体。我是否可以(以及如何)创建实体类来执行此操作(无需保存操作)?我只想显示它们。查询视图没有什么特别的地方——它只是一个虚拟表。以这种方式设置实体的表格,并享受: /** * @ORM\Entity * @ORM\Table(name="your_view_table") */ class YourEntity { // ... } 被接受的答案是正确的,但我想提供一些您可能需要考虑的其他建议: 将实体标记为只读 将构造函数设置为私有

假设我有一个视图表。我想从中获取数据到一个实体。我是否可以(以及如何)创建实体类来执行此操作(无需保存操作)?我只想显示它们。

查询视图没有什么特别的地方——它只是一个虚拟表。以这种方式设置实体的表格,并享受:

/**
 * @ORM\Entity
 * @ORM\Table(name="your_view_table")
 */
class YourEntity {
    // ...
}

被接受的答案是正确的,但我想提供一些您可能需要考虑的其他建议:

将实体标记为只读

将构造函数设置为私有,以便只有条令可以创建实例

/**
 * @ORM\Entity(readOnly=true)
 * @ORM\Table(name="your_view_table")
 */
class YourEntity {
    private function __construct() {}
}

前面的两个答案都是正确的,但是如果您使用条令迁移工具并执行
schema:update
,它将失败

因此,除了将实体标记为只读并使构造函数私有(在Ian Phillips的回答中解释)之外:

在执行模式更新时,需要将模式工具设置为忽略实体

为此,您只需在bundle中创建此命令,并在IgnoreIdentity列表中设置yout entity:

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);
  }

}

除上述问题外,如果您正在使用条令迁移进行模式更新,则以下配置工作正常

/**
 * @ORM\Entity(readOnly=true)
 * @ORM\Table(name="view_table_name")
 */
class YourEntity {
    private function __construct() {}
}
这里的答案与上面的答案相同。在这里,您需要将条令配置为不绑定模式

doctrine:
    dbal:
        schema_filter: ~^(?!view_)~
上面的过滤器定义过滤所有带有“view_u1;”前缀的表以及可以使用regex扩展的视图。只需确保您已使用“视图”前缀命名视图

但是条令:schema:update——dumpsql仍然显示视图,我希望它们也将相同的过滤器集成到schema更新中

我希望这个解决方案能帮助其他人


来源:

除了上面的答案,我还混合了一些示例代码来扩展doctrineUpdate命令

这是我的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);
 }
}

感谢您提供了正确的方法

除了上述答案之外,您还必须拥有视图实体和虚拟表的命名策略,例如:view_your_table,然后您必须将以下代码添加到doctor.yaml中,以禁用在视图中创建新的迁移文件:
schema\u filter:~^(?!view\u)~

我花了一天时间在这上面,因为有必要在我的数据库中引入一个关于Zend实现的视图

如前所述,您应该创建一个实体,该实体必须具有
Id()
注释:

/**
*@Doctrine\ORM\Mapping\Table(name=“您的视图”)
*@Doctrine\ORM\Mapping\Entity(readOnly=true)
*/
为YourViewEntity设置类
{
/**
*@var-sometentityinterface
*@Doctrine\ORM\Mapping\Id()
*@Doctrine\ORM\Mapping\OneToOne(targetEntity=“SomeMainEntity”,fetch=“LAZY”)
*@Doctrine\ORM\Mapping\JoinColumn(nullable=false,referencedColumnName=“id”)
*/
受保护的美元;
/**
*@var-AnotherEntityInterface
*@Doctrine\ORM\Mapping\manytone(targetEntity=“AnotherEntity”,fetch=“LAZY”)
*@Doctrine\ORM\Mapping\JoinColumn(nullable=false,referencedColumnName=“id”)
*/
另加一美元;
//将构造函数设置为私有,以便只有条令可以创建实例。
私有函数_构造(){}
}
也可以使用私有构造函数,如中所述。但这并不能阻止
orm:schema工具:update
基于新实体创建表,试图覆盖我们的视图。。。尽管在生产中应该避免使用
orm:schema-tool:update
,而应该使用迁移脚本,但对于开发目的来说,这是非常有用的

由于
schema\u过滤器:~^(?!view\u)~
似乎都不起作用,也不推荐使用,我设法找到了一个技巧,即在实体管理器中添加一个
EventListener
Subscriber
,这将阻止为我们创建表。地雷执行情况如下:

类SkipaToGenerateTableSubscriber实现EventSubscriber
{
public const CONFIG_KEY=“跳过自动生成实体”;
私人$ignoredEntities=[];
公共函数构造($config)
{
如果(数组_键_存在(self::CONFIG_键,$CONFIG)){
$this->ignoredEntities=(数组)$config[self::config_KEY];
}
}
公共函数getSubscribedEvents()
{
返回[
ToolEvents::postGenerateSchema
];
}
公共函数postGenerateSchema(GenerateSchemaEventArgs$args)
{
$schema=$args->getSchema();
$em=$args->getEntityManager();
$ignoredTables=[];
foreach($this->ignoredEntities as$entityName){
$ignoredTables[]=$em->getClassMetadata($entityName)->getTableName();
}
foreach($schema->getTables()作为$table){
if(在数组中($table->getName(),$ignoredTables)){
$schema->dropTable($table->getName());
}
}
}
}

这不仅解决了
orm:schema工具
的问题,而且解决了
条令/迁移
模块的
迁移:差异
的问题。

@GusDeCooL,好吧,然后放一个标识符。;)非常非常糟糕的做法。调用条令:架构:更新。。。和表将被重写为简单表(不是视图)。@user1954544,使用ORM生成架构是一种不好的做法。@ElnurAbdurrakhimov使用和ORM生成架构是Symfony建议的做法。另外,由于正在运行的查询的性质,许多视图没有标识符。@SergeVelikanov,如果让ORM为您生成表,您就有麻烦了。;)但这只在调用update时有效,验证显示失败。你是对的,Marcus,我刚刚尝试过,但失败了。。。我想如果您使用验证,您应该将实体添加到排除列表中进行验证(类似于我对更新所做的)。这是可能的,但将实体排除在更新之外已经是一种黑客行为,我认为symfony应该实现
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);
 }
}