从 PHP 中的空值创建默认对象?

Posted

技术标签:

【中文标题】从 PHP 中的空值创建默认对象?【英文标题】:Creating default object from empty value in PHP? 【发布时间】:2012-02-12 14:46:23 【问题描述】:

我仅在将我的 php 环境升级到 PHP 5.4 及更高版本后才看到此错误。错误指向这行代码:

错误:

从空值创建默认对象

代码:

$res->success = false;

我首先需要声明我的$res 对象吗?

【问题讨论】:

你是如何/在哪里发起$res 的? @NAVEED There. 【参考方案1】:

对于 PHP 版本 E_STRICT 警告 enabled in error_reporting,或者对于 PHP 版本 >= 5.4,只需将 error_reporting 设置为至少 E_WARNING。当$resNULL 或尚未初始化时会触发该错误:

$res = NULL;
$res->success = false; // Warning: Creating default object from empty value

如果$res 已经初始化为某个值但不是对象,PHP 将报告不同的错误消息:

$res = 33;
$res->success = false; // Warning: Attempt to assign property of non-object

为了符合 PHP 5.4 之前的 E_STRICT 标准,或 PHP >= 5.4 中的正常 E_WARNING 错误级别,假设您正在尝试创建一个通用对象并分配属性 success,您需要在全局命名空间中将$res 声明为stdClass 的对象:

$res = new \stdClass();
$res->success = false;

【讨论】:

你应该检查对象是否已经存在:if (!isset($res)) $res = new stdClass();。否则,此代码不是“旧 PHP”隐式对象创建的等效替代品。 @Tomas 我们需要再做一次吗?模组上次清理了评论线程,因为它几乎没有增加价值。没有“旧 PHP”隐式对象创建。一直报错,一直发出警告,只是5.4的时候从E_STRICT改成了E_WARNING,所以有些人没注意E_STRICT就没遇到过。 @PeterAlfvin 在那一次特定的运行中没有定义!但是在不同的运行中,在代码中完全相同的位置,对象可能已经被定义了!这是人们经常犯的错误想法,这也是我试图强调这一点的原因。 Michael,即使在 5.4 中,隐式对象创建一直存在并且仍然存在。顺便说一句,在 PHP @tomas 哦,好吧,我认为我明白你的意思。你/迈克尔无法就此结束,这似乎很奇怪。顺便说一句,这次交流让我意识到斜体【参考方案2】:

不,你没有......当你将成功值添加到对象时,它会创建它。如果你不指定,则继承默认类。

【讨论】:

虽然它会返回 Strict Standards 消息...首先手动创建对象只是一个好习惯,虽然 PHP 对伪劣的编码实践相对宽容,但你不应该忽视正确地做事. 明白了,我只是用简单的是或否来回答这个问题,而不是定义或捍卫最佳实践:)【参考方案3】:

试试这个:

ini_set('error_reporting', E_STRICT);

【讨论】:

谢谢。当您使用第三方库(例如 nusoap)并且不想/不能更改源时,这是使用完整的。在这种情况下,您可以在需要其他源文件之前将 error_reporting 更改为 E_STRICT 级别。 虽然我只是将它添加到 nusoap 的顶部来解决我的问题。 嗯?此处的代码禁用除E_STRICT 错误之外的所有错误报告,包括抑制致命错误的消息。这不是解决此特定警告的合理建议,更重要的是,您几乎永远都不想这样做。为什么有 5 个人对此表示赞同,我不知道。 这太糟糕了!在调试时使用ini_set('error_reporting', -1);,但不要像以前一样使用上面的。 好的,所以你通过隐藏这个来解决问题?不确定您的代码会按预期工作...【参考方案4】:

对于 PHP E_STRICT。自 PHP 5.4 起,不幸地更改为 E_WARNING。由于E_WARNING 消息很有用,您不想完全禁用它们。

要消除此警告,您必须使用以下代码:

if (!isset($res)) 
    $res = new stdClass();

$res->success = false;

这是完全等效的替换。它确保了与 PHP 正在默默地做的完全相同的事情——不幸的是现在有警告——隐式对象创建。您应该始终检查对象是否已经存在,除非您绝对确定它不存在。 Michael 提供的代码一般来说并不好,因为在某些情况下,对象有时可能已经在代码中的同一位置定义,具体取决于具体情况。

【讨论】:

@carlosvini,这会给你Undefined variable: res @Pacerier 你是对的,你能做的最好的是: $res = isset($res) ? $res : 新的 stdClass(); -- 这就是我 6 个月前没有启用 E_NOTICE 的原因,因为它太冗长了。【参考方案5】:

此问题是由于您分配给未启动的对象实例而引起的。例如:

您的情况:

$user->email = 'exy@gmail.com';

解决方案:

$user = new User;
$user->email = 'exy@gmail.com';

【讨论】:

你不是假设“用户”类存在吗?它可能不会,现在它会产生不同的错误? 实际上我没有创建用户对象的实例,所以我得到了一个错误。但是在创建实例之后。它起作用了.. 这是 OOP 概念的一个普遍问题 :) 好吧,实际上真正的问题是您的示例假定要定义用户类,这不是面向对象的一般问题,它是一个关键要求;) 我宁愿用一个通用的“stdClass”代替暗示“用户”的前提。【参考方案6】:

如果你有数组并添加对象,试试这个。

$product_details = array();

foreach ($products_in_store as $key => $objects) 
  $product_details[$key] = new stdClass(); //the magic
  $product_details[$key]->product_id = $objects->id; 
   //see new object member created on the fly without warning.

这会发送 ARRAYObjects 供以后使用~!

【讨论】:

