Doctrine 1.2: How do i prevent a contraint from be

2019-09-20 15:29发布

问题:

Is there a way to prevent Doctrine from assigning a contraint on both sides of a one-to-one relationship? Ive tried moving the definition from one side to the other and using owning side but it still places a constraint on both tables. when I only want the parent table to have a constraint - ie. its possible for the parent to not have an associated child.

For example iwant the following sql schema essentially:

CREATE TABLE `parent_table` (
  `child_id` varchar(50) NOT NULL,
  `id` integer UNSIGNED NOT NULL auto_increment,
  PRIMARY KEY (`id`)
);

CREATE TABLE `child_table` (
  `id` integer UNSIGNED NOT NULL auto_increment,
  `child_id` varchar(50) NOT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY (`child_id`),
  CONSTRAINT `parent_table_child_id_FK_child_table_child_id`
    FOREIGN KEY (`child_id`)
    REFERENCES `parent_table` (`child_id`)
);

However im getting something like this:

CREATE TABLE `parent_table` (
  `child_id` varchar(50) NOT NULL,
  `id` integer UNSIGNED NOT NULL auto_increment,
  PRIMARY KEY (`id`),
  CONSTRAINT `child_table_child_id_FK_parent_table_child_id`
    FOREIGN KEY (`child_id`)
    REFERENCES `child_table` (`child_id`)
);

CREATE TABLE `child_table` (
  `id` integer UNSIGNED NOT NULL auto_increment,
  `child_id` varchar(50) NOT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY (`child_id`),
  CONSTRAINT `parent_table_child_id_FK_child_table_child_id`
    FOREIGN KEY (`child_id`)
    REFERENCES `parent_table` (`child_id`)
);

I could just remove the constraint manually or modify my accessors to return/set a single entity in the collection (using a one-to-many) but it seems like there should built in way to handle this.

Also im using Symfony 1.4.4 (pear installtion ATM) - in case its an sfDoctrinePlugin issue and not necessarily Doctrine itself.

回答1:

sfDoctrinePlugin configures doctrine model builder in way that creates opposite side relations automatically. In PHP 5.2 you can't do anything with it.

As of PHP 5.3, where ReflectionProperty::setAccessible() method is available, you could manipulate protected/private properties of Doctrine_Relation_Parser instance which can be obtained by $this->getTable()->getRelationParser(). So you have to override BaseSomething::setUp() method and drop unneeded relations manually using php's reflection API. You have to use reflection API because Doctrine_Relation_Parser doesn't provide a method which allows to drop relations at will.



回答2:

I've solved this by setting the doctrine state for the opposite "null object" BEFORE we save the record:

/* @var $address Address */
$address = $form->getObject();

// the null object is here the "address position", let's change it's state
$address->getAddressPosition()->state(Doctrine_Record::STATE_CLEAN);

// now we can save the address and doctrine won't insert the null object
$address = $form->save();