普通关系方法通常没有条件,并且往往看起来像这样:
@implementation MySingleton (Shared)
+ (MySingleton*)shared {
static MySingleton* mySingleton;
static dispatch_once_t predicate;
dispatch_once(&predicate, ^{
SomeClass* someClass = [[SomeClass alloc] init];
mySingleton = [[MySingleton alloc] initWithSomeClass:someClass];
});
return mySingleton;
}
@end
在我的模型中,像这样的关系方法中有一个条件:
class StripeCustomer extends Model
{
public function user()
{
return $this->belongsTo(User::class, 'stripe_customer_id');
}
}
Laravel是否像上面那样在Eloquent中支持条件关系。许多常用方法仍然可以像这样工作:
class StripeCustomer extends Model
{
public function user()
{
if ($this->type === 'normal') {
return $this->hasOne(User::class, 'stripe_customer_id');
} else {
return $this->hasOne(User::class, 'stripe_customer_charity_id');
}
}
}
但是可以预期以下工作:
StripeCustomer::get()->first()->user;
StripeCustomer::get()->first()->user()->get();
这里的问题是,我不确定“ with”运算符在Eloquent内部如何工作。
我认为它也不起作用的原因是,Foo::with('user')->get();
方法需要为每个模型执行。但是,当我在方法开始时添加user()
时,发现它只运行了一次,表明dump(...)
不起作用。
答案 0 :(得分:1)
不,它不适用于with()
。当您尝试执行以下代码时,您会怎么想:
Foo::with('user')->get();
答案是Laravel将创建Foo
的新实例,并尝试调用user()
以获取关系对象。这个新实例没有任何type
((new Foo)->type
将是null
),因此您的方法user()
将始终返回$this->hasOne(Bar::class, 'b_id')
,并且此关系对象将是用于构造查询。
如您所见,这显然不是您想要的,因为只有B类用户才会渴望加载所有Foo
行。在这种情况下,您需要为用户创建两个关系(每种类型一个)和访问者(获取/设置):
class Foo extends Model
{
public function userA()
{
return $this->hasOne(Bar::class, 'a_id');
}
public function userB()
{
return $this->hasOne(Bar::class, 'b_id');
}
public function getUserAttribute()
{
if ($this->type === 'a') {
return $this->userA;
} else {
return $this->userB;
}
}
public function setUserAttribute($user)
{
if ($this->type === 'a') {
$this->userA()->associate($user);
} else {
$this->userB()->associate($user);
}
}
}
然后,您可以对两个关系使用with()
来利用紧急加载:
$fooRows = Foo::with('userA', 'userB')->get();
...
foreach ($fooRows as $row) {
$row->user;
}
修改: 由于您已经在问题中编辑了代码,因此我回答中的示例代码不再代表您的情况,但我希望您有所了解。
答案 1 :(得分:-1)
是的,with()
有效。它对您的user()
方法返回的任何关系运行子查询。由于您的关系已经具有约束,因此可以按预期将约束应用于子查询。