* 8.0:
Fix merge
[VarDumper] Wrong dumper output for Accept: aplication/json requests
[HttpKernel] Reset router locale to default when finishing main request
Only decrement pendingRequests when it's more than zero
[Dotenv] Fix self-referencing variables with defaults and env key resolution during deferred expansion
Improve Bulgarian translations in validators.bg.xlf
[Cache] Fix ChainAdapter ignoring item expiry when propagating to earlier adapters
[Form] Fix typed property initialization in ValidatorExtension
[Messenger] Fix duplicate pending messages in Redis transport with batch handlers
Fix deprecation notices for "@method" annotations when implementing interfaces directly
* 7.4:
[VarDumper] Wrong dumper output for Accept: aplication/json requests
[HttpKernel] Reset router locale to default when finishing main request
Only decrement pendingRequests when it's more than zero
[Dotenv] Fix self-referencing variables with defaults and env key resolution during deferred expansion
Improve Bulgarian translations in validators.bg.xlf
[Cache] Fix ChainAdapter ignoring item expiry when propagating to earlier adapters
[Form] Fix typed property initialization in ValidatorExtension
[Messenger] Fix duplicate pending messages in Redis transport with batch handlers
Fix deprecation notices for "@method" annotations when implementing interfaces directly
* 6.4:
[HttpKernel] Reset router locale to default when finishing main request
Only decrement pendingRequests when it's more than zero
[Dotenv] Fix self-referencing variables with defaults and env key resolution during deferred expansion
Improve Bulgarian translations in validators.bg.xlf
[Cache] Fix ChainAdapter ignoring item expiry when propagating to earlier adapters
[Form] Fix typed property initialization in ValidatorExtension
[Messenger] Fix duplicate pending messages in Redis transport with batch handlers
Fix deprecation notices for "@method" annotations when implementing interfaces directly
The early return in the constructor prevented typed properties from
being initialized when a Form constraint already existed, causing
PHP errors when the extension was used (PHP 8.0+ typed property
requirement).
This fix moves property initialization before the early return check,
ensuring typed properties are always initialized while preserving
the duplicate constraint prevention functionality.
Includes a test case to verify the fix works correctly when the
early return condition is met.
* 8.0:
[HttpFoundation] Fix session cookie_lifetime not applied in mock session storage
[Validator] Fix test
[Serializer] Fix denormalization of magic `__set` properties
[Config] Fix NodeDefinition template to be covariant
Add 'sms' to hostless schemes
[Validator] Fix required options check when extending a constraint with a simplified constructor
[Validator] Skip ExpressionLanguage requirement in When constraint for closure expressions
[Cache] Add timeout and slot eviction to LockRegistry stampede prevention
[Console] Fix OUTPUT_RAW corrupting binary content on Windows
[Form] Fix session data contamination by non-serializable objects in form flow
[Mime] Use shell_exec() instead of passthru() in FileBinaryMimeTypeGuesser
[HttpClient] Fix streaming from CachingHttpClient
[DoctrineBridge] Rename `_schema_subscriber_check` table to `schema_subscriber_check_` for Oracle compatibility
[HttpClient] Fix CachingHttpClient compatibility with decorator clients on 304 responses
[FrameworkBundle] Fix stale container after reboot in KernelTestCase
[Form] Fix duplicate validation errors when ValidatorExtension is instantiated multiple times
* 7.4:
[HttpFoundation] Fix session cookie_lifetime not applied in mock session storage
[Validator] Fix test
[Serializer] Fix denormalization of magic `__set` properties
[Config] Fix NodeDefinition template to be covariant
Add 'sms' to hostless schemes
[Validator] Fix required options check when extending a constraint with a simplified constructor
[Validator] Skip ExpressionLanguage requirement in When constraint for closure expressions
[Cache] Add timeout and slot eviction to LockRegistry stampede prevention
[Console] Fix OUTPUT_RAW corrupting binary content on Windows
[Form] Fix session data contamination by non-serializable objects in form flow
[Mime] Use shell_exec() instead of passthru() in FileBinaryMimeTypeGuesser
[HttpClient] Fix streaming from CachingHttpClient
[DoctrineBridge] Rename `_schema_subscriber_check` table to `schema_subscriber_check_` for Oracle compatibility
[HttpClient] Fix CachingHttpClient compatibility with decorator clients on 304 responses
[FrameworkBundle] Fix stale container after reboot in KernelTestCase
[Form] Fix duplicate validation errors when ValidatorExtension is instantiated multiple times
* 6.4:
[FrameworkBundle] Fix stale container after reboot in KernelTestCase
[Form] Fix duplicate validation errors when ValidatorExtension is instantiated multiple times
* 8.0: (26 commits)
Fix merge
[RateLimiter] Fix retryAfter when consuming exactly all remaining tokens in FixedWindow and TokenBucket
[RateLimiter] Fix retryAfter value on last token consume (SlidingWindow)
[RateLimiter] Fix reservations outside the second fixed window
[Filesystem] makePathRelative with existing files, remove ending /
[Config][Routing] Fix exclude option being ignored for non-glob and PSR-4 resources
[Serializer][Validator] Fix propertyPath in ConstraintViolationListNormalizer with MetadataAwareNameConverter
[Messenger][Amqp] Don't use retry routing key when sending to failure transport
[Messenger] Fix re-sending failed messages to a different failure transport
[DependencyInjection] Fix #[AsTaggedItem] discovery through multi-level decoration chains
[Config] Fix ArrayShapeGenerator required keys with deep merging
[Validator] Add a guard when `Parser::IGNORE_UNKNOWN_VARIABLES` is not defined
[Validator] Correctly handle null `allowedVariables` in `ExpressionSyntaxValidator`
[DependencyInjection] Fix PriorityTaggedServiceTrait not discovering #[AsTaggedItem] on decorated services
[Mailer] Clarify the purpose of SentMessage's "message id" concept
[ObjectMapper] fix nested mapping with class-level transform
[TwigBridge] Fix Bootstrap 4 form error layout
[Form] Fix merging POST params and files when collection entries have mismatched indices
[Validator] Fix type error for non-array items when Unique::fields is set
[HttpKernel] Fix default locale ignored when Accept-Language has no enabled-locale match
...
* 7.4: (25 commits)
[RateLimiter] Fix retryAfter when consuming exactly all remaining tokens in FixedWindow and TokenBucket
[RateLimiter] Fix retryAfter value on last token consume (SlidingWindow)
[RateLimiter] Fix reservations outside the second fixed window
[Filesystem] makePathRelative with existing files, remove ending /
[Config][Routing] Fix exclude option being ignored for non-glob and PSR-4 resources
[Serializer][Validator] Fix propertyPath in ConstraintViolationListNormalizer with MetadataAwareNameConverter
[Messenger][Amqp] Don't use retry routing key when sending to failure transport
[Messenger] Fix re-sending failed messages to a different failure transport
[DependencyInjection] Fix #[AsTaggedItem] discovery through multi-level decoration chains
[Config] Fix ArrayShapeGenerator required keys with deep merging
[Validator] Add a guard when `Parser::IGNORE_UNKNOWN_VARIABLES` is not defined
[Validator] Correctly handle null `allowedVariables` in `ExpressionSyntaxValidator`
[DependencyInjection] Fix PriorityTaggedServiceTrait not discovering #[AsTaggedItem] on decorated services
[Mailer] Clarify the purpose of SentMessage's "message id" concept
[ObjectMapper] fix nested mapping with class-level transform
[TwigBridge] Fix Bootstrap 4 form error layout
[Form] Fix merging POST params and files when collection entries have mismatched indices
[Validator] Fix type error for non-array items when Unique::fields is set
[HttpKernel] Fix default locale ignored when Accept-Language has no enabled-locale match
[FrameworkBundle] Make `ConfigDebugCommand` use its container to resolve env vars
...
* 6.4:
[RateLimiter] Fix retryAfter when consuming exactly all remaining tokens in FixedWindow and TokenBucket
[RateLimiter] Fix retryAfter value on last token consume (SlidingWindow)
[RateLimiter] Fix reservations outside the second fixed window
[Filesystem] makePathRelative with existing files, remove ending /
[Config][Routing] Fix exclude option being ignored for non-glob and PSR-4 resources
[Serializer][Validator] Fix propertyPath in ConstraintViolationListNormalizer with MetadataAwareNameConverter
[Messenger][Amqp] Don't use retry routing key when sending to failure transport
[Messenger] Fix re-sending failed messages to a different failure transport
[DependencyInjection] Fix #[AsTaggedItem] discovery through multi-level decoration chains
[DependencyInjection] Fix PriorityTaggedServiceTrait not discovering #[AsTaggedItem] on decorated services
[Mailer] Clarify the purpose of SentMessage's "message id" concept
[TwigBridge] Fix Bootstrap 4 form error layout
[Form] Fix merging POST params and files when collection entries have mismatched indices
[Validator] Fix type error for non-array items when Unique::fields is set
[HttpKernel] Fix default locale ignored when Accept-Language has no enabled-locale match
[FrameworkBundle] Make `ConfigDebugCommand` use its container to resolve env vars
[Console] Fix various completion edge cases
[Messenger][AmazonSqs] Add test for default queue_name when not set in DSN path or options
This PR was squashed before being merged into the 8.1 branch.
Discussion
----------
[Form] Add support for submitting forms with unchecked checkboxes in request handlers
| Q | A
| ------------- | ---
| Branch? | 8.1
| Bug fix? | yes
| New feature? | yes
| Deprecations? | no
| Tickets | Fix#20179, #14938
| License | MIT
When a form contains only checkboxes (or a collection of checkboxes), there is no way to distinguish between:
- A user visiting a page that contains the form (not a submission)
- A user submitting the form with all checkboxes unchecked
This is because unchecked checkboxes are omitted entirely from the HTTP request. When the form's name is absent from the request, the current handlers bail out early and don't submit the form - so unchecked checkboxes can never reset a true default value.
This PR introduces `MissingDataHandler`, which walks the form's children recursively at request-handling time to detect whether the form would have appeared in the request had any checkbox been checked. Concretely:
- If a form (or any of its children) has a `false_values` option (the marker used by `CheckboxType`), it means the form contains a checkbox. When that checkbox key is absent from the submitted data, `MissingDataHandler` injects the first false value (i.e. `'0'` for a standard checkbox) so the form is submitted and data is set to `false`.
- An `stdClass` sentinel object is used to distinguish "key was absent" from `null`, making the logic explicit and identity-safe.
- `PATCH` requests are excluded intentionally, since PATCH is meant for partial updates and omitted fields should be left untouched.
Before/after
```php
// Form with a single checkbox, default data = true
$form = $factory->createNamed('agree', CheckboxType::class, true);
// POST request with no body (all checkboxes unchecked)
$handler->handleRequest($form, $request);
// Before: form is never submitted, data stays true
// After: form is submitted, data is false ✓
```
Commits
-------
4ed039397f9 [Form] Add support for submitting forms with unchecked checkboxes in request handlers
* 8.0:
[Form] Add resource tracking for type extension classes in FormPass
[Mailer] Postal mailer transport apikey
[FrameworkBundle] Fix phpstan false-positive about config/reference.php
* 7.4:
[Form] Add resource tracking for type extension classes in FormPass
[Mailer] Postal mailer transport apikey
[FrameworkBundle] Fix phpstan false-positive about config/reference.php
When a form type extension uses getExtendedTypes() without the extended_type
tag, FormPass calls the static method at build time but does not track the
class as a container resource. This means the cache is not invalidated when
the method is edited.
Call $container->getReflectionClass() before accessing getExtendedTypes()
so that the class is automatically registered as a ReflectionClassResource,
the same pattern used by RegisterListenersPass in the EventDispatcher
component.
* 8.0: (27 commits)
[JsonStreamer] Fix exponential resource class memory growth
[Cache] Fix DSN auth not passed to clusters in RedisTrait
do not parse "scalar" as an object
[Form] Fix OrderedHashMap auto-increment logic with mixed keys
[HttpClient] Skip HTTP/3 when using a proxy
don't skip custom view transformers while normalizing submitted newlines
[Serializer] Fix is/has/can accessor naming regression while preserving collision detection
fix exception "Symfony\Component\TypeInfo\Exception\InvalidArgumentException: "Symfony\Component\TypeInfo\Type\UnionType" expects at least 2 types." when property phpdoc is "value-of<Enum>|null"
[DoctrineBridge] Fix custom type based on Uid on entity loader
let tests fail on PHPUnit notices
[PropertyInfo] Throw when phpdocumentor/reflection-docblock v6 is in use (branch 6.4 only)
do not use PHPUnit mock objects without configured expectations
[Form] Fix ICU 72+ whitespace handling in `DateTimeToLocalizedStringTransformer`
[ErrorHandler] fix parsing of complexe type
do not use PHPUnit mock objects without configured expectations
[Process] Adjust Process mustRun method phpdoc
do not use PHPUnit mock objects without configured expectations
do not use PHPUnit mock objects without configured expectations
do not use PHPUnit mock objects without configured expectations
do not use PHPUnit mock objects without configured expectations
...
* 7.3:
[JsonStreamer] Fix exponential resource class memory growth
[Cache] Fix DSN auth not passed to clusters in RedisTrait
do not parse "scalar" as an object
[Form] Fix OrderedHashMap auto-increment logic with mixed keys
[HttpClient] Skip HTTP/3 when using a proxy
don't skip custom view transformers while normalizing submitted newlines
[Serializer] Fix is/has/can accessor naming regression while preserving collision detection
* 6.4:
[Cache] Fix DSN auth not passed to clusters in RedisTrait
do not parse "scalar" as an object
[Form] Fix OrderedHashMap auto-increment logic with mixed keys
don't skip custom view transformers while normalizing submitted newlines
[Serializer] Fix is/has/can accessor naming regression while preserving collision detection
* 7.3:
do not use PHPUnit mock objects without configured expectations
[Form] Fix ICU 72+ whitespace handling in `DateTimeToLocalizedStringTransformer`
[Process] Adjust Process mustRun method phpdoc
[Serializer] Fix NameConverter not detecting wrong input format with allow_extra_attributes=false
* 6.4:
do not use PHPUnit mock objects without configured expectations
[Form] Fix ICU 72+ whitespace handling in `DateTimeToLocalizedStringTransformer`
[Process] Adjust Process mustRun method phpdoc
[Serializer] Fix NameConverter not detecting wrong input format with allow_extra_attributes=false
* 8.0:
do not use PHPUnit mock objects without configured expectations
do not use PHPUnit mock objects without configured expectations
do not use PHPUnit mock objects without configured expectations
fix CS
do not use PHPUnit mock objects without configured expectations
[Scheduler] Fix array to string conversion in `#[AsCronTask]` arguments
do not use PHPUnit mock objects without configured expectations
do not use PHPUnit mock objects without configured expectations
do not use PHPUnit mock objects without configured expectations
do not use PHPUnit mock objects without configured expectations
fix merge
do not use PHPUnit mock objects without configured expectations
* 7.4:
do not use PHPUnit mock objects without configured expectations
do not use PHPUnit mock objects without configured expectations
do not use PHPUnit mock objects without configured expectations
fix CS
do not use PHPUnit mock objects without configured expectations
[Scheduler] Fix array to string conversion in `#[AsCronTask]` arguments
do not use PHPUnit mock objects without configured expectations
do not use PHPUnit mock objects without configured expectations
do not use PHPUnit mock objects without configured expectations
do not use PHPUnit mock objects without configured expectations
fix merge
do not use PHPUnit mock objects without configured expectations
* 7.3:
do not use PHPUnit mock objects without configured expectations
do not use PHPUnit mock objects without configured expectations
do not use PHPUnit mock objects without configured expectations
do not use PHPUnit mock objects without configured expectations
* 8.0:
fix merge
do not use PHPUnit mock objects without configured expectations
do not use PHPUnit mock objects without configured expectations
do not use PHPUnit mock objects without configured expectations
do not use PHPUnit mock objects without configured expectations
[HttpClient] update chunk items' expiration on revalidation
[FrameworkBundle] Better deprecation message when running `bin/console debug:container --show-arguments`
[PropertyAccess][PropertyInfo][Serializer] Skip methods that look like getters but return void or never
[Form][TwigBridge] Prevent cached block prefixes from leaking across nested collections
[Uid] Remove $uid from InvalidArgumentException message
* 7.4:
do not use PHPUnit mock objects without configured expectations
do not use PHPUnit mock objects without configured expectations
do not use PHPUnit mock objects without configured expectations
do not use PHPUnit mock objects without configured expectations
[HttpClient] update chunk items' expiration on revalidation
[FrameworkBundle] Better deprecation message when running `bin/console debug:container --show-arguments`
[PropertyAccess][PropertyInfo][Serializer] Skip methods that look like getters but return void or never
[Form][TwigBridge] Prevent cached block prefixes from leaking across nested collections
[Uid] Remove $uid from InvalidArgumentException message
* 7.3:
do not use PHPUnit mock objects without configured expectations
do not use PHPUnit mock objects without configured expectations
do not use PHPUnit mock objects without configured expectations
do not use PHPUnit mock objects without configured expectations
[FrameworkBundle] Better deprecation message when running `bin/console debug:container --show-arguments`
[PropertyAccess][PropertyInfo][Serializer] Skip methods that look like getters but return void or never
[Form][TwigBridge] Prevent cached block prefixes from leaking across nested collections
[Uid] Remove $uid from InvalidArgumentException message
* 6.4:
do not use PHPUnit mock objects without configured expectations
do not use PHPUnit mock objects without configured expectations
do not use PHPUnit mock objects without configured expectations
[PropertyAccess][PropertyInfo][Serializer] Skip methods that look like getters but return void or never
[Form][TwigBridge] Prevent cached block prefixes from leaking across nested collections
[Uid] Remove $uid from InvalidArgumentException message
* 8.0:
[Config][FrameworkBundle] Allow using ParamConfigurator with every configurable value
[HttpFoundation] Improve doc blocks in `ParameterBag`
[HttpClient] Fix ever growing $maxHostConnections
Fix typo
[DependencyInjection] Fix referencing build-time array parameters
cs fix
[FrameworkBundle] Fix cache:pool:prune exit code on failure
[Form] Add type hint for FormTypeInterface in FormBuilderInterface
[Form] Always normalize CRLF and CR to LF in `TextareaType`
[Cache] Fix stampede protection when forcing item recomputation
[DoctrineBridge] Fix checking for the session table when using PDO
fix(messenger): allow signing message without routing definition
[Console] Fix EofShortcut instruction when using a modern terminal on Windows
[Console] Do not call non-static method via class-name
[Console] Fix choice autocomplete issue when string has spaces
Update SameOriginCsrfTokenManager.php
[Serializer] Fix inconsistent field naming from accessors when using groups
[Finder] Fix converting unanchored glob patterns to regex