Vykreslení komponenty na všech stránkách (@layout.latte) pomocí BasePresenteru
- Desttro
- Člen | 126
Zdravím,
mám hotovou komponentu – menu, které bych rád zobrazil na
@layout.latte. Příjde mi blbé to mít v každém Presenteru jako
render, tak mne napadlo to renderovat v BasePresenteru.
Postupoval jsem podle tohoto návodu: https://forum.nette.org/…pomoci-mysql
Nette mi ale vždy vyhodí tuhle chybu:
Recoverable Error
Argument 1 passed to FrontModule\MenuControl::__construct() must be an instance
of FrontModule\Nette\Database\Context, null given, called in
/home/psabrnak/web/maxsecure.cz/public_html/app/FrontModule/presenters/BasePresenter.php
on line 36 and defined
Nevím si rady, pomůžete mi prosím? Děkuji.
MenuControl:
namespace FrontModule;
use Nette\Application\UI\Control;
class MenuControl extends Control
{
/** @var Nette\Database\Context */
private $database;
public function __construct(Nette\Database\Context $database)
{
parent::__construct();
$this->database = $database;
}
public function render()
{
$template = $this->template;
$template->setFile(__DIR__ . '/MenuControl.latte');
$template->menu = $this->database->table('menu');
$template->render();
}
}
BasePresenter:
namespace FrontModule;
use Nette,
App\Model;
abstract class BasePresenter extends \Nette\Application\UI\Presenter
{
/** @var \Nette\Database\Context */
private $database;
public function __construct(\Nette\Database\Context $database)
{
$this->database = $database;
}
protected function createComponentMenu()
{
$menu = new MenuControl($this->database);
return $menu;
}
}
- David Matějka
- Moderator | 6445
Pravdepodobne prekryvas konstruktor v nejakem konkretnim presenteru.
Minimalne v base presenterech (ale klidne i v konkretnich presenterech)
injectuj zavislosti pomoci @inject
anotace
/** @var \Nette\Database\Context @inject */
public $database;
(musi byt public)
Editoval matej21 (24. 6. 2014 16:06)
- Desttro
- Člen | 126
Oli napsal(a):
Zkus dát před `Nette `zpětný lomítko
public function __construct(\Nette\Database\Context $database) { parent::__construct(); $this->database = $database; }
nebo použij
use Nette;
nepomohlo, komponenty mám v app, a ne ve FrontModule jako je třeba BasePresenter
matej21 napsal(a):
Pravdepodobne prekryvas konstruktor v nejakem konkretnim presenteru. Minimalne v base presenterech (ale klidne i v konkretnich presenterech) injectuj zavislosti pomoci
@inject
anotace/** @var \Nette\Database\Context @inject */ public $database;
(musi byt public)
zkusil jsem dát do BasePresenteru a nette mi vypsalo:
Compile Error
Access level to FrontModule\HomepagePresenter::$database must be public (as in
class FrontModule\BasePresenter)
A když dám public $database; do HomepagePresenteru, tak to hlásí:
Argument 1 passed to FrontModule\MenuControl::__construct() must be an instance of FrontModule\Nette\Database\Context, instance of Nette\Database\Context given, called in /home/psabrnak/web/maxsecure.cz/public_html/app/FrontModule/presenters/BasePresenter.php on line 36 and defined
Dám zde ještě HomepagePresenter:
namespace FrontModule;
use Nette,
App\Model;
class HomepagePresenter extends BasePresenter
{
/** @var \Nette\Database\Context */
private $database;
/** @var \App\Components\ICategoryFactory @inject */
public $categoryFactory;
public function __construct(\Nette\Database\Context $database)
{
$this->database = $database;
}
protected function createComponentCategory()
{
return $this->categoryFactory->create();
}
public function renderDefault()
{
$this->template->hotels = $featured;
//$this->template->categories = $this->database->table('blog_categories');
//$control = $this->getComponent('node');
}
}
Editoval Desttro (24. 6. 2014 16:14)
- Šaman
- Člen | 2666
Když to injectuješ do BasePresenteru, tak už tu proměnnou samozřejmě nevytvářej v potomcích. A jestli jsi použil injectování anotací, tak ji potomkům nepředávej konstruktorem.
Obecně – proměnné předka vidí i potomek, takže pokud nepřepisuješ
metody (třeba konstruktor), tak potomek databázi má automatocky a nic k tomu
nepotřebuje, než podědit od BasePresenteru. Výjimkou je to předávání
konstruktorem, kde si musíš znovu vyžadovat parametr $db
a
předat ho do parent::__construct($db);
. Tomu se ale raději
vyhýbej pomocí inject metody, nebo inject anotací.
Editoval Šaman (24. 6. 2014 16:27)
- David Matějka
- Moderator | 6445
Ty properties museji byt public, aby se do nich nechalo injectnout. (ano slo by to nejakyma hackama, ale to ted resit nebudu). Je to sice poruseni zapouzdreni, ale v ramci presenteru je to tolerovatelne
Editoval matej21 (24. 6. 2014 16:25)
- Šaman
- Člen | 2666
Desttro napsal(a):
Teď jsem zkusil dát do všech presenterů, které mám ve FrontModule ten inject:
/** @var \Nette\Database\Context @inject */ public $database;
a web jede, ale asi není dobré mát proměnnou $database public že? Jde to nějak vyřešit?
Nedávej to do všech, jen do BasePresenteru. To jsou základy OOP.
Jinak nepříliš čistou property injection (tj. anotace) můžeš nahradit inject metodou. (Raději si prostuduj celou odkazovanou stránku.)
- Desttro
- Člen | 126
Šaman napsal(a):
Desttro napsal(a):
Teď jsem zkusil dát do všech presenterů, které mám ve FrontModule ten inject:
/** @var \Nette\Database\Context @inject */ public $database;
a web jede, ale asi není dobré mát proměnnou $database public že? Jde to nějak vyřešit?
Nedávej to do všech, jen do BasePresenteru. To jsou základy OOP.
Jinak nepříliš čistou property injection (tj. anotace) můžeš nahradit inject metodou. (Raději si prostuduj celou odkazovanou stránku.)
Děkuji, už jsem na to přišel, že to vlastně může dědit. Určitě nastuduji. Děkuji vám hoši.