简体   繁体   English

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

[英]How to define an empty object in PHP

with a new array I do this:用一个新数组我这样做:

$aVal = array();

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

Is there a similar syntax for an object对象是否有类似的语法

(object)$oVal = "";

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

A comment in the manual sums it up best: 手册中评论总结得最好:

stdClass is the default PHP object. stdClass 是默认的 PHP 对象。 stdClass has no properties, methods or parent. stdClass 没有属性、方法或父级。 It does not support magic methods, and implements no interfaces.它不支持魔术方法,也没有实现任何接口。

When you cast a scalar or array as Object, you get an instance of stdClass.当您将标量或数组转换为 Object 时,您将获得 stdClass 的一个实例。 You can use stdClass whenever you need a generic object instance.只要需要通用对象实例,就可以使用 stdClass。

The standard way to create an "empty" object is:创建“空”对象的标准方法是:

$oVal = new stdClass();

But I personally prefer to use:但我个人更喜欢使用:

$oVal = (object)[];

It's shorter and I personally consider it clearer because stdClass could be misleading to novice programmers (ie "Hey, I want an object, not a class!"...).它更短,我个人认为它更清晰,因为stdClass可能会误导新手程序员(即“嘿,我想要一个对象,而不是一个类!”...)。


(object)[] is equivalent to new stdClass() . (object)[]等价于new stdClass()

See the PHP manual ( here ):请参阅 PHP 手册( 此处):

stdClass : Created by typecasting to object. stdClass :通过对对象进行类型转换而创建。

and here : 在这里

If an object is converted to an object, it is not modified.如果将对象转换为对象,则不会对其进行修改。 If a value of any other type is converted to an object, a new instance of the stdClass built-in class is created .如果将任何其他类型的值转换为对象,则会创建 stdClass 内置类的新实例

and here (starting with PHP 7.3.0, var_export() exports an object casting an array with (object) ):在这里(从 PHP 7.3.0 开始, var_export()导出一个使用(object)转换数组的(object) ):

Now exports stdClass objects as an array cast to an object ((object) array( ... )), rather than using the nonexistent method stdClass::__setState().现在将 stdClass 对象作为转换为对象的数组导出 ((object) array( ... )),而不是使用不存在的方法 stdClass::__setState()。 The practical effect is that now stdClass is exportable, and the resulting code will even work on earlier versions of PHP.实际效果是现在 stdClass 是可导出的,生成的代码甚至可以在早期版本的 PHP 上运行。


However remember that empty($oVal) returns false , as @PaulP said:但是请记住, empty($oVal) 返回 false ,正如@PaulP 所说:

Objects with no properties are no longer considered empty.没有属性的对象不再被认为是空的。

Regarding your example, if you write:关于你的例子,如果你写:

$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 < 8 creates the following Warning, implicitly creating the property key1 (an object itself) PHP < 8 创建以下警告,隐式创建属性key1 (对象本身)

Warning: Creating default object from empty value警告:从空值创建默认对象

PHP >= 8 creates the following Error: PHP >= 8 创建以下错误:

Fatal error: Uncaught Error: Undefined constant "key1"致命错误:未捕获错误:未定义常量“key1”

In my opinion your best option is:在我看来,你最好的选择是:

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

I want to point out that in PHP there is no such thing like empty object in sense:我想指出,在 PHP 中没有像空对象这样的东西:

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

but of course $obj will be empty.但当然 $obj 将是空的。

On other hand empty array mean empty in both cases另一方面,空数组在两种情况下都意味着空

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

Quote from changelog function empty来自变更日志功能的引用为

Objects with no properties are no longer considered empty.没有属性的对象不再被认为是空的。

Short answer简答

$myObj = new stdClass();

// OR 

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

Long answer长答案

I love how easy is to create objects of anonymous type in JavaScript:我喜欢在 JavaScript 中创建匿名类型的对象是多么容易:

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

So I always try to write this kind of objects in PHP like javascript does :所以我总是尝试像 javascript 那样用 PHP 编写这种对象:

//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

But as this is basically an array you can't do things like assign anonymous functions to a property like js does:但由于这基本上是一个数组,因此您不能像 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)"

Well, you can do it, but IMO isn't practical / clean:好吧,你可以做到,但 IMO 不实用/干净:

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

Also, using this synthax you can find some funny surprises , but works fine for most cases.此外,使用这个合成器你会发现一些有趣的惊喜,但在大多数情况下都可以正常工作。

php.net 说最好:

$new_empty_object = new stdClass();

In addition to zombat's answer if you keep forgetting stdClass除了 zombat 的答案,如果你一直忘记stdClass

   function object(){

        return new stdClass();

    }

Now you can do:现在你可以这样做:

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

You can use new stdClass() (which is recommended):您可以使用new stdClass() (推荐):

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

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

Or you can convert an empty array to an object which produces a new empty instance of the stdClass built-in class:或者,您可以将空数组转换为生成 std​​Class 内置类的新空实例的对象:

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

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

Or you can convert the null value to an object which produces a new empty instance of the stdClass built-in class:或者您可以将null值转换为一个对象,该对象生成 std​​Class 内置类的新空实例:

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

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

