【问题标题】:Ardent model does not validate after save保存后 Ardent 模型不验证
【发布时间】:2014-01-22 12:33:51
【问题描述】:

我在以一对多关系插入对象时遇到问题。这是我的代码:

/** 
 * Migrations 
 **/
// Create user__groups table
Schema::create('user__groups', function (Blueprint $table) {
    $table->increments('id');
    $table->string('name', 50);
});

// Create users table
Schema::create('users', function (Blueprint $table) {
    $table->increments('id');
    $table->timestamps(); // created_at, updated_at DATETIME

    $table->string('username', 40);
    $table->string('password', 20);

    $table->integer('user_group_id')->unsigned();
    $table->foreign('user_group_id')->references('id')->on('user__groups');
});

/** 
 * Models 
 **/
class User extends Ardent {
    protected $table = 'users';
    public $timestamps = true;
    protected $hidden = array('password');
    public $autoPurgeRedundantAttributes = true;
    protected $fillable = array(*);

    // Validation rules for fields in this entity
    public static $rules = array(
        'username'              => 'required|unique:users',
        'password'              => 'required|alpha_dash|min:6|max:20|confirmed',
        'password_confirmation' => 'required|alpha_dash|min:6|max:20'
    );

    // Relations
    public static $relationsData = array(
        'userGroup' => array(self::BELONGS_TO, 'UserGroup')
    );

    // Model mock data for test purposes
    public static $factory = array(
        'username'              => 'string',
        'password'              => '123123',
        'password_confirmation' => '123123',
        'user_group_id'         => 'factory|UserGroup'
    );
}

class UserGroup extends Ardent {
    protected $table = 'user__groups';
    public $timestamps = false;
    public $autoPurgeRedundantAttributes = true;
    protected $fillable = array('*');

    // Validation rules for fields in this entity
    public static $rules = array(
        'name' => 'required|unique:user__groups|alpha_dash'
    );

    // Relations
    public static $relationsData = array(
        'users' => array(self::HAS_MANY, 'User')
    );

    // Model mock data for test purposes
    public static $factory = array(
        'name' => 'string'
    );
}

PHP单元测试

public function test_assignUserToGroup() {
    /* @var $user User */
    $user = FactoryMuff::instance('User');

    // Test assigning user to group 1
    $group1 = FactoryMuff::create('UserGroup');
    $this->assertTrue($group1->users()->save($user) !== false, "User model did not save!".$user->errors());

    // Test assigning user to group 2 (this fails)
    $group2 = FactoryMuff::create('UserGroup');
    $this->assertTrue($group2->users()->save($user) !== false, "User model did not update!".$user->errors()); // <-- The save method always returns false
}

测试运行将反映用户对象不会被更新。为什么?我究竟做错了什么?我希望// Test assigning user to group 2 下面的代码对现有对象执行更新,但DB::getQueryLog() 只显示选择和插入。这真的很烦人。

-- 编辑--

实际上阻止我的是验证。我在上面的测试中添加了对 Model->errors() 的调用。这指出保存后,包含在 User 对象中的用户名不再是唯一的 - 因为它发现自己在数据库中(WTF?)。它还说 password_confirmation 字段被标记为必需,但为空 - 因为它在上次保存时被删除。

这只是愚蠢的,我不知道是 Eloquent、Ardent 还是我的错。如果它在保存前有效,那么它在保存后也应该有效 - 对吧?我将更改问题的标题以反映问题的真正原因。

【问题讨论】:

    标签: php laravel eloquent ardent


    【解决方案1】:

    我发现这个问题的唯一解决方案是不使用“唯一”和“确认”验证规则。我只会在提交表单时处理这些验证。

    我实际上对这个解决方案不是很满意,所以我想出了一个稍微不同的方法:

    // Validation rules for fields in this entity
    public static $rules = array(
        'username'              => 'required|alpha_dash|min:4|max:40',
        'password'              => 'required|alpha_dash|min:6|max:20',
        'password_confirmation' => ''
    );
    
    // Extra validation for user creation
    public static $onCreateRules = array(
        'username'              => 'required|alpha_dash|min:4|max:40|unique:users',
        'password'              => 'required|alpha_dash|min:6|max:20|confirmed'
    );
    

    这里我将验证规则拆分为两个静态数组,而不是直接从 Ardent 扩展类,而是从自定义类扩展它:

    use LaravelBook\Ardent\Ardent;
    class ModelBase extends Ardent {
        public function save(array $rules = array(), array $customMessages = array(), array $options = array(), Closure $beforeSave = null, Closure $afterSave = null) {
            if (!$this->exists && isset(static::$onCreateRules)) {
                $rules = array_merge($rules, static::$onCreateRules);
            }
            return parent::save($rules, $customMessages, $options, $beforeSave, $afterSave);
        }
    }
    

    这会覆盖 Ardent 保存方法并仅在此实体以前不存在时应用 $onCreateRules 进行验证。 :-)

    我仍然认为 Eloquents 验证引擎坏了。对 validate() 的调用应该只验证一个脏字段。其次,它应该自动从唯一检查中排除当前实体 ID。因此,无论如何,我在这里提出的解决方案是一种解决方法。

    我希望 Laravel 的人能看到这一点,并在他们的心中找到它来解决它。

    【讨论】:

    猜你喜欢
    • 2014-01-27
    • 1970-01-01
    • 2014-02-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-09-25
    相关资源
    最近更新 更多