programing

belongsToMany 관계가 존재하는지 확인합니다(라벨).

randomtip 2022. 9. 23. 21:40
반응형

belongsToMany 관계가 존재하는지 확인합니다(라벨).

내 테이블 중 2개(클라이언트 및 제품)는 Larabel의 blongToMany와 피벗 테이블을 사용하여 ManyToMany 관계를 가지고 있습니다.이제 특정 고객이 특정 제품을 가지고 있는지 확인하고 싶습니다.

피벗 테이블에서 체크하는 모델을 만들 수 있지만, Larabel은 belongsToMany 메서드에 이 모델이 필요하지 않기 때문에 피벗 테이블 모델이 없어도 특정 관계가 있는지 확인할 수 있는 다른 방법이 있는지 궁금합니다.

이를 위한 공식적인 방법은 다음과 같습니다.

$client = Client::find(1);
$exists = $client->products->contains($product_id);

좀 아깝긴 한데...SELECT쿼리, 모든 결과 가져오기Collection그리고 나서 마지막으로foreach에 걸쳐서Collection아이디로 모델을 찾을 수 있습니다.그러나 피벗 테이블을 모델링할 필요가 없습니다.

이러한 낭비가 싫으면 SQL/Query Builder에서 직접 수행할 수 있습니다.또한 테이블을 모델링할 필요도 없습니다(또한Client모델(다른 용도로 아직 가지고 있지 않은 경우):

$exists = DB::table('client_product')
    ->whereClientId($client_id)
    ->whereProductId($product_id)
    ->count() > 0;

이 질문은 매우 오래되었지만, 다른 사람들이 해결책을 찾는 데 도움이 될 수 있습니다.

$client = Client::find(1);
$exists = $client->products()->where('products.id', $productId)->exists();

@alexrusell의 솔루션과 같은 "낭비"가 없고, 쿼리도 더 효율적입니다.

알렉스의 솔루션은 작동하지만, 이 솔루션은 로딩될 것입니다.Client모델 및 관련된 모든 것ProductDB에서 메모리로 모델을 변환한 후에야 관계가 존재하는지 여부를 확인합니다.

이를 위한 더 나은 웅변적 방법은 방법을 사용하는 것입니다.

1. 클라이언트 모델을 로드할 필요 없이 아이디만 사용하시면 됩니다.

2. 또한 Alex처럼 해당 클라이언트와 관련된 모든 제품을 메모리에 로드할 필요는 없습니다.

3. DB에 대한 SQL 쿼리 1개

$doesClientHaveProduct = Product::where('id', $productId)
    ->whereHas('clients', function($q) use($clientId) {
        $q->where('id', $clientId);
    })
    ->count();

업데이트: 저는 여러 관계를 확인하는 것의 유용성을 고려하지 않았습니다.그렇다면 @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()
        );
    }

사용자/클라이언트 모델에 넣을 수도 있고 Client Repository에 저장하여 필요에 따라 사용할 수도 있습니다.

if ($this->clientRepository->clientHasProduct($clientId, $productId)
{
    return 'Awesome';
}

그러나 클라이언트 웅변 모델에 belongsToMany 관계를 이미 정의한 경우에는 클라이언트 모델 내에서 대신 다음과 같이 할 수 있습니다.

    return ! is_null(
        $this->products()
             ->where('product_id', $productId)
             ->first()
    );

@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);
}

그 후, 간단하게 다음과 같이 할 수 있습니다.

$user = User::first();
$user->hasProduct($someId); // true / false

// or
Auth::user()->hasProduct($someId);

쿼리는 1개만 실행되며 어레이로 작업할 수 있습니다.


가장 쉬운 방법은 다음과 같습니다.contains@"russell" 입니다.

이것은 취향의 문제라고 생각하기 때문에, 당신의 앱이 꽤 크고 많은 최적화를 필요로 하지 않는 한, 작업하기 쉬운 것을 선택할 수 있습니다.

여러분 안녕하세요) 이 문제에 대한 저의 해결책: 저는 자체 클래스를 만들고, 웅변에서 확장하여 모든 모델을 확장했습니다.이 수업에서 나는 다음과 같은 간단한 함수를 썼다.

function have($relation_name, $id) {
    return (bool) $this->$relation_name()->where('id','=',$id)->count();
}

기존 관계를 확인하려면 다음과 같이 작성해야 합니다.

if ($user->have('subscribes', 15)) {
    // do some things
}

이렇게 하면 테이블에서 실제 데이터를 수신하지 않고 SELECT 카운트(...) 쿼리만 생성됩니다.

두 모델 간의 관계를 확인하기 위해 필요한 것은 조인 없이 피벗 테이블에 대한 단일 쿼리입니다.

은 빌트인 「」를 해 실현할 수 .newPivotStatementForId★★★★

$exists = $client->products()->newPivotStatementForId($product->id)->exists();

특성 사용:

trait hasPivotTrait
{
    public function hasPivot($relation, $model)
    {
        return (bool) $this->{$relation}()->wherePivot($model->getForeignKey(), $model->{$model->getKeyName()})->count();
    }
}

.

if ($user->hasPivot('tags', $tag)){
    // do some things...
}

시간은 있지만 누군가를 도울 수 있을지도 몰라

if($client->products()->find($product->id)){
 exists!!
}

제품 및 고객 모델이 있어야 합니다. 도움이 되었으면 합니다.

언급URL : https://stackoverflow.com/questions/24555697/check-if-belongstomany-relation-exists-laravel

반응형