Předání závislého interface
- tttpapi
- Člen | 100
Ahoj,
chtěl jsem si vytvořit obecnější odesílač emailu.
Mám třídy a interface:
<?php
namespace App\Model\Mails;
class MailTemplateFactory extends \Nette\Object {
const DEFAULT_FROM = "test@test.cz";
private $template;
public function __construct(IMailTemplate $template) {
$this->template = $template;
}
public function getMailTemplate($subject, $body, $to, $from = self::DEFAULT_FROM) {
return $this->template->getMailTemplate($subject, $body, $to,
$from);
}
}
?>
<?php
namespace App\Model\Mails;
interface IMailTemplate {
public function getMailTemplate($subject, $body, $to, $from);
}
?>
<?php
class NetteMailTemplate implements IMailTemplate {
private $template;
public function __construct() {
$this->template = new \Nette\Mail\Message();
}
public function getMailTemplate($subject, $body, $to, $from) {
$this->template = new \Nette\Mail\Message();
$this->template->setFrom($from);
$this->template->setBody($body);
$this->template->setSubject($subject);
$this->template->addTo($to);
return $this->template;
}
}
?>
<?php
namespace App\Model\Mails;
use Nette;
class MailSenderFactory extends Nette\Object {
private $mailSender;
public function __construct(IMailSender $mailSender) {
$this->mailSender = $mailSender;
}
public function send(IMailTemplate $template) {
$this->mailSender->send($template);
}
}
?>
<?php
namespace App\Model\Mails;
interface IMailSender {
function send(IMailTemplate $template);
}
?>
<?php
class NetteMailSender implements IMailSender {
public function __construct() {
}
public function send(IMailTemplate $template) {
$mailSender = new Nette\Mail\SendmailMailer();
$mailSender->send($template);
}
}
?>
Pak si v konstruktoru předávám závislosti na továrničky.
<?php
public function __construct(Nette\Database\Context $database,
Mails\MailTemplateFactory $mailTemplateFactory, Mails\MailSenderFactory $mailSenderFactory) {
?>
A v neonu mám:
<?php
services:
- App\Model\UserManager
- App\RouterFactory
- App\Model\Documents
- App\Model\FileFeeder
- App\Model\Users
- App\Model\Mails\MailSenderFactory
- App\Model\Mails\MailTemplateFactory
- App\Model\Mails\IMailSender
- App\Model\Mails\IMailTemplate
?>
Takhle mi to po spuštění zahlásí:
Interface App\Model\Mails\IMailSender used in service
‚61_App_Model_Mails_IMailSender‘ must have just one non-static method
create() or get().
A pokud smažu poslední 2 řádky v neonu, tak mi to hlásí:
Service ‚61_App_Model_Mails_MailSenderFactory‘: No service of type
App\Model\Mails\IMailSender found. Make sure the type hint in
App\Model\Mails\MailSenderFactory::__construct() is written correctly and
service of this type is registered
Mohl by mi někdo poradit, jak na to?
Budu rád za každou radu nebo kritiku.
Díky.
- Michal Vyšinský
- Člen | 608
Ahoj,
interface je to, co používáš na injektování (v konstruktoru). Do neon dáváš třídu konkrétní implementace takže:
App\Model\Mails\IMailSender → NetteMailSender
App\Model\Mails\IMailTemplate → NetteMailTemplate
Tím, že tam předáš interface si nette myslí, že má generovat továrničku podle daného interface. Použití interfaců pro závislosti je dobrý postup – lehce jde cokoliv změnit. V neon konfiguraci ale dáváš konkrétní konfiguraci pro konkrétní aplikaci, takže tam se dávají už konkrétní implementace.
- Michal Vyšinský
- Člen | 608
Na tyto specifické věci (mail, databáze) je dobré mít config/local.neon, který nebudeš mít v gitu (jestli jej používáš).
Pak v boostrapu přidáš:
$configurator->addConfig(__DIR__ . '/config/local.neon');
V local.neon můžeš mít veškerá specifická nastavení jako je právě připojení k databázi, logování atd. Můžeš tam dát i definici služeb.
- tttpapi
- Člen | 100
To mám. Ještě bych ale teda potřeboval mít různé configy pro různá prostředí – a zajímalo by mě, jestli je možnost si je nějak automaticky přepínat, nebo jestli to musím někde vždycky po přesunu ručně změnit, že např. místo config.production.neon bude používat config.localhost.neon…
- Michal Vyšinský
- Člen | 608
Možná něco takového, když local.neon nevyhovuje:
vytvořit soubor config/env.php:
<?php
return 'production';
A přidat do bootstrap.php:
$env = require __DIR__ . '/config/evn.php';
$configurator->addConfig(__DIR__ . '/config/config.' . $env . '.neon');
- Jan Endel
- Člen | 1016
To je relativně jednoduché, řešením jsou sekce v config.neonu, nějak takto:
common:
database:
dbname: my_app
production < common:
database:
user: my_app
password: xgarR4tGV$dx5#
host: example.com
port: 3307
development < common:
database:
user: pilec
password: jakobin
host: localhost
Pozn. znak <
je v neonu použit pro
dědění sekcí
- tttpapi
- Člen | 100
Jan Endel napsal(a):
To je relativně jednoduché, řešením jsou sekce v config.neonu, nějak takto:
common: database: dbname: my_app production < common: database: user: my_app password: xgarR4tGV$dx5# host: example.com port: 3307 development < common: database: user: pilec password: jakobin host: localhost
Pozn. znak
<
je v neonu použit pro dědění sekcí
To je přesně to, co jsem chtěl.
A jak ještě oznámím aplikaci, na kterém prostředí se nacházím?