如何在 PHP 中定义一个空对象

Posted

技术标签:

【中文标题】如何在 PHP 中定义一个空对象【英文标题】:How to define an empty object in PHP 【发布时间】:2010-11-28 21:28:05 【问题描述】:

使用新数组我这样做:

$aVal = array();

$aVal[key1][var1] = "something";
$aVal[key1][var2] = "something else";

对象是否有类似的语法

(object)$oVal = "";

$oVal->key1->var1 = "something";
$oVal->key1->var2 = "something else";

【问题讨论】:

$var = (object) (boolean) (string) (int) (array) new StdClass; 你知道,只是为了安全。 Google 已将此问题标题编入索引:Arrays - How to define an empty object in php。与数组无关 @KolobCanyon 这条评论到底给这个问题增加了什么? 【参考方案1】:

创建“空”对象的标准方法是:

$oVal = new stdClass();

但我个人更喜欢使用:

$oVal = (object)[];

它更短,我个人认为它更清晰,因为 stdClass 可能会误导新手程序员(即“嘿,我想要一个对象,而不是一个类!”...)。


(object)[] 等价于new stdClass()

请参阅 PHP 手册 (here):

stdClass:通过类型转换为对象创建。

和here:

如果将对象转换为对象,则不会对其进行修改。如果将任何其他类型的值转换为对象,则创建 stdClass 内置类的新实例

和here(从 PHP 7.3.0 开始,var_export() 导出一个对象,该对象使用(object) 转换为数组):

现在将 stdClass 对象导出为强制转换为对象 ((object) array( ... )) 的数组,而不是使用不存在的方法 stdClass::__setState()。实际效果是现在 stdClass 是可导出的,生成的代码甚至可以在早期版本的 PHP 上运行。


但是请记住,empty($oVal) 返回 false,正如 @PaulP 所说:

没有属性的对象不再被认为是空的。

关于你的例子,如果你写:

$oVal = new stdClass();
$oVal->key1->var1 = "something"; // this creates a warning with PHP < 8
                                 // and a fatal error with PHP >=8
$oVal->key1->var2 = "something else";

PHP key1(对象本身)

警告:从空值创建默认对象

PHP >= 8 会产生以下错误:

致命错误:未捕获错误:未定义常量“key1”

在我看来,你最好的选择是:

$oVal = (object)[
  'key1' => (object)[
    'var1' => "something",
    'var2' => "something else",
  ],
];

【讨论】:

不是解决问题,而是创建一个新问题。需要解决的问题是人们应该知道stdClass 做了什么。 我写了stdClass 所做的事情。我在回答问题的代码上使用了stdClass。很抱歉,我并没有制造新问题,这是我个人的看法(正如我所写)。 “个人喜好”!=“问题” @Pacerier,我不明白你的固执。问题是“如何在 PHP 中定义一个空对象”。我的回答是正确的,我写信使用“new stdClass()”。我提供给用户“ed209”的代码是正确的,我使用了“new stdClass()”。此外,我添加了个人意见,并使用了粗体的“个人”来明确这不是“标准”的方式。在我看来,一个值得这么多 cmets 的问题至少应该是一个错误的答案。相反,如果您认为个人意见是一个问题,那么 this 可能是一个建设性分享想法的问题。 我真的很喜欢简写(object) []【参考方案2】:

也可以通过解析JSON得到一个空对象:

$blankObject= json_decode('');

【讨论】:

请不要重复现有的答案,尤其是如果您没有提供任何进一步的解释【参考方案3】:

简答

$myObj = new stdClass();

// OR 

$myObj = (object) [
    "foo" => "Foo value",
    "bar" => "Bar value"
];

长答案

我喜欢在 javascript 中创建匿名类型的对象是多么容易:

//JavaScript
var myObj = 
    foo: "Foo value",
    bar: "Bar value"
;
console.log(myObj.foo); //Output: Foo value

所以我总是尝试在 PHP 中编写这种对象就像 javascript 所做的那样

//PHP >= 5.4
$myObj = (object) [
    "foo" => "Foo value",
    "bar" => "Bar value"
];

//PHP < 5.4
$myObj = (object) array(
    "foo" => "Foo value",
    "bar" => "Bar value"
);

echo $myObj->foo; //Output: Foo value

但由于这基本上是一个数组,因此您不能像 js 那样将匿名函数分配给属性:

//JavaScript
var myObj = 
    foo: "Foo value",
    bar: function(greeting) 
        return greeting + " bar";
    
;
console.log(myObj.bar("Hello")); //Output: Hello bar

//PHP >= 5.4
$myObj = (object) [
    "foo" => "Foo value",
    "bar" => function($greeting) 
        return $greeting . " bar";
    
];
var_dump($myObj->bar("Hello")); //Throw 'undefined function' error
var_dump($myObj->bar); //Output: "object(Closure)"

好吧,你可以做到,但 IMO 不实用/干净:

