Diskuze: Pripojenie komponenty k DB
Jindřich Máca:24.5.2016 0:34
Ahoj, jednoduše si závislost na modelu předám pomocí DI.
Dominik Gavrecký:24.5.2016 0:40
Takze klasicky cez konstruktor ako v presenteri ?
Dominik Gavrecký:24.5.2016 13:29
<?php
/**
* Created by PhpStorm.
* User: Dominik Gavrecký
* Date: 22.05.2016
* Time: 19:26
*/
namespace Nette\Forms\Controls;
use Nette\Application\UI\Control;
use App\Model\NewsManager;
class Category extends Control
{
/** @var newsManager*/
public $newsManager;
/**
* Category constructor.
* @param newsManager $newsManager
*/
public function __construct(newsManager $newsManager)
{
parent::__construct();
$this->newsManager = $newsManager;
}
public function renderCategory($id){
$this->template->categoryName = $this->newsManager->getCategory()->where('id', $id);
$this->template->news = $this->newsManager->getNews();
$this->template->setFile(__DIR__ . '/name.latte');
$this->template->render();
}
}
Takto som to skúsil spraviť ale nabehne mi error.
Argument 1 passed to Nette\Forms\Controls\Category::__construct() must be an instance of App\Model\NewsManager, none given, called in /web/htdocs3/rewizeu/home/subdoms/dev/app/AdminModule/presenters/NewsPresenter.php on line 146
Jindřich Máca:24.5.2016 13:52
Ahoj, mám k tomu hned několik věcí.
- Máš tam rozházená malá a velká písmena...
// Podle tohoto namespace, se ta třída jmenuje "NewsManager".
use App\Model\NewsManager;
// Potom ale dodržuj ten správný název s velkými písmeny.
/** @var NewsManager*/
public $newsManager;
/**
* Category constructor.
* @param NewsManager $newsManager
*/
public function __construct(NewsManager $newsManager)
{
parent::__construct();
$this->newsManager = $newsManager;
}
- Máš ten model dobře zaregistrovaný v konfiguračním souboru?
- Máš ten název a namespace dobře napsaný i v definici té třídy NewsManager?
Tohle si nejdříve vyřeš a potom se uvidí.
Dominik Gavrecký:24.5.2016 14:42
Teraz by to malo byť správne. Registrovaný aj správne napísaný ten namespace je presne rovnakým spôsobom ako sa ho snažím využiť v komponente ho využívam aj v presenteri s tým rozdielom že v presenteri mi to funguje.
<?php
/**
* Created by PhpStorm.
* User: Dominik Gavrecký
* Date: 22.05.2016
* Time: 19:26
*/
namespace Nette\Forms\Controls;
use Nette\Application\UI\Control;
use App\Model\NewsManager;
class Category extends Control
{
/** @var NewsManager */
public $newsManager;
/**
* Category constructor.
* @param NewsManager $newsManager
*/
public function __construct(NewsManager $newsManager)
{
parent::__construct();
$this->newsManager = $newsManager;
}
/**
* @param $id
* Render Category a jeho vykreslenie do name.latte
*/
public function renderCategory($id){
$this->template->categoryName = $this->newsManager->getCategory()->where('id', $id);
$this->template->news = $this->newsManager->getNews();
$this->template->setFile(__DIR__ . '/name.latte');
$this->template->render();
}
}
Jindřich Máca:24.5.2016 16:25
No, tak ještě jedna technická připomínka, které jsem si před tím nevšiml, ale také by neměla mít vliv na funkčnost...
// Ten atribut by měl být spíš private.
/** @var NewsManager */
private $newsManager;
A potom si promaž cache i log a podívej se, jestli to pořád hází tu samou chybu nebo třeba nějakou jinou?
A pokud je to ta samá, tak sem ještě pošli, jak inicializuješ tu komponentu Category v rámci presenteru, ve kterém ji používáš. Mám takový pocit, že chyba bude nejspíše tam.
Dominik Gavrecký:24.5.2016 16:42
Toto mám v presenteri s tým že som ten controler premenoval a cache som zmazal a namespace mám správny
protected function createComponentCategory()
{
$control= new NewsComponent;
return $control;
}
Dominik Gavrecký:24.5.2016 16:45
Pre istotu tu dám aj upravený controler
<?php
/**
* Created by PhpStorm.
* User: Dominik Gavrecký
* Date: 22.05.2016
* Time: 19:26
*/
namespace Nette\Forms\Controls;
use Nette\Application\UI\Control;
use App\Model\NewsManager;
class NewsComponent extends Control
{
/** @var NewsManager */
private $newsManager;
/**
* Category constructor.
* @param NewsManager $newsManager
*/
public function __construct(NewsManager $newsManager)
{
parent::__construct();
$this->newsManager = $newsManager;
}
/**
* @param $id
* Render Category a jeho vykreslenie do name.latte
*/
public function renderCategory($id){
$this->template->categoryName = $this->newsManager->getCategory()->where('id', $id);
$this->template->news = $this->newsManager->getNews();
$this->template->setFile(__DIR__ . '/name.latte');
$this->template->render();
}
}
Jindřich Máca:24.5.2016 16:57
Tak pak je to úplně jasné...
protected function createComponentCategory()
{
$control= new NewsComponent; // TOHLE JE ŠPATNĚ!*
return $control;
}
* Pokud totiž instanciuješ komponentu tímto způsobem, pomocí new, musíš se o předání závislostí v konstruktoru postarat sám. Druhým způsobem je pak používání továrniček, kde se o dodání závislostí stará Nette samo, pomocí DI. Tohle vše je popsané v mém seriálu o Nette.
Dominik Gavrecký:24.5.2016 17:33
Ako to myslis sám mohol by si mi poskytnúť nejaký názorný príklad ?
Jindřich Máca:24.5.2016 21:46
No dobrá, tak že jsi to ty.
- Předání závislostí v konstruktoru. Tohle by jsi měl bezpečně znát, protože to patří do základů OOP.
// Uvnitř daného presenteru.
/** @var NewsManager */
private $newsManager;
/**
* Presenter constructor.
* @param NewsManager $newsManager
*/
public function __construct(NewsManager $newsManager)
{
parent::__construct();
$this->newsManager = $newsManager;
}
protected function createComponentCategory()
{
/* Předáváš závislost v konstruktoru,
přičemž tu předávanou instanci musíš samozřejmě někde získat,
v tomto případě pomocí DI v rámci daného presenteru. */
$control= new NewsComponent($this->newsManager);
return $control;
}
- Automatické předání závislosti pomocí DI za použití továrničky pro danou komponentu Category. Jelikož Nette navíc umožňuje vytvářet generované továrničky s autowiringem, tak je dobré toho využít. Tohle už je samozřejmě pokročilá technika z Nette, takže bližší info najdeš třeba tady - https://pla.nette.org/…h-autowiring
// Uvnitř souboru s třídou komponenty *Category* přidáme ještě interface.
class Category extends Control
{
...
}
interface ICategoryFactory
{
/**
*
* @return Category
*/
public function create();
}
// Ten pak musíme zaregistrovat jako službu továrničky v konfiguračním souboru.
services:
- Nette\Forms\Controls\ICategoryFactory
// A dále tuto továrničku získáme v presenteru pomocí DI a použijeme pro tvorbu komponenty.
// Uvnitř daného presenteru.
/** @var ICategoryFactory */
private $categoryFactory;
/**
* Presenter constructor.
* @param ICategoryFactory $categoryFactory
*/
public function __construct(ICategoryFactory $categoryFactory)
{
parent::__construct();
$this->categoryFactory = $categoryFactory;
}
protected function createComponentCategory()
{
// Instance se prostě vytvoří a o všechny její závislosti je postaráno automaticky.
$control= $this->categoryFactory->create();
return $control;
}
Tak si myslím, že víc názornější už jsem snad být nemohl. Máš k tomu ještě nějaké otázky?
+20 Zkušeností
+2,50 Kč
Dominik Gavrecký:24.5.2016 21:47
Ďakujem ti vážne si to od teba strašne vážim
TomasGlawaty:24.5.2016 22:57
Dodal bych jen takové detaily. Pro vlastní komponenty nepoužívej namespace Nette\Forms\Controls ale nejaky vlastní, tohle platí pro všechny třídy. Proste to nedává smysl, jelikož ta tvoje komponenta neni součásti Nette dále v konstruktoru potomka UI\Control neni potřeba volat předkuv kontruktor, jelikož by mel byt volný.
Zobrazeno 16 zpráv z 16.