This is the second part of the blog post showcasing the main DX (developer experience) features introduced in Symfony 7.3. Read the first part of this blog post.
Verify URI Signatures
The feature to sign URIs provides two methods (check()
and checkRequest()
)
to validate the signature of given URLs. In Symfony 7.3, we're adding a new
verify()
method, similar to check()
, but which throws different exceptions
if invalid. It doesn't return anything if the signature is valid:
1 2 3 4 5 6 7 8 9 10 11 12 13
try {
$uriSigner->verify($uri);
} catch (UnSignedUriException $e) {
// the URI does not contain a signature
$e->uri; // the URI value
} catch (UnverifiedSignedUriException $e) {
// the signature is invalid
$e->uri; // the URI value
} catch (ExpiredSignedUriException $e) {
// the signature is valid but it's expired
$e->uri; // the URI value
$e->expiredAt; // \DateTimeImmutable
}
Using Enums in Config Nodes
The Config component allows using PHP enums as possible values for some configuration options. However, you previously needed to provide the possible values explicitly:
1 2 3 4 5 6 7
$rootNode
->children()
->enumNode('delivery')
->values(Delivery::cases())
->end()
->end()
;
In Symfony 7.3, we're improving this feature so you can pass the FQCN of the enum, and Symfony will get all values automatically:
1 2 3 4 5 6 7
$rootNode
->children()
->enumNode('delivery')
->enumClass(Delivery::class)
->end()
->end()
;
Improved MapQueryString
The #[MapQueryString]
attribute lets you map and validate the request query
string into an object like a DTO. In Symfony 7.3, we've added support for a
key
argument to target a nested part of the query. For example, if the URL is:
1
https://example.org?search[term]=foo&search[category]=bar
Then:
1 2 3 4 5
#[MapQueryString]
// returns an object with $search property = ['term' => 'foo', 'category' => 'bar']
#[MapQueryString(key: 'search')]
// returns an object with $term property = 'foo' and $category property = 'bar'
Native Lazy Objects
PHP 8.4 added support for lazy objects, which are only initialized when their state is observed or modified. Symfony already uses lazy-loading extensively to improve performance.
In Symfony 7.3, lazy services will now leverage PHP's native lazy objects when running on PHP 8.4 or higher. No changes are required; just upgrade your PHP version and Symfony will use them automatically.
Defining Array Shapes
The TypeInfo component allows extracting and defining type information, e.g. when using it with the JsonStreamer component. In Symfony 7.3, it now supports defining array shapes too:
1 2 3 4 5 6 7 8 9
// resolving type data from a PHPdoc definition
$typeResolver->resolve('array{id: int, name?: string}');
// returns an "ArrayShapeType" instance with 'id' is required, 'name' is optional
// defining an array shape programmatically
$type = Type::arrayShape([
'id' => Type::int(),
'name' => ['type' => Type::string(), 'optional' => true],
]);
IPv6 and HTTP/3 Support in HTTP Client
In Symfony 7.3, the HttpClient component gains two major improvements.
First, if you're using PHP 8.4 or newer, you can enable HTTP/3 as the version for your requests:
1 2 3 4 5
# config/packages/framework.yaml
framework:
http_client:
default_options:
http_version: '3.0'
Second, the NativeHttpClient now supports IPv6 out of the box. Just upgrade to Symfony 7.3 and you're ready to go.
Logging Channel per Exception
Symfony allows you to log messages to different files using log channels. In Symfony 7.3, this feature is improved so you can configure a different log channel per exception type, helping to separate critical exception logs:
1 2 3 4 5 6 7 8 9 10
# config/packages/framework.yaml
framework:
exceptions:
Symfony\Component\HttpKernel\Exception\BadRequestHttpException:
log_level: debug
status_code: 422
Symfony\Component\Security\Core\Exception\AuthenticationException:
log_channel: security
Gotenberg\Exceptions\GotenbergApiErroed:
log_channel: pdf
This is the final blog post in the New in Symfony 7.3 series. We hope you enjoyed it and are excited to upgrade to Symfony 7.3!
Thank you for this great blogpost Javier 🖖