Привет! Использую в своем проекте удобный пакет
SaveRelationsBehavior для работы со связями. Все вроде бы отлично работает, за исключением hasOne.
Суть. Сразу скажу, смысла в коде не ищите. Важна сама логика.
Значит у нас есть UserServie, User, UserProfile.
User:
class User extends \yii\db\ActiveRecord implements IdentityInterface
{
public function behaviors() {
return [
'saveRelations' => [
'class' => SaveRelationsBehavior::class,
'relations' => ['profile'],
],
];
}
public function rules() {
return [
[['profile'], 'safe']
];
}
public static function create($username) {
$model = new static();
$model->username = $username;
retuqn $model;
}
public function getProfile() : ActiveQuery {
return $this->hasOne(UserProfile::class,['user_id' => 'id']);
}
}
UserProfile:
class UserProfile extends \yii\db\ActiveRecord
{
public static function create() {
return new static();
}
}
UserService:
$user = User::create($username);
$user->profile = UserProfile::create();
$this->repository->save($user);
При таком подходе юзер успешно создается и так же успешно создается связь профиля с юзером. Тут все отлично.
НО!! При попытке создать профиль у УЖЕ существующего юзера возникает баг. К примеру:
UserService:
$user = User::findOne(1);
$user->profile = UserProfile::create();
$this->repository->save($user);
Если существует к примеру юзер и у него нету профиля, НО его пытаешься досоздать через реляцию - $user->profile = UserProfile::create(); В таком случае связь тоже создается, но в таблице юзеров у юзера меняется id на 0, а в таблице профиля связь создается, но user_id так же равно 0.
Эту проблему решить можно если в UserProfile передать user_id:
class UserProfile extends \yii\db\ActiveRecord
{
public static function create($userId) {
$model = new static();
$model->user_id = userId;
return $model;
}
}
Однако, я не понимаю тогда почему при создании юзера с профилем связь отлично проставляется, а при попытке добавить у существующего юзера профиль происходит такой баг. С чем это связано?
Если же поменять реляцию на hasMany:
public function getProfile() : ActiveQuery {
return $this->hasMany(UserProfile::class,['user_id' => 'id']);
}
а в UserService поменять так, при этом Не передавать в UserProfile $user_id ($model->user_id = userId):
$user = User::findOne(1);
$profile = $user->profile;
$profile[] = UserProfile::create();
$user->profile = $profile;
$this->repository->save($user);
то связь тоже отлично создается. То есть полю user_id автоматом присваивается id юзера.
Еще раз. смысла в коде не ищите, вместо UserProfile может быть любой объект. Важно понять почему такая работа через hasOne.....
UPD. В общем эту проблему уже
поднимали.