谢谢!!!!这就是帮助完成工作的原因。我需要逐步告诉 PHP 每个元素是什么。感谢您提醒我不要编写懒惰的代码。【参考方案7】:

简单地说,

    $res = (object)array("success"=>false); // $res->success = bool(false);

或者您可以使用以下方法实例化类:

    $res = (object)array(); // object(stdClass) -> recommended

    $res = (object)[];      // object(stdClass) -> works too

    $res = new \stdClass(); // object(stdClass) -> old method

并使用以下内容填充值:

    $res->success = !!0;     // bool(false)

    $res->success = false;   // bool(false)

    $res->success = (bool)0; // bool(false)

更多信息: https://www.php.net/manual/en/language.types.object.php#language.types.object.casting

【讨论】:

为什么 new stdClass() 被认为是“旧”方法?其他的更好吗? 它只是来自旧的 php 版本 在我的情况下 $this->route->uri = new stdClass(); 对我不起作用,我仍然有警告。注意:$this->route 已存在。 也许这与新版本的 php 不兼容?你用的是哪个版本?【参考方案8】:

我将以下内容放在出错的 PHP 文件的顶部,错误不再显示:

error_reporting(E_ERROR | E_PARSE);

【讨论】:

【参考方案9】:

得到这个错误的一个简单方法是在下面输入(a),意思是输入(b)

(a) $this->my->variable

(b) $this->my_variable

微不足道,但如果您不寻找它,很容易被忽视并且很难发现。

【讨论】:

这与原始问题有什么关系? _-> 之间没有混淆【参考方案10】:

如果你把“@”字符放在行的开头,那么 PHP 不会显示任何关于这一行的警告/通知。例如:

$unknownVar[$someStringVariable]->totalcall = 10; // shows a warning message that contains: Creating default object from empty value

为防止此行出现此警告,您必须将“@”字符放在该行的开头,如下所示:

@$unknownVar[$someStringVariable]->totalcall += 10; // no problem. created a stdClass object that name is $unknownVar[$someStringVariable] and created a properti that name is totalcall, and it's default value is 0.
$unknownVar[$someStringVariable]->totalcall += 10; // you don't need to @ character anymore.
echo $unknownVar[$someStringVariable]->totalcall; // 20

我在开发时使用了这个技巧。我不喜欢禁用所有警告消息,因为如果您没有正确处理警告,那么它们将来会成为一个大错误。

【讨论】:

@ 确实通过抑制警告来防止警告,只要您有可管理的代码,看起来就可以。但是如果你的代码变得更大并且你遇到了问题,你会以某种方式后悔使用它。您会发现自己正在寻找所有那些“@”来寻找您想要取消隐藏的警告,因为暂时它已经达到了它的目的,认为您实际上已经解决了问题,而实际上它一直在与您交谈而您只是不会不听。 我已经知道了。这是简短而快速的答案。有很多解决方案。 太棒了!不过,我是否可以礼貌地请求不同意,隐藏错误并不能真正解决问题(正如拉米纳斯尔所评论的那样)。 这个解决方法是我在 php 7.2 上唯一的工作。【参考方案11】:

您可能需要检查变量是否声明且类型正确。

if (!isset($res) || !is_object($res)) 
    $res = new \stdClass();
    // With php7 you also can create an object in several ways.
    // Object that implements some interface.
    $res = new class implements MyInterface ;
    // Object that extends some object.
    $res = new class extends MyClass ;
 

$res->success = true;

见PHP anonymous classes。

【讨论】:

【参考方案12】:

我有类似的问题,这似乎解决了问题。您只需要将 $res 对象初始化为 class 。假设这里的类名是 test。

class test

   //You can keep the class empty or declare your success variable here

$res = new test();
$res->success = false;

【讨论】:

【参考方案13】:

尝试使用:

$user = (object) null;

【讨论】:

一般来说,如果答案包含对代码的用途的解释,以及为什么在不介绍其他人的情况下解决问题的原因,答案会更有帮助。【参考方案14】:

我在尝试将变量添加到从 API 返回的对象时遇到了类似的问题。我正在使用 foreach 循环遍历数据。

foreach ( $results as $data ) 
    $data->direction = 0;

这在 Laravel 中引发了“从空值创建默认对象”异常。

我做了一个很小的改动。

foreach ( $results as &$data ) 
    $data->direction = 0;

只需将 $data 设为引用即可。

我希望这对我很烦的人有所帮助!

【讨论】:

【参考方案15】:

这是我在 PHP 7 中遇到的警告,解决此问题的简单方法是在使用变量之前对其进行初始化

$myObj=new \stdClass();

一旦你初始化了它,你就可以将它用于对象

 $myObj->mesg ="Welcome back - ".$c_user;

【讨论】:

【参考方案16】:

    首先认为你应该创建对象 $res = 新 \stdClass();

    然后用键和值 thay 分配对象 $res->成功=假;

【讨论】:

(我不明白thay。)如果您想在某些内容之后换行,请在该行的可见内容前附加两个空格。跨度> 【参考方案17】:

在 PHP 7 中可以这样创建匿名对象:

$res = new class 
    public $success = false;
;

https://www.php.net/manual/en/language.oop5.anonymous.php http://sandbox.onlinephpfunctions.com/code/ab774707a8219c0f35bdba49cc84228b580b52ee

【讨论】:

以上是关于从 PHP 中的空值创建默认对象?的主要内容,如果未能解决你的问题,请参考以下文章

PHP 5.4:禁用警告“从空值创建默认对象”

从空值 Laravel 8 创建默认对象

PHP过滤数组中的空值

如何修复 PHP Strict 错误“从空值创建默认对象”?

空对象模式

在存储在 hdfs 中的 orc 文件上创建外部表后,select * 返回时间戳的空值