PHP Doctrine 2 - 如何使用 Cascade 选项自动保存一对多关系

PHP Doctrine 2 - How to save One To Many relationship automatically with Cascade options

我无法使用 Cascade 保存 Doctrine 2 中的关系。 在我的应用中,Computers 有很多 Action,一个 Action 可以属于很多不同的 Computer。但我还有一个额外的属性 Active,用于指定哪些操作将处于活动状态 per Computer.

我的表格如下:

CREATE TABLE IF NOT EXISTS computers (
      id INT NOT NULL PRIMARY KEY AUTO_INCREMENT,
      name VARCHAR(50) NOT NULL UNIQUE,
      os VARCHAR(30) NOT NULL,
      date_creation TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
      date_modification TIMESTAMP,
      online BOOLEAN NOT NULL DEFAULT FALSE,
      id_user_creation INT,
      id_user_modification INT DEFAULT NULL,

      CONSTRAINT fk_users_computers_creation FOREIGN KEY (id_user_creation) REFERENCES users(id),
      CONSTRAINT fk_users_computers_modification FOREIGN KEY (id_user_modification) REFERENCES users(id)
);

CREATE TABLE IF NOT EXISTS actions (
      id INT NOT NULL PRIMARY KEY AUTO_INCREMENT,
      name VARCHAR(50) NOT NULL UNIQUE,
      description TEXT,
      date_creation TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
      date_modification TIMESTAMP,
      id_user_creation INT NOT NULL,
      id_user_modification INT DEFAULT NULL,

      CONSTRAINT fk_users_actions_creation FOREIGN KEY (id_user_creation) REFERENCES users(id),
      CONSTRAINT fk_users_actions_modification FOREIGN KEY (id_user_modification) REFERENCES users(id)
);

CREATE TABLE IF NOT EXISTS computers_actions (
      id INT NOT NULL PRIMARY KEY AUTO_INCREMENT,
      id_computer INT NOT NULL,
      id_action INT NOT NULL,
      active BOOLEAN NOT NULL DEFAULT FALSE,

      CONSTRAINT fk_computers FOREIGN KEY (id_computer) REFERENCES computers(id),
      CONSTRAINT fk_actions FOREIGN KEY (id_action) REFERENCES actions(id)
);

上面的代码只是我的数据库脚本的一部分,受我当前问题的影响。 我的实体如下:

计算机实体:

/**
 * @var ArrayCollection
 * @OneToMany(targetEntity="ComputerAction", mappedBy="computer", cascade={"persist"})
 */
private $actions;

public function __construct()
{
    $this->actions = new ArrayCollection();
}

动作实体:

/**
 * @var ArrayCollection
 * @OneToMany(targetEntity="ComputerAction", mappedBy="action", cascade={"persist"})
 */
private $computers;

public function __construct()
{
    $this->computers = new ArrayCollection();
}

关系,ComputerAction 实体。 我需要这个关系的属性,这就是我没有使用 ManyToMany 注释的原因。 在这种情况下,一台 Computer 有很多 ComputerAction,而一个 ComputerAction 只有一台 Computer。动作也是如此。

/**
 * @var Computer
 * @ManyToOne(targetEntity="Computer", inversedBy="actions", cascade={"persist"})
 * @JoinColumn(name="id_computer", referencedColumnName="id")
 */
private $computer;

/**
 * @var Action
 * @ManyToOne(targetEntity="Action", inversedBy="computers", cascade={"persist"})
 * @JoinColumn(name="id_action", referencedColumnName="id")
 */
private $action;

/**
 * @var boolean
 * @Column(type="boolean")
 */
private $active;

这些属性有自己的 getter 和 setter,正如您所注意到的,OneToMany 具有 Doctrine ArrayCollection 类型。

在我的计算机中添加操作是在 ComputerController 的添加操作中完成的,如下所示:

// ComputerController, action add

$computer->setName($post['name']);
$computer->setOs($post['os']);
$computer->setOnline(false);
$computer->setUserOwner($this->getUserService()->find($this->retrieveUser()['id']));

foreach($post['action'] as $id_action) {
    $relation = new ComputerAction();
    $relation->setAction($this->getActionService()->find($id_action));
    $relation->setComputer($computer);
    $computer->setActions($relation);
}

if($computer = $this->getComputerService()->save($computer)) {
    $this->setMessage(sprintf('Computer [%s] added successfully!', $computer->getName()), MessageSkin::SUCCESS);
} else {
    $this->setMessage('The Computer could not be added. Try again later.', MessageSkin::DANGER);
}

在“计算机添加”视图中,我有一个 Select 多个带有操作 ID 的计算机。我获得了这些 ID,并在一个循环中创建了一个新的 ComputerAction,将 $action 属性设置为包含该 ID 的操作实体。然后我在 $computer 属性中设置当前计算机,最后,我将这个 ComputerAction 实例添加到 Computer Entity 中的 $actions ArrayCollection。

问题是:为什么不保存 ComputerAction 实体?

我用级联选项尝试了很多不同的方法,但都没有成功。请帮忙!

谢谢!

西佩

你应该记住,在任何关系中,Doctrine 在关系中都有主要实体和映射实体(从属实体)。它是关于 OneToOne、OneToMany、ManyToMany 关系和其他关系。无论你写什么,你都不能从从属实体中保存主要实体。

这也许能帮到你。

我通过将 $active 属性设置为 "false" 解决了我的问题,因为它在数据库中不能为空。我真的不知道为什么会这样,因为它在数据库中是 DEFAULT FALSE。 Doctrine 既没有警告我也没有报告任何错误。