to access data in a stdClass in similar fashion you do with an asociative array just use the {$var} syntax.要以与关联数组类似的方式访问 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};

Use a generic object and map key value pairs to it.使用通用对象并将键值对映射到它。

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

Or cast an array into an object或将数组转换为对象

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

As others have pointed out, you can use stdClass.正如其他人指出的那样,您可以使用 stdClass。 However I think it is cleaner without the (), like so:但是我认为没有 () 会更干净,如下所示:

$obj = new stdClass;

However based on the question, it seems like what you really want is to be able to add properties to an object on the fly.但是,根据这个问题,您似乎真正想要的是能够动态地向对象添加属性。 You don't need to use stdClass for that, although you can.尽管可以,但您不需要为此使用 stdClass。 Really you can use any class.你真的可以使用任何类。 Just create an object instance of any class and start setting properties.只需创建任何类的对象实例并开始设置属性。 I like to create my own class whose name is simply o with some basic extended functionality that I like to use in these cases and is nice for extending from other classes.我喜欢创建我自己的类,它的名字只是 o,带有一些我喜欢在这些情况下使用的基本扩展功能,并且非常适合从其他类扩展。 Basically it is my own base object class.基本上它是我自己的基础对象类。 I also like to have a function simply named o().我也喜欢有一个简单地命名为 o() 的函数。 Like so:像这样:

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

function o() {
  return new o;
}

If you don't like to have your own base object type, you can simply have o() return a new stdClass.如果您不喜欢拥有自己的基本对象类型,您可以简单地让 o() 返回一个新的 stdClass。 One advantage is that o is easier to remember than stdClass and is shorter, regardless of if you use it as a class name, function name, or both.一个优点是 o 比 stdClass 更容易记住并且更短,无论您将它用作类名、函数名还是两者。 Even if you don't have any code inside your o class, it is still easier to memorize than the awkwardly capitalized and named stdClass (which may invoke the idea of a 'sexually transmitted disease class').即使您的 o 类中没有任何代码,它仍然比笨拙的大写和命名的 stdClass(这可能会引发“性传播疾病类”的想法)更容易记住。 If you do customize the o class, you might find a use for the o() function instead of the constructor syntax.如果您确实自定义了 o 类,您可能会发现使用 o() 函数而不是构造函数语法。 It is a normal function that returns a value, which is less limited than a constructor.它是一个返回值的普通函数,其限制比构造函数少。 For example, a function name can be passed as a string to a function that accepts a callable parameter.例如,函数名称可以作为字符串传递给接受可调用参数的函数。 A function also supports chaining.一个函数也支持链接。 So you can do something like: $result= o($internal_value)->some_operation_or_conversion_on_this_value();所以你可以这样做: $result= o($internal_value)->some_operation_or_conversion_on_this_value();

This is a great start for a base "language" to build other language layers upon with the top layer being written in full internal DSLs.对于基础“语言”来说,这是一个很好的开始,可以在其上构建其他语言层,顶层是用完整的内部 DSL 编写的。 This is similar to the lisp style of development, and PHP supports it way better than most people realize.这类似于 lisp 的开发风格,PHP 对它的支持比大多数人意识到的要好。 I realize this is a bit of a tangent for the question, but the question touches on what I think is the base for fully utilizing the power of PHP.我意识到这对这个问题有点切题,但这个问题涉及我认为充分利用 PHP 功能的基础。

If you want to create object (like in javascript) with dynamic properties, without receiving a warning of undefined property.如果您想创建具有动态属性的对象(如在 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

You can try this way also.你也可以试试这个方法。

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

Output:输出:

object(stdClass)#1 (0) { }

If you don't want to do this:如果你不想这样做:

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

You can use one of the following:您可以使用以下方法之一:

PHP >=5.4 PHP >=5.4

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

PHP <5.4 PHP <5.4

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

Here an example with the iteration:这是一个迭代示例:

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

stdClass is the default PHP object. stdClass 是默认的 PHP 对象。 stdClass has no properties, methods or parent. stdClass 没有属性、方法或父级。 It does not support magic methods, and implements no interfaces.它不支持魔术方法,也没有实现任何接口。

When you cast a scalar or array as Object, you get an instance of stdClass.当您将标量或数组转换为 Object 时,您将获得 stdClass 的一个实例。 You can use stdClass whenever you need a generic object instance.只要需要通用对象实例,就可以使用 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 is NOT a base class! stdClass 不是基类! PHP classes do not automatically inherit from any class. PHP 类不会自动从任何类继承。 All classes are standalone, unless they explicitly extend another class.所有类都是独立的,除非它们显式扩展另一个类。 PHP differs from many object-oriented languages in this respect. 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)
?>

You cannot define a class named 'stdClass' in your code.您不能在代码中定义名为“stdClass”的类。 That name is already used by the system.该名称已被系统使用。 You can define a class named 'Object'.您可以定义一个名为“Object”的类。

You could define a class that extends stdClass, but you would get no benefit, as stdClass does nothing.您可以定义一个扩展 stdClass 的类,但您不会得到任何好处,因为 stdClass 什么都不做。

(tested on PHP 5.2.8) (在 PHP 5.2.8 上测试)

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

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

您还可以通过解析 JSON 来获取空对象:

$blankObject= json_decode('{}');

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM