我在以一对多关系插入对象时遇到问题。这是我的代码:
/**
* 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'
);
}
PHPUnit测试
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
}
testrun将反映用户对象不会更新。为什么?我究竟做错了什么?我希望// Test assigning user to group 2
下面的代码可以对现有对象执行更新,而DB::getQueryLog()
只显示选择和插入。这真令人讨厌。
- 编辑 -
实际上验证是阻止了我。我在上面的测试中添加了对Model-&gt; errors()的调用。这指出在保存之后,User对象中包含的用户名不再是唯一的 - 因为它发现自己在数据库中(WTF?)。它还说password_confirmation字段标记为必需,但是为空 - 因为它在上次保存时被删除。
这只是愚蠢的,我不知道是不是Eloquent,Ardent或我在这里有过错。如果它在保存之前有效,它在保存后也应该有效 - 对吗?我将更改问题的标题以反映问题的真正原因。
答案 0 :(得分:2)
我发现此问题的唯一解决方案是不使用“唯一”和“确认”验证规则。我将仅在表单提交时处理这些验证。
我对这个解决方案实际上并不满意,所以我想出了一个稍微不同的方法:
// 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 save方法并仅在此实体以前不存在的情况下应用$ onCreateRules进行验证。 : - )
我仍然认为Eloquents验证引擎已被破坏。对validate()的调用应仅验证脏字段。其次,它应该自动从唯一检查中排除当前实体ID。因此,无论如何,我在这里提出的解决方案是一种解决方法。
我希望Laravel的某个人能够看到这一点,并在心中找到解决它的方法。