Taking advantage of Doctrine relations in frontend applications in Symfony
Let's consider the following simple schema (in Doctrine, but Propel users are welcome too):
开发者_开发问答User:
columns:
name: string
Article:
columns:
user_id: integer
content: string
relations:
User:
local: user_id
foreign: id
Now, if you create a route for Article model and generate a module via doctrine:generate-module-for-route frontend @article_route
you get a CRUD application that manages all the articles. But in frontend you would normally want to manage objects related to signed-in User, so you have to manually get the id of the User, pass id to the model and write a bunch of methods that would retrieve objects related to this User, for example:
public function executeIndex(sfWebRequest $request)
{
$this->articles = Doctrine::getTable('Articles')
->getUserArticles(this->getUser());
}
public function executeShow(sfWebRequest $request)
{
$this->article = $this->getRoute()->getObject();
if (!$this->article->belongsToUser($this->getUser()))
{
$this->redirect404();
}
}
and model:
class ArticleTable extends Doctrine_Table
{
public function getUserArticles(sfUser $user)
{
$q = $this->createQuery('a')
->where('a.user_id = ?', $user->getId());
return $q->execute();
}
}
class Article extends BaseArticle
{
public function belongsToUser(sfUser $user)
{
return $this->getUserId() == $user->getId();
}
}
This is trivial stuff and yet you have to manually write this code for each new relation. Am I missing some kind of way to take advantage of Doctrine relations? Anyways, how would you do it? Thank you.
I believe you should be able to do this with a custom routing class. I have never done this, but there is a tutorial in the More with Symfony book: Advanced Routing. My guess is that it should look something like this:
class objectWithUserRoute extends sfDoctrineRoute
{
public function matchesUrl($url, $context = array())
{
if (false === $parameters = parent::matchesUrl($url, $context))
{
return false;
}
$parameters['user_id'] = sfContext::getInstance()->getUser()->getId();
return array_merge(array('user_id' => sfContext::getInstance()->getUser()->getId()), $parameters);
}
protected function getRealVariables()
{
return array_merge(array('user_id'), parent::getRealVariables());
}
protected function doConvertObjectToArray($object)
{
$parameters = parent::doConvertObjectToArray($object);
unset($parameters['user_id']);
return $parameters;
}
}
You would then need to set the routing class in routing.yml
to use objectWithUserRoute
. I haven't tested this, but I think it is the best way to go about solving the problem.
精彩评论