PhpStorm 2020.3: PHP 8, PHPStan and Psalm, Xdebug 3, Tailwind CSS, and Collaborative Development

Read this post in other languages:

PhpStorm 2020.3 is now available!

This major release includes full support for PHP 8, static analyzers PHPStan and Psalm, Xdebug 3, Tailwind CSS, collaborative development via Code With Me, and much more.

Download PhpStorm 2020.3

Read on for details on all the new features and significant updates, along with a ton of GIFs!

  • PHP 8: support for all language features, and even open-source Custom Attributes.
  • PHPStan and Psalm can detect issues directly in the code editor or in batch mode.
  • Xdebug 3 with streamlined configuration, and Debugger Improvements such as inline watches and interactive hints.
  • HTTP Client can now run Guzzle requests and copy requests as cURL.
  • Collaborative Development lets you share your project with others and work on it together in real-time.
  • In the Editor, you can now render diagrams and charts with Mermaid.js, split tabs easier, and instantly preview files without opening them.
  • All sorts of IDE enhancements: Search Everywhere got some new moves. IDE visual theme stays in sync with the OS. Setting PhpStorm as a default application for opening files.
  • Git stage is now supported as an alternative to changelists.
  • Database Tools bring support for SQL for MongoDB and new data extractors.
  • Tailwind CSS, with coding assistance for Tailwind classes.


PHP 8.0 has already been released. We would like to say a big thank you to all the contributors and the release managers! The folks from PHP even let us participate in creating the announcement page – check it out.

PhpStorm 2020.3 supports all of the latest language changes. Here’s what’s available and how you can use it in the IDE.

Set language level from the status bar

The status bar now always displays the current language level of the project. Switch it from there to take advantage of the new features of PHP 8.

If switching is inactive, it means there is a constraint on the language version in the project’s composer.json you should adjust it in that file.

Named arguments

In PHP 8, function and method arguments can be passed by specifying a parameter name. Calls are now self-documented, and optional parameters have become truly optional because you can omit them.

Convert positional arguments to named arguments with the Add name identifiers quick-fix:

PhpStorm highlights arguments if they include a typo or if there is no matching parameter:

If the passed value is the same as the parameter’s default, PhpStorm will grey out the argument and you can safely remove it with a quick-fix:

Developers often use options arrays to pass a set of parameters. With named arguments, this is not necessary because you can specify the parameters you need. And as a bonus, arguments passed this way are type-safe, unlike array elements.


Attributes a.k.a. annotations are a new, structured way to specify metadata in PHP. They replace PHPDoc comments.

To create an attribute, declare a usual class and add an #[Attribute] marker on top of it. PhpStorm provides all the expected features here, including highlighting, code completion, finding usages, refactorings, and so on.

PHP itself only validates attributes when you call ReflectionAttribute::newInstance(). Until then, if not accessed via reflection, attributes are ignored completely to avoid having to load classes and create objects.

With PhpStorm, you can see whether attributes are valid or not without running the reflection API. The following rules are enforced:

  • The specified class can really be an attribute.

  • This attribute is applied only in the allowed targets: class, property, method, parameter, function, or class constant.

  • This attribute is repeated only if it has the Attribute::IS_REPEATABLE flag.

Here are attributes in action with Symfony:

Custom PHP 8 Attributes in PhpStorm

Several attributes are available in PhpStorm 2020.3 out of the box under the \JetBrains\PhpStorm\ namespace.

Add them to your codebase right away to get better code completion and more inspections.

If you are using other static analysis tools and you don’t want to get Class not found issues, then you might want to add the attributes package JetBrains/phpstorm-attributes to your composer.json as a dependency.


Like you would with the @deprecated PHPDoc tag, you can use this attribute to mark methods, functions, classes, or class constants that are to be removed in the future.

The main advantage of this new attribute is that you can specify replacements for functions and methods. This will help users of the deprecated functionality to migrate.

Let’s take a look at a real-world example. In the recently released Symfony 5.2, the \Symfony\Component\DependencyInjection\Alias::setPrivate() is deprecated. With the #[Deprecated] attribute, we can make migration easier.

   reason: 'since Symfony 5.2, use setPublic() instead',
   replacement: '%class%->setPublic(!%parameter0%)'


