dimsav / laravel-translatable

[Deprecated] A Laravel package for multilingual models
MIT License
1.95k stars 320 forks source link

How to extend Laravel-Translatable to translate pivot values #420

Closed tomasvanrijsse closed 6 years ago

tomasvanrijsse commented 6 years ago

I've read issue #303 and was thinking about an approach to tackle pivot values. We have implemented the Entity-Attribute-Value database design for products and their properties. Our simplified schema looks like this

Products Entity

ID name
1 Fancy Bike
2 Fancier Bike

Properties Attribute

ID name
77 Wheel size
78 Color

Product Properties Value

ID product_id property_id value
101 1 77 23 inch
102 1 78 red
103 2 77 23 inch
104 2 78 silver

Using the pivot table as a many-to-many relation gives us a syntax like

Class Product {
  function properties(){
    $this->belongsToMany(Property::class)->withPivot('value');
  }
}

//somewhere else
foreach($product->properties as $property) {
  echo $property->value;
  // echoes red, silver etc.
}

To us the syntax in that foreach-loop makes sense. Using a separate model for the pivot table however would force awkward syntax like $product->value->property. Therefore we would like to keep the pivot functionality as it is.

Ideally the pivot table would look like this

Product Properties Value

ID product_id property_id value locale
101 1 77 23 inch en
102 1 78 red en
103 1 77 58,4 cm nl
104 1 78 rood nl

Do you concur that this schema would be a good solution? How should laravel-translatable be extended to make this scenario work?

Gummibeer commented 6 years ago

Your last table is what the table would look like if you use this package. Yes this would be another Model but your implementation wouldn't really change:

foreach($product->getTranslation() as $value) {
    echo $value->property->name . ': ' . $value->value;
}

This will output: en

Color: red Wheel size: 23 inch

nl

Kleur: rood Wielgrootte: 58,4 cm

In this case I've also added the translatable trait to the properties model itself.

AshrafHefny commented 6 years ago

@tomasvanrijsse , @Gummibeer you can use using() over the belongsToMany() relation - see https://github.com/dimsav/laravel-translatable/issues/303#issuecomment-417402510

Assuming your models as the following:

class Product extends \Illuminate\Database\Eloquent\Model
{
  public function properties() 
  {
    return $this
        ->belongsToMany(Property::class)
        ->withPivot(['product_id', 'property_id'])
        ->using(ProductProperties::class);
  }
}

class Property extends \Illuminate\Database\Eloquent\Model
{
}

class ProductProperties extends \Illuminate\Database\Eloquent\Relations\Pivot
{
    use Translatable;

    protected $fillable = ['product_id', 'property_id'];
    protected $translatedAttributes = ['value']
}

class ProductPropertyTranslation extends \Illuminate\Database\Eloquent\Model
{
    protected $fillable = ['value'];
}

So then you can normally call the translated value column as the following:

app()->setLocale('en');
$product = Product::with('properties')->find($id);
foreach ($product->properties as $property){
    echo $property->value;
}

https://laravel.com/docs/5.6/eloquent-relationships#many-to-many Defining Custom Intermediate Table Models