Search code examples
phplaravelpolyglot

Reading data using Anahkiasen/Polyglot returns error trying to get property of non-object


After adding the Anahkiasen/Polyglot package to my Laravel 4.2 project I tried to get this to work. I set up everything the way I think it's supposed to be (the documentation is kinda bad). Saving to the database doesn't seem to be a problem but when I want to read I get the following error:

Trying to get property of non-object (View: /Applications/MAMP/htdocs/*my view*.blade.php)

Models:

use Polyglot\Polyglot;

class Page extends Polyglot {

    use SoftDeletingTrait;

    protected $fillable = [
        'lang',
        'meta_title',
        'meta_description',
        'title',
        'page_title',
        'page_content',
    ];
    protected $polyglot = [
        'meta_title',
        'meta_description',
        'title',
        'page_title',
        'page_content',
    ];

    // ...
}

class PageLang extends Eloquent {

    public $timestamps = false;
    protected $fillable = [
        'page_id',
        'lang',
        'meta_title',
        'meta_description',
        'title',
        'page_title',
        'page_content',
    ];
}

My blade template:

$page->nl->title
/*
This is what's causing the error
$page->title doesn't produce errors but is, of course, empty
*/

Been stuck on this for a while now. Any help is greatly appreciated :-)


Solution

  • I'm not familiar with the library, but looking at the base Polyglot class, it looks like this abstraction works by using PHP's magic __get variable to inject n localization object when you access something like $page->nl

    Looking at __get,

    public function __get($key)
    {
        // If the relation has been loaded already, return it
        if (array_key_exists($key, $this->relations)) {
            return $this->relations[$key];
        }
        // If the model supports the locale, load and return it
        if (in_array($key, $this->getAvailable())) {
            $relation = $this->hasOne($this->getLangClass())->whereLang($key);
            if ($relation->getResults() === null) {
                $relation = $this->hasOne($this->getLangClass())->whereLang(Config::get('polyglot::fallback'));
            }
            return $this->relations[$key] = $relation->getResults();
        }
        // If the attribute is set to be automatically localized
        if ($this->polyglot) {
            if (in_array($key, $this->polyglot)) {
                /**
                 * If query executed with join and a property is already there
                 */
                if (isset($this->attributes[$key])) {
                    return $this->attributes[$key];
                }
                $lang = Lang::getLocale();
                return $this->$lang ? $this->$lang->$key : null;
            }
        }
        return parent::__get($key);
    }
    

    there's a number of conditionals that, if failed, result in the parent's __get being called

    return parent::__get($key);
    

    In other words, the normal model behavior. That's probably what's happening above -- and since nl isn't a set object PHP complains when you try to call a method on it.

    Of the three conditionals in __get, this seems like the most likely candidate for failure

        if (in_array($key, $this->getAvailable())) {
            $relation = $this->hasOne($this->getLangClass())->whereLang($key);
            if ($relation->getResults() === null) {
                $relation = $this->hasOne($this->getLangClass())->whereLang(Config::get('polyglot::fallback'));
            }
            return $this->relations[$key] = $relation->getResults();
        }
    

    If your specific case, it's going to look like

        if (in_array('nl', $this->getAvailable())) {
            //...
        }
    

    Looking at getAvailable()

    protected function getAvailable()
    {
        return Config::get('polyglot::locales');
    }
    

    it looks for a configuration field named Config::get('polyglot::locales');. I'd check if calling that configuration field returns nl as a configured locale

    var_dump(Config::get('polyglot::locales'));
    

    My guess would be it doesn't, possibly because you didn't run the artisan command to publish the configuration for the package

    php artisan config:publish anahkiasen/polyglot