如何制作一个PHP结构,它不会';不要抱怨未定义属性的请求?

如何制作一个PHP结构,它不会';不要抱怨未定义属性的请求?,php,Php,我有一大堆可选设置,我厌倦了检查isset和property\u是否存在 在Laravel中,如果我请求一个模型或请求中不存在的属性,我会得到null,并且没有投诉(错误)。如何对我的数据结构执行相同的操作 如果我尝试数组,我不能做简单的$settings['setting13'],我必须用空值预先填充它,或者做isset($settings['setting13'])$设置['setting13']:''或$settings['setting13']??空。如果我尝试一个对象(new\stdC

我有一大堆可选设置,我厌倦了检查
isset
property\u是否存在

在Laravel中,如果我请求一个模型或请求中不存在的属性,我会得到
null
,并且没有投诉(错误)。如何对我的数据结构执行相同的操作

如果我尝试数组,我不能做简单的
$settings['setting13']
,我必须用空值预先填充它,或者做
isset($settings['setting13'])$设置['setting13']:''
$settings['setting13']??空
。如果我尝试一个对象(
new\stdClass()
),则
$settings->setting13
仍会对未定义的属性发出警告

我如何使一个类在被要求提供它没有的属性时响应
null
或空字符串

!empty($settings['setting13']) ? $settings['setting13'] : ''
可以替换为

$settings['setting13'] ?: ''
只要您想要打印的内容和您想要检查的内容存在,都是相同的表达式。这并不是有史以来最干净的事情——检查任何东西的存在——但它相当清晰,可以链接:

echo ($a ?: $b ?: $c ? $default ?: '');
然而,您并不是第一个“厌倦了检查
isset
属性_是否存在”的人,只是我们还必须这样做,否则我们会在最不经意的时候得到意想不到的结果

这不是为了节省时间键入代码,而是为了节省时间而不是调试。

编辑:正如评论中所指出的,我用
isset()
而不是
!empty()
写了第一行。因为
?:
返回左操作数,如果它等于
true
,那么它当然与未检查的变量不兼容,您至少必须事先检查是否存在。可以测试它的空性。
如果左操作数存在并且与
NULL
不同,则返回其左操作数的运算符是
,它可以以与
?:
相同的方式链接。

当然不是最好的方法,但您可以在php中像这样使用错误抑制器:

$value=@$settings['setting13'];

如果未设置
$settings['setting13']
且未报告未定义的变量通知,则将
$value
完全设置为
NULL


对于对象,您应该只调用类中未定义的属性。

只需执行Laravel所做的操作,创建一个处理数据结构的类,如果键存在,该类将返回一个值,如果键不存在,则返回其他值

我将用一个示例类来说明(该类支持访问数组键的“点表示法”):

使用:


正如Jon Stirling在评论中提到的那样,也有可能创建包装器。这种方法将允许保持代码干净,并通过继承添加功能

<?php
class myArray implements ArrayAccess {
    private $container; 

    function __construct($myArray){
        $this->container = $myArray;
    }
    public function offsetSet($offset, $value) {
        if (is_null($offset)) {
            $this->container[] = $value;
        } else {
            $this->container[$offset] = $value;
        }
    }

    public function offsetExists($offset) {
        return isset($this->container[$offset]);
    }

    public function offsetUnset($offset) {
        unset($this->container[$offset]);
    }

    public function offsetGet($offset) {
        return isset($this->container[$offset]) ? $this->container[$offset] : null;
    }

}

$settings = array("setting1"=>1,"setting2"=>2,"setting3"=>3);

$arr = new myArray($settings);

echo $arr['setting1'];
echo "<br>";
echo $arr['setting3'];
echo "<br>";
echo $arr['setting2'];
echo "<br>";
echo "------";
echo "<br>";
echo  $arr['setting4'] ?:"Value is null";

对于对象,您可以在对象中实现magic _call/__get方法来为您执行这些检查,并实现arrayaccess接口以允许数组访问。您在什么结构中请求不存在的变量?@JonStirling感谢关键字,现在我发现了Laravel模型是如何做到这一点的。这是som吗E如果不明确定义一个类怎么办?我只需要一个地方,但似乎
stdClass
不支持神奇的方法。@GrumpyCrouton简化示例-表单上的文本字段。如果它们是通过各种方式设置的(获取查询、用户首选项),我需要填充它们。因此,我从GET中获取一些内容,为特定字段添加一些内容,并在视图中为文本字段设置
name=“field5”value=“”
。我真的希望避免在那里进行检查。您是对的,它不适用于stdClass,您必须使用您在Laravel中发现的自己的类。:)我在“纯”中这样做没有问题“PHP文件。但是在视图中-要在每个文本输入中重复检查。。。它看起来非常丑陋,并且破坏了可读性。解决方法是在所有可能的数组键前加上
null
s似乎引入了更多断点……这根本不是什么黑魔法,只是在
之前和之后加上相同表达式的语法糖。记住这一点,因为它只适用于标量。数组实体和对象属性仍然需要您使用函数来检查是否存在。虽然我个人更喜欢较长的语法,但对我来说,该快捷方式不直观,需要花费一些时间来阅读和理解。。。我投票支持最后那句粗体的话。我希望我能将该语句上推两次。@David我通常在视图中使用它,在视图中我打印了很多可能为空的字符串。事实上,这是我发现它可读性和安全性都足以提高效率的唯一一种情况,因为它允许我避免PHP冗长,以免让我的视图变得凌乱,同时又不会失去安全性。在pute PHP代码中,这些快捷方式绝对是不礼貌的。
?:
不会抑制关于不存在索引的警告!唯一执行此操作的操作员是
$my_structure = [
    'url' => 'www.stackoverflow.com',
    'questions' => [
        'title' => 'this is test title'
    ]
];

$config = new MyConfigClass($my_structure);

echo $config->get('url'); // echoes www.stackoverflow.com
echo $config->get('questions.title'); // echoes this is test title
echo $config->get('bad key that is not there'); // returns null
<?php
class myArray implements ArrayAccess {
    private $container; 

    function __construct($myArray){
        $this->container = $myArray;
    }
    public function offsetSet($offset, $value) {
        if (is_null($offset)) {
            $this->container[] = $value;
        } else {
            $this->container[$offset] = $value;
        }
    }

    public function offsetExists($offset) {
        return isset($this->container[$offset]);
    }

    public function offsetUnset($offset) {
        unset($this->container[$offset]);
    }

    public function offsetGet($offset) {
        return isset($this->container[$offset]) ? $this->container[$offset] : null;
    }

}

$settings = array("setting1"=>1,"setting2"=>2,"setting3"=>3);

$arr = new myArray($settings);

echo $arr['setting1'];
echo "<br>";
echo $arr['setting3'];
echo "<br>";
echo $arr['setting2'];
echo "<br>";
echo "------";
echo "<br>";
echo  $arr['setting4'] ?:"Value is null";