不允许动态创建公共属性。

3

让我们从简单的PHP代码开始:

<?php

class Test 
{
}

$test = new Test();
$test->x = 20;
echo $test->x;

这里的问题是,这段代码可以正常运行(在PHP 7.1中测试过,可能在一些旧版本中也可以正常运行)。

我看到的问题是,使用这样的代码很容易编写出非常难以分析并可能包含一些隐藏错误的代码。

问题: 有没有办法防止在类外动态创建对象属性,特别是在类外部?

对于这样的自定义类,可以使用创建自定义__set方法来创建未声明的属性,例如:

public function __set($property, $value)
{
    if (!property_exists($this, $property)) {
        throw new Exception("Property {$property} does not exit");

    }
    $this->$property = $value;
}

但它显然不能解决受保护/私有属性的问题 - property_exists()函数也会对受保护和私有属性返回true(需要使用Reflection来处理)。


__set() 用于在写入数据到无法访问的属性时运行。__get() 用于从无法访问的属性中读取数据。这些魔术方法并不代替 getters 和 setters。它们只允许您处理方法调用或属性访问,否则将导致错误。因此,它们更多地与错误处理相关。还请注意,它们比使用适当的 getter、setter 或直接方法调用要慢得多。 - Scaffold
1个回答

1
<?php
ini_set("display_errors", 1);
class Test 
{
    protected $name="ss";
    public function __set($property, $value)
    {
        //Checked for undefined properties
        if(!isset(get_object_vars($this)[$property]))
        {
             throw new Exception("Property {$property} does not exit");            
        }
        //Checking for public properties
        $prop = new ReflectionProperty($this, "name");
        if(!$prop->isPublic())
        {
            throw new Exception("Property {$property} does not exit");            
        }
        //Checking for non-existing properties
        if (!property_exists($this, $property)) 
        {
            throw new Exception("Property {$property} does not exit");
        }
        $this->$property = $value;
    }
}

$test = new Test();
$test->x = 20;
echo $test->x;

这只是问题中的拼写错误,问题并不在于此。 - Marcin Nabiałek
@MarcinNabiałek 这个问题是:有没有办法不允许在类外特别是动态地为对象创建属性?这是你在问题中写的。 - Sahil Gulati
是的,但这就是我展示的代码。它并没有解决我提到的其他问题,而且对于简单的问题来说,它是相当复杂的解决方案,不是吗? - Marcin Nabiałek
1
@SahilGulati,OP展示了他想要预防的情况。所以当然这是可用的代码,他想在有人试图在未声明属性的对象上设置属性时抛出异常或其他错误。(我想这被称为sealed?) - Jared Farrish
@MarcinNabiałek,我已经更新了我的帖子。我认为反射可以是检查属性类型并防止其在类外部被更新的选项。 - Sahil Gulati

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接