**Shorthand**
`$object = json_decode(json_encode($array));`
Or
`$jsonString = json_encode($array);
$object = json_decode($jsonString);`
要创建一个新的对象 object,使用 new
语句实例化一个类:
<?php
class foo
{
function do_foo()
{
echo "Doing foo.";
}
}
$bar = new foo;
$bar->do_foo();
?>
详细讨论参见手册中类与对象章节。
如果将一个对象转换成对象,它将不会有任何变化。如果其它任何类型的值被转换成对象,将会创建一个内置类
stdClass
的实例。如果该值为
null
,则新的实例为空。
array 转换成 object 将使键名成为属性名并具有相对应的值。注意:在这个例子里, 使用 PHP 7.2.0 之前的版本,数字键只能通过迭代访问。
<?php
$obj = (object) array('1' => 'foo');
var_dump(isset($obj->{'1'})); // PHP 7.2.0 后输出 'bool(true)',之前版本会输出 'bool(false)'
var_dump(key($obj)); // PHP 7.2.0 后输出 'string(1) "1"',之前版本输出 'int(1)'
?>
对于其他值,会包含进成员变量名 scalar
。
<?php
$obj = (object) 'ciao';
echo $obj->scalar; // outputs 'ciao'
?>
**Shorthand**
`$object = json_decode(json_encode($array));`
Or
`$jsonString = json_encode($array);
$object = json_decode($jsonString);`
another way to instantiate an empty generic php object:
<?php $dataObj = json_decode('{}'); ?>
in php 7.2 this code works despite documentation said it gives false
<?php
$obj = (object) array('1' => 'foo');
//output foo
echo $obj->{'1'};
?>
<?php
/**
* Used for checking empty objects/array
* @uses How to check empty objects and array in php code
* @author Aditya Mehrotra<aditycse@gmail.com>
*/
/**
* Empty class
*/
class EmptyClass {
}
$obj = new stdClass();
//or any other class empty object
$emptyClassObj = new EmptyClass();
$array = array();
if (empty($array)) {
echo 'array is empty'; //expected result
} else {
echo 'array is not empty'; //unexpected result
}
echo "<br>";
if (empty($obj)) {
echo 'object is empty'; //expected result
} else {
echo 'object is not empty'; //unexpected result
}
echo "<br>";
if (empty($emptyClassObj)) {
echo 'EmptyClass is empty'; //expected result
} else {
echo 'EmptyClass is not empty'; //unexpected result
}
echo "<br>";
//Result SET 1
//array is empty => expected result
//object is not empty => ouch what happened
//EmptyClass is not empty => ouch what happened
/**
* So what we do for checking empty object
* @solution use any known property or check property count
* Or you can use below method
* Count function will not return 0 in empty object
*/
//Below line print "Object count:1"
echo 'Object count:' . count($obj);
echo "<br>";
/**
* This function is used to get object item counts
* @function getCount
* @access public
* @param object|array $var
* @return integer
*/
function getCount($var) {
$count = 0;
if (is_array($var) || is_object($var)) {
foreach ($var as $value) {
$count++;
}
}
unset($value);
return $count;
}
//Running code again with new logic
if (getCount($array) === 0) {
echo 'array is empty'; //expected result
} else {
echo 'array is not empty'; //unexpected result
}
echo "<br>";
if (getCount($obj) === 0) {
echo 'object is empty'; //expected result
} else {
echo 'object is not empty'; //unexpected result
}
echo "<br>";
if (getCount($emptyClassObj) === 0) {
echo 'EmptyClass is empty'; //expected result
} else {
echo 'EmptyClass is not empty'; //unexpected result
}
//Result SET 2
//array is empty => expected result ##everything is all right
//object is empty => expected result ##everything is all right
//EmptyClass is empty => expected result ##everything is all right
In PHP 5+, objects are passed by reference. This has got me into trouble in the past when I've tried to make arrays of objects.
For example, I once wrote something like the following code, thinking that I'd get an array of distinct objects. However, this is wrong. This code will create an array of multiple references to the same object.
<?php
class myNumber
{
public $value;
}
$arrayOfMyNumbers = array();
$arrayItem = new myNumber();
for( $i = 0; $i<3; $i++ ) {
$arrayItem->value = $i;
$arrayOfMyNumbers[] = $arrayItem;
}
var_dump($arrayOfMyNumbers);
?>
output:
array(3) {
[0]=>
object(myNumber)#1 (1) {
["value"]=>
int(4)
}
[1]=>
object(myNumber)#1 (1) {
["value"]=>
int(4)
}
[2]=>
object(myNumber)#1 (1) {
["value"]=>
int(4)
}
}
notice that the value at each index in the array is the same. That is because the array is just 3 references to the same object, but we change the property of this object every time the for loop runs. This isn't very useful. Instead, I've changed the code below so that it will create an array with three distinct references to three distinct objects. (if you're having a hard time understanding references, think of this as an array of objects, and that this is just the syntax you have to use.)
<?php
class myNumber
{
public $value;
}
$arrayOfMyNumbers = array();
for( $i = 0; $i<3; $i++ ) {
$arrayItem = new myNumber();
$arrayItem->value = $i;
$arrayOfMyNumbers[] = $arrayItem;
}
var_dump($arrayOfMyNumbers);
?>
output:
array(3) {
[0]=>
object(myNumber)#1 (1) {
["value"]=>
int(0)
}
[1]=>
object(myNumber)#2 (1) {
["value"]=>
int(1)
}
[2]=>
object(myNumber)#3 (1) {
["value"]=>
int(2)
}
}
Notice how the creation of a new object ("$arrayItem = new myNumber();") must happen every time the for loop runs for this to work.
This took me forever to figure out, so I hope this helps someone else.
If you need to force json_encode() to produce an object even when an array is empty or does not have successive 0-based numeric indices, you can simply convert the array to an object. JSON_FORCE_OBJECT does the same with ALL arrays, which might not be what you want.
<?php
echo json_encode([[]]), "\n";
// output: [[]]
echo json_encode([[]], JSON_FORCE_OBJECT), "\n";
// output: {"0":{}}
echo json_encode([(object)[]]), "\n";
// output: [{}]
echo json_encode([0=>"a", 1=>"b", 9=>"c"]), "\n";
// output: {"0":"a","1":"b","9":"c"}
echo json_encode([0=>"a", 1=>"b", 2=>"c"]), "\n";
// output: ["a","b","c"]
echo json_encode((object)[0=>"a", 1=>"b", 2=>"c"]), "\n";
// output: {"0":"a","1":"b","2":"c"}
?>
To create an object with values, in javascript you would use `{key: value}`. In PHP you use `[key=>value]`.
<!--Example shows how to convert array to stdClass Object and how to access its value for display -->
<?php
$num = array("Garha","sitamarhi","canada","patna"); //create an array
$obj = (object)$num; //change array to stdClass object
echo "<pre>";
print_r($obj); //stdClass Object created by casting of array
$newobj = new stdClass();//create a new
$newobj->name = "India";
$newobj->work = "Development";
$newobj->address="patna";
$new = (array)$newobj;//convert stdClass to array
echo "<pre>";
print_r($new); //print new object
##How deals with Associative Array
$test = [Details=>['name','roll number','college','mobile'],values=>['Naman Kumar','100790310868','Pune college','9988707202']];
$val = json_decode(json_encode($test),false);//convert array into stdClass object
echo "<pre>";
print_r($val);
echo ((is_array($val) == true ? 1 : 0 ) == 1 ? "array" : "not an array" )."</br>"; // check whether it is array or not
echo ((is_object($val) == true ? 1 : 0 ) == 1 ? "object" : "not an object" );//check whether it is object or not
?>
In PHP 7 there are a few ways to create an empty object:
<?php
$obj1 = new \stdClass; // Instantiate stdClass object
$obj2 = new class{}; // Instantiate anonymous class
$obj3 = (object)[]; // Cast empty array to object
var_dump($obj1); // object(stdClass)#1 (0) {}
var_dump($obj2); // object(class@anonymous)#2 (0) {}
var_dump($obj3); // object(stdClass)#3 (0) {}
?>
$obj1 and $obj3 are the same type, but $obj1 !== $obj3. Also, all three will json_encode() to a simple JS object {}:
<?php
echo json_encode([
new \stdClass,
new class{},
(object)[],
]);
?>
Outputs: [{},{},{}]
As of PHP 5.4, we can create stdClass objects with some properties and values using the more beautiful form:
<?php
$object = (object) [
'propertyOne' => 'foo',
'propertyTwo' => 42,
];
?>
Here a new updated version of 'stdObject' class. It's very useful when extends to controller on MVC design pattern, user can create it's own class.
Hope it help you.
<?php
class stdObject {
public function __construct(array $arguments = array()) {
if (!empty($arguments)) {
foreach ($arguments as $property => $argument) {
$this->{$property} = $argument;
}
}
}
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}()");
}
}
}
// Usage.
$obj = new stdObject();
$obj->name = "Nick";
$obj->surname = "Doe";
$obj->age = 20;
$obj->adresse = null;
$obj->getInfo = function($stdObject) { // $stdObject referred to this object (stdObject).
echo $stdObject->name . " " . $stdObject->surname . " have " . $stdObject->age . " yrs old. And live in " . $stdObject->adresse;
};
$func = "setAge";
$obj->{$func} = function($stdObject, $age) { // $age is the first parameter passed when calling this method.
$stdObject->age = $age;
};
$obj->setAge(24); // Parameter value 24 is passing to the $age argument in method 'setAge()'.
// Create dynamic method. Here i'm generating getter and setter dynimically
// Beware: Method name are case sensitive.
foreach ($obj as $func_name => $value) {
if (!$value instanceOf Closure) {
$obj->{"set" . ucfirst($func_name)} = function($stdObject, $value) use ($func_name) { // Note: you can also use keyword 'use' to bind parent variables.
$stdObject->{$func_name} = $value;
};
$obj->{"get" . ucfirst($func_name)} = function($stdObject) use ($func_name) { // Note: you can also use keyword 'use' to bind parent variables.
return $stdObject->{$func_name};
};
}
}
$obj->setName("John");
$obj->setAdresse("Boston");
$obj->getInfo();
?>
Class like stdClass but with the possibility to add and execute function.
class stdObject {
public function __construct(array $arguments = array()) {
if (!empty($arguments)) {
foreach ($arguments as $property => $argument) {
if ($argument instanceOf Closure) {
$this->{$property} = $argument;
} else {
$this->{$property} = $argument;
}
}
}
}
public function __call($method, $arguments) {
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}()");
}
}
}
If you call var_export() on an instance of stdClass, it attempts to export it using ::__set_state(), which, for some reason, is not implemented in stdClass.
However, casting an associative array to an object usually produces the same effect (at least, it does in my case). So I wrote an improved_var_export() function to convert instances of stdClass to (object) array () calls. If you choose to export objects of any other class, I'd advise you to implement ::__set_state().
<?php
/**
* An implementation of var_export() that is compatible with instances
* of stdClass.
* @param mixed $variable The variable you want to export
* @param bool $return If used and set to true, improved_var_export()
* will return the variable representation instead of outputting it.
* @return mixed|null Returns the variable representation when the
* return parameter is used and evaluates to TRUE. Otherwise, this
* function will return NULL.
*/
function improved_var_export ($variable, $return = false) {
if ($variable instanceof stdClass) {
$result = '(object) '.improved_var_export(get_object_vars($variable), true);
} else if (is_array($variable)) {
$array = array ();
foreach ($variable as $key => $value) {
$array[] = var_export($key, true).' => '.improved_var_export($value, true);
}
$result = 'array ('.implode(', ', $array).')';
} else {
$result = var_export($variable, true);
}
if (!$return) {
print $result;
return null;
} else {
return $result;
}
}
// Example usage:
$obj = new stdClass;
$obj->test = 'abc';
$obj->other = 6.2;
$obj->arr = array (1, 2, 3);
improved_var_export((object) array (
'prop1' => true,
'prop2' => $obj,
'assocArray' => array (
'apple' => 'good',
'orange' => 'great'
)
));
/* Output:
(object) array ('prop1' => true, 'prop2' => (object) array ('test' => 'abc', 'other' => 6.2, 'arr' => array (0 => 1, 1 => 2, 2 => 3)), 'assocArray' => array ('apple' => 'good', 'orange' => 'great'))
*/
?>
Note: This function spits out a single line of code, which is useful to save in a cache file to include/eval. It isn't formatted for readability. If you want to print a readable version for debugging purposes, then I would suggest print_r() or var_dump().
Do you remember some JavaScript implementations?
// var timestamp = (new Date).getTime();
Now it's possible with PHP 5.4.*;
<?php
class Foo
{
public $a = "I'm a!";
public $b = "I'm b!";
public $c;
public function getB() {
return $this->b;
}
public function setC($c) {
$this->c = $c;
return $this;
}
public function getC() {
return $this->c;
}
}
print (new Foo)->a; // I'm a!
print (new Foo)->getB(); // I'm b!
?>
or
<?php
// $_GET["c"] = "I'm c!";
print (new Foo)
->setC($_GET["c"])
->getC(); // I'm c!
?>
By far the easiest and correct way to instantiate an empty generic php object that you can then modify for whatever purpose you choose:
<?php $genericObject = new stdClass(); ?>
I had the most difficult time finding this, hopefully it will help someone else!
i would like to share a curious behavior on casted objects. Casting an object from a class with private/protected attributes results a stdClass with a private/protected attribute for get.
Example:
<?PHP
class Foo{
private $priv = 1;
public $pub = 2;
public function getSimple(){
return (object)(array) $this; //the array cast is to force a stdClass result
}
}
$bar = new Foo();
var_dump($bar->getSimple();// output: object(stdClass)#3 (2) { ["priv:private"]=> int(1) ["pub"]=> int(2) }
var_dump($bar->getSimple()->priv);// output: NULL, not a Fatal Error
var_dump($bar->getSimple()->pub);// output: int(2)
$barSimple = $bar->getSimple();
$barSimple->priv = 10;
var_dump($barSimple->priv);// output: int(10)
?>
Initialization, Instantiation and Instances are terms that can be confusing at first. Let's try to sort it out starting with this simple class definition.
<?php
class User
{
public $first_name;
public $last_name;
public function __toString()
{
return "User [first='$this->first_name', last='$this->last_name']";
}
}
?>
Now create several INSTANCES of User by INSTANTIATING the User class above.
<?php
$user_1 = new User; // $user_1 is an INSTANCE of User
$user_2 = new User; // $user_2 is an INSTANCE of User
echo $user_1 . '<br>'; // User [first='', last='']
echo $user_2 . '<br>'; // User [first='', last='']
?>
Here we have (2) two INSTANCES of User, but each instance was only INSTANTIATED once - when we used the 'new' operator.
And now looking at the printed output, you can see there are no values for their first or last names. This means that the objects themselves have NOT been INITIALIZED. To remedy this situation, rewrite the class definition by adding a __construct() method.
<?php
class User
{
public $first_name;
public $last_name;
public function __construct($first, $last) // Require first and last names when INSTANTIATING
{
$this->first_name = $first; // INITIALIZE $first_name;
$this->last_name = $last; // INITIALIZE $last_name;
}
public function __toString()
{
return "User [first='$this->first_name', last='$this->last_name']";
}
}
?>
Now try it again.
<?php
$user_1 = new User('John', 'Doe'); // $user_i is an INSTANCE of User
$user_2 = new User('Jane', 'Doe'); // $user_2 is an INSTANCE of User
echo $user_1 . '<br>'; // prints: User [first='John', last='Doe']
echo $user_2 . '<br>'; // prints: User [first='Jane', last='Doe']
?>
The __construct() method is called automatically by PHP when it sees the 'new' operator. Our __construct() method above requires the first and last names to be passed in as arguments and uses them to INITIALIZE objects when INSTANTIATING new INSTANCES.
You can create [recursive] objects with something like:
<?php
$literalObjectDeclared = (object) array(
'foo' => (object) array(
'bar' => 'baz',
'pax' => 'vax'
),
'moo' => 'ui'
);
print $literalObjectDeclared->foo->bar; // outputs "baz"!
?>
If having
class BugDetails extends Bug
you want to cast an object of a Bug to BugDetails like this
<?php
$clone = (BugDetails) clone $this;
// OR
$clone = (BugDetails) $bug;
?>
which doesn't work in PHP, you have two options:
1. Copying all (including private) properties manually (you could also use get_object_vars(), but this is shorter):
<?php
$clone = new BugDetails();
foreach ($this as $key => $val) {
$clone->$key = $val;
}
?>
2. Serialize an object Bug, manipulate the resulting string so that it has BugDetails inside and unserialize it.
See here: http://blog.adaniels.nl/articles/a-dark-corner-of-php-class-casting/
Spent two hours looking for more elegant solution, that's my findings.
CAUTION:
"Arrays convert to an object with properties named by keys, and corresponding values".
This is ALWAYS true, which means that even numeric keys are accepted when converting.
But the resulting properties cannot be accessed, since they don't match the variables naming rules.
So this:
<?php
$x = (object) array('a'=>'A', 'b'=>'B', 'C');
echo '<pre>'.print_r($x, true).'</pre>';
?>
works and displays:
stdClass Object
(
[a] => A
[b] => B
[0] => C
)
But this:
<?php
echo '<br />'.$x->a;
echo '<br />'.$x->b;
echo '<br />'.$x->{0}; # (don't use $x->0, which is obviously a syntax error)
?>
fails and displays:
A
B
Notice: Undefined property: stdClass::$0 in...
In response to Harmor and Mithras, you can use the json functions to convert multi-dimensional arrays to objects very reliably.
Also, note that just using (object)$x doesn't allow you to access properties inline. For example, this is invalid:
<?php
$x = array("foo"=>"bar");
echo ((object)$x)->foo; // PHP Parse error, unexpected T_OBJECT_OPERATOR
?>
However, this function will let you do that, and will also handle multi-dimensional arrays without any hassle.
<?php
function to_object ($x) {
return (is_object($x) || is_array($x)) ? json_decode(json_encode($x)) : (object) $x;
}
echo to_object( array("foo"=>"bar") )->foo; // "bar"
?>
Note that *numeric* arrays will not be converted to objects using this method.
In response to harmor: if an array contains another array as a value, you can recursively convert all arrays with:
<?php
function arrayToObject( $array ){
foreach( $array as $key => $value ){
if( is_array( $value ) ) $array[ $key ] = arrayToObject( $value );
}
return (object) $array;
}
?>
In response to sirbinam.
You cannot call a function or method before it exists. In your example, the global instance of stdout is just being passed around to differnet references (pointers). It however exists in the "dump" function scope via the global keyword.
The code below works fine and illustrates that "stdout" has been defined before its instantiation.
<?php
class profiler{
function profiler(){
$this->starttime = microtime();
}
function dump(){
global $stdout;
$this->endtime = microtime();
$duration = $this->endtime - $this->starttime;
$stdout->write($duration);
}
}
class stdout{
function write($msg){
echo $msg;
}
}
$stdout =& new stdout();
$profiler =& new profiler();
$profiler->dump();
?>
All classes and functions declarations within a scope exist even before the php execution reaches them. It does not matter if you have your classes defined on the first or last line, as long as they are in the same scope as where they are called and are not in a conditional statement that has not been evaluated yet.
In reply to the usort thing, you can access a property of an object dynamically by:
<?php
$obj = (object)array("Test" => "bar")
$var = "Test";
echo $obj->$var;
?>
This will output "bar", and do notice I call on ->$var and not just ->var.
You can create a new object using the built-in stdClass or by using type-casting:
<?php
// This is the proper way
$object1 = new stdClass();
// This works too
$object2 = (object) NULL;
// This will create an object from an array
$monkey_array = array('title'=>'Spider Monkey', 'src'=>'monkey.jpg');
$monkey_object = (object) $monkey_array;
print $monkey_object->title . ' ' . $monkey_object->src;
// You can type-cast in the middle of an expression
function customHTML($some_object) {
// this function expects an object as the argument and returns some output
}
print '<p>Writing some output ' . customHTML( (object) array('rows'=>3, 'cols'=>4) );
?>
To sort an array, that contains an object, after one fieldname inside the object, im using this function:
function objectSort($objectarray, $field)
{
for ($a=0;$a < (count($objectarray)); $a++)
{
for ($b=0;$b < (count($objectarray)); $b++)
{
if ($objectarray[$a]->$field < $objectarray[$b]->$field)
{
$temp = $objectarray[$a];
$objectarray[$a] = $objectarray[$b];
$objectarray[$b] = $temp;
}
}
}
return $objectarray;
}
If you use new to create items in an array, you may not get the results you want since the parameters to array will be copies of the original and not references.
By Example:
class Store {
var $item = 3;
}
$a = array( new Store() );
$b = $a;
$a[0]->item = 2;
print( "|" . $b[0]->item . "| <br>" ); //shows 3
$a = array();
$a[] =& new Store();
$b = $a;
$a[0]->item = 2;
print( "|" . $b[0]->item . "| <br>" ); //shows 2
This is extremely important if you intend on passing arrays of classes to functions and expect them to always use the same object instance!
Note: The following syntax is desired (or maybe even the default notation should translate as this):
$a = array( &new Store() );
PHP supports recursive type definitions as far as I've tried. The class below (a _very_ simple tree) is an example:
class Tree {
var $_value = null;
var $_children = array();
function Tree ($value) {
$this->_value = $value;
}
function addChild ($value) {
$aux_node = new Tree ($value);
$this->_children [] = $aux_node;
return $aux_node;
}
}
As you can see, in addChild we reference Tree again...
However, you must be careful about references. See the chapter "References explained" for more details.
Hope this helps.