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 既没有警告我也没有报告任何错误。
我无法使用 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 既没有警告我也没有报告任何错误。