Symfony: загрузка объектов с первичным ключом из нескольких столбцов, которые также являются внешними ключами - PullRequest
2 голосов
/ 04 сентября 2011

Я пишу данные для моего проекта в Symfony, и у меня есть проблемы при попытке добавить объекты к объектам с первичным ключом из нескольких столбцов, который также является внешним ключом для другой таблицы.

Вот схема в MySql Workbench:

MySQL WorkBench representation of the schema

Я сгенерировал sql-код с помощью workbench, а затем сгенерировал файл schema.yml с задачей symfony php symfony doctrine:build-schema.

это sql, сгенерированный для этих таблиц:

-- -----------------------------------------------------
-- Table `mydb`.`MetodoEnvio`
-- -----------------------------------------------------
DROP TABLE IF EXISTS `mydb`.`MetodoEnvio` ;

CREATE  TABLE IF NOT EXISTS `mydb`.`MetodoEnvio` (
  `id` INT UNSIGNED NOT NULL AUTO_INCREMENT ,
  `nombre` VARCHAR(45) NOT NULL ,
  `precio` DECIMAL(10,2) NOT NULL ,
  PRIMARY KEY (`id`) )
ENGINE = InnoDB
DEFAULT CHARACTER SET = utf8
COLLATE = utf8_general_ci;

-- -----------------------------------------------------
-- Table `mydb`.`ZonaEnvio`
-- -----------------------------------------------------
DROP TABLE IF EXISTS `mydb`.`ZonaEnvio` ;

CREATE  TABLE IF NOT EXISTS `mydb`.`ZonaEnvio` (
  `id` INT UNSIGNED NOT NULL ,
  `numero` INT(3) UNSIGNED NOT NULL ,
  `etiqueta` VARCHAR(255) NOT NULL ,
  PRIMARY KEY (`id`, `numero`) ,
  INDEX `fk_ZonaEnvio_MetodoEnvio` (`id` ASC) ,
  INDEX `numeroZona_INDEX` (`numero` ASC) ,
  CONSTRAINT `fk_ZonaEnvio_MetodoEnvio`
    FOREIGN KEY (`id` )
    REFERENCES `mydb`.`MetodoEnvio` (`id` )
    ON DELETE NO ACTION
    ON UPDATE NO ACTION)
ENGINE = InnoDB
DEFAULT CHARACTER SET = utf8
COLLATE = utf8_general_ci;

-- -----------------------------------------------------
-- Table `mydb`.`PrecioEnvio`
-- -----------------------------------------------------
DROP TABLE IF EXISTS `mydb`.`PrecioEnvio` ;

CREATE  TABLE IF NOT EXISTS `mydb`.`PrecioEnvio` (
  `idMetodo` INT UNSIGNED NOT NULL ,
  `zona` INT(3) UNSIGNED NOT NULL ,
  `inicioRango` DECIMAL(10,2) NOT NULL COMMENT 'Marca el inicio del rango de peso para el cual este precio aplica.' ,
  `finRango` DECIMAL(10,2) NULL COMMENT 'Marca el fin del rango de peso para el cual este precio aplica.' ,
  `precio` DECIMAL(10,2) NOT NULL ,
  PRIMARY KEY (`idMetodo`, `inicioRango`, `finRango`, `zona`) ,
  INDEX `fk_PrecioEnvio_ZonaEnvio` (`idMetodo` ASC, `zona` ASC) ,
  CONSTRAINT `fk_PrecioEnvio_ZonaEnvio`
    FOREIGN KEY (`idMetodo` , `zona` )
    REFERENCES `mydb`.`ZonaEnvio` (`id` , `numero` )
    ON DELETE NO ACTION
    ON UPDATE NO ACTION)
ENGINE = InnoDB
DEFAULT CHARACTER SET = utf8
COLLATE = utf8_general_ci;

-- -----------------------------------------------------
-- Table `mydb`.`IntervaloMetodoEnvio`
-- -----------------------------------------------------
DROP TABLE IF EXISTS `mydb`.`IntervaloMetodoEnvio` ;

