Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Updating a One-To-Many Relationship in Laravel's Eloquent

Suppose I have a relationship between the following two Models in Laravel's Eloquent:

<?php

    // user:
    // - user_id
    class User extends Model
    {
        protected $table = 'users';

        public function settings()
        {
            return $this->hasMany('Setting');
        }

        public function settingSet($key, $value)
        {
            \Setting::setConfigItem($key, $value, $this->user_id);
        }

    }

    // settting:
    // - setting_key
    // - setting_value
    // - user_id
    class Setting extends Model
    {
        public function setConfigItem($key, $value, $user_id)
        {
            // Note: I've provided this code here as an example, so it should
            // exist here only as pseudo-code - it has not been tested and
            // is outside the scope of this issue but has been requested by 
            // a commenter so I've provided the basis for this method:
            $existing = \Setting::where(['key' => $key, 'user_id' => $user_id])->first();
            if (!$existing) {
                \Setting::insert([ 'setting_key' => $key, 'setting_value' => $value, 'user_id' => $user_id ]);
            } else {
                $existing->setting_value = $value;
                $existing->save();
            }
        }
    }

And I want to retrieve a single user and his settings, I can do the following:

<?php
$user = User::with(['setting'])->find(1);

Now, with this user, I can update or insert a setting using the settingSet method, as listed above.

<?php
$user->settingSet('foo','bar');

However, if I retrieve the settings at this point, I will get stale data.

<?php
print_r($user->settings); // onoes!

What's the best practice to force the data for this relationship to be updated after an INSERT/UPDATE/DELETE in the User::settingSet method or in other similar methods?

like image 916
gpmcadam Avatar asked Apr 05 '15 23:04

gpmcadam


2 Answers

You can force the data to be updated by using Lazy Eager Loading, load() function.

print_r($user->load('settings'));

source: http://laravel.com/docs/5.0/eloquent#eager-loading

like image 103
mininoz Avatar answered Nov 20 '22 05:11

mininoz


You have this issue due to using query builder instead of the eloquent,I dont understand why your using both,if you're using eloquent then use eloquent if you're using query builder use query builder,but dont use both,at least not when you have the possibility not to.

I find the setConfigItem method useless as you arent pushing a user into a setting but a setting into a user so basically all implementions should be on a user class and not on the settings class

After clearing that out,you could try doing something like this -

public function settingSet($key, $value)
{
    $setting = new Setting([
        'setting_key' => $key,
        'setting_value' => $value
    ]);
    $this->settings()->save($setting);
}

also you could improve this method by instead of accepting just 1 setting at a time you could accept array of settings

btw is there a reason why you arent using pivot table ? are the settings unique foreach user ?

like image 1
Gal Avatar answered Nov 20 '22 03:11

Gal