====== PHP RFC: Array Variable Shorthand ======
* Version: 1.4
* Date: 2026-10-03
* Author: Weilin Du, weilindu@php.net
* Status: Under Discussion
* Implementation: https://github.com/php/php-src/pull/24034
* Discussion thread: https://externals.io/message/132700
* Voting thread: TBD
===== Introduction =====
Associative arrays often repeat a key and a variable with the same name. This RFC proposes '':$name'' as shorthand for ''"name" => $name'' in array construction and destructuring:
$x, 'y' => $y]
[:$x, :$y] = $point; // ['x' => $x, 'y' => $y] = $point
$point = array(:$x, :$y); // array('x' => $x, 'y' => $y)
list(:$x, :$y) = $point; // list('x' => $x, 'y' => $y) = $point
?>
===== Proposal =====
An array element written '':$name'' is equivalent to ''"name" => $name''. The key is the exact, case-sensitive variable name without the leading ''$''. This applies to both array constructors (''[]'' and ''array()'') and destructuring patterns (''[]'' and ''list()''). In construction, the variable is read; in destructuring, the value at that key is assigned to the variable. All existing behavior of an explicit keyed element applies, including duplicate keys and missing-key warnings.
Here, ''$name'' means one directly named variable token (''T_VARIABLE''). The shorthand does not accept variable variables, array dimensions, object or static properties, or arbitrary expressions: '':$$name'', '':$name[0]'', and '':$object->name'' are invalid. For those values, write an explicit key, for example ''["name" => $object->name]''.
Whitespace after '':'' is allowed. This includes an ASCII space, tab (''\t''), line feed (''\n''), and carriage return (''\r''). Comments may also appear between '':'' and the variable.
The identifier determines both the variable and its string key preserving case exactly.
The shorthand works at any nesting level and in destructuring patterns used by ''foreach''. It adds an array-element form but not a function-argument form. ''foo(:$name)'' is invalid. ''array()'' and ''list()'' are language constructs with array-element syntax, so they are included alongside their ''[]'' equivalents.
==== Examples ====
=== Construction ===
An array can mix the shorthand with explicit keys:
1, :$name, :$age];
// ['id' => 1, 'name' => 'Weilin', 'age' => 26]
?>
The shorthand also works beside positional elements and unpacking:
10, 1 => 20, 'name' => 'Weilin']
?>
=== Destructuring ===
The shorthand can also be mixed with explicit keys when destructuring:
'Weilin', 'age' => 26];
[:$name, 'age' => $years] = $user;
// $name === 'Weilin'; $years === 26
?>
The same keyed targets work with ''list()'':
'Weilin', 'age' => 26];
list(:$name, 'age' => $years) = $user;
// $name === 'Weilin'; $years === 26
?>
=== ArrayAccess destructuring ===
An object implementing ''ArrayAccess'' can be destructured by key, as with an explicit keyed element. This reads an array offset, not an object property:
'Ada']);
[:$name] = $object; // Equivalent to ['name' => $name] = $object
echo $name; // Ada
list(:$name) = $object;
echo $name; // Ada
?>
=== Foreach ===
Here is an example in a foreach loop:
'Weilin']];
foreach ($rows as [:$name]) {
echo $name; // Weilin
}
?>
=== Long syntax ===
The long forms support the same shorthand, including ''foreach'' destructuring:
1, :$name); // array('id' => 1, 'name' => 'Weilin')
list(:$name) = $user; // $name === 'Weilin'
foreach (array($user) as list(:$name)) {
echo $name; // Weilin
}
?>
=== Nesting ===
Nested construction and destructuring work in the same way:
array(:$name)];
// ['user' => ['name' => 'Weilin']]
['user' => [:$name]] = $record;
echo $name; // Weilin
?>
A valid nested pattern uses ''list()'' at both levels:
['name' => 'Ada']];
list('user' => list(:$name)) = $record;
echo $name; // Ada
?>
You cannot mix ''[]'' with ''list()'' within one nested destructuring pattern. This is an existing restriction, including when no shorthand is used:
['name' => 'Ada']];
['user' => [:$name]] = $record; // Valid
list('user' => list(:$name)) = $record; // Valid
list('user' => [:$name]) = $record; // Invalid: cannot mix list() and []
?>
=== Keyed and unkeyed destructuring ===
You cannot mix keyed and unkeyed elements at the same level of a destructuring pattern. This also applies without the shorthand. Array construction can still mix them:
26, 'name' => 'Weilin']
[:$name, $age] = $user; // Invalid: keyed and unkeyed at the same level
?>
=== Duplicate keys ===
'old', :$name]; // ['name' => 'new']
$second = [:$name, 'name' => 'later']; // ['name' => 'later']
?>
=== Unpacking with duplicate keys ===
When array unpacking and the shorthand produce the same string key, the later element wins:
'old'], :$name]; // ['name' => 'new']
$second = [:$name, ...['name' => 'later']]; // ['name' => 'later']
?>
=== Missing keys ===
=== What counts as a variable ===
Each of these shorthand forms is invalid; the last line shows the explicit-key alternative:
name]; // Invalid: object property
[:$class::$property]; // Invalid: static property
[:($name)]; // Invalid: expression
['name' => $object->name]; // Valid
?>
=== Whitespace and case ===
'lower']
?>
=== Undefined source variable ===
Construction reads the variable normally, including its warning if it has not been defined:
null]
?>
=== References ===
When constructing an array, ''[:$name]'' does not create a new reference to the original variable. A reference requires the existing explicit-key form:
&$name];
$name = 'after';
echo $byValue['name']; // before
echo $byReference['name']; // after
// [:&$name] is invalid.
?>
When destructuring, assignment to ''$name'' follows ordinary assignment. If ''$name'' is already a reference, the value it points to is overwritten:
'after'];
echo $target; // after
?>
===== Backward Incompatible Changes =====
None. The proposed syntax is currently invalid.
===== Proposed PHP Version(s) =====
PHP 8.7.
===== RFC Impact =====
==== To the Ecosystem ====
Static analyzers must recognize the new element form in ''[]'', ''array()'', and ''list()''.
==== To Existing Extensions ====
None.
==== To SAPIs ====
None.
===== Open Issues =====
None.
===== Future Scope =====
Shorthand in function calls is outside this RFC.
===== Voting Choices =====
TBD. Not in the voting process.
===== Patches and Tests =====
The draft implementation and PHPT tests are available at [[https://github.com/php/php-src/pull/24034|php-src PR #24034]].
===== Implementation =====
See [[https://github.com/php/php-src/pull/24034|draft implementation in php-src PR #24034]].
===== References =====
* [[https://wiki.php.net/rfc/named_params#shorthand_syntax_for_matching_parameter_and_variable_name|Named Arguments RFC: Future Scope]]
* [[https://www.php.net/manual/en/language.types.array.php#language.types.array.destructuring|PHP manual: array destructuring]]
* [[https://www.php.net/manual/en/class.arrayaccess.php|PHP manual: ArrayAccess]]
* [[https://www.php.net/manual/en/language.types.array.php#language.types.array.unpacking|PHP manual: array unpacking]]
* [[https://github.com/php/php-src/blob/179753061cb2268132310748fa8556b90cc4d52f/Zend/zend_language_scanner.l#L1409|PHP source: lexical whitespace definition]]
* [[https://docs.raku.org/syntax/Colon%20Pair|Raku documentation: colon pairs]]
* [[https://perldoc.perl.org/perlop#Comma-Operator|Perl documentation: the fat comma]]
* [[https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Object_initializer#property_definitions|MDN: JavaScript shorthand properties]]
* [[https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring|MDN: JavaScript object destructuring]]
===== Rejected Features =====
An earlier equals-sign prefix was replaced with '':$name''.
===== Changelog =====
* 2026-09-30: Initial draft.
* 2026-09-30: Added examples and changed status to Under Discussion.
* 2026-09-30: Included ''array()'' and ''list()'' and specified which variables qualify.
* 2026-09-30: Documented the ternary-syntax overlap.
* 2026-10-03: Changed the shorthand spelling to '':$name'' and added ArrayAccess and unpacking examples.
* 2026-10-03: Documented Raku and JavaScript shorthand as prior art.
* 2026-10-03: Clarified whitespace, ternary parsing, nested destructuring, keyed/unkeyed elements, references, and implementation status.