Nette extension allows you not only to create open-source packages, but also to <strong>split your application to small and logical chunks of code</strong>.
Open-source extensions are more complex using many Nette\DI features, but today I will show you, how to <strong>start with one Nette\DI method and one service only</strong>.
I consider Nette Sandbox the best way to show learn any Nette feature. Let's use it.
If you want to register a service, what will you do?
# app/config/config.neon
services:
- App\Model\UserManager # put it there
File app/config/config.neon
is like a socket.
There is one place to active your computer, when you plug it in.
But what if your want to plug in computer and mobile charger in the same time?
To load more services, we use the same interface as app/config/config.neon
: a file with service section that lists services.
Let's say we want to decouple a FileSystem utilities.
What about "FileSystem"? If you agree, create src/FileSystem
directory.
We will put configuration (sevices.neon) and classes there.
Starting small, one service will do. When it grows, we can decouple it later.
# src/FileSystem/FileSystem.php
<?php declare(strict_types=1);
namespace FileSystem;
final class FileSystem
{
// some awesome methods!
}
This is similar to app/config/services.neon
, just in different location:
# src/FileSystem/config/services.neon
- FileSystem\FileSystem
# src/FileSystem/DI/FileSystemExtension.php
<?php declare(strict_types=1);
namespace FileSystem\DI;
use Nette\DI\Compiler;
use Nette\DI\CompilerExtension;
final class FileSystemExtension extends CompilerExtension
{
public function loadConfiguration()
{
// this method loads servcies from config and registers them do Nette\DI Container
Compiler::loadDefinitions(
$this->getContainerBuilder(),
$this->loadFromFile(__DIR__.'/../config/services.neon')
);
}
}
# app/config/config.neon
extensions:
- FileSystem\DI\FileSystemExtension
That's it!
Now try using FileSystem\FileSystem
in HomepagePresenter:
# app/presenters/HomepagePresenter.php
<?php declare(strict_types=1);
namespace App\Presenters;
use FileSystem\FileSystem;
class HomepagePresenter extends BasePresenter
{
public function __construct(FileSystem $fileSystem)
{
$this->fileSystem = $fileSystem;
}
}
and running application:
Fails? Damn, I can't put this on my blog.
Oh, we need to tell composer about these classes. He doesn't know, where to find it.
{
"require-dev": {
"..."
},
"autoload": {
"psr-4": {
"FileSystem\\": "src/FileSystem"
}
}
}
And manually rebuild autoload.php
(composer does by default only after composer update
):
composer dump-autoload
Refresh and...
...it works!
Phew! That would have been embarrassing.
Now you know how to do your first extension.
/src
/src/<package-name>/services.neon
/src/DI/<package-name>Extension.neon
app/config/config.neon
autoload
section in composer.json
(prevents from putting failing code to public blog :))Let me know if you get stuck somewhere. I want this tutorial to be as easy to understand as possible.
Do you learn from my contents or use open-souce packages like Rector every day?
Consider supporting it on GitHub Sponsors.
I'd really appreciate it!