====== PHP RFC: Single-Expression functions ======
* **Version:** 1.0
* **Date:** 2025-05-22
* **Author:** Dmitrii Derepko, xepozzd@gmail.com
* **Status:** Voting
* **First Published at:** https://wiki.php.net/rfc/single-expression-functions
* **Implementation:** https://github.com/php/php-src/pull/17677
===== Introduction =====
This RFC proposes an alternative syntax for single-expression functions using the => operator instead of curly braces and explicit return statements.
This syntax provides a concise way to declare simple functions without the overhead of traditional function body syntax.
In PHP there are several types of functions:
* traditional/classic: function ...(...) {...}
* closures: function ...(...) use (...) {...}
* anonymous: $var = function (...) {...}
* class methods: class ... { function ...(...) {...} }
* arrow(+auto captures): fn(...) => ...
I'd like to discuss about class methods and classic functions.
Basically, they don't capture variable from outer scope. Class methods live inside the "this" scope.
There are a lot of code variants to be written in one line, but it's not acceptable with the functions.
One-liner is accepted with arrow function (fn () => ...), but methods cannot be written with "fn" declaration instead of "function", as long as classic functions.
===== Proposal =====
This RFC introduces a shorthand syntax for functions that consist of a single return statement.
The proposed syntax uses the => operator to denote that the function directly returns the result of the expression.
//*Shorthand syntax does not affect how capturing works.//*
==== Reasoning ====
Modern codebases typically contain numerous entities, models, forms, data transfer objects (DTOs), and value objects (VOs) with many getter and setter methods. These methods are usually simple one-liners that create significant cognitive overhead with minimal functional value.
Concise syntax makes it easier to associate function names with their return values, reducing mental parsing overhead.
Pipe (https://wiki.php.net/rfc/pipe-operator-v3) and Partial Function Application https://wiki.php.net/rfc/partial_function_application_v2 develop ideology of functional programming and boost one-liners.
==== PSR ====
PSR-compliant syntax requires multi-line formatting:
function getName()
{
return "Name";
}
Even compact syntax contains redundant elements:
function getName() { return "Name"; }
==== Cognitive Processing Analysis ====
When reading traditional function syntax, developers mentally process:
function getName() { return "Name"; }
The brain performs this parsing:
* function - skip (boilerplate)
* getName - identify function purpose
* () - note no parameters
* { - skip (boilerplate)
* return - skip (expected keyword)
* "Name" - identify return value
* ; - skip (boilerplate)
* } - skip (boilerplate)
Effectively, the brain extracts:
getName() "Name"
This syntax directly represents the mental model: function maps to value, making the code more readable and reducing the cognitive load required to understand simple getter/setter methods.
Unfortunately, it's not acceptable by PHP, so there should be a delimiter, e.g. =>, which is used in arrow functions. Plus functionality scope keyword, meaning "function starts".
function getName() => "Name"
==== Syntax ====
function functionName(parameters): returnType => expression;
This is functionally equivalent to:
function functionName(parameters): returnType
{
return expression;
}
==== Examples ====
Basic function:
// Short syntax
function getVersion(): int => 1;
// Equivalent traditional syntax
function getVersion(): int
{
return 1;
}
Function with parameters:
// Short syntax
function add(int $a, int $b): int => $a + $b;
// Equivalent traditional syntax
function add(int $a, int $b): int
{
return $a + $b;
}
Class methods:
class Calculator
{
// Short syntax
public function multiply(int $a, int $b): int => $a * $b;
// Equivalent traditional syntax
public function divide(int $a, int $b): float
{
return $a / $b;
}
}
Proxy classes:
class Proxy
{
private $decorated;
public function doA() => $this->decorated->doA();
public function doB() => $this->decorated->doB();
}
Data Models classes:
class User
{
private $name;
private $age;
private $username;
public function getAge() => $this->age;
public function setAge($value) => $this->age = $value;
public function getName() => $this->username;
public function setName($value) => $this->name = $value;
public function getUsername() => $this->username;
public function setUsername($value) => $this->username = $value;
}
It should be possibly done with native property getter/setters, but such methods have different purpose compared to getters/setters. E.g. mind of UserInterface.
===== Backward Incompatible Changes =====
This change introduces no breaking changes. The proposed syntax would currently result in a parse error, making it safe to implement.
===== Proposed PHP Version(s) =====
PHP 8.5
===== RFC Impact =====
==== To SAPIs ====
The implementation is purely lexical—during parsing, the short syntax is transformed into the equivalent traditional syntax before further processing. This ensures no impact to SAPIs.
==== To Existing Extensions ====
Nope.
==== To Opcache ====
Implementation does compile-time changes that do not affect Opcache.
==== New Constants ====
Nope.
==== php.ini Defaults ====
Nope.
===== Open Issues =====
Make sure there are no open issues when the vote starts!
===== Unaffected PHP Functionality =====
Parent scope won't be captured as arrow functions do.
Current RFC do lexer/parser modification allows to shorten typical code.
===== Future Scope =====
This section details areas where the feature might be improved in future, but that are not currently proposed in this RFC.
===== Proposed Voting Choices =====
Single voting widget that requires 2/3rd majority.
* Yes
* No
===== Patches and Tests =====
Links to any external patches and tests go here.
If there is no patch, make it clear who will create a patch, or whether a volunteer to help with implementation is needed.
Make it clear if the patch is intended to be the final patch, or is just a prototype.
For changes affecting the core language, you should also provide a patch for the language specification.
===== Implementation =====
* [[https://github.com/php/php-src/pull/17677|Pull Request / php-src]]
===== References =====
* [[rfc:short-functions|Original Short Functions RFC]]
* [[rfc:arrow_functions_v2|Arrow Functions RFC]]
* [[rfc:pipe-operator-v3|Pipe Operator RFC]]
* [[rfc:clone_with_v2|Clone RFC]]
* [[https://kotlinlang.org/docs/functions.html#single-expression-functions|Single-expression functions in Kotlin]]
===== Rejected Features =====
Keep this updated with features that were discussed on the mail lists.