This attribute is useful for working with simple data structures or object-like arrays when defining a real class may feel excessive.

The syntax is as follows:

// ‘key’ => ’type’,
   ‘key1’ => ‘int’,
   ‘key2’ => ‘string’,
   ‘key3’ => ‘Foo’,
   ‘key3’ => App\PHP 8\Foo::class,
function functionName(...): array

The type can be specified as a string or as a class reference in the form of an FQN string or a::class constant.

Here’s an array that defines a shape. Extract it into a constant and then reuse it inside the attributes where it applies:

const  MY_ARRAY_SHAPE = [];

In PhpStorm, we’ve already annotated some internal PHP functions like parse_url() with #[ArrayShape], so you can benefit from the attributes right away.

Fortunately, the syntax of one-line attributes is backward-compatible. If you add the #[ArrayShape] attribute on a separate line in your PHP 7.* project, the PHP interpreter will parse it as a commented line. However, multiline attributes are not safe for versions of PHP prior to 8.

Unlike the PHP interpreter, PhpStorm will analyze attributes anyway! So even if your project runs on PHP 7.4 or lower, you’ll still benefit from adding #[ArrayShape] attributes.


Immutable objects cannot be changed after being initialized or created. Using them makes the program state more predictable and debugging easier.

Mark objects or specific properties with the #[Immutable] attribute to make sure they will not be changed.

PhpStorm will check the usages of objects and properties and highlight change attempts.

You can allow the property to be changed only in a constructor or in private/protected methods too.

To do this, pass one of the constants CONSTRUCTOR_WRITE_SCOPE, PRIVATE_WRITE_SCOPE, or PROTECTED_WRITE_SCOPE to the #[Immutable] attribute constructor.


Mark functions that do not produce any side effects as pure. Such functions can be safely removed if their execution result is not used in the code afterwards.

If the function is marked as pure but you try to change something outside of it, that is, it produces a side effect, then PhpStorm will highlight the unsafe code.

All internal PHP pure functions are marked as such in PhpStorm.


With this attribute, you can specify which values a function accepts as parameters and which it can return.

This is similar to what the expectedArguments() function would do in .phpstorm.meta.php, except that the meta version is more like a completion adversary. The attribute, by contrast, assumes that there are no other possible values for the argument or return value.

For example, let’s take the count function:

count ( array|Countable $array_or_countable [, int $mode = COUNT_NORMAL ] ) : int

Its second argument is an integer, but in reality, it is not an arbitrary integer. Rather, it is one of the constants COUNT_NORMAL or COUNT_RECURSIVE, which correspond to 0 and 1.
See how the #[ExpectedValues] attribute can be useful here.

How to specify possible values or bitmasks.

Expected values are passed to the attribute constructor and can be any of the following:

  • Numbers: #[ExpectedValues(values: [1,2,3])]
  • String literals: #[ExpectedValues(values: [‘red’, ‘black’, ‘green’])]
  • Constant references: #[ExpectedValues(values: [COUNT_NORMAL, COUNT_RECURSIVE])]
  • Class constant references: #[ExpectedValues(values: [Code::OK, Code::ERROR])]

And there are a few ways to specify expected arguments:

  • #[ExpectedValues(values: [1,2,3])] means that only one of the values is expected.
  • #[ExpectedValues(flags: [1, 2, 3])] means that a bitmask of the specified values is expected, e.g. 1 | 3.
  • #[ExpectedValues(valuesFromClass: MyClass::class)] means that any of the constants from the class `MyClass` is expected.
  • #[ExpectedValues(flagsFromClass: ExpectedValues::class)] means that a bitmask of the constants from the class `MyClass` is expected.

#[ExpectedValues] example
Let’s take a look at the response() helper in Laravel. It takes the HTTP status code as the second argument.

This leaves us missing two key features:

  • Code completion for possible status codes
  • Validation in the editor

Let’s fix this by adding the attribute #[ExpectedValues(valuesFromClass: Response::class)]


Some functions in a codebase may cause the execution of a script to stop. Mark such functions as exit points with the #[NoReturn] attribute to get a more accurate control flow analysis.

