Php Symfony 1.4条件验证

Php Symfony 1.4条件验证,php,symfony1,symfony-1.4,Php,Symfony1,Symfony 1.4,我有一个从sfGuardRegisterForm 我有以下字段: $this->useFields( array('first_name', 'last_name', 'email_address', 'country', 'language', 'current_password', 'new_password', 'password_ag

我有一个从
sfGuardRegisterForm

我有以下字段:

$this->useFields(
    array('first_name', 
          'last_name',
          'email_address',
          'country',
          'language',
          'current_password',
          'new_password',
          'password_again',
    )
);
必填字段为:

电子邮件地址
国家
语言

条件是:

  • 如果
    电子邮件地址
    与当前
    电子邮件地址不相等
    然后检查它是否是唯一的,然后保存它
  • 如果
    当前密码
    是用户的实际密码,则验证
    新密码
    密码
    是否相等,并验证
    新密码
    不等于用户的实际密码
  • 我只是不知道如何实现这一点

    编辑

    感谢1ed您的示例很有效,但问题是我加载了用户配置文件,并用实际登录的用户填写了字段:
    “名字”、“姓氏”、“电子邮件地址”、“国家”、“语言”
    ,因此
    电子邮件地址字段将显示电子邮件地址:

    //...
    $this->widgetSchema['email_address']->setDefault($this->_user->getEmailAddress());
    //...
    
    如果用户不更改电子邮件,它将始终显示以下消息:

    已存在具有相同“电子邮件地址”的对象

    我只想跳过这个

    此外,此
    $this->getObject()->checkPassword()
    不起作用,请始终显示此消息:

    当前密码不正确

    我使用:

    $this->_user=sfContext::getInstance()->getUser()->getGuardUser()

    获取实际用户配置文件

    EDIT2

    再次感谢1ed

    这是非常奇怪的,我越来越沮丧,这就是情况

  • 我对此有一个“变通方法”,但它不符合标准,我可以使用
    sfContext::getInstance()->getUser()->getGuardUser()使其工作并且它将是更多不必要的代码
  • 如果我使用
    new ProfileForm($user)
    自动填充所有字段,这很好但是我不能
    setDefault()
    我不能设置
    null
    empty
    任何字段,所以我不能使用
    doUpdateObject()
    ,因为这个函数只在当前数据更新时起作用,我还测试了重写
    bind()
    save()
    等,但没有结果

  • 我将尝试以系统的方式解释这一点,而不是给你一大块代码。。。。 所以首先,你想如果(email\u addr!=当前电子邮件)如果是这样,继续做 如果(新通行证!=当前通行证)然后继续确保如果(新通行证==再次新通行证) 在所有这些IFs中,您可以返回真/假或某种标志,或者只返回括号内的//do代码:p


    编辑:将这些if封装在:如果(国家!=NULL和语言!=NULL和电子邮件地址!=NULL)电子邮件地址唯一性:您应该在模式中,在
    sfDoctrineGuardPlugin中设置
    唯一性:true
    ,默认情况下就是这样,因此,在
    basesfguardusterform
    中,您应该已经看到了一个唯一的验证器:
    sfValidatorDoctrineUnique(数组('model'=>'sfguarduster','column'=>array('email_address'))

    当前密码:您应该为此创建回调类型后验证程序

    // in sfGuardRegisterForm::configure()
    
    // these fields can be blank
    $this->getValidator('current_password')->setOption('required', false);
    $this->getValidator('new_password')->setOption('required', false);
    $this->getValidator('password_again')->setOption('required', false);
    
    // check the current password (this validator is not `required` by default)
    $this->mergePostValidator(new sfValidatorCallback(array(
      'callback' => array($this, 'checkPassword'),
    ), array(
      'invalid' => 'Incorrect current password.'
    )));
    
    // add this method to the same form class
    public function checkPassword(sfValidatorBase $validator, array $values, array $arguments)
    {
      // if a new password is given check whether the old one is correct or not and rise an error if not correct
      if(0 != strlen($values['new_password']) && !$this->getObject()->checkPassword($values['current_password']))
      {
        throw new sfValidatorErrorSchema($validator, array(
          'current_password' => new sfValidatorError($validator, 'invalid')
        ));
      }
    
      return $values;
    }
    
    或者,您可以创建一个自定义后验证器,但我认为这不是必需的

    编辑:

    如果您希望像密码字段一样显示空电子邮件地址,请将这些字段添加到表单类中:

    // at form load remove the default value
    protected function updateDefaultsFromObject()
    {
      parent::updateDefaultsFromObject();
    
      if (isset($this['email_address']))
      {
        $this->setDefault('email_address', '');
      }
    }
    
    // before save remove empty email address
    protected function doUpdateObject($values)
    {
      if (isset($values['email_address']) && 0 == strlen($values['email_address']))
      {
        unset($values['email_address']);
      }
    
      parent::doUpdateObject($values);
    }
    

    谢谢,我已经这么做了,我现在面临的问题是检查email\u address!=实际的\u email,并检查email在数据库中是否是唯一的。因此,您需要获取数据库中的每一封电子邮件并将其放入数组中,然后执行foreach()比较它们,然后返回是否正确。对于当前的电子邮件,只需通过数据库选择users USERNAME并通过用户索引,获取当前的电子邮件,并进行比较。这样的逻辑可能会令人困惑,我不经常使用DBs,但如果你在Google上搜索,比如如何在php m中搜索数据库的所有索引ysql/sqlite您应该想出一些办法,我认为验证器不起作用,因为您没有设置底层用户对象;`这不是一个好主意,如果可能的话,请尽量避免使用sfContext。在创建表单的操作中,您应该获取用户对象并将其传递给表单,所有值都将根据用户填写。
    $user=$this->getUser()->getGuardUser();$this->form=new ProfileForm($user);
    setDefault()
    调用不是必需的。有一件事是,
    sfValidatorSchemaCompare
    验证器不是必需的,因为它已经在
    BasesfGuardUserAdminForm
    中,所以我删除了它。你说得对,我已经更改了
    $this->form=newprofileform($this->getUser()->getGuardUser())
    而且它可以工作,我正在考虑不显示电子邮件地址并将其放入
    required=false
    我刚刚修复了“0”的
    chackPassword()
    输入,请更新您的代码,并对此表示歉意。密码字段是一个特殊字段,因为如果您提供空密码,则不会发生任何情况,但如果您使用空电子邮件发布表单,则前一封电子邮件将从数据库中删除。如果您确实希望显示空电子邮件字段并仅在电子邮件发生更改时修改数据库看看我的最新答案。