【问题标题】:How to convert a value before saving the form?如何在保存表单之前转换值?
【发布时间】:2012-09-28 08:56:49
【问题描述】:

我想保存表单之前转换一个值。 我不知道在哪里添加代码,因为唯一的方法是form->save()

你能帮帮我吗?

编辑:

  if ($this->form->isValid())
  {
    $url = $this->form->getObject()->getLink();
    parse_str(parse_url($url, PHP_URL_QUERY), $my_array_of_vars);
    $this->form->getObject()->setLink($my_array_of_vars['v']); 

    $song = $this->form->save();

    $this->getUser()->setFlash('notice', 'Thank you, the song has been added');

    $this->redirect('@homepage');
  }

【问题讨论】:

  • 您是否必须在不同的地方使用此表单(即:在后端、在个人资料用户中、在视频编辑中等...)还是只一次
  • 我只会在我的主模块中使用它。

标签: php symfony-1.4


【解决方案1】:

@pankar 的答案几乎很好。但是$this->form->save() 会覆盖setLink

首先,定义检索 youtube id 的函数,如在新的 tools 类中定义的 herelib/myTools.class.php

<?php

class myTools
{
  /**
   * Get youtube video ID from URL
   *
   * @see https://stackoverflow.com/a/6556662/569101
   * @param string $url
   * @return string Youtube video id or FALSE if none found. 
   */
  public static function youtube_id_from_url($url)
  {
    $pattern = 
      '%^# Match any youtube URL
      (?:https?://)?  # Optional scheme. Either http or https
      (?:www\.)?      # Optional www subdomain
      (?:             # Group host alternatives
        youtu\.be/    # Either youtu.be,
      | youtube\.com  # or youtube.com
        (?:           # Group path alternatives
          /embed/     # Either /embed/
        | /v/         # or /v/
        | /watch\?v=  # or /watch\?v=
        )             # End path alternatives.
      )               # End host alternatives.
      ([\w-]{10,12})  # Allow 10-12 for 11 char youtube id.
      $%x'
      ;
    $result = preg_match($pattern, $url, $matches);
    if (false !== $result)
    {
      return $matches[1];
    }
    return false;
  }
}

然后,用这个更新你的操作:

if ($this->form->isValid())
{
  // save the form
  $song = $this->form->save();

  // update saved value
  $youtube_id = myTools::youtube_id_from_url($song->getLink());
  $song->setLink($youtube_id);
  $song->save();

  $this->getUser()->setFlash('notice', 'Thank you, the song has been added');

  $this->redirect('@homepage');
}

顺便说一句,如果您在只在一个地方使用您的表单,这种方法是可以的。由于更新是在操作中执行的,而不是在表单类中。否则,正如@glerendegui 所说,您将不得不在表单类中执行此操作。但我宁愿在doUpdateObject 而不是doSave 中这样做。由于代码说:

  /**
   * Updates the values of the object with the cleaned up values.
   *
   * If you want to add some logic before updating or update other associated
   * objects, this is the method to override.
   *
   * @param array $values An array of values
   */
  abstract protected function doUpdateObject($values);

所以我会这样做,在你的表单中 (lib/form/doctrine/yourForm.class.php):

class yourForm extends BaseYourForm
{
  public function configure()
  {
  }

  protected function doUpdateObject($values)
  {
    $youtube_id = myTools::youtube_id_from_url($values['link']);
    $this->getObject()->setLink($youtube_id);

    return parent::doUpdateObject($values);
  }
}

【讨论】:

  • 因为成功后用户被重定向到@homepage,如果setLink 方法被计算值覆盖没有区别。毕竟,该字段所需的输入是计算值而不是提交的值!不过,如果表单再次呈现给用户,您就有了意义。
  • +1 遇到麻烦以提供完整的答案,捕捉需要集中/通用方法来提取 youtube videoIds
  • 谢谢,我会尽快测试。我应该创建一个自定义验证器来检查我的链接是否是 youtube 链接,不是吗?
【解决方案2】:

在您的execute* 操作中绑定后表单:

在 OP 输入后编辑

  if ($this->form->isValid())
  {
    $url = $this->form->getObject()->getLink(); // get the url

    $videoId=parse_url($url, PHP_URL_QUERY); // extract the videoid portion

    $this->form->getObject()->setLink($videoId); // update object with the new value

    $song = $this->form->save(); // save the object

    $this->getUser()->setFlash('notice', 'Thank you, the song has been added');

    $this->redirect('@homepage');
  }

【讨论】:

  • 太好了,我发现很多主题都解释了如何覆盖保存方法。我更喜欢那个解决方案。
  • 我测试过,但它不起作用。我编辑我的帖子向您展示我的代码。
  • 我在“歌曲”上得到了这个未知的记录属性/相关组件“值”
  • ehm...getValue()/setValue() 只是一个例子。您应该使用模型中所需字段的名称,即如果该字段名为url,则您应该使用getUrl()setUrl()。希望这是有道理的
  • 哦.. 对不起,我没有这样理解。我试图在参数中添加我的字段:getValue('link')。但它仍然不起作用。我的代码更新了。
【解决方案3】:

你应该在表单本身中添加这个行为,而不是在动作中(这是关于 symfony 表单的想法)。因此,覆盖表单的doSave($con = null),类似于:

class yourForm extends whateverForm {

 public function configure() { ... }
 public function doSave($con = null) {
   // process form values
   return parent::doSave();
 }
}

【讨论】:

  • 如果我选择这种方法,我必须在哪里写这个代码?与其他解决方案相比,这是最佳做法吗?
  • 这是您的表单类代码。例如,在您的操作中,如果您这样做:$this->form = new xxxForm(...),那么,编辑 xxxForm.class(可能在 lib/form/doctrine/xxxForm.class.php 中)。您唯一应该添加的是 doSave() 部分。
  • 关于它是否是最佳实践,这取决于你想做什么。 Symfony 表单理论认为表单应该是独立于动作的,所以这样它们就可以在任何时候在你的代码的任何地方使用(甚至是其他项目,在动作自定义代码或生成的模块中)。这就是代码重用的想法。如果你要做的这个价值改变是形式的一部分,那么应该是他行为的一部分。考虑在一些生成的模块中使用你的。
猜你喜欢
  • 1970-01-01
  • 2012-02-14
  • 1970-01-01
  • 2021-12-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-01-15
  • 1970-01-01
相关资源
最近更新 更多