PhpStorm will offer to propagate the attribute down across the hierarchy, along with a quick-fix to get even more well-defined analysis.


Add this attribute to string parameters that contain text in another (programming) language, such as RegExp, SQL, and so on. This will reveal additional PhpStorm features.

Let’s get back to the PHP 8 features.

Constructor property promotion

To make objects smaller and more readable, you can now initialize variables through a constructor.

Convert constructor properties to promoted properties, or change them back, with the Convert to promoted property quick-fix.

PhpStorm makes sure that promoted properties are only used in the way allowed by PHP 8:

  • Cannot declare a promoted property outside a constructor.
  • Cannot declare a promoted property in an abstract constructor.
  • Cannot declare a variadic promoted property.
  • Property cannot have the ‘Callable’ type.
  • Redeclaration of a property is not allowed.

If the property is promoted but there is a left-over assignment in the constructor body, then PhpStorm will suggest removing it.

Match expression

PHP 8 introduces a new expression match which is similar to switch but uses a strict comparison and can be assigned to a value or returned.

PhpStorm determines if a switch block can be converted to a match and will do it automatically with an Alt+Enter quick-fix:

With the new expression, it might be hard to see inappropriate usages, so PhpStorm will highlight them.

Duplicate values in conditions are detected:

A match expression with a single default branch can be safely replaced with a ternary expression.

And if there is only a default branch left, you might not need the match at all.

Lastly, if there are identical bodies in different branches, they can be merged.

Nullsafe operator

Instead of cumbersome conditions with null checks, you can now use a chain of calls with the new ?-> nullsafe operator.

PhpStorm will check that the operator is used correctly:

Trailing comma

It’s now acceptable to add a comma after the last parameter in a function call and in the use list of closures.

Non-capturing catches

In PHP 8, it is possible to catch exceptions without applying them to variables.
Use the Alt+Enter quick-fix to add, or to remove, a variable in a catch statement:

Throw expression

Throwing exceptions is allowed in arrow functions, the coalesce operator ??, and the ternary/elvis operator ? :, which was not possible before.

To quickly add a throw expression, type thr and press tab – this will expand a live template.

Allow ::class on objects

In previous PHP versions, to get an FQN you could do ClassName::class, but on objects you had to call get_class(). In PHP 8, you can safely replace get_class($object) with $object::class.

PhpStorm provides an Alt+Enter quick-fix for that and will also warn you if ::class is used inappropriately.

New functions for strings: str_contains(), str_starts_with(), str_ends_with()

How do I check if a string contains a specific word? – This is the most viewed PHP question on Stack Overflow ever. PHP 8 has a clear answer to that question: use the str_contains() function.

PhpStorm 2020.3 detects strpos() usages that can be replaced with str_contains():

There are also new str_starts_with() and str_ends_with() functions to determine if a string starts or ends with a specific substring. PhpStorm highlights where the old substr() calls can be replaced with new alternatives:

Reclassified engine warnings

In PHP 8 many errors were categorized into new severity levels. Instead of a Warning in many cases you’ll get an Exception or a Type Error.

PhpStorm reflects this, and some inspections have two different severity levels that can be set separately: for PHP 8, and for older versions.

All the other changes in the PHP 8 release are supported too.

Psalm and PHPStan Support

Both static analyzers can be used in PhpStorm 2020.3 to get on-the-fly file highlighting of problems in the editor.


You can add PHPStan or Psalm as your dev-dependency in composer.json. Near the corresponding line, there will be a wrench icon that opens the tool settings.

From there you can go to the Inspection settings and enable highlighting in the editor. Click on the PHPStan Inspection / Psalm Inspection link. To turn on highlighting, select the corresponding inspection in the PHP | Quality tools list.

Here you can specify the configuration file path and adjust the command-line arguments of the tools. For example, you can set PHPStan’s error level or toggle unused code detection for Psalm.

Note: PHPStan can work without a configuration file, but Psalm requires one.
If you have psalm.xml or phpstan.neon in the root directory, PhpStorm will detect them automatically.

