简体   繁体   中英

Why is ${0x0} correct?

The following code is working perfectly:

${0x0} = 'test';
echo ${0x0}; // prints "test"

But I can't figure out why. 0x0 (or 0 , as non-hex people call it) is a random container, it could have been any number, but php variables can't start with a number. What's so special about the { } used here, and what are their limitations ?

First of all, 0x0 is just a regular 0 in hexadecimal representation that gets cast to string '0 ' when used with the variable variable syntax:

var_dump(0x0===0); // prints "bool(true)"

${0x0} = 'test';
echo ${0x0}; // prints "test"
echo ${'0'}; // prints "test" as well
var_dump(get_defined_vars()); // contains ["0"] => string(4) "test"

You're correct whey you say that it isn't a valid variable name :

Variable names follow the same rules as other labels in PHP. A valid variable name starts with a letter or underscore, followed by any number of letters, numbers, or underscores. As a regular expression, it would be expressed thus: '[a-zA-Z_\\x7f-\\xff][a-zA-Z0-9_\\x7f-\\xff]*'

This is the reason why $0foo = 'Test'; triggers a parse error.

Some quick testing with the variable variables syntax reveals that, in fact, PHP does not seem to really care about variable names as far as they are strings:

${'123 abc xyz    '} = 'Test';
echo ${'123 abc xyz    '}; // Test
echo ${'123 abc xyz   '}; // PHP Notice:  Undefined variable: 123 abc xyz    in ...
var_dump(get_defined_vars()); // ["123 abc xyz    "] => string(4) "Test"

My guess is that the aforementioned naming restriction is imposed by the source code parser rather than the language core. It needs such rules to tell variables apart when analysing PHP code. Internally, the Zend engine that powers PHP handles variables as a hash map:

PHP variables, in general, consist out of two things: The label, which might, for instance, be an entry in a symbol table, and the actual variable container.

So as far as it receives a valid string for the label, it's happy.

From the documentation :

Curly braces may also be used, to clearly delimit the property name. They are most useful when accessing values within a property that contains an array, when the property name is made of mulitple parts, or when the property name contains characters that are not otherwise valid (eg from json_decode() or SimpleXML).

To me this implies that if you use ${...} , there are no limitations regarding what characters may be used in a variable name. Whether you should however...

In other words everything within the curly braces in such cases is a string!

So s 0x0 is indeed the hex version of 0 but here both are strings! That is why ${0x0} or ${0} work, where $0 or $0x0 won't!

PHP parser provides a special syntax to create a variable name from any expression that returns string (or can be casted to string), eg.:

<?php

define('A', 'aaa');

${'    _   '} = 'blah';
${'test' . A . (2 + 6)} = 'var';

echo ${'    _   '}; // blah
echo ${'testaaa8'}; // var

${'123'} = 'blah';
echo ${100 + 23}; // blah

function returnVarName() {
    return 'myVar';
}

$myVar = 12;
echo ${returnVarName()}; // 12

This syntax is also available for object properties:

$object->{' some property    ... with strage name'};

0x0 is just a hex representation of 0 literal.

On top of what @Michael Robinson said, in your example this will also be valid:

${0x0} = 'test';
$var = "0";
echo $$var; // prints "test"

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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