CREATE  TABLE IF NOT EXISTS `mydb`.`IntervaloMetodoEnvio` (
  `idMetodo` INT UNSIGNED NOT NULL ,
  `zona` INT(3) UNSIGNED NOT NULL ,
  `intervalo` DECIMAL(10,2) NOT NULL ,
  `precio` DECIMAL(10,2) NOT NULL ,
  PRIMARY KEY (`idMetodo`, `zona`) ,
  INDEX `fk_IntervaloMetodoEnvio_ZonaEnvio` (`idMetodo` ASC, `zona` ASC) ,
  CONSTRAINT `fk_IntervaloMetodoEnvio_ZonaEnvio`
    FOREIGN KEY (`idMetodo` , `zona` )
    REFERENCES `mydb`.`ZonaEnvio` (`id` , `numero` )
    ON DELETE NO ACTION
    ON UPDATE NO ACTION)
ENGINE = InnoDB
DEFAULT CHARACTER SET = utf8
COLLATE = utf8_general_ci;

это схема, сгенерированная для этих таблиц:

MetodoEnvio:
  connection: doctrine
  tableName: MetodoEnvio
  columns:
    id:
      type: integer(4)
      fixed: false
      unsigned: true
      primary: true
      autoincrement: true
    nombre:
      type: string(45)
      fixed: false
      unsigned: false
      primary: false
      notnull: true
      autoincrement: false
    precio:
      type: 'decimal(10, 2)'
      fixed: false
      unsigned: false
      primary: false
      notnull: true
      autoincrement: false
  relations:
    TiendaOrden:
      local: id
      foreign: metodoenvio
      type: many
    ZonaEnvio:
      local: id
      foreign: id
      type: many
ZonaEnvio:
  connection: doctrine
  tableName: ZonaEnvio
  columns:
    id:
      type: integer(4)
      fixed: false
      unsigned: true
      primary: true
      autoincrement: false
    numero:
      type: integer(4)
      fixed: false
      unsigned: true
      primary: true
      autoincrement: false
    etiqueta:
      type: string(255)
      fixed: false
      unsigned: false
      primary: false
      notnull: true
      autoincrement: false
  relations:
    MetodoEnvio:
      local: id
      foreign: id
      type: one
    IntervaloMetodoEnvio:
      local: id
      foreign: idmetodo
      type: many
    IntervaloMetodoEnvio_2:
      class: IntervaloMetodoEnvio
      local: numero
      foreign: zona
      type: many
    PrecioEnvio:
      local: id
      foreign: idmetodo
      type: many
    PrecioEnvio_2:
      class: PrecioEnvio
      local: numero
      foreign: zona
      type: many
PrecioEnvio:
  connection: doctrine
  tableName: PrecioEnvio
  columns:
    idmetodo:
      type: integer(4)
      fixed: false
      unsigned: true
      primary: true
      autoincrement: false
    zona:
      type: integer(4)
      fixed: false
      unsigned: true
      primary: true
      autoincrement: false
    iniciorango:
      type: 'decimal(10, 2)'
      fixed: false
      unsigned: false
      primary: true
      autoincrement: false
    finrango:
      type: 'decimal(10, 2)'
      fixed: false
      unsigned: false
      primary: true
      autoincrement: false
    precio:
      type: 'decimal(10, 2)'
      fixed: false
      unsigned: false
      primary: false
      notnull: true
      autoincrement: false
  relations:
    ZonaEnvio:
      local: idmetodo
      foreign: id
      type: one
    ZonaEnvio_2:
      class: ZonaEnvio
      local: zona
      foreign: numero
      type: one
IntervaloMetodoEnvio:
  connection: doctrine
  tableName: IntervaloMetodoEnvio
  columns:
    idmetodo:
      type: integer(4)
      fixed: false
      unsigned: true
      primary: true
      autoincrement: false
    zona:
      type: integer(4)
      fixed: false
      unsigned: true
      primary: true
      autoincrement: false
    intervalo:
      type: 'decimal(10, 2)'
      fixed: false
      unsigned: false
      primary: false
      notnull: true
      autoincrement: false
    precio:
      type: 'decimal(10, 2)'
      fixed: false
      unsigned: false
      primary: false
      notnull: true
      autoincrement: false
  relations:
    ZonaEnvio:
      local: idmetodo
      foreign: id
      type: one
    ZonaEnvio_2:
      class: ZonaEnvio
      local: zona
      foreign: numero
      type: one

Затем я написал следующие материалы:

MetodoEnvio:
  personal:
    nombre: Retiro Personal
    precio: 0.0

  mrw:
    nombre: MRW
    precio: 5.0

  dhl:
    nombre: DHL
    precio: -1.0
ZonaEnvio:
  dhl_zona1:
    MetodoEnvio: dhl
    numero: 1
    etiqueta: DHL (Envios en la Zona Metropolitana)

  dhl_zona5:
    MetodoEnvio: dhl
    numero: 5
    etiqueta: DHL (Envios al interior del pais)
