Společná závislost pro více tříd
- SamuelThorn
- Člen | 29
Ahoj.
Procházel jsem fórum, ale na svou otázku jsem odpověď bohužel nenašel.
Mám několik tříd (*DAO), které jsou potomkem třídy
BaseDAO a volají uložené procedury (SP) v MSSQL databázi.
Každá uložená procedura potřebuje pro své volání kromě jiných také
parametr param1
, který se nachází v entitě přihlášeného
uživatele. Pokud uživatel není přihlášený, má param1
hodnotu null
.
Všechno začalo tím, že jsem si z presenteru předával
param1
do volání metody příslušné *DAO služby. Tato volání
jsou ale na desítkách až stovkách míst, proto mě napadlo, jestli by si
hodnotu param1
nemohla řešit příslušná *DAO služba
automaticky. Přidal jsem tedy závislost na \Nette\Security\User
,
ze kterého si vytáhnu Identity
, ve které mám
param1
uložený. Nicméně volání různých SP jdou také do
desítek a tedy by bylo nasnadě posunout práci s param1
„výše“, tedy že by BaseDAO byla závislá na
\Nette\Security\User
a její potomci (služby *DAO) by se jen
obrátili na svého rodiče. A tady právě narážím, protože nevím, jak to
vyřešit.
Dal jsem závislost na \Nette\Security\User
do konstruktoru
BaseDAO, ale pak to po mně vyžaduje uvedení této
závislosti ve všech konstruktorech potomků, kde volám
parent::__construct
. V případě přidání další podobné
závislosti nastane constructor hell.
Četl jsem články tady „Získávání závislostí“, i další různě po netu, ale bohužel jsem na to nepřišel.
Snad jsem problém vylíčil dost jasně. Kdyby ne, tak určitě informace doplním.
Poradíte prosím? Má něco takové řešení, nebo na to jdu úplně špatně?
- SamuelThorn
- Člen | 29
CZechBoY: To by ale znamenalo, že v každém z nich
proběhne test, jestli je v User
daná hodnota a naplnění
param1
buď touto hodnotou, nebo null, a že tedy bude na mnoha
místech identický kód. Tomu jsem chtěl předejít. Těch DAO objektů je
nyní 14 (a patrně jich bude více).
- SamuelThorn
- Člen | 29
matopeto: Mohl bys to prosím trochu rozvést?
Teď je to:
<?php
class BaseDAO {
}
class JednoDAO extends BaseDAO {
public function __construct(User $user)
{
$this->userData = isset($user->identity->data) ? $user->identity->data : null;
}
}
class DruheDAO extends BaseDAO {
public function __construct(User $user)
{
$this->userData = isset($user->identity->data) ? $user->identity->data : null;
}
}
?>
a před každým voláním SP je pak:
<?php
$params['param1'] = isset($this->userData) ? $this->userData['param1'] : null;
//proveď SP
...
?>
A tohle by se mi opakovalo před každým voláním. Je to tedy spousta naprosto stejného, opakujícího se kódu.
Čím víc o tom přemýšlím, bylo by asi lepší rozšířit metodu
execute
objektu PDO, aby si tento parametr přidávala sama. Ale to
už vůbec nevím, jak udělat.
- matopeto
- Člen | 395
nejako takto som to myslel:
abstract class BaseDAO {
protected $userData;
protected function __construct(User $user)
{
$this->userData = isset($user->identity->data) ? $user->identity->data : null;
}
protected getParam1() {
return isset($this->userData) ? $this->userData['param1'] : null;
}
}
final class JednoDAO extends BaseDAO {
public function __construct(User $user) : base($user)
{
}
}
final class DruheDAO extends BaseDAO {
public function __construct(User $user) : base($user)
{
}
}
a před každým voláním SP je pak:
$params['param1'] = $this->getParam1();
//proveď SP
...
Editoval matopeto (14. 6. 2017 16:37)
- SamuelThorn
- Člen | 29
matopeto napsal(a):
nejako takto som to myslel:
Ha, takto to funguje, děkuju.
Jen se tedy ujistím, že pokud by přibyla nějaká podobná společná závislost, je potřeba ji vepsat do konstruktorů všech potomků, je to tak?
- SamuelThorn
- Člen | 29
matopeto napsal(a):
Ano
Ok. Děkuju. Snažil jsem se tomu vyhnout, ale zjevně to není možné. :)
- SamuelThorn
- Člen | 29
Martk napsal(a):
Využil bych dekorátor od nette, více zde
Díky za tip. Nakonec mě to, co poradil matopeto, přivedlo na nápad, jak to celé vyřešit lépe. A zdá se, zbude jen jedno BaseDAO a ostatní nebudou potřeba.