How to access object properties with names like integers or invalid property names?
Updated for PHP 7.2
PHP 7.2 introduced a behavioral change to converting numeric keys in object and array casts, which fixes this particular inconsistency and makes all the following examples behave as expected.
One less thing to be confused about!
Original answer (applies to versions earlier than 7.2.0)
PHP has its share of dark alleys that you really don't want to find yourself inside. Object properties with names that are numbers is one of them...
What they never told you
Fact #1: You cannot access properties with names that are not legal variable names easily
$a = array('123' => '123', '123foo' => '123foo');
$o = (object)$a;
echo $o->123foo; // error
Fact #2: You can access such properties with curly brace syntax
$a = array('123' => '123', '123foo' => '123foo');
$o = (object)$a;
echo $o->{'123foo'}; // OK!
Fact #3: But not if the property name is all digits!
$a = array('123' => '123', '123foo' => '123foo');
$o = (object)$a;
echo $o->{'123foo'}; // OK!
echo $o->{'123'}; // error!
Live example.
Fact #4: Well, unless the object didn't come from an array in the first place.
$a = array('123' => '123');
$o1 = (object)$a;
$o2 = new stdClass;
$o2->{'123'} = '123'; // setting property is OK
echo $o1->{'123'}; // error!
echo $o2->{'123'}; // works... WTF?
Live example.
Pretty intuitive, don't you agree?
What you can do
Option #1: do it manually
The most practical approach is simply to cast the object you are interested in back into an array, which will allow you to access the properties:
$a = array('123' => '123', '123foo' => '123foo');
$o = (object)$a;
$a = (array)$o;
echo $o->{'123'}; // error!
echo $a['123']; // OK!
Unfortunately, this does not work recursively. So in your case you 'd need to do something like:
$highlighting = (array)$myVar->highlighting;
$data = (array)$highlighting['448364']->Data;
$value = $data['0']; // at last!
Option #2: the nuclear option
An alternative approach would be to write a function that converts objects to arrays recursively:
function recursive_cast_to_array($o) {
$a = (array)$o;
foreach ($a as &$value) {
if (is_object($value)) {
$value = recursive_cast_to_array($value);
}
}
return $a;
}
$arr = recursive_cast_to_array($myVar);
$value = $arr['highlighting']['448364']['Data']['0'];
However, I 'm not convinced that this is a better option across the board because it will needlessly cast to arrays all of the properties that you are not interested in as well as those you are.
Option #3: playing it clever
An alternative of the previous option is to use the built-in JSON functions:
$arr = json_decode(json_encode($myVar), true);
$value = $arr['highlighting']['448364']['Data']['0'];
The JSON functions helpfully perform a recursive conversion to array without the need to define any external functions. However desirable this looks, it has the "nuke" disadvantage of option #2 and additionally the disadvantage that if there is any strings inside your object, those strings must be encoded in UTF-8 (this is a requirement of json_encode
).
How to access object property with invalid characters
In JavaScript, object properties can be accessed by dot notation or bracket notation. Dot notation is often cleaner, but has restrictions. As you have noticed, your property contains an invalid character and therefore can't be accessed via dot notation. The solution, then, is to access the property using bracket notation like this: total['ga:newVisits']
so that your complete code will be {{total['ga:newVisits']}}
. Live demo here (click).
Another nice feature about bracket notation is that it allows you to use a variable name as a property:
var myObj {
bar: '123'
};
var foo = 'bar';
console.log(myObj[foo]); //logs '123'
Object property name as number
You can reference the object's properties as you would an array and use either me[123]
or me["123"]
Valid property names, property assignment and access in JavaScript
Short Answer
Object property names can be any valid identifier, numeric literal, or string literal (including the empty string).
With that said, there are some potentially confusing intricacies to keep in mind about JavaScript property names, as described below.
And unless you're working with valid (non-negative integer) array indexes, it's a good idea to explicitly assign all numerical property names as strings.
Negative Numbers
What might look like a negative number is actually an expression — something property names do not support.
// SyntaxError
const obj = { -12: 'nope' };
Fortunately, bracket notation handles expressions for us.
// Successful property assignment.
const obj = {};
obj[-12] = 'yup';
Typecasting
All property names are typecasted into strings before being stored.
const obj = {
12: '12'
};
console.log(typeof Object.keys(obj)[0]); // -> string
Parsing
But even before typecasting occurs, keys are parsed according to the syntax used, and transformed into a decimal literal.
const obj = {
// Valid string literal
'022': '022',
// Interpreted as decimal
6: '6',
// Interpreted as floating-point
.345: '0.345',
// Interpreted as floating-point
1.000: '1',
// Interpreted as floating-point
8.9890: '8.989',
// Interpreted as decimal
000888: '888',
// Interpreted as octal
0777: '511',
// Interpreted as hexadecimal
0x00111: '273',
// Interpreted as binary
0b0011: '3',
};
/* Quoted property name */
console.log(obj['022']); // "022"; as expected
console.log(obj[022]); // undefined; 022 is an octal literal that evaluates to 18 before our lookup ever occurs
/* Valid (non-negative integer) array index */
console.log(obj[6]); // "6"; as expected
console.log(obj['6']); // "6"; as expected
/* Non-valid array index */
console.log(obj[0x00111]); // "273"; we're accessing the property name as it was assigned (before it was parsed and typecasted)
console.log(obj['0x00111']); // undefined; after parsing and typecasting, our property name seems to have disappeared
console.log(obj['273']); // "273"; there it is, we found it using the evaluation of our original assignment
How can I access an object attribute that starts with a number?
What about this :
$Beeblebrox->{'2ndhead'}
Actually, you can do this for pretty much any kind of variable -- even for ones that are not class properties.
For example, you could think about a variable's name that contains spaces ; the following syntax will work :
${"My test var"} = 10;
echo ${"My test var"};
Even if, obviously, you would not be able to do anything like this :
$My test var = 10;
echo $My test var;
No idea how it's working internally, though... And after a bit of searching, I cannot find anything about this in the PHP manual.
Only thing I can find about {}
and variables is in here : Variable parsing -- but not quite related to the current subject...
But here's an article that shows a couple of other possiblities, and goes farther than the examples I posted here : PHP Variable Names: Curly Brace Madness
And here's another one that gives some additionnal informations about the way those are parsed : PHP grammar notes
How do you access a dynamic property in an object?
This won't work in PHP < 7.2.0 and the issue is that the string-integer array keys are actually converted to integer property names, not strings. An alternate way to get an object from an array that will work:
$var = json_decode(json_encode(array('1' => 'Object one','2' => 'Object two')));
$num = "2";
var_dump( $var->$num );
See the Demo, in PHP < 7.2.0 the (object)
cast converts to integer properties but json_decode
creates string properties.
How to create an object with number properties?
Er... Yes, you can. It's the very same syntax you are already using:
$obj = (object)nuLL;
$obj->{1} = 'Hi!';
var_dump($obj);
(Demo)
need help understanding php object property names versus array keys
I 'm not sure if xdebug has any problems with non-standard property names, but you definitely do not want to use property names like these on purpose. It doesn't make sense.
If you intend to use objects for OO purposes then you will declare their properties formally. In this case it is flat out impossible to use "strange" property names and there is nothing more to say.
If you don't intend to use objects for OO then you simply end up having arrays into which you can index $like->this
instead of $like['this']
. While the first form is shorter and I do prefer it myself, it becomes much uglier when using properties $with->{'strange-names'}
-- worse than the array access in fact. So again, there is nothing to be gained from doing this.
In some really exceptional situations there might be a case for property names like that -- for example if an object uses the names of its properties as column names in a database table. But even in such cases it is usually much more convenient to add a translation layer between PHP property names and database column names instead of fighting with the syntax every step of the way.
Bonus argument: If one look at this question is not enough to change your mind, nothing will. It's just a specific corner case, but we are talking about PHP. Corner cases should be... avoided.
How do I get the 'Status' element out of this object?
You can use curly brace syntax to access properties with invalid names
<?php
$myObject = json_decode('{"8772622": [{"status": "RENEWED"}]}');
var_dump($myObject);
var_dump($myObject->{'8772622'}[0]->status);
Output:
object(stdClass)#2 (1) {
["8772622"]=>
array(1) {
[0]=>
object(stdClass)#1 (1) {
["status"]=>
string(7) "RENEWED"
}
}
}
string(7) "RENEWED"
Alternativley, you could cast the object to an array and access it by index number
$status = ((array)$myObject)[8772622][0]->status;
Probably, you got this object from using json_decode()
on the API response. Set it's second argument to true
to get an array instead of an object in the first place.
Related Topics
PHP + MySQL Transactions Examples
How to Get the Last Inserted Id of a MySQL Table in PHP
Allow PHP Sessions to Carry Over to Subdomains
How to Access This Object Property With an Illegal Name
Do Htmlspecialchars and MySQL_Real_Escape_String Keep My PHP Code Safe from Injection
Bind Multiple Parameters into MySQLi Query
How to Get Id of the Last Updated Row in MySQL
PHP Domdocument Loadhtml Not Encoding Utf-8 Correctly
How to Read Any Request Header in PHP
Convert Time in Hh:Mm:Ss Format to Seconds Only
Formatting a Number With Leading Zeros in PHP
What Are the Best PHP Input Sanitizing Functions
Accessing @Attribute from Simplexml
PHP - Should I Call Exit() After Calling Location: Header
How to Find All Youtube Video Ids in a String Using a Regex