PHP - 有什么方法可以区分 unset 和 null 吗?

标签 php

考虑以下代码:

class Test {
    public $definedButNotSet;
}

$Test = new Test();

var_dump($Test->definedButNotSet=== null); // true
var_dump(isset($Test->definedButNotSet)); // false

$Test->definedButNotSet = null;
var_dump(isset($Test->definedButNotSet)); // false
在我看来,PHP 隐式地将定义的变量设置为 null。有什么办法可以规避这一点,并区分显式设置为 null 的变量吗?和一个仅定义但未设置为任何值的变量?
更新 :
我基本上想看看在运行期间是否 definedButNotSet变量是否已更新。所以我对以下代码的预期结果是:
$Test = new Test();
var_dump(isset($Test->definedButNotSet)); // false

$Test->definedButNotSet = null;
var_dump(isset($Test->definedButNotSet)); // true expected here but php returns false
差异确实很重要的实际用例,基本上这也是我的用例:更新数据库中的行时,我想更新表的行,用户仅在调用更新方法时才更改。为此,我必须知道,用户是否隐式修改了表示表中行的类中的任何变量。
我正在运行一个自定义 ORM,目前它失败了,如果我在数据库中插入一行,其中的列将 default_timestamp 方法设置为默认值,并且在同一运行时,我尝试再次更新同一行,因为数据库设置值没有反射(reflect)在我的类实例中,因此在更新时 PHP 向他发送他的值为 null,这是不允许的。

最佳答案

稍微挑战一下问题的框架,您要做的是区分对同一属性的两种类型的写入:一种由您的 ORM 自动触发,另一种由用户手动触发。将在插入时提供默认值的值是其中的一个子集,但从数据库检索的值也可能需要与用户提供的值进行不同的处理(例如,跟踪是否需要更新)。
这样做的方法是将属性设为私有(private),并提供 getter 和 setter,或者使用魔法 __get 模拟属性访问器。和 __set方法(和 @property IDE 使用的注释)。然后,您可以在初始化代码之外存储已写入哪些属性的映射。
一个简单且可能有问题的实现来显示总体思路:

/**
 * This doc-block will be read by IDEs and provide auto-complete
 * @property int|null $id
 * @property string|null $name
 */
class Test {
    private ?int $id = null;
    private ?string $name = null;

    private array $updatedFields = [];

    /**
     * @internal Only to be called by the ORM
     */
    public function construct(?int $id, ?string $name) {
        $this->id = $id;
        $this->name = $name;
    }

    public function __get(string $property) {
        if ( property_exists($property, $this) ) {
             return $this->$property;
        }
        else {
             throw new LogicError("No such property '$property'");
        }
    }

    public function __set(string $property, $newValue) {
        if ( property_exists($property, $this) ) {
             $this->$property = $newValue;
             $this->updatedFields[ $property ] = true;
        }
        else {
             throw new LogicError("No such property '$property'");
        }
    }

    /**
     * Standard meaning of isset() for external code 
     */
    public function __isset(string $property) {
        if ( property_exists($property, $this) ) {
             return isset($this->$property);
        }
        else {
             throw new LogicError("No such property '$property'");
        }
    }

    /**
     * Special function for ORM code to determine which fields have changed
     */
    public function hasBeenWritten(string $property): bool {
        if ( property_exists($property, $this) ) {
             return $this->updatedFields[ $property ] ?? false;
        }
        else {
             throw new LogicError("No such property '$property'");
        }
    }
}

关于PHP - 有什么方法可以区分 unset 和 null 吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64822565/

相关文章:

php - 在 phpmyadmin 中使用 json 数据填充 mysql 表

php - 学说 2 @joincolumns

javascript - 当用户单击浏览器后退按钮时提交表单

PHP - 保护数字下载

PHP 无法连接到文件

php - 如何使用 json_encode 从 php 获取数据到 javascript?

php - 数据库类中的准备语句

php - Yii 用户在 15-30 分钟后退出,尽管 session 超时设置为至少 1 天

php - 解析错误 : syntax error, 意外 'endif' (T_ENDIF)?

php - HTTP header 未更改 : yii2