问题描述
如何处理指向同一个活动记录的多个逆关系? 例如:
class Bicycle extends ActiveRecord {
public function getFrontWheel() {
return $this
->hasOne(Wheel::class,['id' => 'front_wheel_id'])
->inverSEOf('bicycles');
}
public function getRearWheel() {
return $this
->hasOne(Wheel::class,['id' => 'rear_wheel_id'])
->inverSEOf('bicycles');
}
}
class Wheel extends ActiveRecord {
public function getBicycles() {
return $this
->hasMany(Bicycle::class,['???' => 'id'])
->inverSEOf('??????');
}
}
我可以在这里做什么?我非常需要逆关系。
解决方法
这是我自己的解决方案。 要点:
- 这一切都归结为正确的命名。
- 逆关系是bijective!换句话说,每个关系总是必须在另一端有自己独特的镜像关系。
class Bicycle extends ActiveRecord {
public function getFrontWheel() {
return $this
->hasOne(Wheel::class,['id' => 'front_wheel_id'])
->inverseOf('frontWheelBicycles');
}
public function getRearWheel() {
return $this
->hasOne(Wheel::class,['id' => 'rear_wheel_id'])
->inverseOf('rearWheelBicycles');
}
}
class Wheel extends ActiveRecord {
public function getFrontWheelBicycles() {
return $this
->hasMany(Bicycle::class,['front_wheel_id' => 'id'])
->inverseOf('frontWheel');
}
public function getRearWheelBicycles() {
return $this
->hasMany(Bicycle::class,['rear_wheel_id' => 'id'])
->inverseOf('rearWheel');
}
}
,
我建议您执行以下操作:
创建两个新类:
- class FrontWheel extends Wheel {
- class RearWheel extends Wheel {
在新课程中,您可以轻松设置关系。
如何实例化正确的类? ActiveRecord instantiate() 中有一个方法,您可以在其中编写需要创建哪个轮类的逻辑。
class Wheel extends ActiveRecord {
...
public static function instantiate ( $row ) {
if($row['type'] === 'RearWheel') {
return new RealWheel();
}
...
}
完整代码:
class Bicycle extends ActiveRecord
{
public function getFrontWheel()
{
return $this
->hasOne(Wheel::class,['id' => 'front_wheel_id'])
->inverseOf('bicycles');
}
public function getRearWheel()
{
return $this
->hasOne(Wheel::class,['id' => 'rear_wheel_id'])
->inverseOf('bicycles');
}
}
abstract class Wheel extends ActiveRecord
{
public static function instantiate($row)
{
if ($row['type'] === 'RearWheel') {
return new RealWheel();
}
if ($row['type'] === 'FrontWheel') {
return new FrontWheel();
}
throw new InvalidConfigException();
}
abstract public function getBicycles();
}
class RealWheel extends Wheel
{
public function getBicycles()
{
return $this
->hasMany(Bicycle::class,['rear_wheel_id' => 'id'])
->inverseOf('rearWheel');
}
}
class FrontWheel extends Wheel
{
public function getBicycles()
{
return $this
->hasMany(Bicycle::class,['front_wheel_id' => 'id'])
->inverseOf('frontWheel');
}
}