About this PHP formatter
The engine is @prettier/plugin-php, the PHP plugin for Prettier. It reads the code into a full syntax tree and prints it back from scratch, so the original spacing barely matters: a controller crammed onto one line comes out with the same layout as a tidy one, and only the blank lines you left between statements carry over. It understands current PHP, including enums, readonly promoted constructor properties, attributes such as #[Route], match expressions, named arguments and the nullsafe ?-> operator.
Everything happens in the browser tab. That is worth knowing with PHP in particular, where wp-config.php and .env-loading bootstrap files tend to hold database passwords and salts.
Braces, quotes and indentation
- Braces has two settings. PER Coding Style / PSR-12 puts the opening brace of classes, interfaces, enums and functions on its own line, while
if,foreachand other control structures keep it on the same line. This is the layout PHP-FIG recommends and the one most frameworks use. 1TBS (same line) keeps every opening brace at the end of its line, which some WordPress and legacy code bases prefer. - Single quotes controls which quote character plain strings get. When it is off, the formatter prefers double quotes, so
'paid'becomes"paid". That surprises many PHP developers, who are used to single quotes for literals; turn the option on to keep them. Strings that contain$variablesor escape sequences such as\nkeep double quotes either way, because changing them would change what the string means. - Indent in the toolbar applies too. PHP starts at 4 spaces because PSR-12 requires it; switch to 2 spaces or tabs only for a code base that already uses them.
Changes beyond whitespace
A few rewrites go further than spacing. Long-form array(...) literals are converted to the short [...] syntax. When a function call, parameter list or array no longer fits in 80 columns, it is split one item per line and a trailing comma is added after the last item, which PHP accepts since version 8.0 in parameter lists. Code that must run on PHP 7 should be checked for those commas.
Nothing is reordered: use statements stay in the order written, and blank lines between namespace, use and the class are not added for you.
Files with HTML in them
PHP only starts at <?php or <?=. Anything outside those tags is inline HTML and is passed through unchanged, so a snippet pasted without the opening tag comes back exactly as it went in. Add <?php at the top if nothing seems to happen.
Templates that weave PHP and markup together, such as WordPress theme files, are formatted inside the PHP blocks only. The HTML around them is left as written, and a short alternative-syntax foreach (...): inside a template line may be broken over several lines in ways that look odd. For template-heavy files, format the logic in a separate class and keep the template simple. Input that starts with <?php is detected automatically; Ctrl/Cmd+Enter reruns the PHP printer.
Examples
Repository class with PSR-12 braces
Class and method braces move to their own lines, the long prepare call is wrapped with a trailing comma, and single quotes are kept.
<?php
namespace App\Repository;
use PDO;
class UserRepository{public function __construct(private PDO $db){}
public function findActive(int $limit=50):array{$stmt=$this->db->prepare('SELECT id, email FROM users WHERE active = 1 LIMIT :limit');$stmt->bindValue(':limit',$limit,PDO::PARAM_INT);$stmt->execute();return $stmt->fetchAll(PDO::FETCH_ASSOC);}}<?php
namespace App\Repository;
use PDO;
class UserRepository
{
public function __construct(private PDO $db) {}
public function findActive(int $limit = 50): array
{
$stmt = $this->db->prepare(
'SELECT id, email FROM users WHERE active = 1 LIMIT :limit',
);
$stmt->bindValue(':limit', $limit, PDO::PARAM_INT);
$stmt->execute();
return $stmt->fetchAll(PDO::FETCH_ASSOC);
}
}
PHP 8 enum, match and named arguments
Each match arm gets its own line, and with Single quotes off the plain string literals switch to double quotes.
<?php
enum Status:string{case Paid='paid';case Refunded='refunded';case Open='open';}
final class Money{public function __construct(public readonly int $amount,public readonly string $currency='SGD'){}}
$label=match($status){Status::Paid=>'Paid',Status::Refunded=>'Refunded',default=>'Open'};
$refund=new Money(amount:500,currency:'EUR');
$name=$user?->profile?->name??'guest';<?php
enum Status: string
{
case Paid = "paid";
case Refunded = "refunded";
case Open = "open";
}
final class Money
{
public function __construct(
public readonly int $amount,
public readonly string $currency = "SGD",
) {}
}
$label = match ($status) {
Status::Paid => "Paid",
Status::Refunded => "Refunded",
default => "Open",
};
$refund = new Money(amount: 500, currency: "EUR");
$name = $user?->profile?->name ?? "guest";
Legacy config array with 1TBS braces
Both array() calls become short [] syntax, and the interpolated string keeps its double quotes.
<?php
$config=array('db'=>array('host'=>'localhost','port'=>3306),'debug'=>false);
foreach($config['db'] as $key=>$value){if($value===null){continue;}echo "$key=$value\n";}<?php
$config = ['db' => ['host' => 'localhost', 'port' => 3306], 'debug' => false];
foreach ($config['db'] as $key => $value) {
if ($value === null) {
continue;
}
echo "$key=$value\n";
}
Common errors and how to fix them
| Error | Cause | Fix |
|---|---|---|
Parse Error : syntax error, unexpected '{', expecting T_VARIABLE on line 1 | A function parameter list is not closed, or a parameter is missing its $ sign, so PHP found a brace where it expected a variable. | Close the parameter list with ) and make sure every parameter name starts with $. |
Parse Error : syntax error, unexpected 'echo' (T_ECHO), expecting ';' on line 3 | The statement on the previous line has no semicolon, so the parser ran into the next keyword. The line number is where it noticed, one after the real mistake. | Add the missing ; at the end of the line before the one reported. |
Parse Error : syntax error, expecting '}' on line 2 | A class, function or control block was opened and never closed before the input ended. | Add the closing } for the block that is still open. |
Parse Error : syntax error, unexpected ';' on line 2 | An assignment or expression is incomplete, as in $total = ; with nothing on the right-hand side. | Complete the expression or delete the stray semicolon. |
Parse Error : syntax error, expecting '"' on line 2 | A double-quoted string was opened and not closed, so everything after it was read as part of the string. | Close the string. If it should contain a literal double quote, escape it as ". |
Frequently asked questions
Does this follow PSR-12?
Brace placement follows PER Coding Style and PSR-12 with the default Braces setting, and the default 4-space Indent covers the indentation rule. It is a formatter, not a linter, so naming rules and other non-layout parts of PSR-12 are not checked.
Why did my single quotes turn into double quotes?
With the Single quotes option off, Prettier’s PHP plugin prefers double quotes for plain strings. Turn Single quotes on to keep them; strings with variables or escapes are never switched.
Nothing changed when I formatted my code. Why?
The input probably has no opening <?php tag, so it was treated as inline HTML and passed through. Add <?php at the top and format again.
Does it work with Laravel and WordPress code?
Yes for plain PHP files such as controllers, models, plugins and functions.php. Blade templates are a separate syntax and are not supported.
Will the trailing commas break PHP 7?
Trailing commas in function calls work from PHP 7.3, but in parameter lists they need PHP 8.0. Remove them by hand if the code must run on older versions.