$barFunc = $myObj->bar;
echo $barFunc("Hello"); //Output: Hello bar

此外,使用此合成器您可以找到一些 funny surprises,但在大多数情况下都可以正常工作。

【讨论】:

【参考方案4】:

stdClass 是默认的 PHP 对象。 stdClass 没有属性、方法或父级。它不支持魔术方法,也不实现任何接口。

当您将标量或数组转换为 Object 时,您将获得 stdClass 的一个实例。您可以在需要通用对象实例时使用 stdClass。

<?php
// ways of creating stdClass instances
$x = new stdClass;
$y = (object) null;        // same as above
$z = (object) 'a';         // creates property 'scalar' = 'a'
$a = (object) array('property1' => 1, 'property2' => 'b');
?>

stdClass 不是基类! PHP 类不会自动从任何类继承。所有类都是独立的,除非它们明确扩展另一个类。 PHP 在这方面不同于许多面向对象的语言。

<?php
// CTest does not derive from stdClass
class CTest 
    public $property1;

$t = new CTest;
var_dump($t instanceof stdClass);            // false
var_dump(is_subclass_of($t, 'stdClass'));    // false
echo get_class($t) . "\n";                   // 'CTest'
echo get_parent_class($t) . "\n";            // false (no parent)
?>

您不能在代码中定义名为“stdClass”的类。该名称已被系统使用。您可以定义一个名为“Object”的类。

你可以定义一个扩展stdClass的类,但是你不会得到任何好处,因为stdClass什么都不做。

(在 PHP 5.2.8 上测试)

【讨论】:

【参考方案5】:

使用通用对象并将键值对映射到它。

$oVal = new stdClass();
$oVal->key = $value

或者将数组转换为对象

$aVal = array( 'key'=>'value' );
$oVal = (object) $aVal;

【讨论】:

【参考方案6】:

这里是一个迭代的例子:

<?php
$colors = (object)[];
$colors->red = "#F00";
$colors->slateblue = "#6A5ACD";
$colors->orange = "#FFA500";

foreach ($colors as $key => $value) : ?>
    <p style="background-color:<?= $value ?>">
        <?= $key ?> -> <?= $value ?>
    </p>
<?php endforeach; ?>

【讨论】:

【参考方案7】:

如果您不想这样做:

$myObj = new stdClass();
$myObj->key_1 = 'Hello';
$myObj->key_2 = 'Dolly';

您可以使用以下方法之一:

PHP >=5.4

$myObj = (object) [
    'key_1' => 'Hello',
    'key_3' => 'Dolly',
];

PHP

$myObj = (object) array(
    'key_1' => 'Hello',
    'key_3' => 'Dolly',
);

【讨论】:

【参考方案8】:

你也可以试试这个方法。

<?php
     $obj = json_decode(""); 
     var_dump($obj);
?>

输出:

object(stdClass)#1 (0)  

【讨论】:

【参考方案9】:

您可以使用new stdClass()(推荐):

$obj_a = new stdClass();
$obj_a->name = "John";
print_r($obj_a);

// outputs:
// stdClass Object ( [name] => John ) 

或者您可以将一个空数组转换为一个对象,该对象会生成一个新的 stdClass 内置类的空实例:

$obj_b = (object) [];
$obj_b->name = "John";
print_r($obj_b);

// outputs: 
// stdClass Object ( [name] => John )  

或者您可以将 null 值转换为一个对象,该对象会生成 std​​Class 内置类的新空实例:

$obj_c = (object) null;
$obj_c->name = "John";
print($obj_c);

// outputs:
// stdClass Object ( [name] => John ) 

【讨论】:

【参考方案10】:

如果您想创建具有动态属性的对象(如在 javascript 中),而不会收到未定义属性的警告。

class stdClass 

public function __construct(array $arguments = array()) 
    if (!empty($arguments)) 
        foreach ($arguments as $property => $argument) 
            if(is_numeric($property)):
                $this->$argument = null;
            else:
                $this->$property = $argument;
            endif;
        
    


public function __call($method, $arguments) 
    $arguments = array_merge(array("stdObject" => $this), $arguments); // Note: method argument 0 will always referred to the main class ($this).
    if (isset($this->$method) && is_callable($this->$method)) 
        return call_user_func_array($this->$method, $arguments);
     else 
        throw new Exception("Fatal error: Call to undefined method stdObject::$method()");
    


public function __get($name)
    if(property_exists($this, $name)):
        return $this->$name;
    else:
        return $this->$name = null;
    endif;


public function __set($name, $value) 
    $this->$name = $value;




$obj1 = new stdClass(['property1','property2'=>'value']); //assign default property
echo $obj1->property1;//null
echo $obj1->property2;//value

$obj2 = new stdClass();//without properties set
echo $obj2->property1;//null

【讨论】:

【参考方案11】:

