Skip to content

Removed laminas-eventmanager dependency, refactored validators#168

Merged
gsteel merged 6 commits intolaminas:3.0.xfrom
Jurj-Bogdan:validator-chain-refactor
Jan 23, 2026
Merged

Removed laminas-eventmanager dependency, refactored validators#168
gsteel merged 6 commits intolaminas:3.0.xfrom
Jurj-Bogdan:validator-chain-refactor

Conversation

@Jurj-Bogdan
Copy link
Contributor

Q A
Documentation no
BC Break yes
New Feature no
RFC yes

Description

Based on #167.

I agree with @gsteel 's suggestion of dropping the "event" flow for session validation, and since the dependency was not used in other places, I have removed laminas/laminas-eventmanager. To go in a bit more detail:

  • the dependency was dropped.
  • the ValidatorChain class that was using it has been removed.
    • as it was already agreed in previous PRs that going forward validators should only be added via config and only "automatically" called after session start, the whole storing of the configured validators under the "_VALID" key as previously done in ValidatorChain has also been completely removed.
  • updated the shipped Laminas\Session\ValidatorInterface and all validators using it to suit the new validation flow.

While mentioned in the initial issue, I haven't touched the Csrf validator and its dependency laminas/laminas-validator here, as that's probably better suited for a new PR - right now this validator already cannot be used in the same way as the other validators implementing the own ValidatorInterface ( neither in v3 nor v2 ).

@arhimede
Copy link
Member

@laminas/tsc-reviewers
Let's take a look at this one in order to have a release of version 3.0 until next Monday at TSC meeting

@froschdesign
Copy link
Member

While mentioned in the initial issue, I haven't touched the Csrf validator and its dependency laminas/laminas-validator here, as that's probably better suited for a new PR

If this component defines its own interface for validators, then this should also be used by validators in this component. This not only reduces dependencies, but also confusion.

@gsteel
Copy link
Member

gsteel commented Nov 25, 2025

If this component defines its own interface for validators, then this should also be used by validators in this component. This not only reduces dependencies, but also confusion.

The problem here is naming.

It's entirely aceptable to have 2 different types of validator:

  • One for validating user input (via laminas-validator with the CSRF validator)
  • One for validating sessions - as described here.

Renaming the session validator interface from Session\ValidatorInterface to SessionValidator\SessionValidatorInterface would reduce the potential for confusion at the expense of another BC break.

I'd support a rename of the interface/namespace as I find it unlikely that many users implement custom validators outside of those already shipped, and, the BC breaks are already very significant in this portion of the library.

The fact that the CSRF validator is in the same namespace is really unfortunate. Extracting it to a separate library (and removing the laminas-validator dependency) would clean things up nicely, but it's even more maintenance.

@Jurj-Bogdan
Copy link
Contributor Author

The fact that the CSRF validator is in the same namespace is really unfortunate. Extracting it to a separate library (and removing the laminas-validator dependency) would clean things up nicely, but it's even more maintenance.

@gsteel Should I maybe remove this feature altogether then? I'm not sure that form CSRF validation should be in the laminas-session library use case, especially not when it requires the laminas-validator dependency without much other use.

@gsteel
Copy link
Member

gsteel commented Nov 25, 2025

@gsteel Should I maybe remove this feature altogether then? I'm not sure that form CSRF validation should be in the laminas-session library use case, especially not when it requires the laminas-validator dependency without much other use.

I agree, but I'd gather some more opinions first.

Who's going to make sure that there is a CSRF implementation available to users of Laminas Session for example. Is it even necessary based on the current fate of MVC? Mezzio already has an equivalent that doesn't use laminas-validator.

cc @laminas/technical-steering-committee

@froschdesign
Copy link
Member

Is it even necessary based on the current fate of MVC?

I think the main use is in the CSRF element of laminas-form.

@gsteel
Copy link
Member

gsteel commented Nov 25, 2025

Is it even necessary based on the current fate of MVC?

