本文介绍了Symfony2 Doctrine2 - 通过doctrine从现有数据库生成一对多注释:mapping:import的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想使用Doctrine工具从现有数据库中生成实体,用于逆向工程

  / * 
* SET FOREIGN_KEY_CHECKS = 0;
- ----------------------------
- `country` $的表结构
- ----------------------------
DROP TABLE IF EXISTS`country`;
CREATE TABLE`country`(
`id` int(11)unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(255)NOT NULL DEFAULT'',
PRIMARY KEY `id`)
)ENGINE = InnoDB AUTO_INCREMENT = 38 DEFAULT CHARSET = utf8;


- ----------------------------
- 表结构对于`provider`
- ----------------------------
DROP TABLE IF EXISTS`provider`;
CREATE TABLE`provider`(
`id` int(11)unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(255)NOT NULL DEFAULT'',
PRIMARY KEY `id`)
)ENGINE = InnoDB AUTO_INCREMENT = 13 DEFAULT CHARSET = utf8;

- ----------------------------
- `provider_country`的表结构
- ----------------------------
DROP TABLE IF EXISTS`provider_country`;
CREATE TABLE`provider_country`(
`id` int(11)unsigned NOT NULL AUTO_INCREMENT,
`providerId` int(11)unsigned NOT NULL,
`countryId` int 11)unsigned NOT NULL,
PRIMARY KEY(`id`),
KEY`fk_provider_has_id0_idx`(`providerId`),
KEY`fk_user_country_idx`(`countryId`),
CONSTRAINT`fk_rss_has_id` FOREIGN KEY(`providerId`)引用```````````````````` id`)ON删除没有操作更新无操作
)ENGINE = InnoDB AUTO_INCREMENT = 8 DEFAULT CHARSET = utf8;

SET FOREIGN_KEY_CHECKS = 1;
* /

您可以要求Doctrine导入模式并构建相关的实体类以下两个命令。



1 $ php app / console doctrine:mapping:import AcmeBlogBu​​ndle annotation

2 $ php app / console doctrine:generate:entities AcmeBlogBu​​ndle



但现在doctrine只检测ManyToOne在许多方面只有ProviderCountry表中的关系



如果我需要添加OneToMany关系,我必须通过添加下面的注释添加注释



在Provider.php中添加

  / ** 
* @ORM \OneToMany(targetEntity =ProviderCountry,mappedBy =providerId,cascade = {persist})
* /
private $ datas;

在ProviderCountry.php中添加

  / ** 
* @var提供程序
*
* @ ORM\ManyToOne(targetEntity =Provider,inversedBy =datas)
* @ ORM \JoinColumn(name =providerId,referencedColumnName =id)
* /

private $ userid;

那么如何通过doctrine命令来生成一对多注释

解决方案

只要这是在doctrine orm lib内的变化,



/ p>

vendor / doctrine / orm / lib / Doctrine / ORM / Mapping / Driver / DatabaseDriver.php



以下语句

  foreach($ foreignKeys as $ foreignKey){
$ foreignTable = $ foreignKey-> getForeignTableName ;
$ cols = $ foreignKey-> getColumns();
$ fkCols = $ foreignKey-> getForeignColumns();

$ localColumn = current($ cols);
$ associationMapping = array();
$ associationMapping ['fieldName'] = $ this-> getFieldNameForColumn($ tableName,$ localColumn,true);
$ associationMapping ['targetEntity'] = $ this-> getClassNameForTable($ foreignTable);

if($ primaryKeyColumns&& in_array($ localColumn,$ primaryKeyColumns)){
$ associationMapping ['id'] = true;
}

for($ i = 0; $ i< count($ cols); $ i ++){
$ associationMapping ['joinColumns'] [] = array
'name'=> $ cols [$ i],
'referencedColumnName'=> $ fkCols [$ i],
);
}

//这里我们需要检查$ cols是否和$ primaryKeyColums一样
if(!array_diff($ cols,$ primaryKeyColumns)){
$ metadata-> mapOneToOne($ associationMapping);
} else {
$ metadata-> mapManyToOne($ associationMapping);
}
}

更改为

  foreach($ foreignKeys as $ foreignKey){
$ foreignTable = $ foreignKey-> getForeignTableName();
$ cols = $ foreignKey-> getColumns();
$ fkCols = $ foreignKey-> getForeignColumns();

$ localColumn = current($ cols);
$ associationMapping = array();
$ associationMapping ['fieldName'] = $ this-> getFieldNameForColumn($ tableName,$ localColumn,true);
$ associationMapping ['targetEntity'] = $ this-> getClassNameForTable($ foreignTable);

for($ i = 0; $ i< count($ cols); $ i ++){
$ associationMapping ['joinColumns'] [ name'=> $ cols [$ i],
'referencedColumnName'=> $ fkCols [$ i],
);
}
$ metadata-> mapManyToOne($ associationMapping);
}

foreach($ this-> tables as $ tableCandidate){
if($ this-> _sm-> getDatabasePlatform() - > supportsForeignKeyConstraints ){
$ foreignKeysCandidate = $ tableCandidate-> getForeignKeys();
} else {
$ foreignKeysCandidate = array();
}

foreach($ foreignKeysCandidate as $ foreignKey){
$ foreignTable = $ foreignKey-> getForeignTableName();

if($ foreignTable == $ tableName&&!isset($ this-> manyToManyTables [$ tableCandidate-> getName()])){

$ fkCols = $ foreignKey-> getForeignColumns();
$ cols = $ foreignKey-> getColumns();


$ localColumn = current($ cols);

$ associationMapping = array();
$ associationMapping ['fieldName'] = $ this-> getFieldNameForColumn($ tableCandidate-> getName(),$ tableCandidate-> getName(),true);
$ associationMapping ['targetEntity'] = $ this-> getClassNameForTable($ tableCandidate-> getName());
$ associationMapping ['mappedBy'] = $ this-> getFieldNameForColumn($ tableCandidate-> getName(),$ localColumn,true);

try {
$ primaryKeyColumns = $ tableCandidate-> getPrimaryKey() - > getColumns();
if(count($ primaryKeyColumns)== 1){
$ indexColumn = current($ primaryKeyColumns);
$ associationMapping ['indexBy'] = $ indexColumn;
}
} catch(SchemaException $ e){

}

$ metadata-> mapOneToMany($ associationMapping);
}
}
}



现在如果你运行doctrine:映射:import



您将找到OneToMany注释。



然后运行doctrine:generate:entities



您会发现两侧的单向关系。


I want to generate Entities from an Existing Database by using Doctrine tools for reverse engineering

/*
 * SET FOREIGN_KEY_CHECKS=0;
  -- ----------------------------
  -- Table structure for `country`
  -- ----------------------------
  DROP TABLE IF EXISTS `country`;
  CREATE TABLE `country` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `name` varchar(255) NOT NULL DEFAULT '',
  PRIMARY KEY (`id`)
  ) ENGINE=InnoDB AUTO_INCREMENT=38 DEFAULT CHARSET=utf8;


  -- ----------------------------
  -- Table structure for `provider`
  -- ----------------------------
  DROP TABLE IF EXISTS `provider`;
  CREATE TABLE `provider` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `name` varchar(255) NOT NULL DEFAULT '',
  PRIMARY KEY (`id`)
  ) ENGINE=InnoDB AUTO_INCREMENT=13 DEFAULT CHARSET=utf8;

  -- ----------------------------
  -- Table structure for `provider_country`
  -- ----------------------------
  DROP TABLE IF EXISTS `provider_country`;
  CREATE TABLE `provider_country` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `providerId` int(11) unsigned NOT NULL,
  `countryId` int(11) unsigned NOT NULL,
  PRIMARY KEY (`id`),
  KEY `fk_provider_has_id0_idx` (`providerId`),
  KEY `fk_user_country_idx` (`countryId`),
  CONSTRAINT `fk_rss_has_id` FOREIGN KEY (`providerId`) REFERENCES `provider` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION,
  CONSTRAINT `fk_user_country` FOREIGN KEY (`countryId`) REFERENCES `country` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION
  ) ENGINE=InnoDB AUTO_INCREMENT=8 DEFAULT CHARSET=utf8;

  SET FOREIGN_KEY_CHECKS=1;
 */

you can ask Doctrine to import the schema and build related entity classes by executing the following two commands.

1 $ php app/console doctrine:mapping:import AcmeBlogBundle annotation
2 $ php app/console doctrine:generate:entities AcmeBlogBundle

but now the doctrine detect only ManyToOne relation in many side only "ProviderCountry" table

if i need to add the OneToMany relation i have to add the annotation by my hand by adding the follwing annotation

in Provider.php add

/**
 * @ORM\OneToMany(targetEntity="ProviderCountry", mappedBy="providerId", cascade={"persist"})
 */
private $datas;

in ProviderCountry.php add

    /**
     * @var Provider
     *
     * @ORM\ManyToOne(targetEntity="Provider", inversedBy = "datas")
     * @ORM\JoinColumn(name="providerId", referencedColumnName="id")
     */

private $userid;

so how can I genrate One-To-Many annotation by doctrine command

解决方案

Simply this is change inside doctrine orm lib,

you can fix that by changes in

vendor/doctrine/orm/lib/Doctrine/ORM/Mapping/Driver/DatabaseDriver.php

replace the following statements

foreach ($foreignKeys as $foreignKey) {
          $foreignTable = $foreignKey->getForeignTableName();
          $cols = $foreignKey->getColumns();
          $fkCols = $foreignKey->getForeignColumns();

          $localColumn = current($cols);
          $associationMapping = array();
          $associationMapping['fieldName'] = $this->getFieldNameForColumn($tableName, $localColumn, true);
          $associationMapping['targetEntity'] = $this->getClassNameForTable($foreignTable);

          if ($primaryKeyColumns && in_array($localColumn, $primaryKeyColumns)) {
          $associationMapping['id'] = true;
          }

          for ($i = 0; $i < count($cols); $i++) {
          $associationMapping['joinColumns'][] = array(
          'name' => $cols[$i],
          'referencedColumnName' => $fkCols[$i],
          );
          }

          //Here we need to check if $cols are the same as $primaryKeyColums
          if (!array_diff($cols, $primaryKeyColumns)) {
          $metadata->mapOneToOne($associationMapping);
          } else {
          $metadata->mapManyToOne($associationMapping);
          }
          }

change to

foreach ($foreignKeys as $foreignKey) {
            $foreignTable = $foreignKey->getForeignTableName();
            $cols = $foreignKey->getColumns();
            $fkCols = $foreignKey->getForeignColumns();

            $localColumn = current($cols);
            $associationMapping = array();
            $associationMapping['fieldName'] = $this->getFieldNameForColumn($tableName, $localColumn, true);
            $associationMapping['targetEntity'] = $this->getClassNameForTable($foreignTable);

            for ($i = 0; $i < count($cols); $i++) {
                $associationMapping['joinColumns'][] = array(
                    'name' => $cols[$i],
                    'referencedColumnName' => $fkCols[$i],
                );
            }
            $metadata->mapManyToOne($associationMapping);
        }

        foreach ($this->tables as $tableCandidate) {
            if ($this->_sm->getDatabasePlatform()->supportsForeignKeyConstraints()) {
                $foreignKeysCandidate = $tableCandidate->getForeignKeys();
            } else {
                $foreignKeysCandidate = array();
            }

            foreach ($foreignKeysCandidate as $foreignKey) {
                $foreignTable = $foreignKey->getForeignTableName();

                if ($foreignTable == $tableName && !isset($this->manyToManyTables[$tableCandidate->getName()])) {

                    $fkCols = $foreignKey->getForeignColumns();
                    $cols = $foreignKey->getColumns();


                    $localColumn = current($cols);

                    $associationMapping = array();
                    $associationMapping['fieldName'] = $this->getFieldNameForColumn($tableCandidate->getName(), $tableCandidate->getName(), true);
                    $associationMapping['targetEntity'] = $this->getClassNameForTable($tableCandidate->getName());
                    $associationMapping['mappedBy'] = $this->getFieldNameForColumn($tableCandidate->getName(), $localColumn, true);

                    try {
                        $primaryKeyColumns = $tableCandidate->getPrimaryKey()->getColumns();
                        if (count($primaryKeyColumns) == 1) {
                            $indexColumn = current($primaryKeyColumns);
                            $associationMapping['indexBy'] = $indexColumn;
                        }
                    } catch (SchemaException $e) {

                    }

                    $metadata->mapOneToMany($associationMapping);
                }
            }
        }

now if you run doctrine:mapping:import

you will find OneToMany annotation.

then run doctrine:generate:entities

you will find A unidirectional relationship on both sides.

这篇关于Symfony2 Doctrine2 - 通过doctrine从现有数据库生成一对多注释:mapping:import的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

09-05 04:01