让我们考虑以下简单的模式(在 Doctrine 中,但也欢迎 Propel 用户):
User:
columns:
name: string
Article:
columns:
user_id: integer
content: string
relations:
User:
local: user_id
foreign: id
现在,如果您为文章模型创建路径并通过
doctrine:generate-module-for-route frontend @article_route
生成模块,您将获得一个管理所有文章的 CRUD 应用程序。但在前端,您通常需要管理与登录用户相关的对象,因此您必须手动获取用户的 id,将 id 传递给模型并编写一堆方法来检索与该用户相关的对象,例如示例:
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();
}
}
及型号:
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();
}
}
这是微不足道的事情,但您必须为每个新关系手动编写此代码。我是否缺少某种利用教义关系的方法?不管怎样,你会怎么做呢?谢谢你。
我相信您应该能够使用自定义路由类来做到这一点。我从来没有这样做过,但是 More with Symfony 书中有一个教程:Advanced Routing。我的猜测是它应该看起来像这样:
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;
}
}
然后,您需要在
routing.yml
中设置路由类才能使用 objectWithUserRoute
。我还没有测试过,但我认为这是解决问题的最佳方法。