alm*_*lmo 61 php laravel laravel-4
我的两个表(客户端和产品)使用Laravel的blongToMany和一个数据透视表具有ManyToMany关系.现在我想检查某个客户是否有某种产品.
我可以创建一个模型来检查数据透视表,但由于Laravel不需要这个模型用于belongsToMany方法,我想知道是否有另一种方法来检查某个关系是否存在而没有数据透视表的模型.
ale*_*ell 154
我认为这样做的官方方法是:
$client = Client::find(1);
$exists = $client->products->contains($product_id);
Run Code Online (Sandbox Code Playgroud)
这是因为它会做的有点浪费SELECT查询,得到的所有结果为Collection,最后做一个foreach在Collection寻找与您传递ID的模式.然而,它并不需要建模数据透视表.
如果您不喜欢它的浪费,您可以在SQL/Query Builder中自己完成,这也不需要对表建模(Client如果您还没有将模型用于其他目的,也不需要获取模型:
$exists = DB::table('client_product')
->whereClientId($client_id)
->whereProductId($product_id)
->count() > 0;
Run Code Online (Sandbox Code Playgroud)
Mou*_*gip 18
问题已经很久了,但这可能有助于其他人寻求解决方案:
$client = Client::find(1);
$exists = $client->products()->where('products.id', $productId)->exists();
Run Code Online (Sandbox Code Playgroud)
没有@ alexrussell解决方案中的"浪费",查询也更有效率.
Ale*_*nin 11
Alex的解决方案正在运行,但它会将Client模型和所有相关Product模型从DB 加载到内存中,只有在此之后,它才会检查关系是否存在.
更好的雄辩方法是使用whereHas()方法.
1.您不需要加载客户端模型,只需使用他的ID即可.
2.您也不需要像Alex那样将与该客户端相关的所有产品加载到内存中.
3.对DB的一个SQL查询.
$doesClientHaveProduct = Product::where('id', $productId)
->whereHas('clients', function($q) use($clientId) {
$q->where('id', $clientId);
})
->count();
Run Code Online (Sandbox Code Playgroud)
更新:我没有考虑检查多个关系的有用性,如果是这种情况,那么@deczo可以更好地回答这个问题.只运行一个查询以检查所有关系是所需的解决方案.
/**
* Determine if a Client has a specific Product
* @param $clientId
* @param $productId
* @return bool
*/
public function clientHasProduct($clientId, $productId)
{
return ! is_null(
DB::table('client_product')
->where('client_id', $clientId)
->where('product_id', $productId)
->first()
);
}
Run Code Online (Sandbox Code Playgroud)
您可以将其放在用户/客户端模型中,也可以将其放在ClientRepository中,并在需要的地方使用它.
if ($this->clientRepository->clientHasProduct($clientId, $productId)
{
return 'Awesome';
}
Run Code Online (Sandbox Code Playgroud)
但是,如果您已经在Client Eloquent模型上定义了belongsToMany关系,则可以在Client模型中执行此操作,而不是:
return ! is_null(
$this->products()
->where('product_id', $productId)
->first()
);
Run Code Online (Sandbox Code Playgroud)
@ nielsiano的方法可行,但他们会查询每个用户/产品对的DB,这在我看来是浪费.
如果您不想加载所有相关模型的数据,那么我将为单个用户执行此操作:
// User model
protected $productIds = null;
public function getProductsIdsAttribute()
{
if (is_null($this->productsIds) $this->loadProductsIds();
return $this->productsIds;
}
public function loadProductsIds()
{
$this->productsIds = DB::table($this->products()->getTable())
->where($this->products()->getForeignKey(), $this->getKey())
->lists($this->products()->getOtherKey());
return $this;
}
public function hasProduct($id)
{
return in_array($id, $this->productsIds);
}
Run Code Online (Sandbox Code Playgroud)
然后你可以简单地这样做:
$user = User::first();
$user->hasProduct($someId); // true / false
// or
Auth::user()->hasProduct($someId);
Run Code Online (Sandbox Code Playgroud)
只执行1个查询,然后使用该数组.
最简单的方法是使用contains像@alexrussell建议的那样.
我认为这是一个偏好问题,所以除非您的应用程序非常庞大且需要大量优化,否则您可以选择更容易使用的内容.
要检查两个模型之间是否存在关系,我们只需要对数据透视表进行一次查询,无需任何连接。
您可以使用内置newPivotStatementForId方法来实现它:
$exists = $client->products()->newPivotStatementForId($product->id)->exists();
Run Code Online (Sandbox Code Playgroud)
大家好)我解决这个问题的方法:我创建了一个自己的类,从Eloquent扩展,并从中扩展我的所有模型.在这堂课中我写了这个简单的功能:
function have($relation_name, $id) {
return (bool) $this->$relation_name()->where('id','=',$id)->count();
}
Run Code Online (Sandbox Code Playgroud)
要检查现有关系,您必须编写如下内容:
if ($user->have('subscribes', 15)) {
// do some things
}
Run Code Online (Sandbox Code Playgroud)
这种方式只生成SELECT count(...)查询而不从表中接收实际数据.
| 归档时间: |
|
| 查看次数: |
61722 次 |
| 最近记录: |