正如其他人指出的那样,您可以使用 stdClass。但是我认为没有 () 会更干净,就像这样:

$obj = new stdClass;

但是,根据这个问题,您似乎真正想要的是能够动态地向对象添加属性。尽管可以,但您不需要为此使用 stdClass 。真的你可以使用任何类。只需创建任何类的对象实例并开始设置属性。我喜欢创建自己的类,它的名称只是 o,并带有一些我喜欢在这些情况下使用的基本扩展功能,并且很适合从其他类扩展。基本上它是我自己的基础对象类。我也喜欢有一个简单地命名为 o() 的函数。像这样:

class o 
  // some custom shared magic, constructor, properties, or methods here


function o() 
  return new o;

如果您不喜欢拥有自己的基础对象类型,您可以简单地让 o() 返回一个新的 stdClass。一个优点是 o 比 stdClass 更容易记住并且更短,无论您是否将其用作类名、函数名或两者兼而有之。即使您的 o 类中没有任何代码,它仍然比笨拙的大写和命名的 stdClass 更容易记住(这可能会引发“性传播疾病类”的想法)。如果您确实自定义了 o 类,您可能会发现使用 o() 函数而不是构造函数语法。它是一个返回值的普通函数,它的限制比构造函数少。例如,函数名称可以作为字符串传递给接受可调用参数的函数。一个函数也支持链接。因此,您可以执行以下操作: $result= o($internal_value)->some_operation_or_conversion_on_this_value();

对于基础“语言”来说,这是一个很好的开始,可以在其上构建其他语言层,顶层是用完整的内部 DSL 编写的。这类似于 lisp 开发风格,PHP 对它的支持比大多数人意识到的要好得多。我意识到这与这个问题有点切线,但这个问题涉及到我认为充分利用 PHP 强大功能的基础。

【讨论】:

@Pacerier 你的意思是没有括号吗? ;) cis.upenn.edu/~matuszek/General/JavaSyntax/parentheses.html 打错字了,应该是无括号。 @Pacerier 好点 english.stackexchange.com/questions/130219/…【参考方案12】:

以与您类似的方式访问 stdClass 中的数据 对于关联数组,只需使用 $var 语法。

$myObj = new stdClass;
$myObj->Prop1 = "Something";
$myObj->Prop2 = "Something else";

// then to acces it directly

echo $myObj->'Prop1';
echo $myObj->'Prop2';

// or what you may want

echo $myObj->$myStringVar;

【讨论】:

【参考方案13】:

如果你一直忘记stdClass,除了zombat的回答

   function object()

        return new stdClass();

    

现在你可以这样做了:

$str='';
$array=array();
$object=object();

【讨论】:

我喜欢这种技术,尽管大多数 IDE 不会将“对象”这个术语强调为一个可能会让其他程序员感到困惑的函数。但是,嘿,它对我有用!【参考方案14】:

你有这个糟糕但有用的技术:

$var = json_decode(json_encode([]), FALSE);

【讨论】:

【参考方案15】:

php.net 说最好:

$new_empty_object = new stdClass();

【讨论】:

是的,这肯定是推荐的方式。【参考方案16】:

我想指出,在 PHP 中没有空对象之类的东西:

$obj = new stdClass();
var_dump(empty($obj)); // bool(false)

当然 $obj 是空的。

另一方面,空数组在这两种情况下都是空的

$arr = array();
var_dump(empty($arr));

引用更新日志函数empty

没有属性的对象不再被认为是空的。

【讨论】:

我在更改日志中找不到空的引用。 @powpow12 It used to be there。它在 5.0.0 中更改。【参考方案17】:
$x = new stdClass();

comment in the manual 总结得最好:

stdClass 是默认的 PHP 对象。 stdClass 没有属性、方法或 父母。它不支持魔法 方法,并且不实现接口。

当您将标量或数组转换为 对象,你得到一个实例 标准类。您可以使用 stdClass 每当您需要通用对象时 实例。

【讨论】:

$o=(object)NULL; -- 如果一个对象被转换为一个对象,它不会被修改。如果将任何其他类型的值转换为对象,则会创建 stdClass 内置类的新实例。如果值为 NULL,则新实例将为空。数组转换为具有由键命名的属性和相应值的对象。对于任何其他值,名为 scalar 的成员变量将包含该值。 我只是在脑海中说stdClass是“标准类” @zombat,括号里的 stdClass() 是什么? 如果遇到“找不到”:new \stdClass();PHP Namespace Doc @IvanCastellanos 你能解释一下你是如何从AIDS这个词中记住stdClass()的吗?

以上是关于如何在 PHP 中定义一个空对象的主要内容,如果未能解决你的问题,请参考以下文章

php 中如何创建一个空对象

PHP 变量类型的强制转换 & 创建空对象

PHP中怎样创建一个空对象

php实现空对象模式

设计模式之空对象模式(php实现)

PHP laravel 返回空对象 {}