Once you have set this up, you can then open any file and see the problems highlighted in the editor. There may be a short delay before the highlighting appears.


Code annotated with extended Psalm tags is now valid in the editor, and @psalm-* is correctly highlighted. Though, in most cases, it is now safe to remove the @psalm- prefix from tags, i.e. @psalm-return -> @return and @psalm-param -> @param.

Type support

We’ve added support for some Psalm types and improved our type inference too. Everything that depends on type inference is now more accurate, including inspections, code generation, and completion.

This includes scalar, numeric, and so on.

Constants in types
Constant value unions and wildcards are both supported in type definitions via @param and @var.

Array typehints
Type inference for array definitions array<array-key, Type> now works as expected. This applies to nested definitions, too.

Generics with @tempate
We believe that support for generics is an advanced feature that lacks a proper specification and has many edge cases. Yet, we have decided to implement basic support for the @template construct based on the Psalm syntax, to see how it goes.

So far, only a simple scenario, when the function returns one of its parameters, is supported.

This support for generics is basic and still considered experimental. This is where we’d like to understand how you would like to use it and what you’d like to see more of. Please give us your feedback by submitting requests with your real-life template usages to our issue tracker.

Xdebug 3

The PHP debugger extension has received a major update. It is now significantly faster and easier to set up. Learn more about Xdebug 3 in the Upgrade guide.

To configure Xdebug 3, you only need to specify xdebug.mode (e.g. XDEBUG_MODE=debug).
Xdebug’s default debugging port has changed from 9000 to 9003. To ease migration, PhpStorm is now listening on both ports by default. You can adjust the port and other settings for Xdebug under Preferences/Settings | Languages & Frameworks | PHP | Debug.

Debugger Improvements

We’ve made a few improvements to the debugging experience and simplified examining variables.

Interactive hints
Now when you are in debug mode, you’ll get clickable inline hints that you can expand to see all the fields of the variable. You can also change the variable values from there.

Inline Watches
In previous versions, you could see how a certain expression evaluates throughout the steps by adding it to watches.

In PhpStorm 2020.3, you can tie your watch expression to the place in the code where it is relevant.

Click Add as Inline Watch in the hint popup.

Or, choose Add Inline Watch in the editor’s context menu.

Or, select any variable, right-click on it, and choose Add Inline Watch.

Highlight and rename variables in Twig

Select a variable or put the caret on one to highlight all its usages in the template. Use the Shift + F6 shortcut to Rename all occurrences of the variable.

Code With Me for collaborative development

PhpStorm 2020.3 bundles Code With Me – a new tool from JetBrains for collaborative development and pair programming. Code With Me enables you to share the project you currently have open in your IDE with others, and work on it together in real time. Check out these posts to learn more about Code With Me.

HTTP Client

Guzzle integrated with PhpStorm’s HTTP client

Guzzle is one of the most popular HTTP clients for PHP. Imagine there is an HTTP request somewhere in the code. If you wanted to test it without running your actual code, you’d have to go and copy all the parameters manually.

PhpStorm 2020.3 lets you convert simple Guzzle requests to .http files. If the request is supported, there will be a gutter icon next to it. Clicking it will create a new scratch file with the correct URL, query parameters, methods, headers, body, and simple auth. You can then run it directly from the code editor with the IDE’s internal HTTP client.

You can play around with the request and then save it as an .http file in your project.

Learn more about HTTP client in the video overview.

Export HTTP Requests to cURL

To export an HTTP request to a cURL string, press Alt+Enter in the HTTP request editor and select Convert to cURL and copy to clipboard. Use it in the terminal, documentation, or any API testing tool.


Markdown editing and preview enhancements

Use the Mermaid.js syntax in markdown files to describe diagrams and charts. PhpStorm can render a preview for them right in the editor. Enable it in Preferences/Settings | Languages & Frameworks | Markdown.

You can now reformat the content of your .md files to conform to popular Markdown style guides. To do so, press ⌘⌥L / Ctrl+Alt+L. You can modify the related code style settings in Preferences/Settings | Editor | Code Style | Markdown.

Finally, if you click the Auto-Scroll Preview button in the top right-hand corner of the preview pane, that pane will scroll along with the editor.

