Nette\Database: podmíněné části dotazu
- David Růžička
- Člen | 43
Zkouším aplikaci Todolist z tutoriálu zbavit dibi a vyzkoušet místo toho Nette\Database. Pro ilustraci vybírám metodu todoCount, která s dibi vypadala takhle:
public function todoCount($where = NULL)
{
return dibi::fetchSingle('SELECT COUNT([id]) FROM [tasks] %if',
isset($where), 'WHERE', isset($where) ? $where : array()
);
}
Lze i s Nette\Database zkonstruovat nějak jednoduše dotaz s podmínkou „%if“? Zatím mám tohle:
public function todoCount($where = NULL)
{
return self::$connection2->table('tasks')->count('id');
}
V $connection2 je instance Nette\Database\Connection.
Lze tam nějak dostat to podmíněné where nebo se to musí rozepsat do více
příkazů?
- Vojtěch Dobeš
- Gold Partner | 1316
$count = self::$connection2->table('tasks')->count('id');
if (isset($where)) {
$count->where($where);
}
return $count;
- David Růžička
- Člen | 43
Díky. Takže rozepsat. Ale co když těch podmínek bude víc? To pak ta konstrukce bude dost šílená, ne? Neexistuje jednodušší zápis?
Příklad opět z tutoriálu:
public function findAllTodos($order = NULL, $where = NULL, $offset = NULL, $limit = NULL)
{
return dibi::query(
'SELECT * FROM [tasks]',
'%if', isset($where), 'WHERE %and', isset($where) ? $where : array(), '%end',
'%if', isset($order), 'ORDER BY %by', $order, '%end',
'%if', isset($limit), 'LIMIT %i %end', $limit,
'%if', isset($offset), 'OFFSET %i %end', $offset
)->setRowClass('Todo');
}
- spidy
- Člen | 55
No když už používáš Nette\Databse, tak je nejspíš blbost to řešit takle… Spíš jenom:
public function findAllTodos() {
return return self::$connection2->table('tasks');
}
A v presenteru, popř. šabloně si můžeš ještě přidat třeba order:
public function renderDefault($order = 'added DESC') {
$this->template->todos = $model->findAllTodos()->order($order)
}
viz MVC paradox
- josef.sabl
- Člen | 153
spidy napsal(a):
public function renderDefault($order = 'added DESC') { $this->template->todos = $model->findAllTodos()->order($order) }
Řeším problém s escapováním sql identifikátoru. Kód viz. výše
obsahuje SQL injection. Výraz v $order
se totiž už neescapuje a
vzhledem k tomu, že přichází přímo requestem, může si tam uživatel
doplnit vlastní sql.
Zavolání URL http://test.loc/?order=title; DELETE FROM user
smaže obsah tabulky user.
Jak správně a systémově v duchu Nette/Database opravit kód?
- petr.pavel
- Člen | 535
public function renderDefault($order = 'added, $direction = 'DESC') {
$allowedOrder = in_array($order, array('added', 'modified', ...));
$allowedDirection = in_array($direction, array('DESC', 'ASC'));
if ((!$allowedOrder) || (!$allowedDirection)) {
die('bugger off!');
}
$this->template->todos = $model->findAllTodos()->order($order.' '.$direction);
}
- josef.sabl
- Člen | 153
petr.pavel napsal(a):
public function renderDefault($order = 'added, $direction = 'DESC') { $allowedOrder = in_array($order, array('added', 'modified', ...)); $allowedDirection = in_array($direction, array('DESC', 'ASC')); if ((!$allowedOrder) || (!$allowedDirection)) { die('bugger off!'); } $this->template->todos = $model->findAllTodos()->order($order.' '.$direction); }
Heh whitelist, takhle jsem to přesně udělal :-) Díky za ujištění ;-)
- saimons
- Člen | 293
Muzu mit k tomu doplnujici dotaz? Take zacinam s Nette DB. Kydz teda udelam toto:
Presenter (Control)
public function render() {
$editLang = $this->getPresenter()->getParam('editLang');
$template->menu = $this->menuModel->getArticlesMenu()->where('nazevSystem', $editLang);
}
Model komponenty
public function getArticlesMenu() {
return $this->database->table('lokalizace');
}
tak je to nachylne na SQL inj.? Pokud bych predal $editLang do modelu a tam udelal where tak je to v poradku?
return $this->database->table('lokalizace')->where('nazevSystem', $editLang);
Editoval saimons (22. 12. 2011 15:37)
- josef.sabl
- Člen | 153
where()
sám ošetří druhý parametr, tzn. tady by injekce
narozdíl od order()
být neměla.
Je úplně jedno, jestli where provedeš v presenteru nebo modelu. Kód v modelu se spouští stejně jako kód v presenteru. Oddělení je jen kvůli správné organizaci kódu.
Editoval josef.sabl (22. 12. 2011 15:52)