ActiveRow – jak zjistit existenci sloupce?
- OK3
- Člen | 91
Díky za reakci, bžel to nefunguje. isset
vrací pro hodnotu
NULL
též FALSE
, což je myslím napsáno
i v dokumentaci.
Zatím to řeším blokem try/catch, jen se divím, proč se nejde na existenci sloupce prostě nějakým jednoduchým způsobem zeptat? Našel jsem pár let staré diskuse, kde se to řešilo, ovšem vyšlo to jaksi doztracena.
<?php
// v obálce nad ActiveRow...
try {
return $this->row->$key;
} catch (\Nette\MemberAccessException $e) {
// vyhodit vlastní výjimku
}
?>
- uestla
- Backer | 799
Zjišťovat existenci databázového sloupce na instanci
ActiveRow
považuju za nešťastné z následujících
důvodů:
ActiveRow
představuje výsledekTable\Selection
dotazu- může obsahovat aliasované sloupce (
xyz AS abc
) - na úrovni
ActiveRow
se mohou cachovat jen použité sloupce (pokud nepoužiješ explicitně$selection->select('xyz')
)
Pokud potřebuješ zjistit, zda sloupec existuje v určité tabulce, je IMHO
vhodnější využít Nette\Database\Structure
:
/* $structure instanceof Nette\Database\Structure */
$columnExists = in_array('my_column', array_column($structure->getColumns('my_table'), 'name'), TRUE);
EDIT
Popř. pokud ti nejde o existenci sloupce v tabulce, ale potřebuješ jen
zjistit, že daná „property“ (nejde přímo o property třídy) na
ActiveRow
existuje, zkusil bych
$columnExists = array_key_exists('my_column', $row->toArray(), TRUE);
Editoval uestla (28. 3. 2016 13:33)
- David Matějka
- Moderator | 6445
Co se konkretne snazis vyresit, ze potrebujes vedet, jestli sloupec existuje? pripada mi, ze se spis snazis vyresit nejaky spatny navrh db/aplikace.
Jinak ActiveRow ma funkci accessColumn, ktera vrati bool dle toho, jestli sloupec existuje. Ale pozor je interni (tzn snadno muze dojit ke smazani nebo ke zmene chovani bez ohledu na BC)!
- OK3
- Člen | 91
Díky @uestla za elaboraci nad tématem. Asi jsem se na začátku
nevyjádřil přesně. Nejde ani tak o zjištění existence sloupce v tabulce
jako o zjistění existence odvozeného atributu v objektu
ActiveRow
. Jednotlivé modely netuší nic o své struktuře a
požadavané atributy vytahují z „ze zdroje“ on-the-fly. Pokud v kódu
požaduji atribut, který není k dispozici, uvědomí mě o tom výjimka.
Cílem je mít přehledný a jednoduchý kód (bez zbytečné práce třeba ve
formě převádění objektu na pole a zjišťování těch věcí
na něm).
@DavidMatějka Mám jednoduchou aplikaci, jejíž modely jsou obálky
nad ActiveRow
. Pro přístup k hodnotám se používá magický
getter a setter. Konkrétní modely (potomci BaseModel) pak obsahují jen
anotace @property (pro napovíddání v IDE) a případně implementují
jen další gettery a settery, když jsou potřeba.
(kód je osekán)
<?php
namespace App\Models;
use Nette\Database\Table\ActiveRow;
use App\Error;
class BaseModel
{
/** @var \Nette\Database\Table\ActiveRow */
protected $source;
/**
* @param ActiveRow $row
*/
public function __construct(ActiveRow $row)
{
$this->source = $row;
}
/**
* @param string $key Attribute
* @return mixed
* @throws Error if property or getter is missing
*/
public function __get($key)
{
// getter lookup
$getter = sprintf('get%s', ucfirst($key));
if (method_exists($this, $getter)) {
return $this->$getter();
}
$booler = sprintf('is%s', ucfirst($key));
if (method_exists($this, $booler)) {
return $this->$booler();
}
// tady by se mi víc líbilo něco jako
if ($this->source->columnExists($key)) { // stačilo by i offsetExists($key)
return $this->source->$key;
}
throw new Error(sprintf('No such attribute (getter): %s (%s, %s)', $key, $getter, $booler));
// ale místo toho musím mít tohle
try {
return $this->source->$key;
} catch (\Nette\MemberAccessException $e) {
throw new Error(...);
}
}
}
?>
Editoval OK3 (30. 3. 2016 14:39)
- David Matějka
- Moderator | 6445
V tomhle pripade je spravne reseni chytat vyjimku a vyhodit vlastni (s tim, ze bys mel original vyjimku uvest do previous)