nette/application 3.2: attribute #[Requires]

David Grudl
Nette Core | 8182
+
+2
-

I've added a new #[Requires] attribute to Nette Application 3.2. (Currently in the 3.2.x-dev branch).

With this attribute, for example, you can allow access to the presenter only for certain HTTP methods:

#[Requires(methods: 'POST')]
class MyPresenter extends Nette\Application\UI\Presenter
{
}

#[Requires(methods: ['GET', 'POST'])]
class MyPresenter extends Nette\Application\UI\Presenter
{
}

(This setting bypasses and replaces the $allowedMethods array in the presenter.)

You can require an AJAX request:

#[Requires(ajax: true)]
class MyPresenter extends Nette\Application\UI\Presenter
{
}

You can require access only from the same domain:

#[Requires(sameOrigin: true)]
class MyPresenter extends Nette\Application\UI\Presenter
{
}

You can require that the presenter can be accessed only indirectly via forward():

#[Requires(forward: true)]
class MyPresenter extends Nette\Application\UI\Presenter
{
}

You can allow access only to certain actions:

#[Requires(actions: 'default')]
class MyPresenter extends Nette\Application\UI\Presenter
{
}

#[Requires(actions: ['add', 'edit'])]
class MyPresenter extends Nette\Application\UI\Presenter
{
}

All these values can be combined.

Attributes on Methods

The use becomes much more interesting due to the fact that the attribute can be applied not only to the class but also to these methods:

  • action<Name>()
  • render<Name>()
  • handle<Name>()
  • createComponent<Name>()

The last two methods also apply to all components!

So, for example, you can control that an action is executable only by an AJAX POST request:

	#[Requires(methods: 'POST', ajax: true)]
	public function actionDelete(int $id)
	{
		...
	}

Or that the render method will be available only if it is accessed indirectly (forward or setView() in the action method):

	#[Requires(forward: true)]
	public function renderNotFound()
	{
		...
	}

Or, for example, control that a component will be available only in certain actions:

	#[Requires(actions: ['add', 'edit'))]
	public function createComponentPostForm()
	{
		...
	}

For handle methods #[Requires(sameOrigin: false)] replaces the #[CrossOrigin] attribute.

Alternative notation

Attributes can also be written in this way:

	#[Requires(methods: 'POST')]
	#[Requires(ajax: true)]
	public function actionDelete(int $id)
	{
		...
	}

Custom Combinations

You can also inherit the attribute and have a specific configuration under one name:

#[\Attribute]
class AllowAllMethods extends Nette\Application\Attributes\Requires
{
	public function __construct()
	{
		parent::__construct(methods: ['GET', 'HEAD', 'POST', 'PUT', 'DELETE', 'CONNECT', 'OPTIONS', 'TRACE', 'PATCH']);
	}
}

#[AllowAllMethods]
class MyPresenter extends Nette\Application\UI\Presenter
{
}

I would be glad if you could test this and write any comments and suggestions.

Update: the final description of how it works can be found at https://doc.nette.org/…ute-requires