Question

I working on this issue for a while now but I don't seem to get the ideal solution.

I am working on a webshop with Products. These products can contain different sizes, colors or/ and materials.

What I want:
A product with multiple selectlists. For Example: If the product is "trousers" the customer should be able to select from a selectlist size and from another selectlist color.

What I have
DB:

Table Products: Id|Name|Price|etc...


Table: Properties: Id|Name|Value


Table Product_properties: Id|Product_id|Property_1_id|Property_2_id|Supply

To be able to access them properly with Laravel I also created these classes that extends to eloquent. I've set the relationships in the classes as the following:

Product:

public function productProperties()
    {
        return $this->hasMany('ProductProperty', 'product_id');
    }

ProductProperty:

public function product()
{
    return $this->belongsTo('Product');
}

public function properties()
{
    return $this->hasMany('Property', 'id');
}

Property:

public function properties()
{
    return $this->belomgsTo('ProductProperty');
}

My question
Is this properly configured? How do I get them efficiently into a selectlist?

No correct solution

OTHER TIPS

I modified the schema a bit and came up with a decent solution. It seems confusing, but it's actually very simple.

Each type of property should have it's own table, in this case, size and material. This will make adding additional types of properties very easy as all you have to do is create the table and the model, and you'll be able to start utilizing it right away with no additional changes to code.

class Size extends Eloquent {

    public function properties()
    {
        return $this->morphMany('Property', 'imageable');
    }

}

class Material extends Eloquent {

    public function properties()
    {
        return $this->morphMany('Property', 'imageable');
    }

}

To bring all the properties together and make them easier to work with, I created a polymorphic table called properties, which will store the id of the property itself in its table and the class it belongs to, Size, or Material.

class CreatePropertiesTable extends Migration {

    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('properties', function($table)
        {
            $table->increments('id');
            $table->integer('imageable_id');
            $table->string('imageable_type');
        });
    }
}

This table will serve 2 purposes, it will obviously act as the table that's managing our polymorphic relations with the Size and Material models, and it will be a part of a many-to-many relationship with the products table (a product can have many properties and a property can belong to many products). Here's the model for that table.

class Property extends Eloquent {

    public function imageable()
    {
        return $this->morphTo();
    }

    public function products()
    {
        return $this->belongsToMany('Product');
    }

}

Finally, to finish our Product/Property relation, we will have the products table.

class CreateProductTable extends Migration {

    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('products', function($table)
        {
            $table->increments('id');
            $table->string('name');
            $table->timestamps();
        });
    }
}

And the Product model...

class Product extends Eloquent {

    public function properties()
    {
        return $this->belongsToMany('Property');
    }

}

And lastly, the table for the Product/Property many-to-many relationship...

class CreatePropertyProductTable extends Migration {

    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('product_property', function($table)
        {
            $table->increments('id');
            $table->integer('product_id');
            $table->integer('property_id');
        });
    }
}

Now with that in mind, it's become extremely easy to answer your original question. To get sizes, just use the Size model...

$sizes = Size::all()->lists('id', 'name');

and to get them into a select list, when you create your view, pass the variable along in your controller or route

return View::make('some.view')->with('sizes', $sizes);

And in the view

{{ Form::select('size', $sizes, Input::old('size')) }}

To get all the properties for a certain product, that's fairly easy too...

$product = Product::find(1);
foreach($product->properties as $property) {
    $property = $property->imageable;
    $class = get_class($property);
    echo $class;
    echo ': ';
    echo $property->name;
    echo "<br />";
}

You will probably eventually want to limit your sizes available (or other properties, Color/Material etc...) based on what product is selected, in which case, I suggest adding an additional table for managing those, which would have a row for each possible product/property combo. So for example, a product_size table which would have a row for each possible product/size combo. Then query that relationship when filling out your select values $sizes = Product::find(1)->possibleSizes;

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top