Prenasanie zavislosti – viac instancii triedy – kontajner?
- Dendy
- Člen | 8
Zdravim Vas,
som troska zmeteny ako vytvorit viac instancii jednej triedy.
Aktuálny stav
Mam triedu Objednavka
, zatial iba s jednym parametrom –
pripojeniu k DB:
<?php
class Objednavka extends DBConnection {
public function __construct(Nette\Database\Context $db) {
parent::construct($db);
}
// atd ...
}
?>
V prezentery sa trieda inicializuje v konstruktore cez DI:
<?php
class FormularPresenter extends BasePresenter {
/** @var \App\Model\Objednavka */
private $order;
public function __construct(\App\Model\Objednavka $order) {
$this->order = $order;
}
?>
Tam bez problemov pracujem s $this->order
. O všetky
zavislosti sa postara DI.
Problem
V prezentery mozem teda pracovat s jednou Objednavkou
. Ale
potreboval by som
- aby som mohol mat viac instancii triedy
Objednavka
. Cize pole objektov objednavok, - aby som mohol predavat parameter
$id
Ako na to
Mam použit kontajner? V tom pripade neviem ako tam predavat pripojenie na
$db
. Chcel by som iba nieco taketo:
<?php
$pole[] = new \App\Model\Objednavka(5); // 5 je cislo objednavky
?>
Dakujem za akukolvek radu a usmernenie.
- ViPEr*CZ*
- Člen | 818
Trochu špatnej návrh ne? V konstruktoru předáváte DB konekci a hned o pár řádků níže cpete do kontruktoru číslo 5? Myslím, že tomu nikdo nebudeme rozumět. Obecně pokud chcete nějakou třídu instancovat vícekrát a třída je registrovaná v configu, pak si udělejte tzv. factory, která bude umět z dané třídy dělat instance. Poté budete mít operátor new na jednom místě a o závyslosti se postará DI.
- David Matějka
- Moderator | 6445
Pripada mi, ze michas dohromady, kdy Objednavka reprezentuje nejakou modelovou tridu pro praci s tabulkou objednavek a kdy ta stejna trida reprezentuje jednu objednavku samotnou – to neni dobry.
Tak nejdriv budes mit nejakou modelovou tridu – rikejme ji treba OrderRepository (nebudem michat cestinu a anglictinu, ze ne? :) ). Ta bude umet nacist jednu objednavku z db, pripadne vic objednavek dle nejakych kriterii
class OrderRepository
{
private $database;
public function __construct(Nette\Database\Context $database)
{
$this->database = $database;
}
public function find($id)
{
...
}
public function findNewOrders()
{
...
}
}
tahle trida bude registrovana jako sluzba v neonu
services:
- OrderRepository
a ted, pokud opravdu potrebujes reprezentovat jednu objednavku vlastnim objektem a nebude ti stacit treba ActiveRow z Nette\Database, tak si vytvoris novou tridu
class Order
{
...
}
ta jiz nebude registrovana jako sluzba a jeji instance bude vytvaret OrderRepository
- romiix.org
- Člen | 343
Nepoužívam takýto model, ale viac inštancií toho istého typu je dobré generovať továrničkou.
namespace App\Model;
interface IOrderFactory
{
/** @return App\Model\Objednavka */
public function create();
}
Toto si zaregistruj medzi služby:
services:
- App\Model\IOrderFactory
Nette ti podla anotácií a typehintov vygeneruje továrničku s týmto
interfacom.
Do presentra si injectni App\Model\IOrderFactory
a
v kóde použi:
$order = $this->orderFactory->create();
$order->id = $id;
Nestíham, stihli ma predbehnúť :)
Editoval romiix.org (4. 3. 2016 13:23)
- Dendy
- Člen | 8
v kazdom pripade dakujem za odpoved,
ale asi som to zle napisal, v podstate dva problemy, jeden porieseny:
- cez factory sa vyriesi, ze budem si moct vytvarat viac instacii, to chapem.
- ale ako tam budem prenasat
$db
? (preto som napisal iba(5)
a nie($db, 5)
lebo chcel som aby sa nejak DB tam automaticky naplnila. Musim niekde o uroven vyssie si inicialozvat DB a potom to tam vlozit ako parameter?
(ospravedlnujem sa ak je to blba otazka :/ )
ViPErCZ napsal(a):
Trochu špatnej návrh ne? V konstruktoru předáváte DB konekci a hned o pár řádků níže cpete do kontruktoru číslo 5? Myslím, že tomu nikdo nebudeme rozumět. Obecně pokud chcete nějakou třídu instancovat vícekrát a třída je registrovaná v configu, pak si udělejte tzv. factory, která bude umět z dané třídy dělat instance. Poté budete mít operátor new na jednom místě a o závyslosti se postará DI.
- romiix.org
- Člen | 343
Dendy napsal(a):
v kazdom pripade dakujem za odpoved,
ale asi som to zle napisal, v podstate dva problemy, jeden porieseny:
- cez factory sa vyriesi, ze budem si moct vytvarat viac instacii, to chapem.
- ale ako tam budem prenasat
$db
? (preto som napisal iba(5)
a nie($db, 5)
lebo chcel som aby sa nejak DB tam automaticky naplnila. Musim niekde o uroven vyssie si inicialozvat DB a potom to tam vlozit ako parameter?
No práve tá factory ako som ti ju napísal (genrovaná z interfacu) ti automaticky dodá objekt rovno s dodanou závislosťou na DB.
- Dendy
- Člen | 8
Dakujem, pomohlo.
David Matějka napsal(a):
Pripada mi, ze michas dohromady, kdy Objednavka reprezentuje nejakou modelovou tridu pro praci s tabulkou objednavek a kdy ta stejna trida reprezentuje jednu objednavku samotnou – to neni dobry.
Tak nejdriv budes mit nejakou modelovou tridu – rikejme ji treba OrderRepository (nebudem michat cestinu a anglictinu, ze ne? :) ). Ta bude umet nacist jednu objednavku z db, pripadne vic objednavek dle nejakych kriterii
class OrderRepository { private $database; public function __construct(Nette\Database\Context $database) { $this->database = $database; } public function find($id) { ... } public function findNewOrders() { ... } }
tahle trida bude registrovana jako sluzba v neonu
services: - OrderRepository
a ted, pokud opravdu potrebujes reprezentovat jednu objednavku vlastnim objektem a nebude ti stacit treba ActiveRow z Nette\Database, tak si vytvoris novou tridu
class Order { ... }
ta jiz nebude registrovana jako sluzba a jeji instance bude vytvaret OrderRepository
- kleinpetr
- Člen | 480
Udělej si nějakou modelovou vrstvu pro práci s databází. Např. třídu
Table
, která v konstruktoru přijme Database/Context
a udělej si nějaké univerzální metody. find($id), findBy($array), apod.
V téhle třídě si vytvoř protekční proměnnou $table; od téhle třídy
potom budeš dědit další třídy, které budou nastavovat pouze proměnnou
$table; Takže ve finále by to mohlo vypadat nějak takhle:
abstract class Table extends Nette\Object
{
/** @var Nette\Database\Context */
protected $db;
public function __construct(Nette\Database\Context $db)
{
$this->db = $db;
}
protected function getTable()
{
return $this->db->table($this->tableName);
}
public function findAll()
{
return $this->getTable();
}
public function findBy(array $by)
{
return $this->getTable()->where($by);
}
Model Objednávek by mohl vypadat takto
class Objednavky extends Table
{
protected $table = 'objednavky';
}
Tento model si přidej do configu
- App\Model\Table\Objednavky
a potom v presenteru načti v konstruktoru
__construct(App\Model\Table\Objednavky $objednavky){..}
a pak už jen pracuj s tím modelem:
public function renderObjednavka($id){
$this->template->objednavka = $this->objednavky->find($id);
}
Editoval kleinpetr (4. 3. 2016 13:46)