Nastavení ‚magických‘ vlastností DibiRow jako private
- Šaman
- Člen | 2666
Ahoj, při práci s modelem používám vlastní třídu odvozenou od DibiRow (viz příklad TodoList v distribuci) a potřeboval bych všechny vlastnosti (které si ona třída nějak sama vytáhne z výsledků) nastavit jako private a navenek zpřístupnit jen moje vlastní gettery a settery.
Máte s tím někdo zkušenosti, pls?
P.S. Předpokládám, že ten příklad TodoList většina nettistů zná. Jestli není jasný co potřebuji, mohu to trochu víc rozvinout.
///edit: Tak to nastavení proměnných probíhá v konstruktoru DibiRow (https://api.dibiphp.com/…Row.php.html#21) na řádku 26, ale nevím jak je zprivátnit.
Editoval Šaman (13. 8. 2010 9:50)
- westrem
- Člen | 398
Vyuzi magicke metody __get()
a __set()
.
Je trochu skoda, ze triedy v dibi nededia od Object
pretoze by
si mal vystarane, kazdopadne premenne si nastav na private. V
__get()
potom len skontroluj ci dana premenna naozaj ako private
existuje a ak ano tak ju nastav ak nie, vyhod vynimku.
- Šaman
- Člen | 2666
Tak jsem to vyřešil, ale nevím jestli jsem to moc nezbastlil.
Pomocí setRowClass jsem si nastavil vlastní třídu která od DibiRow nedědí, ale v konstruktoru si ji vytváří.
<?php
class Location extends Object
{
private $dibiRow = null;
public function __construct($locationData)
{
$this->dibiRow = new DibiRow($locationData);
}
...
/**
* Vrátí název lokace
* @return string název lokace
*/
public function getLabel()
{
return $this->dibiRow->label;
}
}
?>
Zdá se, že všechno funguje, přístup k datům mám ošetřený přes
gettery, IDE mi je našeptává, ALE v dokumentaci se
u setRowClass (https://api.dibiphp.com/…ult.php.html#191)
píše, že třída by měla být odvozena od DibiRow. Což
není, pouze akceptuje stejný argument v konstruktoru. A otázka zní –
vadí to, případně může to vadit při nějaké budoucí aktualizaci
Nette?
Díky.
- Šaman
- Člen | 2666
westrem napsal(a):
Vyuzi magicke metody
__get()
a__set()
.Je trochu skoda, ze triedy v dibi nededia od
Object
pretoze by si mal vystarane, kazdopadne premenne si nastav na private. V__get()
potom len skontroluj ci dana premenna naozaj ako private existuje a ak ano tak ju nastav ak nie, vyhod vynimku.
Aha, chvíli jsem nechápal jak nastavit na privátní, ale pak mi došlo,
že pokud si je v mé odvozené třídě explicitně definuji, tak ten
konstruktor mi je jenom naplní.
Existenci proměnné ani nemusím kontrolovat v __get(), ale stačí jen nevolat
parent construct, a naplnit si proměnné ve vlastním konstruktoru sám.
Díky, to bude asi nejlepší řešení.
Editoval Šaman (13. 8. 2010 12:59)
- westrem
- Člen | 398
Problem bude v:
class DibiRow implements ArrayAccess, IteratorAggregate, Countable
Teda tvojmu objektu chybaju tieto metody, ktore sa mozu vyuzivat v DibiResult ak sa nemylim.
Viem, ze riesenie, ktore teraz navrhnem je z hladiska navrhu kodu typu prasackeho ale myslim si, ze v tomto pripade sa da nad tym prizmurit ocko.
Jednoducho do tvojej classy pridaj vsetko co je v DibiRow a zaroven si poded od Object, cim ziskavas presne co si chcel.
Osobne tak trochu nechapem preco aj DibiRow nededi od DibiObject, asi aby nevznikali nejake nezrovnalosti, ale clovek by to cakal.
- Šaman
- Člen | 2666
Díky, už jsem to změnil zpátky a moje třída dědí DibiRow.
Ve vlastním konstruktoru si kontroluji existenci proměnné a jen pokud už
existuje, tak ji nastavuji.
<?php
class Location extends DibiRow
{
// seznam promennych ktere ocekavame v poli $locationData
// pokud nejaka promenna neni definovana, je vyhozena vyjimka
private $id_location; // read only
private $label;
private $gps_n;
private $gps_e;
private $description;
/**
* Location constructor
* @param array
*/
public function __construct($locationData)
{
foreach ($locationData as $key => $value)
{
if (property_exists('Location', $key))
{
$this->$key = $value;
}
else
{
throw new Exception("Pokus o přístup k neznámé proměnné: Location->$key");
}
}
}
/**
* Vrátí ID lokace
* @return int ID lokace
*/
public function getId()
{
return $this->id_location;
}
...
}
?>
Jediný problém, který ale zatím nehodlám řešit, je přístup k privátním proměnným přes pomocné metody třídy DibiRow. Např:
<?php
/**
* Converts value to boolean.
* @param string key
* @return mixed
*/
public function asBool($key)
{
$value = $this[$key];
if ($value === NULL || $value === FALSE) {
return $value;
} else {
return ((bool) $value) && $value !== 'f' && $value !== 'F';
}
}
?>
Editoval Šaman (13. 8. 2010 13:53)
- Šaman
- Člen | 2666
Tak po celodením testování si už připadám jako král Půlnoční země: ovdolávám co jsem odvolal a nařizuji co jsem nařídil :p
Pokud třída odvozená od DibiRow má všechny vlastnosti private, jeví se při iterování jako prázdná a tudíž ztrácí vlastnosti DibiRow. Přišel jsem na to při pokusu implementovat funkci save().
Vracím se tedy k mezivrstvě – třídě která od DibiRow nedědí, ale obaluje jí. DibiRow tak funguje jako přepravka na data (o něco chytřejší pole) a moje třída zaručí veškerou obsluhu. Viz. 3. příspěvek.
Ale abych výledky do mé vlastní třídy dostal, musím ji nastavit pomocí
setRowClass(), kde je varování, že by tato měla být typu DibiRow.
Takže ještě jednou otázka: Vadí nějak Nette či Dibi to, že moje třída
nemá vlastnosti ArrayAcess, Iterable apod.?
Mě to nijak neva – pro mě je to třída modelu, nikoliv výsledek dotazu.
Zdá se mi, že jediné, jak musí být kompatibilní je, aby akceptovala
stejná vstupní data, což splňuji.
- westrem
- Člen | 398
Šaman napsal(a):
Pokud třída odvozená od DibiRow má všechny vlastnosti private, jeví se při iterování jako prázdná a tudíž ztrácí vlastnosti DibiRow. Přišel jsem na to při pokusu implementovat funkci save().
To je nejake divne, nemal by tam dovod tohto chovania. Mozes ukazat implementaciu tej funkcii save?
- v6ak
- Člen | 206
Jako každopádně je to určitý hack a to, co nevadí dnes, může vadit
zítra.
Dědíš-li z DibiRow (nebo obecně nějaké třídy) a přepisuješ-li
konstruktor, měl bys volat parent constructor před prvním voláním metody
předka (popř. přístupu k jeho vlastnosti), jinak bude tato metoda pracovat
s potenciálně nekonzistentním objektem.
To, že nedědí z DibiRow, se také může časem vymstít. Dibi třeba může
přidat možnost nějakého seskupení a nebude to fungovat.