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

对于一个新数组,我这样做:

$aVal = array();


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

对象是否有类似的语法

(object)$oVal = "";


$oVal->key1->var1 = "something";
$oVal->key1->var2 = "something else";
523049 次浏览
$x = new stdClass();

A 手册中的注释最好地总结了它:

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

将标量或数组强制转换为 对象的实例 stdClass。你可以使用stdClass 当你需要一个通用对象时 实例。< / p >

Php.net说它是最好的:

$new_empty_object = new stdClass();

我想指出的是,在PHP中,没有像空对象这样的东西:

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

当然$obj是空的。

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

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

引用自变更日志函数

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

你有这个不好但有用的技术:

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

正如其他人指出的那样,您可以使用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()函数而不是构造函数语法的用法。它是一个返回值的普通函数,比构造函数限制更少。例如,函数名可以作为字符串传递给接受可调用形参的函数。函数还支持链接。所以你可以这样做: (结果= o美元internal_value)→some_operation_or_conversion_on_this_value (); < / p >

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

< p >编辑/更新: 我不再推荐这些方法了。这使得静态分析工具、ide和基于AST的自定义工具难以理解、验证、帮助您查找或编写代码。一般来说,魔术是不好的,除非在某些情况下,如果你能够让你的工具理解魔术,如果你以足够标准的方式来做,即使是标准的社区工具也能理解它,或者如果你的工具非常先进和功能齐全,以至于你只使用自己的工具。此外,我认为他们正在反对在即将到来的PHP版本中向随机对象添加属性的能力,我认为它只适用于某些对象,但我不建议使用该功能

除了僵尸的答案,如果你一直忘记stdClass

   function object(){


return new stdClass();


}

现在你可以做:

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

以类似的方式访问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};

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

$oVal = new stdClass();

但是我就我个人而言更喜欢使用:

$oVal = (object)[];

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


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

请参阅PHP手册(在这里):

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

在这里:

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

在这里(从PHP 7.3.0开始,var_export()导出使用(object)转换数组的对象):

现在将stdClass对象作为数组导出到对象((对象)数组(…)),而不是使用不存在的方法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 & lt;8创建以下Warning,隐式创建属性key1(对象本身)

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

PHP >= 8创建以下错误:

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

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

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

如果你想创建一个具有动态属性的对象(如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

你可以使用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值转换为一个对象,该对象产生stdClass内置类的一个新的空实例:

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


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

简短的回答

$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)"

好吧,你可以这样做,但在我看来并不实用/干净:

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

此外,使用这个语法,你可以找到一些有趣的惊喜,但在大多数情况下工作正常。

你也可以试试这种方法。

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

输出:

object(stdClass)#1 (0) { }

如果你不想这样做:

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

您可以使用以下其中之一:

PHP > = 5.4

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

PHP & lt; 5.4

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

这里有一个迭代的例子:

<?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; ?>

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

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

或者将数组强制转换为对象

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

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上测试)

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

$blankObject= json_decode('{}');