web-dev-qa-db-ja.com

MySQL(Laravel Eloquent)-2つの列に同時に2つ以上の値がある場合にレコードを取得する

私はこのデータベースを持っています この投稿 製品とそのバリエーションを管理しています:

+---------------+     +---------------+
| PRODUCTS      |-----< PRODUCT_SKUS  |
+---------------+     +---------------+
| #product_id   |     | #product_id   |
|  product_name |     | #sku_id       |
+---------------+     |  sku          |
        |             |  price        |
        |             +---------------+
        |                     |
+-------^-------+      +------^------+
| OPTIONS       |------< SKU_VALUES  |
+---------------+      +-------------+
| #product_id   |      | #product_id |
| #option_id    |      | #sku_id     |
|  option_name  |      | #option_id  |
+---------------+      |  value_id   |
        |              +------v------+
+-------^-------+             |
| OPTION_VALUES |-------------+
+---------------+
| #product_id   |
| #option_id    |
| #value_id     |
|  value_name   |
+---------------+

問題は、ユーザーが希望する製品のオプションを選択した時点で、SKUをどのように取得するかがわからないことです。

SKU_VALUES
==========
product_id sku_id option_id value_id
---------- ------ --------- --------
1          1      1         1        (W1SSCW; Size; Small)
1          1      2         1        (W1SSCW; Color; White)
1          2      1         1        (W1SSCB; Size; Small)
1          2      2         2        (W1SSCB; Color; Black)

ユーザーがID 1の製品を選択し、オプションがsize-smallとcolor-blackであると仮定すると、sku_idをどのように取得できますか(この場合、sku_idから値2が必要になります)。 PRODUCT_SKUSテーブル内の価格を取得するため。

私は明らかな理由でこのようなことはできません:

SELECT sku_id FROM SKU_VALUES 
WHERE (SKU_VALUES.option_id = 1 AND SKU_VALUES.value_id = 1) 
AND (SKU_VALUES.option_id = 2 AND SKU_VALUES.value_id = 2)

製品から利用できるオプションの数と同じ数の条件(または必要なもの)を追加する必要があるように見えることに注意してください。この場合、製品には2つのオプション(サイズと色)、ただし、製品に「n」オプションがある場合があります。

誰かがこのクエリを案内してくれたら、RAWクエリを使用する代わりにLaravel Eloquentを使用してそれを実行できるかどうか、私は感謝します。

私が作成したモデルは次のとおりです。

"製品モデル:

namespace App\Models;

use Illuminate\Database\Eloquent\Model;

class Producto extends Model
{
    protected $table = 'productos';

    protected $fillable = [
        'nombre',
        'descripcion'

    ];

public function opciones(){
    return $this->hasMany('App\Models\OpcionProducto', 'producto_id');
}

public function skus(){
    return $this->hasMany('App\Models\ProductoSku', 'producto_id');
}
}

「オプション」モデル:

namespace App\Models;

use Illuminate\Database\Eloquent\Model;

use App\Traits\HasCompositePrimaryKey;

class OpcionProducto extends Model
{
    use HasCompositePrimaryKey;

    protected $table = 'productos_opciones';

    protected $primaryKey = array('producto_id', 'opcion_id');

    protected $fillable = [
        'producto_id',
        'opcion_id',
        'nombre_opcion',
        'valor'
    ];


    public function producto(){
        return $this->belongsTo('App\Models\Producto', 'producto_id');
    }

    public function valores(){
        return $this->hasMany('App\Models\OpcionValorProducto', 'opcion_id', 'opcion_id');
    }

    public function skusValores(){
        return $this->hasMany('App\Models\SkuValor', 'opcion_id', 'opcion_id');
    }
}

「OptionValues」モデル:

namespace App\Models;

use Illuminate\Database\Eloquent\Model;

use App\Traits\HasCompositePrimaryKey;

class OpcionValorProducto extends Model
{
    use HasCompositePrimaryKey;

    protected $primaryKey = array('producto_id', 'opcion_id', 'valor_id');

    protected $table = 'productos_opciones_valores';

    protected $fillable = [
        'producto_id',
        'opcion_id',
        'valor_id',
        'valor_variacion',
        'valor'
    ];


    public function producto(){
        return $this->belongsTo('App\Models\Producto', 'producto_id');
    }

    public function opcion(){
        return $this->belongsTo('App\Models\OpcionProducto', 'opcion_id', 'opcion_id');
    }
}

「Product_SKUS」モデル:

namespace App\Models;

use Illuminate\Database\Eloquent\Model;

use App\Traits\HasCompositePrimaryKey;

class ProductoSku extends Model
{
    use HasCompositePrimaryKey;

    protected $primaryKey = array('producto_id', 'sku_id');

    protected $table = 'productos_skus';

    protected $fillable = [
        'producto_id',
        'sku_id',
        'imagen_id',
        'precio',
        'stock',
        'sku'
    ];


    public function producto(){
        return $this->belongsTo('App\Models\Producto', 'producto_id');
    }

    public function valoresSku(){
        return $this->hasMany('App\Models\SkuValor', 'sku_id');
    }

    }
}

「SKU_VALUES」モデル:

namespace App\Models;

use Illuminate\Database\Eloquent\Model;

use App\Traits\HasCompositePrimaryKey;

class SkuValor extends Model
{
    use HasCompositePrimaryKey;

    protected $primaryKey = array('producto_id', 'sku_id', 'opcion_id');

    protected $table = 'valores_skus';

    protected $fillable = [
        'producto_id',
        'sku_id',
        'opcion_id',
        'valor_id',
    ];


    public function producto(){
        return $this->belongsTo('App\Models\Producto', 'producto_id');
    }

    public function opcion(){
        return $this->belongsTo('App\Models\OpcionProducto', 'opcion_id', 'opcion_id');
    }

    public function sku(){
        return $this->belongsTo('App\Models\ProductoSku', 'sku_id', 'sku_id');
    }
}
3

あなたの質問を終えた後、これは私が思いついたコードです。もちろん、これはテストされていません。これを試してみてください。

_$skuValor = SkuValor::with('producto', 'opcion.valores', 'sku')
    ->whereHas('producto', function ($q) use ($request) {
        $q->where('id', $request->get('product_id')); // id: 1
    })
    ->whereHas('opcion', function ($q) use ($request) {
        $q->whereIn('id', $request->get('option_ids')) // id: [1, 2] where 1=size, 2=color
        ->whereHas('valores', function($q2) use ($request) {
            $q2->whereIn('id', $request->get('value_ids')); // id: [1, 3] where 1=small, 3=pink
        });
    })
    ->get();

$skuValor->sku->id; // sky id
_

with():これは Eager Loading と呼ばれます。モデルを取得するときに、いくつかの関係をロードします。

whereHas()クエリ関係の存在 。このメソッドを使用すると、カスタマイズされた制約を関係制約に追加できます。

use():内部(その特定の)クエリが使用できるようにデータを渡す。 1つはオプションに、もう1つは勇気に使用していることに注意してください。

whereIn():このメソッドは、指定された列の値が指定された配列内に含まれていることを確認します。

行き詰まった場合はコメントしてください。

1
Digvijay

これはLaravel subqueries を使用して可能ですが、必要な値を取得するためにRAWクエリを作成し、Laravelクエリビルダー。

多数のテーブルを含むクエリの場合、Eloquentは何らかの非効率的な結果を招く可能性があり、保守不可能なコードを記述する必要があります。

追加の提案、テーブル名が他の言語である場合でも、完全な英語モデルを作成することをお勧めします。どのフィールドがどのプロパティに関連付けられているかを指定できます。

0
Mirdrack