从 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
。当$res
为NULL
或尚未初始化时会触发该错误:
$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 哦,好吧,我认为我明白你的意思。你/迈克尔无法就此结束,这似乎很奇怪。顺便说一句,这次交流让我意识到斜体不,你没有......当你将成功值添加到对象时,它会创建它。如果你不指定,则继承默认类。
【讨论】:
虽然它会返回 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.
这会发送 ARRAY 的 Objects 供以后使用~!
【讨论】:
谢谢!!!!这就是帮助完成工作的原因。我需要逐步告诉 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 中的空值创建默认对象?的主要内容,如果未能解决你的问题,请参考以下文章