PrecioEnvio:
  fila1_zona1:
    ZonaEnvio: dhl_zona1
    inicioRango: 0.00
    finRango: 0.50
    precio: 26.90

  fila1_zona5:
    ZonaEnvio: dhl_zona5
    inicioRango: 00
    finRango: 0.50
    precio: 59.60
IntervaloMetodoEnvio:
  dhl_zona_1:
    ZonaEnvio: dhl_zona1
    intervalo: 0.5
    precio: 3.05

  dhl_zona_5:
    ZonaEnvio: dhl_zona5
    intervalo: 0.5
    precio: 7.15

Когда я делаю команду php symfony doctrine:data-load, она возвращает ошибку:

SQLSTATE[23000]: Integrity constraint violation: 1452 Cannot add or update a child row: a foreign key constraint fails (`mydb`.`PrecioEnvio`, CONSTRAINT `fk_PrecioEnvio_ZonaEnvio` FOREIGN KEY (`idMetodo`, `zona`) REFERENCES `ZonaEnvio` (`id`, `numero`) ON DELETE NO ACTION ON UPDATE NO ACTION)

Так как ошибка связана с внешними ключами, я думаю, что это может иметь какое-то отношение к моим ссылкам в схеме в таких строках, как ZonaEnvio: dhl_zona1. Как я могу ссылаться на «родительский объект»? Я думаю, что это не наследство, а слабые отношения ...

Пожалуйста, простите за мой вопрос, но я хотел предоставить вам всю необходимую информацию, чтобы вы могли мне помочь!

СПАСИБО ОГРОМНОЕ ЗА ВАШУ ПОМОЩЬ!

Ответы [ 2 ]

1 голос
/ 04 сентября 2011

Я нашел, в чем проблема. Это связано с тем, как были определены отношения в файле schema.yml. Обратите внимание, что он представляет первичный ключ двух полей, определяющий два отношения к одному и тому же классу:

.
.
.
  relations:
     ZonaEnvio:
        local: idmetodo
        foreign: id
        type: one
     ZonaEnvio_2:
        class: ZonaEnvio
        local: zona
        foreign: numero
        type: one

Отношения определяются следующим образом: PrecioEnvio и IntervaloMetodoEnvio, обе слабые сущности ZonaEnvio. Итак, мне просто нужно было дать значения для обоих отношений в моих приборах и указать их на один и тот же экземпляр ранее определенного ZonaEnvio объекта. Как это:

IntervaloMetodoEnvio:
  dhl_zona_1:
    ZonaEnvio: dhl_zona1
    ZonaEnvio_2: dhl_zona1
    intervalo: 0.5
    precio: 3.05

  dhl_zona_5:
    ZonaEnvio: dhl_zona5
    ZonaEnvio_2: dhl_zona5
    intervalo: 0.5
    precio: 7.15

PrecioEnvio:
  fila1_zona1:
    ZonaEnvio: dhl_zona1
    ZonaEnvio_2: dhl_zona1
    inicioRango: 0.00
    finRango: 0.50
    precio: 26.90

  fila1_zona5:
    ZonaEnvio: dhl_zona5
    ZonaEnvio_2: dhl_zona5
    inicioRango: 00
    finRango: 0.50
    precio: 59.60

Уведомление

ZonaEnvio: dhl_zona1
ZonaEnvio_2: dhl_zona1

обе строки находятся в одном и том же определении прибора и указывают на один и тот же экземпляр. Таким образом, приборы успешно загружены.

В любом случае, спасибо за ваши усилия, gview!

1 голос
/ 04 сентября 2011

Это ошибка ограничения mysql, означающая, что вставляемое значение не существует в связанной таблице.

Ваш формат приспособления не соответствует моему пониманию того, каким он должен быть для комбинации версии 1.x Symfony / Doctrine.Посмотрите на эту справку для правильного формата: http://www.symfony -project.org / doctrine / 1_2 / ru / 05-Data-Fixtures .Например, создавая строку с идентификатором 1:

MetodoEnvio:
  MetodoEnvio_1:
    nombre: Retiro Personal
    precio: 0.0

Затем, когда вам нужно обратиться к таблице, которая относится к MetodoEnvio с id = 1, вы можете использовать MetodoEnvio_1, хотя вы, вероятно, можете просто использовать id:1, зная, что идентификатор будет 1.

...