dimsav / laravel-translatable

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

Undefined property $translations #41

Closed f4ndor closed 10 years ago

f4ndor commented 10 years ago

hello, i'm getting an error, and i don't know where screwed up. Any help would be appriciated.

here is the error: Undefined property: Product::$translations private function getTranslationByLocaleKey($key) { --> foreach ($this->translations as $translation) { if ($translation->getAttribute($this->getLocaleKey()) == $key) ... I followed every instruction to the letter.. any idea what could couse this error? is it maybe some debug setting?

dimsav commented 10 years ago

Hi @f4ndor

probably something is missing from your Product class. My guess would be you are not extending Eloquent.

Just paste your classes here if can't find it.

f4ndor commented 10 years ago

okay so here are my classes: in the product model, i had to do some aliasing, since Stapler uses the same getAttribute functions ( this might couse the problem, but i need Stapler and didnt know how else to solve it)

use \Dimsav\Translatable\Translatable;
use Illuminate\Database\Eloquent\Model as Eloquent;

class Product extends Eloquent
{

    use \Codesleeve\Stapler\Stapler{
        getAttribute as getStaplerAttribute;
        setAttribute as setStaplerAttribute;
    }
    use Translatable{
        getAttribute as getTransAttribute;
        setAttribute as setTransAttribute;
    }

    protected $guarded = array('id');

    protected $table = 'products';

    public $translatedAttributes = array('name','description');
    protected $fillable = ['name','description'];

    public $translations;

    public function getAttribute($key)
    {
        if (in_array($key, $this->translatedAttributes))
        {
            return $this->getTransAttribute($key);
        }
        return $this->getStaplerAttribute($key);
    }
    public function setAttribute($key,$value)
    {
        if (in_array($key, $this->translatedAttributes))
        {
            $this->setTransAttribute($key,$value);
        }
        $this->setStaplerAttribute($key,$value);
    }

// ...

}

and the other class is just this:

use Illuminate\Database\Eloquent\Model as Eloquent;

class ProductTranslation extends Eloquent { protected $fillable = ['name','description']; }

and the table:

     Schema::create('product_translations', function(Blueprint $table) {
            $table->increments('id');
            $table->integer('product_id')->unsigned();
            $table->string('name');
            $table->text('description');
            $table->string('locale')->index();

            $table->unique(['product_id','locale']);
            $table->foreign('product_id')->references('id')->on('products')->onDelete('cascade');
        });
f4ndor commented 10 years ago

the public $translations; in the product model was just an attempt to fix the problem, but it didnt work.

dimsav commented 10 years ago

First, remove the public $translations as it is accessed by a laravel's magic method through the relationship of translations().

The problem is probably in here:

public function getAttribute($key)
    {
        if (in_array($key, $this->translatedAttributes))
        {
            return $this->getTransAttribute($key);
        }
        return $this->getStaplerAttribute($key);
    }

When LaravelTranslatable uses $this->translation, in_array($key, $this->translatedAttributes) returns false but it should return true because we have to use LaravelTranslatable's getAttribute().

Try something like that:

public function getAttribute($key)
    {
        if (in_array($key, $this->translatedAttributes) || $key == 'translations')
        {
            return $this->getTransAttribute($key);
        }
        return $this->getStaplerAttribute($key);
    }
f4ndor commented 10 years ago

okay the error is gone, but i'm still not getting the translated values. saving was successful, but not getting it back. $product->name is supposed to go trough the getAttribute function, right?

f4ndor commented 10 years ago

solved it with extending the setAttribute function like this:

    public function setAttribute($key,$value)
    {
        if ( in_array($key, $this->translatedAttributes) || ($key == $this->getLocaleKey()) || ($key == 'translations') )
        {
            $this->setTransAttribute($key,$value);
        }
        $this->setStaplerAttribute($key,$value);
    }

however i still have an issue: if a product or a cateogry doesn't have any translations in the _translations table, it doesn't return the original 'name' value from the source table. Is this intended or still something im missing?

dimsav commented 10 years ago

What do you mean the "original name" value? The main table is not supposed to contain any name column. See the example below, the countries table should not contain any "name" column.

Schema::create('countries', function(Blueprint $table)
{
    $table->increments('id');
    $table->timestamps();
});

Schema::create('country_translations', function(Blueprint $table)
{
    $table->increments('id');
    $table->integer('country_id')->unsigned();
    $table->string('name');
    $table->string('locale');
});
f4ndor commented 10 years ago

how could i miss that?! .. thanks