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

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

错误:

从空值创建默认对象

代码:

$res->success = false;

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

【问题讨论】:

  • 你是如何/在哪里发起$res 的?
  • @NAVEED There.

标签: php


【解决方案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】:
            1. 首先认为你应该创建对象 $res = 新 \stdClass();

            2. 然后用键和值 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

            【讨论】:

              猜你喜欢
              • 2017-09-30
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2022-06-10
              • 2023-03-09
              • 1970-01-01
              • 2020-04-09
              • 1970-01-01
              相关资源
              最近更新 更多