Developer Experience (DX) refers to how smooth and efficient it feels to work with a framework or tool. In Symfony 7.4, we've added many small DX improvements, and this post highlights some of them.
Question Helper Timeout
The Question helper from the Console component provides utilities to ask
users for input. In Symfony 7.4, you can now set a timeout for questions.
If the user doesn't respond within the specified time, a MissingInputException
will be thrown:
1 2 3 4 5 6 7 8 9 10 11 12
use Symfony\Component\Console\Exception\MissingInputException;
use Symfony\Component\Console\Question\ConfirmationQuestion;
// ...
public function __invoke(InputInterface $input, OutputInterface $output): int
{
// ...
$helper = new QuestionHelper();
$question = new ConfirmationQuestion('Restart the server?', false);
$question->setTimeout(10); // user must confirm in 10 seconds or less
}
Enum Type Guesser for Forms
The Symfony Form component uses type guessers to decide which form types to use for fields that don't define their type explicitly. In Symfony 7.4, we added a new type guesser for PHP enums.
You no longer need to define enum fields manually. Symfony will automatically use
the EnumType class and set its class option whenever it finds an enum field.
New Command to Generate OIDC Tokens
In Symfony 6.3, we introduced an OpenID Connect Token Handler that allows you to decode JWT tokens, validate them, and extract user information. In Symfony 7.4, we're adding a command to generate JWTs, which is useful for testing and development:
1 2 3 4 5 6
$ php bin/console security:oidc-token:generate jane.doe@example.com \
--firewall="api" \
--algorithm="HS256" \
--issuer="https://example.com" \
--ttl=7200 \
--not-before=tomorrow
Default Locale Outside HTTP Context
When generating URLs outside the HTTP context, there are special challenges, such as defining the hostname or locale. In Symfony 7.4, the kernel.default_locale parameter is now also used as the default locale when generating URLs outside HTTP requests.
New Helpers for BrowserKit
The BrowserKit component simulates the behavior of a web browser, allowing you to make requests, click links, and submit forms programmatically. In Symfony 7.4, it adds two new helpers:
isFirstPage(): returnstrueif the current position is at the start of the history stack.isLastPage(): returnstrueif the current position is at the end of the history stack.
These are especially useful in tests, so we also added a few new PHPUnit constraints:
1 2 3 4
$this->assertBrowserHistoryIsOnFirstPage();
$this->assertBrowserHistoryIsNotOnFirstPage();
$this->assertBrowserHistoryIsOnLastPage();
$this->assertBrowserHistoryIsNotOnLastPage();
Better Dumps in non-HTML Contexts
In Symfony 7.4, we improved exceptions in the terminal to avoid rendering
them as HTML. Similarly, the dd() and dump() functions now only render HTML
when the request contains an Accept HTTP header with an html value.
In all other cases (e.g. API debugging, terminal output), dumps are rendered as
plain text.
Simpler Target Attributes
When dealing with multiple implementations of the same type, the #[Target] attribute helps you select which one to inject. In Symfony 7.4, we've simplified how you can define those values.
You can now use the same names as in your configuration files, without adding extra suffixes based on the service type:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
// Before - Asset Packages
#[Target('foo_package.package')] private PackageInterface $package
// After
#[Target('foo_package')] private PackageInterface $package
// Before - Lock Factories
#[Target('invoice.lock.factory')] private LockFactory $lockFactory
// After
#[Target('invoice')] private LockFactory $lockFactory
// Before - Rate Limiters
#[Target('anonymous_api.limiter')] RateLimiterFactoryInterface $rateLimiter
// After
#[Target('anonymous_api')] RateLimiterFactoryInterface $rateLimiter