Modules #
Use modules! If you think you don’t need them, in the future you will need them.
If you are working on application with login, start with the AuthModule.
Then you will find out what modules you will need.
Basic configuration in common.neon for a modular application should look like this:
application:
errorPresenter: Error:Error
mapping:
*: [App, Modules\*Module, Presenters\*Presenter]
This mapping will handle nesting of your modules with a correct namespace.
For example, when you are working on e-shop, you will be able to create
BackofficeModule which will contains e.g. ProductModule and SaleModule in a Modules namespace.
Then your namespace for a presenter CategoryPresenter with category management will look like
App\Modules\BackofficeModule\Modules\ProductModule\Presenters
app/
|-- Modules/
| |-- BackofficeModule/
| | |-- Modules/
| | | | -- ProductModule/Presenters/CategoryPresenter.php
| | | | -- SaleModule/Presenters/OrderPresenter.php
This is a basic premise to keep your project structure tree clean.
Root Directory #
Your app directory should be as clean as possible. You should not put any application specific logic into base (or root) presenters.
Only abstract base presenters with should be defined.
app/
|-- Presenters/
| |-- BasePresenter.php
| |-- BaseSecuredPresenter.php
| |-- templates/
| | |-- @layout.latte
Base Presenter #
Define properties you will use through all your presenters. These properties are only to make your IDE known them.
You can also define orm property because, it will be used almost in every next presenter.
<?php
namespace App\Presenters;
use App\Model\Orm;
use Nette\Bridges\ApplicationLatte\Template;
use Nette\Utils\ArrayHash;
/**
* @property-read string $name
* @property-read string $action
* @property-read Template|ArrayHash $template
*/
abstract class BasePresenter extends Presenter
{
#[Inject]
public Orm $orm;
}
Base Secured Presenter #
For secured presenters - which will need a logged-in user.
<?php
declare(strict_types=1);
namespace App\Presenters;
use Nette\Application\AbortException;
use Nette\Security\UserStorage;
abstract class BaseSecuredPresenter extends BasePresenter
{
/**
* @throws AbortException
*/
protected function startup(): void
{
parent::startup();
if (!$this->user->isLoggedIn()) {
if ($this->user->getLogoutReason() === UserStorage::LOGOUT_INACTIVITY) {
$this->flashMessage('flash.signOut.inactivity');
}
$this->redirect(':Auth:SignIn:', ['backlink' => $this->storeRequest()]);
}
// TODO any other security checks
}
}
Error Module #
Error presenters and templates from Nette Sandbox should be moved to separate module – ErrorModule.
Don’t forget to fix the namespaces in presenters.
app/
|-- Modules/
| |-- ErrorModule/
| | |-- Presenters/
| | | |-- ErrorPresenter.php
| | | |-- Error4xxPresenter.php
| | | |-- templates/
| | | | |-- @layout.latte
| | | | |-- Error/
| | | | | |-- 4xx.latte
| | | | | |-- 403.latte
| | | | | |-- 404.latte
| | | | | |-- ...
Check it if it’s all working by change of your configuration in common.neon by appending:
application:
catchExceptions: true
Module Directory Tree #
Each module can contain:
Controlswith implementation and factories for module-specific controls,Datagridsdirectory with datagrid factories,Formswith form factories, container factories, etc.Filterswith module-specific latte filters,Modulesif there are any sub-modules,Presenterswhere source code of presenters will be,Presenters/AbstractPresenter.phpwhich will be parent presenter for this module,Presenters/templateswhere latte templates will be placed,Serviceswith at least services to handle forms processing.
Controls #
Datagrids #
Forms #
Filters #
Presenters #
Services #
Root Layout Template #
To use a one layout template across all your modules and sub-modules, you need to overwrite method formatLayoutTemplateFiles
and append at the end a new path to layout template.
<?php
namespace App\Presenters;
// ...
abstract class BasePresenter extends Presenter
{
// ...
/**
* @return string[]
*/
public function formatLayoutTemplateFiles(): array
{
$files = parent::formatLayoutTemplateFiles();
$files[] = __DIR__ . '/templates/@layout.latte';
return $files;
}
}
If you need a single module with a different layout, it doesn’t need any more configuration.
Just create @layout.latte in your module, it will work as is planned in Nette as default – suitable for example
for your AuthModule as follows:
app/
|-- Modules/
| |-- AuthModule/
| | |-- Presenters/
| | | |-- SignInPresenter.php
| | | |-- SignUpPresenter.php
| | | |-- templates/
| | | | |-- @layout.latte
| | | | |-- SignIn.default.latte
| | | | |-- SignUp.default.latte
|-- Presenters/
| |-- BasePresenter.php
| |-- BaseSecuredPresenter.php
| |-- templates/
| | |-- @layout.latte