programming on an interface, not an implementation
- gregor_nette
- Member | 13
Hi,
I try to achieve something like exchanging database connection by using an
interface for a presenter and defining the implemention elsewhere. By this
I want to be able to exchange the implementation without touching the
presenter
My current idea is the following setup.
IArticleFacade is the Interface, DibiArticleFacade is the implementation and
somehow there is a connection telling ArticlelistPresenter to use
DibiArticleFacade.
IArticleFacade.php:
<?php
namespace App\Model;
interface IArticleFacade {
public function getHomepageArticle();
public function getPublicArticles();
public function getArticle(string $artnr);
}
DibiArticleFacade.php:
<?php
namespace App\Model;
use Dibi;
final class DibiArticleFacade implements IArticleFacade{
private Dibi\Connection $database;
public function __construct(Dibi\Connection $database) {
$this->database = $database;
}
public function getPublicArticles() {
return $this->database->query('SELECT * FROM artikel %lmt', 10)->fetchAll(); //
}
public function getHomepageArticle() {
return $this->database->query('SELECT * FROM artikel WHERE sk1 = "1" %lmt', 10)->fetchAll(); //
}
public function getArticle(string $artnr) {
return $this->database->query('SELECT * FROM artikel WHERE artnr = ?', $artnr)->fetch(); //
}
}
and the presenter is something like
<?php
declare(strict_types = 1)
;
namespace App\Presenters;
use App\Model\IArticleFacade;
use Nette;
final class ArticlelistPresenter extends Nette\Application\UI\Presenter {
private IArticleFacade $facade;
public function __construct(IArticleFacade $facade) {
$this->facade = $facade;
}
public function renderDefault(): void {
$this->template->posts = $this->facade->getPublicArticles();
}
}
How do I achieve that?
If my question is unclear or you need some more details, leave a comment. I'm starting with nette…
Thank you very much
- gregor_nette
- Member | 13
Hi,
I guess so… WHERE do I define the implementation?
Is it in something like local.neon ??? Can you point me to an example?
extensions:
dibi: Dibi\Bridges\Nette\DibiExtension22
dibi:
host: 'localhost'
username:
password:
database: test
lazy: true
....
services.neon:
services:
- App\Router\RouterFactory::createRouter
- App\Model\DibiArticleFacade
How do I tell the presenter to use dibi?
Do you have a link to the corresponding docs?
Last edited by gregor_nette (2021-11-03 16:16)
- gregor_nette
- Member | 13
Ok…
to answer my questiton: This works.
I have most likely a different problem, but THAT part seems to work fine.
- Milo
- Nette Core | 1283
Yes, you register services in NEON file. But the local.neon
is
mostly used only for database configuration and similar. It's different for
production and developent. You can use common.neon
or any else
loaded by configurator.
About doc – probably DI autowiring chapter – https://doc.nette.org/…n/autowiring
If you register DibiArticleFacade
as the only
IArticleFacade
implementation, it will be injected into presenter.
But if you want to inject specific implementation, just change
presenter's constructor signature to DibiArticleFacade $facade
and
DI container will choose this one.
If you register more than one IArticleFacade
services
implementation, autowiring for IArticleFacade
typehint will stop
work. You can disable autowiring for the one of IArticleFacade
. Or,
you can specify injected service manually, like:
services:
- App\Presenters\ArticlelistPresenter(facade: DibiArticleFacade)