peterdickins's avatar

Calling a scope function twice not unique table/alias mysql error

Hi,

I have an ecommerce application and have the following models: Sku and Variation. It's a many to many relationship:

class Sku extends Model
{
    public function variations(): BelongsToMany
    {
        return $this->belongsToMany(Variation::class)
            ->using(VariationSku::class)
            ->withPivot('value');
    }

    public function product(): BelongsTo
    {
        return $this->belongsTo(Product::class);
    }

    /**
     * Scope a query to only include skus of a given variation.
     */
    public function scopeOfVariation(Builder $query, $variation): void
    {
        $query->whereHas('variations', function ($query) use ($variation) {
            $query->where('name', $variation);
        });
    }

    /**
     * Scope a query to only include skus of a given variation value.
     */
    public function scopeOfVariationValue(Builder $query, $variationValue): void
    {
        $query->join('variation_sku', 'skus.id', '=', 'variation_sku.sku_id')
            ->where('value', $variationValue);
    }
}

class Variation extends Model
{
	public const COLOR = 'color';
	public const SIZE = 'size';
    public const SIZE_SMALL = 'small';
	public const COLOR_RED = 'red';

    public function skus(): BelongsToMany
    {
        return $this->belongsToMany(Sku::class)
            ->using(VariationSku::class)
            ->withPivot('value');
    }

    public function product(): BelongsTo
    {
        return $this->belongsTo(Product::class);
    }
}

I am having an issue when I try to query for a skus where I have to scope by variation more than once, for example:

Sku::ofVariation(Variation::SIZE)
        ->ofVariationValue(Variation::SIZE_SMALL)
        ->ofVariation(Variation::COLOR)
        ->ofVariationValue(Variation::COLOR_RED)
        ->get();

I am getting the following sql error:

SQLSTATE[42000]: Syntax error or access violation: 1066 Not unique table/alias: 'variation_sku' (SQL: select * from `skus` inner join `variation_sku` on `skus`.`id` = `variation_sku`.`sku_id` inner join `variation_sku` on `skus`.`id` = `variation_sku`.`sku_id` where exists (select * from `variations` inner join `variation_sku` on `variations`.`id` = `variation_sku`.`variation_id` where `skus`.`id` = `variation_sku`.`sku_id` and `name` = size) and `value` = small and exists (select * from `variations` inner join `variation_sku` on `variations`.`id` = `variation_sku`.`variation_id` where `skus`.`id` = `variation_sku`.`sku_id` and `name` = color) and `value` = red)

Any suggestions would be very much appreciated.

0 likes
1 reply
peterdickins's avatar

For anyone facing this issue, this is the solution I ended up using:

/**
 * Scope a query to only include skus of a given variation value.
 */
public function scopeOfVariationValue(Builder $query, $variationValue): void
{
    $query->join(
        'variation_sku as variation_sku_' . $variationValue,
        'skus.id',
        '=',
        'variation_sku_' . $variationValue . '.sku_id'
    )
        ->where('variation_sku_' . $variationValue . '.value', $variationValue);
}

Please or to participate in this conversation.