Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/php/294.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Php Laravel雄辩5.1高效更新相关模型_Php_Laravel_Orm_Eloquent_Laravel 5.1 - Fatal编程技术网

Php Laravel雄辩5.1高效更新相关模型

Php Laravel雄辩5.1高效更新相关模型,php,laravel,orm,eloquent,laravel-5.1,Php,Laravel,Orm,Eloquent,Laravel 5.1,我正在寻找一个干净的解决方案,用于查询和修改存储在另一个表中的雄辩模型的动态属性 我的主要型号是User。一个用户可能有多个用户变量s。当通过UserRepository加载模型时,我可能会也可能不会急于加载变量 我想要实现的是UserVariables可以在内存中修改,并且只有在保存User时才会自动保存 这是我的解决方案(去掉了不相关的部分),它可以工作,但既不优雅,也不可扩展: /** * @property boolean $isCommentingEnabled */ class

我正在寻找一个干净的解决方案,用于查询和修改存储在另一个表中的雄辩模型的动态属性

我的主要型号是
User
。一个
用户
可能有多个
用户变量
s。当通过
UserRepository
加载模型时,我可能会也可能不会急于加载变量

我想要实现的是
UserVariable
s可以在内存中修改,并且只有在保存
User
时才会自动保存

这是我的解决方案(去掉了不相关的部分),它可以工作,但既不优雅,也不可扩展:

/**
 * @property boolean $isCommentingEnabled
 */
class User extends \Illuminate\Database\Eloquent\Model
{
    public function variables()
    {
        return $this->hasMany('UserVariable', 'var_userid', 'user_id');
    }

    public function getIsCommentingEnabledAttribute()
    {
        foreach ($this->variables as $variable) {
            if ($variable->name == UserVariable::IS_COMMENTING_ENABLED) {
                return (boolean) $variable->value;
            }
        }
        return false;
    }

    public function setIsCommentingEnabledAttribute($enabled)
    {
        foreach ($this->variables as $variable) {
            if ($variable->name == UserVariable::IS_COMMENTING_ENABLED) {
                $variable->value = $enabled ? 1 : 0;
                return;
            }
        }
        $this->variables()->add(new UserVariable([
                'name'  => UserVariable::IS_COMMENTING_ENABLED,
                'value' => $enabled ? 1 : 0,
        ]));
    }
}

/**
 * @property-read int $id Unique ID of the record.
 * @property string $name Must be one of the constants in this class.
 * @property int $userId
 * @property string $value
 */
class UserVariable extends EloquentModel {}

class UserRepository
{
    public function findById($id)
    {
        return User::with('variables')->find($id);
    }

    public function saveUser(User $user)
    {
        return $user->push();
    }
}
这个解决方案显然无法扩展。如果用户有5+个变量,即使我提取了循环,代码也会非常丰富

我怀疑在Laravel中一定有一个简洁明了的解决方案,只需按名称弹出一个
用户
用户变量
,或者如果它不存在,则获取一个新的,修改其值并将其放回模型。当调用
User::push()
时,它会自动保存。完成了

我在找像这样的东西

$user->variables()->where('name', UserVariable::IS_COMMENTING_ENABLED)->first()->value
        = $enabled ? 1 : 0;
但是上面的方法不能正常工作,因为它使用的是DB,而不是模型。感谢您的帮助


注意:我正在处理一个大型的遗留代码库,因此现在不可能更改数据库结构。

不幸的是,没有内置的方法来完成此操作。幸运的是,仅仅实施并不太糟糕

我们有一个带有
->变量
关系的模型

class User extends \Illuminate\Database\Eloquent\Model {
    public function variables() {
        return $this->hasMany('UserVariable', 'var_userid', 'user_id');
    }
然后,我们需要构建一个方法,告诉我们是否已经加载了所述关系,如果还没有加载,则需要构建一个方法来加载它们

    protected function hasLoadedVariables() {
        $relations = $this->getRelations();
        return array_key_exists('variables', $relations);
    }

    protected function loadVariablesIfNotLoaded() {
        if(!$this->hasLoadedVariables()) {
            $this->load('variables');
        }
    }
这些方法允许我们为
UserVariable
s构建通用的getter和setter

getter确保加载了
变量
关系,然后返回带有匹配键的第一个值

    protected function getVariable($key) {
        $this->loadVariablesIfNotLoaded();
        foreach($this->variables as $variable) {
            if($variable->key === $key) {
                return $variable->value;
            }
        }
        return null;
    }
setter稍微复杂一点,因为我们想要更新现有的
用户变量
模型(如果存在),如果不存在则创建一个,并且在任何一种情况下都保存
->variables
关系中的更改,但不保存DB。(
$this->variables->push($variable)
保存到关系,但不保存到数据库)

Laravel的
->push()
方法不会将默认情况下不存在的记录保存到数据库中,但我们可以重写它来执行此操作

    public function push(array $options = []) {
        if($this->hasLoadedVariables()) {
            foreach($this->variables as $variable) {
                if(!$variable->exists) {
                    $this->variables()->save($variable);
                } else if($variable->isDirty()) {
                    $variable->save();
                }
            }
        }
        parent::push();
    }
最后,所有这些就绪后,我们可以为单个属性添加特定的getter和setter

    protected function setIsCommentingEnabledAttribute($enabled) {
        $this->setVariable(UserVariable::IS_COMMENTING_ENABLED, $enabled);
    }

    protected function getIsCommentingEnabledAttribute($enabled) {
        $this->getVariable(UserVariable::IS_COMMENTING_ENABLED);
    }
}
要使用它,只需按照通常的方式编写代码

$user = User::find(123);
$user->is_commenting_enabled; // Calls the getter, no DB calls
$user->is_commenting_enabled = 1; // Calls the setter, no DB calls
$user->push(); // Saves the user and any variables which have been added or changed.
$user = User::find(123);
$user->is_commenting_enabled; // Calls the getter, no DB calls
$user->is_commenting_enabled = 1; // Calls the setter, no DB calls
$user->push(); // Saves the user and any variables which have been added or changed.