首页 > 解决方案 > 在函数中进行更改时,防止对象内容的一般更改

问题描述

到目前为止,我认为如果我以类实例作为参数调用一个函数,并且在这个函数中我更改属性的值而不返回对象,那么对象的值仅在该函数的范围内被更改。
在做了一些测试之后,简单的代码证明我错了(因此首先是错误)。

<?php
class Test
{
    private bool $var = true;

    public function getVar(): bool
    {
        return $this->var;
    }

    public function setVar(bool $var): void
    {
        $this->var = $var;
    }
}

$test = new Test();

var_dump($test->getVar()); // bool(true)

changeVarValue($test);

var_dump($test->getVar()); // bool(false) I expected that it's true here as well

function changeVarValue(Test $test)
{
    // Changing an attribute here will affect the object outside of this function
    $test->setVar(false);
}

现在的问题是,防止函数中所做的更改仅在函数中有效而不在外部有效的最干净的方法是什么?其他语言的情况如何?

有比以下更好的解决方案吗?

$test = new Test();

$unchangedVarValue = $test->getVar(); // Or even `$unchangedTest = $test` but I'm only interested in one value

var_dump($class->getVar()); // bool(true)

changeVarValue($test);

var_dump($unchangedVarValue); // bool(true)

编辑

既然问了,我的具体用例是注册后的自动登录。

  1. User使用提交的表单创建一个实例。
  2. $insertId = $this->userService->createUser($user);中调用RegisterSubmitAction
  3. createUser函数中,我对密码进行哈希处理并将password属性替换为setPassword($hash).
  4. 然后将此修改后的对象传递到使数据库插入的存储库。
  5. 回到RegisterSubmitAction我想通过标准功能登录用户$userId = $this->authService->GetUserIdIfAllowedToLogin($user);。它从数据库中获取用户并比较信用。在我们不知道哈希的登录提交操作中使用了相同的功能,因此password_verify($pass, $hash)使用了。我将此功能用作双重检查,以确保插入用户时出现问题,而不是为不存在的用户启动会话。

这简化了很多。我没有包括验证等。在写这篇文章时,我想我找到了我想走的路。我将简单地passwordHashUser该类添加一个属性,并可能将 db 列重命名为password_hash.
或者你会怎么做?我非常愿意接受建议。

标签: php

解决方案


你为什么这么期待?将对象用于函数输入时,始终使用“按引用调用”,这意味着不会克隆原始对象。

相反:原始数据类型(如字符串或整数)在用作函数参数时总是被复制,除非你用&


推荐阅读