Correction of misleading protected modifiers in Presenter class – proposal

m.brecher
Generous Backer | 900
+
-2
-

Hello,

In the ApplicationExtension class, the checkPresenter() method enforces that the presenter methods startup(), beforeRender(), afterRender(), shutdown() and checkHttpMethod() must be public and non-static. However, in the base abstract Presenter class within the Nette framework, these methods are defined as protected. While this does not prevent them from being overridden in extended presenter classes, it introduces unnecessary confusion and lacks clear justification.

After upgrading my projects to the latest version of Nette, ApplicationExtension started throwing exceptions such as:

Nette\InvalidStateException:
Method Nette\Application\UI\Presenter::checkHttpMethod(): this method must be public non-static.

This issue occurred only in some of my older projects that had not been updated for a long time, even though all final presenters had correctly set modifiers as public, while the majority of my updated projects remained unaffected. I could not determine why certain projects triggered the exception while others did not. However, after manually refactoring the Presenter class inside /vendor/ and changing the visibility of the mentioned methods from protected to public, the issue was completely resolved, without any loss of normal presenter functionality.

Proposed Change

I propose modifying the affected methods in the nette/application package by changing their visibility from protected to public, for two key reasons:

a) eliminating unnecessary confusion – the protected modifier in this context serves no meaningful purpose and only introduces ambiguity,

b) preventing unnecessary exceptions – under specific conditions, even syntactically correct final presenters can unexpectedly trigger errors, which this change would effectively prevent.

I kindly request the community to provide comments or suggestions regarding this proposal.

To ensure visibility, I am submitting an PR: https://github.com/…ion/pull/347.

Last edited by m.brecher (2025-06-14 14:30)

Marek Bartoš
Nette Blogger | 1307
+
0
-

These methods are never called publically, but inside of Presenter::run()
Also they are defined by the Presenter class, therefore their visibility is enforced by PHP itself and there is no need to add extra checks.
I see in the latest stable implementation that only action*, render*, handle* and createComponent* methods are checked for public visibility, so what is this about?

m.brecher
Generous Backer | 900
+
0
-

Great point @MarekBartoš !

I found the reason why the Nette presenter checker was throwing a false exception in my old project. It turns out that this was an experimental project where I was trying to remove the annoying action method prefix action<Action>() and use the presenter as a simple controller, without render<View>() methods, just calling the action with action().

This piece of code, added to the presenter, confused the presenter checker, but after removing it, everything works as expected:

public static function formatActionMethod(string $action): string // override abstract presenter
{
     return $action;
}

However, one good reason why the listed methods of an abstract presenter should be public rather than protected still remains, it unnecessarily complicates the code and serves no real function.

What do you think?

Last edited by m.brecher (2025-06-14 16:06)