【问题标题】:skip tables when running Doctrine convert-mapping运行 Doctrine 转换映射时跳过表
【发布时间】:2014-12-11 18:47:20
【问题描述】:

我第一次坐下来学习教义,并尝试在现有站点/数据库上使用它的一些命令行工具。我从命令行使用映射和实体逆向工程工具,想看看它会从 php/mysql 中的现有网站生成什么样的文件。

但是,它会在任何异常情况下停止。我已经能够为枚举创建一个类型映射,暂时将它们扔到一个字符串中,但现在它阻止了我在没有指定主 ID 键的表上。我对在链接表中使用主键或复合键的讲座不感兴趣,我只是想在学习 Doctrine 的同时生成一些输出。

有没有办法让教义跳过抛出异常的表,或者在遇到异常时不停止直通?我现在只想要一些示例输出,不想完全重构一个复杂的数据库来看看 Doctrine 能做什么。

SW

【问题讨论】:

  • 创建一个符合原则规范的新应用程序比调整现有应用程序要容易得多。对于像 Symfony 2 这样的全栈框架更是如此。我建议从头开始,用一些简单的东西来看看它是如何工作的。从一个基本表开始,它是 CRUD。接着是一对多关联,然后是多对多关联及其 CRUD。然后使用您所学的知识来转换现有的应用程序。您真的不应该试图强迫教义解决现有应用程序存在的问题,它可能会破坏/破坏它。

标签: php mysql doctrine-orm doctrine


【解决方案1】:

Doctrine 转换和验证的主要问题是它默认读取整个数据库和所有表,而不管它们的实体或映射是否存在。即使在调用orm:convert:mappingorm:generate:entities 时使用--filter="" 标志

要解决此问题并让 Doctrine 跳过抛出异常的表,您可以将 Doctrine 设置为仅读取您想要的表,方法是使用 setFilterSchemaAssetsExpression 定义它们

$isDev = true;

$config = \Doctrine\ORM\Tools\Setup::createAnnotationMetadataConfiguration(array('/path/to/entities'), $isDev);
$config->setFilterSchemaAssetsExpression('/^(table1|table2|prefixed_.*|.*_suffixed)$/');

$em =  \Doctrine\ORM\EntityManager::create(array(
    'driver' => 'db_driver',
    'host' => 'localhost',
    'user' => 'user_name',
    'password' => 'user_password',
    'dbname' => 'database',
), $config);

或者您可以为现有实体管理器的连接设置过滤器。

$em->getConnection()->setFilterSchemaAssetsExpression('/^(filtered_table)$/');

参考: http://doctrine-orm.readthedocs.org/en/latest/reference/configuration.html

当然,这并不是告诉教义忽略异常的一种方式,但应该可以帮助您开始在某些特定表上而不是整个数据库上学习现有应用程序。


作为旁注,因为您提到您有链接表。 如果表中有未包含在过滤器中的外键,则 --from-database 转换仍会为其创建引用。 您必须手动将映射更改为原始形式,而不是关联的 OneToMany、ManyToOne 或 ManyToMany 映射。

来自doctrine orm:convert:mapping --from-database annotation /path/to/entities的注解映射

/**
 * @ORM\Entity
 * @ORM\Table(name="order")
 */
class Order
{
  /** 
   * @var \Customer
   * @ORM\ManyToOne(targetEntity="Customer")
   * @ORM\JoinColumns({
   *   @ORM\JoinColumn(name="customer", referencedColumnName="id", nullable=true)
   * })
   */
   private customer;
}

/**
 * @ORM\Entity
 * @ORM\Table(name="order")
 */
class Order
{
  /** 
   * @var integer
   * @ORM\Column(name="customer", type="integer", nullable=true)
   */
   private customer;
}

然后不要忘记使用doctrine orm:validate-schema 来确保映射是同步的。

【讨论】:

    【解决方案2】:

    再次重温同样的问题。我发现似乎可行的是通过引导文件在 cli 配置中使用过滤:

    // bootstrap.php
    require_once("vendor/autoload.php");
    
    use Doctrine\ORM\Tools\Setup;
    use Doctrine\ORM\EntityManager;
    
    $site_root = realpath(__DIR__ . "/../");
    
    $paths = [ $site_root . "/libraries/Doctrine/Entities" ];
    $isDevMode = false;
    
    // used when building entities from database using command line tool
    $config = Setup::createAnnotationMetadataConfiguration($paths, $isDevMode);
    
    $filter_include = [
        'some_table_name',
        'another_table_name',
        '.*some_sub_portion.*',
        '^some_table_prefix_.*',
        '.*some_table_suffix$'
    ];
    $include_reg = '/^(' . implode('|', $filter_include) . ').*$/';
    
    $filter_exclude = [
        // tables with no primary key generate exceptions
        'some_table_name',
        'another_table_name',
        '.*some_sub_portion.*',
        '^some_table_prefix_.*',
        '.*some_table_suffix$'
    ];
    $exclude_reg = '/^(?!(?:' . implode('|', $filter_exclude) . ')$).*$/';
    
    // use include list
    //$config->setFilterSchemaAssetsExpression($include_reg);
    // use exclude list
    $config->setFilterSchemaAssetsExpression($exclude_reg);
    
    // the connection configuration
    $dbParams = array(
        'driver'   => 'pdo_mysql',
        'user'     => 'myuser',
        'password' => 'mypassword',
        'dbname'   => 'mydatabase',
    );
    
    $entityManager = EntityManager::create($dbParams, $config);
    
    $platform = $entityManager->getConnection()->getDatabasePlatform();
    $platform->registerDoctrineTypeMapping('enum', 'string');
    

    【讨论】:

      【解决方案3】:

      不久前我遇到了同样的问题。完全一样的顺序。首先我必须将枚举映射到字符串,然后它抱怨缺少主键。

      我很确定没有办法忽略异常。或者至少我在文档或在线都找不到。 所以我所做的是为所有没有主键的表添加一个主键。喜欢 alter table add temp_id int primary key not null auto_increment;

      然后我从那里开始查看要保留哪些实体以及要丢弃哪些实体。 否则,您可以复制数据库并删除没有主键的表。 但是如果数据库有很多表,手动操作可能需要一段时间,你应该考虑制作一个过程

      【讨论】:

        猜你喜欢
        • 2019-08-21
        • 1970-01-01
        • 2020-05-18
        • 2018-01-04
        • 1970-01-01
        • 2013-10-22
        • 1970-01-01
        • 1970-01-01
        • 2018-02-16
        相关资源
        最近更新 更多