Allow to Exclude Properties in Cascade Constraint

Alexandre Daubois
Contributed by Alexandre Daubois in #49596

The Cascade constraint is used to validate a whole class, including all the objects that might be stored in its properties. In Symfony 6.3 we're improving it so you can exclude one or more properties from that validation:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// src/Model/BookCollection.php
namespace App\Model;

use App\Model\Author;
use App\Model\BookMetadata;
use Symfony\Component\Validator\Constraints as Assert;

#[Assert\Cascade(exclude: ['metadata', 'author'])]
class BookCollection
{
    #[Assert\NotBlank]
    protected $name = '';

    public BookMetadata $metadata;

    public Author $author;

    // ...
}

Allow to Trim XML Parameters

Alexandre Daubois
Contributed by Alexandre Daubois in #49412

When using XML to configure the service container, you can't define parameters like this:

1
2
3
<parameter key="app.admin_email">
    something@example.com
</parameter>

Symfony doesn't trim the XML contents, so the app.admin_email value would be '\n something@example.com\n'. In Symfony 6.3 we've added a new trim option for XML configuration:

1
2
3
<parameter key="app.admin_email" trim="true">
    something@example.com
</parameter>

The value of the app.admin_email option will now be 'something@example.com'.

Allow Setting Private Services in Testing Container

Nicolas Grekas
Contributed by Nicolas Grekas in #48938

A well-known technique when testing services in Symfony applications is to mock a dependency of some service being tested. In order to make this work, you need to set those services as public in the test container:

1
2
3
4
5
6
# config/services_test.yaml
services:
    # redefine the alias as it should be while making it public
    App\Contracts\Repository\NewsRepositoryInterface:
        alias: App\Repository\NewsRepository
        public: true

In Symfony 6.3 we're improving this feature so you can set private services directly in the service container, without having to make any service public. For example, in your tests, you can use code like this to set the mock service directly:

1
static::getContainer()->set('example.client', new MockHttpClient(...));

DomCrawler Updates of innerText() Method

otsch
Contributed by otsch in #48940

The DomCrawler component defines an innerText() method to return the text that is a direct descendant of the current node, excluding text from child nodes. In Symfony 6.3 we've improved it in some ways:

1
2
3
4
5
6
7
// if content is '<p>Foo <span>Bar</span> Baz</p>' innerText() now
// returns only the first text node 'Foo' instead of 'Foo Baz'
$text = $crawler->filterXPath('//body/p')->innerText();

// innerText() trims whitespace characters by default, but you can get
// the unchanged text by passing FALSE as argument
$text = $crawler->filterXPath('//body/p')->innerText(false);

Exit Code Management while Handling Console Signals

Grégoire Pineau
Contributed by Grégoire Pineau in #49529

In Symfony 6.3 we've made some changes in the logic that handles signals. First, we only exit by default (to mimic PHP behavior) in SIGINT and SIGTERM. Second, you can now tell via the console event to exit with a custom code (thanks to the new $event->setExitCode($code); method).

Finally, inside a console event you can prevent the command to exit:

1
2
3
4
5
6
7
8
use Symfony\Component\Console\ConsoleEvents;
use Symfony\Component\Console\Event\ConsoleSignalEvent;

$dispatcher->addListener(ConsoleEvents::SIGNAL, function (ConsoleSignalEvent $event) {
    // ...

    $event->abortExit();
});
Published in #Living on the edge