I think the main use is in the CSRF element of laminas-form.

Ideally, laminas-form would not have hard or soft deps on laminas-session.

Maybe laminas-csrf is necessary, so it can have the dependency on both form and session.

On the other hand, why not just use mezzio-csrf 🤷‍♂️

@gsteel
Copy link
Member

gsteel commented Nov 25, 2025

@Jurj-Bogdan Perhaps it would be a good idea to bring this up as a topic for the next TSC meet.

1 - Is the CSRF validator and Form element relevant any more? Can they both be deprecated and removed?
2 - If not, should we be making a new library specifically for laminas-csrf to decouple session from validator and form from session

For the purposes of this patch, why don't we:

  • Keep the existing naming (we can rename in a later patch depending on the outcome of the TSC meet)
  • Retain the CSRF validator and leave it unchanged here (Awaiting TSC meet)

@froschdesign
Copy link
Member

1 - Is the CSRF validator and Form element relevant any more? Can they both be deprecated and removed?

The current usage of CSRF token generation and validation via laminas-form is easy:

$form->add([
    'type' => Laminas\Form\Element\Csrf::class,
    'name' => 'example',
]);

Nothing else needs to be done. So this is very user-friendly.
I am in favour of decoupling, but user-friendliness must not suffer as a result. We already have this problem with mezzio-flash.

@gsteel
Copy link
Member

gsteel commented Nov 25, 2025

Nothing else needs to be done. So this is very user-friendly.

Well, yes and no. Currently form is dependent on validator@v2 which ships the (deprecated) CSRF validator.

When validator is upgraded to v3 in form, the future of the CSRF element will be scrutinised because it automatically attaches the CSRF validator via $element->getInputSpecification() and it will need to depend on session to maintain the functionality of the csrf element.

For people using mezzio with form, all of this is irrelevant - they won't be using the csrf element, nor laminas-session, they'll be using mezzio-session and mezzio-csrf, so we'd be asking mezzio users to install laminas-session for functionality they don't want or need.

Should we be dogmatic about soft dependencies? I prefer to be, mainly because it places clear constraints on installable versions - with soft deps, we could end up with session:2 being installed with form:4 (This wouldn't happen because of validator:2 constraints, but, the point remains)

@froschdesign
Copy link
Member

@gsteel
The technical details and dependencies are all clear, and I also do not want to have the laminas-session component in a Mezzio application. I am only concerned with user-friendliness! And mezzio-csrf simply is not user-friendly. Also mezzio-flash.
We can throw away the old elements, but we need replacements that are cleanly implemented and easy to use. So I do not want to stick to the current structures, just keep the user in mind.

@Jurj-Bogdan
Copy link
Contributor Author

While a decision is taken for the Csrf validator, i've gone through some of the requested changes. A couple of things:

  • removed all unnecessary try-catch blocks and left phpunit to fail on the thrown exception where needed
    • the exception for this are the php <8.4 and >= 8.4 tests in IdTest, where the datasets specify if the validator should fail or not
  • added a new factory for the RemoteAddr validator so that it gets its options array passed, but I don't seem to find a required structure for its config - for now i've set it to config.session_manager.options based on test sequences:

session_manager.validators
session_manager.options

This might be better of reorganised, such as session_manager.validators.{validator_name}.options maybe?

@gsteel
Copy link
Member

gsteel commented Dec 5, 2025

Note https://github.com/laminas/technical-steering-committee/blob/main/meetings/minutes/2025-12-01-TSC-Minutes.md#discussion-around-v3-of-laminas-session

In a separate patch, we should delete anything to do with laminas-form or laminas-validator 👍

@arhimede
Copy link
Member

arhimede commented Dec 5, 2025

Note https://github.com/laminas/technical-steering-committee/blob/main/meetings/minutes/2025-12-01-TSC-Minutes.md#discussion-around-v3-of-laminas-session

In a separate patch, we should delete anything to do with laminas-form or laminas-validator 👍

can you open an issue ? to remember later

Copy link
Member

@gsteel gsteel left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry @Jurj-Bogdan! More nit-picks :)

