# RFC: Short Array Variable Shorthand

- Status: Under discussion
- Authors: Weilin Du, weilindu@php.net
- Date: 2026-10-03
- Version: 1.4
- Implementation: https://github.com/php/php-src/pull/24034
- Original: https://wiki.php.net/rfc/array_shorthand
- Page: https://externals.io/rfc/array_shorthand
- More for agents: search with https://externals.io/search.md?q={query} · RFCs at https://externals.io/rfc.md · JSON API at https://externals.io/api · documentation at https://externals.io/llms.txt

## Discussions on the mailing list

- [\[RFC\] Short Array Variable Shorthand](https://externals.io/message/132700.md) — started on 2026-09-29, 12 messages

---

## 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:

```php
<?php
$x = 10;
$y = 20;
 
$point = [:$x, :$y]; // $point = ['x' => $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:

```php
<?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
<?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
<?php
$user = ['name' => 'Weilin', 'age' => 26];
[:$name, 'age' => $years] = $user;
// $name === 'Weilin'; $years === 26
?>
```

The same keyed targets work with `list()`:

```php
<?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
<?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
<?php
$rows = [['name' => 'Weilin']];
foreach ($rows as [:$name]) {
    echo $name; // Weilin
}
?>
```

#### Long syntax

The long forms support the same shorthand, including `foreach` destructuring:

```php
<?php
$name = 'Weilin';
$user = array('id' => 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:

```php
<?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
<?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:

```php
<?php
$record = ['user' => ['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:

```php
<?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
<?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
<?php
$name = 'new';
$first = [...['name' => 'old'], :$name]; // ['name' => 'new']
$second = [:$name, ...['name' => 'later']]; // ['name' => 'later']
?>
```

#### Missing keys

```php
<?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
<?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
<?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
<?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
<?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
<?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](https://github.com/php/php-src/pull/24034).

## Implementation

See [draft implementation in php-src PR #24034](https://github.com/php/php-src/pull/24034).

## References

- [Named Arguments RFC: Future Scope](https://externals.io/rfc/named_params#shorthand_syntax_for_matching_parameter_and_variable_name)
- [PHP manual: array destructuring](https://www.php.net/manual/en/language.types.array.php#language.types.array.destructuring)
- [PHP manual: ArrayAccess](https://www.php.net/manual/en/class.arrayaccess.php)
- [PHP manual: array unpacking](https://www.php.net/manual/en/language.types.array.php#language.types.array.unpacking)
- [PHP source: lexical whitespace definition](https://github.com/php/php-src/blob/179753061cb2268132310748fa8556b90cc4d52f/Zend/zend_language_scanner.l#L1409)
- [Raku documentation: colon pairs](https://docs.raku.org/syntax/Colon%20Pair)
- [Perl documentation: the fat comma](https://perldoc.perl.org/perlop#Comma-Operator)
- [MDN: JavaScript shorthand properties](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Object_initializer#property_definitions)
- [MDN: JavaScript object destructuring](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/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.
