Nefunguje inject v komponentach
- ondrej1
- Člen | 13
Nevie niekto co robim zle?
Mam model:
namespace App\Model;
use Nette;
class Clanok extends Nette\Object {
/** @var Nette\Database\Context */
private $database;
public function __construct(Nette\Database\Context $database) {
$this->database = $database;
}
public function find($typClankov) {
...
return $clanky;
}
}
a komponentu
namespace App\Components;
use Nette\Application\UI;
class Clanok extends UI\Control {
/** @var \App\Model\Clanok @inject */
public $clanok;
/** @var string */
private $typClankov = "vsetky";
public function setTypClankov($typClankov) {
$this->typClankov = $typClankov;
}
public function render() {
$template = $this->template;
$template->setFile(__DIR__ . '/clanok.latte');
**$template->clanky = $this->clanok->find('prvy');**
$template->render();
}
}
v config.neon
services:
- App\Model\Clanok
ale dostanem chybu:
Call to a member function find() on a non-object
(na zvyraznenom riadku v komponente clanok)
Editoval ondrej1 (16. 8. 2017 18:27)
- Zuben45
- Člen | 268
V komponentě předávej závislosti přes konstruktor ;) http://nette.matej21.cz/cs/di
Editoval Zuben45 (16. 8. 2017 20:51)
- ondrej1
- Člen | 13
To vyzera trochu komplikovane. Pri vytvarani komponenty v presenteri cez
new musim potom dodavat zavislost.
presenter:
/** @var \App\Model\Clanok */
private $clanokModel;
public function __construct(\App\Model\Clanok $clanokModel) {
$this->clanokModel = $clanokModel;
}
protected function createComponentVsetkyClanky() {
$clanok = new \App\Components\Clanok($this->clanokModel);
$clanok->setTypClankov("vsetky");
return $clanok;
}
Editoval ondrej1 (19. 8. 2017 14:27)
- CZechBoY
- Člen | 3608
@ondrej1 potom si může vytvořit továrnu na komponentu.
viz odkaz do dokumentace od @DavidMatějka https://doc.nette.org/…n/components#…
- Šaman
- Člen | 2667
Při použití operátoru new
bys musel stejně ty závislosti
předat ručně. Buď do property (protože public property a anotace inject je
pořád jen public property) anebo, lépe, pomocí inject metody (což je jen
přejmenovaný setter).
Anotace a inject metody jsou jen konvence, kterým rozumí Nette DI kontejner
a zohledňuje je, pokud sám vytváři instanci dané třídy.
Když ji ale vytvoříš pomocí new
, tak ti nepředá nikdo nic.
Ani kdybys zkoušel pomocí new
vytvořit presenter (ve kterém
defaultně funguje i anotace).
Takže to, že ony závislosti vyžaduje už konstruktor je dobře! Hned při vytváření vidíš, co musíš předat. Pokud to bude pomocí setteru (inject metoda) nebo dokonce pomocí ošklivého zápisu do vnitřní public proměnné (inject anotace nad public property), tak to jsou závislosti skryté a tedy velmi nebezpečné z hlediska výskytu chyb (nezařve to hned při spuštění, ale bude se to chovat nesprávně).
A obecně platí: pokud chceš správně používat DI kontejner, tak se
operátoru new
vyhýbej. Kromě drobností jako
new DateTime()
a podobných (třeba tříd z
Nette\Utils
).
Editoval Šaman (19. 8. 2017 15:54)
- Petr Parolek
- Člen | 455
@CZechBoY OT: nikdy by mě nenapadlo dělat DateTime přes DI, ani nevím, jak bych instanci vytvářel. Mohl bys mi prosím popsat řešení?
Editoval ppar (21. 1. 2019 22:20)