…rom events

Signed-off-by: Jurj-Bogdan <jurj@dotkernel.com>
…s-strings

Signed-off-by: Jurj-Bogdan <jurj@dotkernel.com>
Signed-off-by: Jurj-Bogdan <jurj@dotkernel.com>
@Jurj-Bogdan Jurj-Bogdan force-pushed the validator-chain-refactor branch from 4df2c90 to f4acb7f Compare December 12, 2025 13:38
@Jurj-Bogdan Jurj-Bogdan requested a review from gsteel December 16, 2025 11:55
Copy link
Member

@gsteel gsteel left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just a few tweaks to

  • Reduce baseline additions
  • Make factories internal to reduce the BC surface

Otherwise 👍

@gsteel gsteel added this to the 3.0.0 milestone Dec 16, 2025
@gsteel gsteel added BC Break Enhancement Dependencies Updates and changes to dependencies labels Dec 16, 2025
Signed-off-by: Jurj-Bogdan <jurj@dotkernel.com>
Signed-off-by: Jurj-Bogdan <jurj@dotkernel.com>
Copy link
Member

@gsteel gsteel left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nearly there!!!

Signed-off-by: Jurj-Bogdan <jurj@dotkernel.com>
Copy link
Member

@gsteel gsteel left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Phew! Thanks @Jurj-Bogdan LGTM!

@froschdesign Anything to add?

@gsteel gsteel self-assigned this Jan 23, 2026
@gsteel gsteel merged commit abfbac5 into laminas:3.0.x Jan 23, 2026
16 of 17 checks passed
Copy link
Member

@Ocramius Ocramius left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

From my PoV, this is a good/stateless design: I provided a lot of feedback on things to improve though, sorry :D

Comment on lines +41 to +50
'classes' => [
Session\Validator\RemoteAddr::class,
Session\Validator\HttpUserAgent::class,
],
'options' => [
'remote_addr' => [
'use_proxy' => false,
'trusted_proxies' => [],
],
]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This type is in the docs, but I don't directly see it reflected in any @psalm-type or array shape in this patch?

* last, however, does not, due to the differences in implementations, and
* the fact that save handlers will often be written in userland. As such
* The first two have corresponding factories inside this namespace.
* "SaveHandlerInterface", however, does not, due to the differences in implementations,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of a quoted string, use {@see ...}?

Comment on lines +135 to +136
/** @var list<class-string<ValidatorInterface>> $validators */
$validators = $validatorsConfig['classes'];
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This type is the one I flagged in the docs: kinda missing anywhere?

Comment on lines +170 to +171
/** @psalm-var list<class-string<ValidatorInterface>> $uniqueValidators */
$uniqueValidators = array_unique($validators);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we even care about uniqueness? What's the disadvantage if more than one is instantiated on accident?


if ($sessionId === null) {
return false;
throw new SessionValidationFailedException('Session id validation failed');
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should explain what failed (missing session ID)

{
return self::class;
if (! (bool) preg_match($pattern, $sessionId)) {
throw new SessionValidationFailedException('Session id validation failed');
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should explain what failed (missing pattern mismatch - the ID and pattern should probably be part of the exception)

{
return self::class;
if ($initial->getUserAgent() !== $current->getUserAgent()) {
throw new SessionValidationFailedException('Http user agent validation failed');
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The mismatching values should be part of the exception

}

if ($this->initialData !== $this->currentData) {
throw new SessionValidationFailedException('Remote address validation failed');
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should add the before/after values to the exception

Comment on lines +14 to +15
/** @throws SessionValidationFailedException */
public function validate(EnvironmentInterface $initial, EnvironmentInterface $current): void;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is obviously a major breaking change, but a welcome one 👍

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

BC Break Dependencies Updates and changes to dependencies Enhancement

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants