开发者

Symfony: How to use same action for CREATE and UPDATE?

Lets say I have a website where I create articles and I also edit existing articles. The template page for creating new articles is the same as the template page for editing existing articles. The only difference is that the form for editing has default/existing values added to it already.

I'm trying to figure out how to use the same action for both routes. Here are my routes:

article_new
  url: /article/new/
  class: sfDoctrineRoute
  options:
    model: MyArticle
    type: object
  param:
    module: article
    action: edit

article_edit
  url: /article/edit/:id/
  class: sfDoctrineRoute
  options:
    model: MyArticle
    type: object
  param:
    module: article
    action: edit
  requirements:
    id: /d+

So both articles point to the following action:

public function executeEdit(sfWebRequest $request)
{
  $article = $this->getRoute()->getObject();

  $this->form = new MyForm( $article );

  // Binding and validation stuff here
  // .....
}

This works great when you want to edit an article. getRoute()->getObject() automatically get the correct article for you from the id slug and passes those values as defaults into the form. Perfect.

But with the article_new route, it doesn't work so well. The getRoute()->getObject() returns the first article in my database table, even though I didn't feed the url any type of id parameter. So the information from the first article in the database gets passed as default values into the form. I obviously don't want this.

I also tried removing the class: sfDoctrineRoute stuff from the article_new route but then getRoute()->getObject() fails because it's no longer ansfRoute` object that I'm working with.

What is the best approach here? I'd like to do everything in one action just to save programming time and future maintenance time.

Also I found that one solution is that I can check to see if $request->ge开发者_JAVA百科tParameter('id') is null and if so, then $article = array(), else the article is retrieved using the getRoute()->getObject(). That seems to work fine but I figured there might be less hacky solution.


The solution is in the direction you pointed out yourself. It's not hacking at all. I'd leave the _new as normal route and as object route only _edit. Like

article_new:
  url: /article/new/
  param:
    module: article
    action: edit

article_edit:
  url: /article/edit/:id/
  class: sfDoctrineRoute
  options:
    model: MyArticle
    type: object
  param:
    module: article
    action: edit
  requirements:
    id: /d+

In the action you only need to check the type of route, like

public function executeEdit(sfWebRequest $request)
{
  if($this->getRoute() instanceof sfRequestRoute){ // new action
    $article = new MyArticle();
  } else {
      $article = $this->getRoute()->getObject();
  }

  $this->form = new MyForm( $article );

  // Binding and validation stuff here
  // .....
}

Testing if $request->hasParameter('id') is also a valid approach. In fact, the sfFormDoctrine does the same in order to determine if the form is in a edit mode ou insert mode.


If possible I'm using the symfony crud approach:

Routing:

article:
  class: sfDoctrineRouteCollection
  options:
    model:                article
    module:               article
    prefix_path:          /article
    column:               id
    with_wildcard_routes: true

actions.class.php:

  public function executeEdit(sfWebRequest $request)
  {
    $this->forward404Unless($article = Doctrine_Core::getTable('Article')->find(array($request->getParameter('id'))), sprintf('Object Gutschein does not exist (%s).', $request->getParameter('id')));
    $this->form = new ArticleForm($gutschein);
  }

  public function executeUpdate(sfWebRequest $request)
  {
    $this->forward404Unless($request->isMethod(sfRequest::POST) || $request->isMethod(sfRequest::PUT));
    $this->forward404Unless($article = Doctrine_Core::getTable('Article')->find(array($request->getParameter('id'))), sprintf('Object Article does not exist (%s).', $request->getParameter('id')));
    $this->form = new ArticleForm($gutschein);

    $this->processForm($request, $this->form);

    $this->setTemplate('edit');
  }

  protected function processForm(sfWebRequest $request, sfForm $form)
  {
    $form->bind($request->getParameter($form->getName()), $request->getFiles($form->getName()));
    if ($form->isValid())
    {
      $gutschein = $form->save();

      $this->redirect('article/edit?id='.$gutschein->getId());
    }
  }

You can do all your form handling in processForm(..).


$request->getParameter('id') doesnt seem hacky at all, but you could also use an if statement and

$this->getRoute()->matchesParameters()

or

$this->getroute()->matchesUrl()

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