PHP RFC: Array Variable Shorthand
- Version: 1.4
- Date: 2026-10-03
- Author: Weilin Du, weilindu@php.net
- Status: Under Discussion
- 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:
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:
<?php $name = 'Weilin'; $age = 26; $user = ['id' => 1, :$name, :$age]; // ['id' => 1, 'name' => 'Weilin', 'age' => 26] ?>
The shorthand also works beside positional elements and unpacking:
<?php $name = 'Weilin'; $values = [10, 20]; $result = [...$values, :$name,]; // [0 => 10, 1 => 20, 'name' => 'Weilin'] ?>
Destructuring
The shorthand can also be mixed with explicit keys when destructuring:
<?php $user = ['name' => 'Weilin', 'age' => 26]; [:$name, 'age' => $years] = $user; // $name === 'Weilin'; $years === 26 ?>
The same keyed targets work with list():
<?php $user = ['name' => '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:
<?php $object = new ArrayObject(['name' => '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:
<?php $rows = [['name' => 'Weilin']]; foreach ($rows as [:$name]) { echo $name; // Weilin } ?>
Long syntax
The long forms support the same shorthand, including foreach destructuring:
Nesting
Nested construction and destructuring work in the same way:
<?php $name = 'Weilin'; $record = ['user' => array(:$name)]; // ['user' => ['name' => 'Weilin']] ['user' => [:$name]] = $record; echo $name; // Weilin ?>
A valid nested pattern uses list() at both levels:
<?php $record = ['user' => ['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:
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:
<?php $name = 'Weilin'; $age = 26; $user = [$age, :$name]; // Valid construction: [0 => 26, 'name' => 'Weilin'] [:$name, $age] = $user; // Invalid: keyed and unkeyed at the same level ?>
Duplicate keys
<?php $name = 'new'; $first = ['name' => '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:
<?php $name = 'new'; $first = [...['name' => 'old'], :$name]; // ['name' => 'new'] $second = [:$name, ...['name' => 'later']]; // ['name' => 'later'] ?>
Missing keys
<?php [:$name] = []; // Warning: Undefined array key "name" var_dump($name); // NULL ?>
What counts as a variable
Each of these shorthand forms is invalid; the last line shows the explicit-key alternative:
<?php [:$$name]; // Invalid: variable variable [:$name[0]]; // Invalid: array dimension [:$object->name]; // Invalid: object property [:$class::$property]; // Invalid: static property [:($name)]; // Invalid: expression ['name' => $object->name]; // Valid ?>
Whitespace and case
<?php $Name = 'upper'; $name = 'lower'; echo json_encode([: $Name, :$name]); // {"Name":"upper","name":"lower"} $array = [: /* key from the variable name */ $name]; // ['name' => 'lower'] ?>
Undefined source variable
Construction reads the variable normally, including its warning if it has not been defined:
<?php $array = [:$missing]; // Warning: Undefined variable $missing // ['missing' => 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:
<?php $name = 'before'; $byValue = [:$name]; $byReference = ['name' => &$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:
<?php $target = 'before'; $name =& $target; [:$name] = ['name' => '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 php-src PR #24034.
Implementation
References
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()andlist()and specified which variables qualify. - 2026-09-30: Documented the ternary-syntax overlap.
- 2026-10-03: Changed the shorthand spelling to
:$nameand 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.