sfValidatorDoctrineUnique失败,因为我有一个自定义setField()

时间:2012-11-26 19:27:59

标签: php symfony-1.4 validation

用户可以发布音乐链接,因为音乐提供商可以变化(Youtube,Deezer,Soundcloud等等),我有一个自定义验证器和自定义 setLink()。 在我的数据库中,链接是视频的ID(youtube示例:CWMYxYoaRBQ)

但结果是我的sfValidatorDoctrineUnique不再起作用了。

我的验证员:

<?php

class videoValidator extends sfValidatorUrl
{
  protected function configure($options = array(), $messages = array())
  {
    parent::configure($options, $messages);
    $this->setMessage('invalid', 'Error message.');
  }

  protected function doClean($url)
  {
    $videoProvider = new videoProvider($url);
    if (false === $videoProvider->isValid())
    {
      throw new sfValidatorError($this, 'invalid', array('value' => $url));
    }

    return $url;
  }
}

?>

我的videoProvider类:

class videoProvider
{
  private $url;
  private $providers = array('youtube','deezer','soundcloud');
  private $youtubePattern = '%^# 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';
  private $deezerPattern = '/\d+/';
  private $soundcloudPattern = '[\w-]+/[\w-]+$';

  public function __construct($url)
  {
    $this->url = $url;
  }

  /**
   * @return true / false
   */
  private function checkYoutube()
  {
    return preg_match($this->youtubePattern, $this->url) ? true : false;
  }

  /**
   * @return true / false
   */
  private function checkDeezer()
  {
     // A Deezer URL has this format : http://www.deezer.com/track/61340079

     return preg_match($this->deezerPattern, $this->url) ? true : false;
  }

  /**
   * @return true / false
   */
  private function checkSoundcloud()
  {
     // A Soundcloud URL has this format : http://soundcloud.com/[A-Z Artist]/[A-Z Title]

     return preg_match($this->soundcloudPattern, $this->url) ? true : false;
  }

  /**
   * @return true / false
   */
  public function isValid()
  {
    // check all video provider as you do in your validator
    // so it will return true if it find one, otherwise false

    foreach ($this->providers as $provider)
    {
      $function = 'check'.ucfirst($provider);

      if (true === $this->$function())
      {
        return true;
      }
    }

    return false;
  }

  /**
   * @return string
   */
  public function getId()
  {
    if ($this->checkYoutube() && preg_match($this->youtubePattern, $this->url, $matches))
    {
      return $matches[1];
    }

    if ($this->checkDeezer() && preg_match($this->deezerPattern, $this->url, $matches))
    {
      return $matches[1];
    }

    if ($this->checkSoundcloud() && preg_match($this->deezerPattern, $this->url, $matches))
    {
      return $matches[1];
    }
  }

  /**
   * @return string
   */
  public function getProvider()
  {
    if ($this->checkYoutube())
    {
      return 'youtube';
    }

    if ($this->checkDeezer())
    {
      return 'deezer';
    }

    if ($this->checkSoundcloud())
    {
      return 'soundcloud';
    }
  }
}

我的歌班:

class Song extends BaseSong
{
  public function setLink($value)
  {
    // only perform this tweak if the value is a http link
    if (preg_match('/^http/i', $value))
    {
      $videoProvider = new videoProvider($value);

      // define url id
      parent::_set('link', $videoProvider->getId());

      // define type id
      $provider = $videoProvider->getProvider();
      $type     = Doctrine_Core::getTable('Type')->findOneByName($provider);

      parent::_set('type_id', $type->getId());
     }
  }
}

我认为sfValidatorDoctrineUnique尝试将完整的URL(表单字段)与视频ID(数据库字段)进行比较。我该如何解决?

1 个答案:

答案 0 :(得分:0)

我认为我找到了一个经过测试和运作的解决方案。

class videoValidator extends sfValidatorUrl
{
  protected function configure($options = array(), $messages = array())
  {
    parent::configure($options, $messages);
    $this->setMessage('invalid', 'Le lien n\'est pas valide. Veuillez entrer un lien Youtube, Deezer ou Soundcloud.');
  }

  protected function doClean($url)
  {
    $videoProvider = new videoProvider($url);
    if (false === $videoProvider->isValid())
    {
      throw new sfValidatorError($this, 'invalid', array('value' => $url));
    }

    $unique = Doctrine_Core::getTable('Song')->findOneByLink($videoProvider->getId());
    if (!empty($unique))
    {
      return $videoProvider->getId();
    }
    return $url;
  }
}

我返回视频的ID,视频已存在于数据库中。然后,我认为sfValidatorDoctrineUnique能够执行它的测试。

这对你来说是否合乎逻辑?