我是 Doctrine 的忠实拥护者,但过去主要将其用于访问我的数据库的更简单和更 OO 的方式。尽管最近我发现自己想对模型做更多的事情,以使我的代码更具语义或逻辑性,并且易于使用。
例如,让我们使用堆栈溢出问题和相应的答案。一个问题可以包含一个或多个答案。在过去,我可能会做这样的事情(下面的所有内容都是 sudo 代码 btw):
/*
* METHOD ONE: Note that this is IMO not that semantic or OO
*/
Class QuestionController{
//.......
public function addAnswer($whichQuestionId, $answerTitle, $answerCopy, $answerAuthorId)
{
//Look, I'm validating stuff here in my controller action
if(!strlen($answerTitle) || !strlen($answerCopy) || !strlen($answerAuthorId))
throw new \Exception('Invalid answer stuff!!');
//Notice here I'm actually doing some DB quering with
$author = $entityManager->find('\StackOverflow\User', $answerAuthorId);
if($author->getIsBanned())
throw new \Exception('This is user can not post answer, they are banned!');
//OK, things are valid, now we're going to load then question and create a new answer
$question = $entityManager->find('\StackOverflow\Question', $whichQuestionId)
$answer = new \StackOverflow\Answer;
$answer->setAuthor($author);
$answer->setTitle($answerTitle);
$answer->setContent($answerCopy);
$question->addAnswer($answer);
//Let's pretend we persisted everything correctly...
//Done!
}
//.......
}
Class \StackOverflow\Answer{
//Normal auto generated stuff here
}
Class \StackOverflow\Qusetion{
//Normal auto generated stuff here
}
好的,所以请注意,我在控制器操作中进行了所有验证,效果很好,但是如果我想在不同的控制器中添加一个问题的答案,那么这并不是很枯燥。我可以将此验证逻辑放在某种“助手”中,但这似乎也不是特别面向对象。
我宁愿做这样的事情(虽然不完全好,但希望你明白)
/*
* METHOD TWO: Hopefully a bit more OO...
*/
Class QuestionController{
public function addAnswer($whichQuestionId, $answerTitle, $answerCopy, $answerAuthorId)
{
$result = new \stdObject();
try{
$question = $entityManager->find('\StackOverflow\Question', $whichQuestionId);
$answer = new \StackOverflow\Answer;
$answer->setAuthor($author);
$answer->setTitle($answerTitle);
$answer->setContent($answerCopy);
//THIS IS NEW!
$answer->validate();
//note that perhaps to take this a step futher, in the \StackOverflow\Question class
//I might actually call the validate function, so it's a bit more transaparent
$question->addAnswer($answer);
//Let's pretend we persisted everything correctly...
//Done!
$result->success = true;
$result->message = 'New answer added!';
}
catch(Exception $e)
{
$result->success = false;
$result->message = $e->getMessage();
}
return json_encode($result);
}
}
Class \StackOverflow\Answer{
//ALL NORMAL AUTO GENERATED GETTERS/SETTERS/ETC HERE
//CUSTOM FUNCTION - perhaps called by one of the LifeCycle callback things that Doctrine has?
public function validate()
{
//Look, I'm validating stuff here in my controller action
if(!strlen($this->getTitle()) || !strlen($this->getContent()) || !strlen($this->getAuthor()))
throw new \Exception('Invalid answer stuff!!');
//Notice here I'm actually doing some DB quering INSIDE of another model
$author = $entityManager->find('\StackOverflow\User', $answerAuthorId);
if($author->getIsBanned())
throw new \Exception('This is user can not post answer, they are banned!');
}
}
Class \StackOverflow\Question{
//Normal auto generated stuff here
}
所以我想这可能会好一点,这是用 Doctrine 做事的正确方法吗?是否可以在现有模型中调用其他模型,或者以其他方式使用 Doctrine Entity Manager?有更清洁的方法吗?
这个具体的例子非常简单,但在现实生活中我有一个类似的关系,但“答案”有更复杂和丑陋的验证,需要查找其他表,获取有关“问题”的信息以进行验证等。它还可能会更新我们示例中的“用户”,例如向问题添加新答案可能会更新用户的“问题回答”值。我宁愿这透明地发生,而不必知道它真的发生了。我想简单地添加一个问题的答案,所有验证和级联更改都会在幕后自动发生。