Improved spelling and grammar checking

You can now address grammar and spelling issues faster:

  • The popup for a mistake will show an explanation and a suggested fix.
  • And if you press Alt+Enter over the highlighted text, you will see all the suggested replacements in the top level, instead of a nested list like before.

Split the editor with drag and drop

If you want to open files side by side, just drag a tab to the desired corner of the screen and drop it there.

There’s one more way to split the editor – Shift+Enter.
Press this key combination on a selected file in Project view or Find results.

Preview Tab

If you want to quickly skim files, you don’t have to open them. Just use the new Preview tab.

To enable it, click the gear icon in the Project view and select both Enable Preview Tab and Open Files with Single Click.

You can now also preview with the Space key in Project view.


Search Everywhere improvements

Results grouped by relevance:

Simple math in Search Everywhere:

Search through Git history:

Switch to light or dark theme automatically

Go to Preferences/Settings | Appearance & Behavior | Appearance | Theme and select the Sync with OS option there.

System shortcut keymap for macOS

An alternative macOS keymap avoids using function keys for essential actions. For example, instead of Fn+Shift+F6 for the Rename refactoring, it’s just ⌥+⌘+R.

macOS shortcuts as words
If you are struggling to read the macOS shortcuts, try toggling the ide.macos.disable.native.shortcut.symbols key in the registry. To access the registry, use Find Action Cmd+Shift+A and then type Registry.

Set PhpStorm as the default application for opening files

Go to Preferences | Settings / Editor / File Types and click the Associate file types with PhpStorm… button. In the dialog, select the extensions for files you wish to open in PhpStorm.

On macOS, you will need to restart your computer to apply these changes.

Templates can now generate multiple files

You can generate a bunch of boilerplate files at the same time, for example, a skeleton for a module or a controller-view combo.

Go to Preferences / Settings | Editor | File and Code Templates and click to create a new template, and then click on the Create Child Template File icon .

In the File name field, you can specify a pattern to generate a filename and path using predefined variables like ${NAME}.

Here’s how the files are generated:

Git stage support

PhpStorm 2020.3 comes with support for the Git staging area. To turn it on, tick the Enable staging area checkbox in Preferences/Settings | Version Control | Git.

In the Commit tool window Cmd+0 / Alt+0, you’ll see the staged and unstaged files.

Stage files by clicking on the + icon near them.

Or stage specific lines by using the gutter icon near the changes in the editor. This way, you can commit some changes in a file and keep the rest uncommitted for further work.

Database Tools

PhpStorm includes almost all of DataGrip’s features as standard. Check out What’s new in Database tools for an overview of the new features we’ve added for working with databases.

SQL for MongoDB

You can now use SQL to query MongoDB databases. PhpStorm 2020.3 supports SELECT queries with clauses such as JOIN, WHERE, GROUP BY, HAVING, ORDER BY, LIMIT, OFFSET, and all available MongoDB functions except map, reduce, filter, and let. If you want to learn more about SQL for MongoDB, read this blog post.

New data extractors

We’ve also introduced two new extractors: One-Row, which allows you to copy a column to a comma-separated string; and SQL-Insert-Multirow, which generates a single INSERT statement with multiple new rows to be inserted.


As usual, all the updates for WebStorm 2020.3 have also been incorporated into PhpStorm. The most notable is Tailwind CSS support.

Tailwind CSS

First, you can now expect PhpStorm to autocomplete Tailwind classes in your HTML files and after the @apply directive. You’ll also see completion suggestions for pseudo-class variants.


Hover over a class in your HTML and CSS files to see the preview of the resulting CSS. You can also see this preview when autocompleting your code, thanks to the Documentation popup F1 / Ctrl+Q.


PhpStorm also supports the customizations you make with tailwind.config.js files. The IDE analyzes these files and provides completion based on your customizations. If you define a custom theme with new colors, for example, you’ll see newly generated classes with the name of the custom color in the completion popup.


The full list of changes in PhpStorm 2020.3 is available in the really long release notes.

That’s all for today. Thanks for reading to the end!

Your JetBrains PhpStorm team
The Drive to Develop

image description