Generování do formulářového selectu z databáze
- Dark0ne
- Člen | 47
Zdravím,
mám takový asi dost elementární dotaz, ale jelikož nejsem s Nette ještě
dostatečný kamarád, ptám se pro urychlení zde :).
Jde mi o to, že potřebuji do klasického formulářového selectu vypsat
záznamy z nějaké databázové tabulky.
$jmena = array(
'1' => 'Lenka',
'2' => 'Petra',
'3' => 'Jana',
);
$form->addSelect('jmeno', 'Jméno:', $jmena)->setPrompt('Zvolte jméno');
Potřebují mít tady v proměnné $jmena pole dat, která jsou ovšem vypsaná přímo z databáze.
V modelu bych vytvořil třeba:
public function VypisJmena(){
$this->db->query("SELECT id, jmeno FROM jmena_zen ORDER BY jmeno ASC");
}
No a teď netuším, jak naplnit to pole a jak ho zavolat
v presenteru…
Předem díky za rady.
Editoval Dark0ne (4. 5. 2015 19:01)
- Mysteria
- Člen | 797
Tohle ti vrátí přesně to pole, který potřebuješ:
public function getFemaleNames() {
return $this->db->table('jmena_zen')->order('jmeno')->fetchPairs('id', 'jmeno');
}
A jak ho zavolat v presenteru?
Normálně ho do presenteru injectneš pomocí anotace a pak ho použiješ:
/** @var SomeModel @inject */
public $someModel;
$form->addSelect('jmeno', 'Jméno:', $this->someModel->getFemaleNames())->setPrompt('Zvolte jméno');
- Dark0ne
- Člen | 47
Modelový soubor vypadá takhle (jedná se o fci getDum):
<?php
namespace App\Model;
use Nette,
Nette\Utils\Strings,
Nette\Security\Passwords,
Nette\Database\Context;
/**a
* Users management.
*/
class BytyModel extends Nette\Object
{
private $db=null;
public function __construct($db) {
$this->db=$db;
}
public function getByty(){
$stmt=$this->db->query("SELECT * FROM byty");
return $stmt->fetchAll();
}
public function getDum() {
return $this->db->table('domy')->order('id_domy')->fetchPairs('id_domy', 'ulice');
}
}
- Oli
- Člen | 1215
Předpokládám, že v configu máš něco jako
- BytyModel(@connection)
. Tak oddělej celý závorky a
v konstruktoru si typehintem vyžádej Context, jak píše @Zax.
Pokud nepředáváš parametry (string, integer, array, …), ale nějakou třídu nebo interface, tak to v configu vubec nemusíš uvádět, napiš to do constructoru a on si to vytáhne. Navíc ti to bude napovídat, jaký metody ta třída má.
- Dark0ne
- Člen | 47
Jsem z toho teď nějaký zmatený, mohl bys to prosím uvést na
konkrétním příkladě? Omlouvám se, ale zatím se v tom, tak dobře
nevyznám.
V config.neon mám pouze něco takového
services:
- App\Model\UserManager
- App\Forms\SignFormFactory
router: App\RouterFactory::createRouter
database: @database.default
- Oli
- Člen | 1215
Tak to jsem teď já zmatenej z tebe :-) Jak tam dostaneš tu třídu
BytyModel, když ji nemáš v configu? Vytváříš ji pomocí
new BytyModel
? To právě vubec nemusíš. Udělal bych to nějak
takhle:
services:
database: @Nette\Database\Context
- App\Model\UserManager
- App\Forms\SignFormFactory
router: App\RouterFactory::createRouter
- BytyModel
BytyModel
class BytyModel extends Nette\Object
{
private $db;
public function __construct(\Nette\Database\Context $db) {
$this->db = $db;
}
public function getByty(){
return $this->db->table('byty');
//$stmt=$this->db->query("SELECT * FROM byty");
//return $stmt->fetchAll();
}
}
Presenter
class MyPresenter extends BasePresenter
{
private $bytyModel;
public function __construct(BytyModel $bytyModel)
{
$this->bytyModel = $bytyModel
}
public function createComponentForm()
{
$form = new Form;
$form->addSelect('flats', 'Byty', $this->bytyModel->getByty()->fetchPairs('id', 'name'))
->setPromt('--- Vyberte ---');
return $form;
}
}
Ještě lepší je si na ten formulář udělat jako komponentu, ale do toho bych teď nezabředával ;-)
Editoval Oli (5. 5. 2015 12:11)
- Dark0ne
- Člen | 47
No :D, já to v Presenteru mám takhle
<?php
namespace App\Presenters;
use Nette,
App\Model,
Nette\Application\UI\Form;
/**
* Homepage presenter.
*/
class BytyPresenter extends BasePresenter
{
private $model=null;
private $data = null; //pridana promena pro edit
private function getModel(){
if(!isset($this->model)){
$this->model=new Model\BytyModel($this->context->getService("database"));
}
return $this->model;
}
public function renderDefault()
{
$this->template->byty = $this->getModel()->getByty();
}
A pak se v něm odkazuju $this->getModel()->Metoda()…
Vím, že jsem asi otravnej, ale nešlo by vyřešit ten můj problém
způsobem, který by šel napasovat na tuto variantu řešení ?(Mám už tímto
způsobem napsánou velkou část aplikace a potřebuji to mít během krátké
doby zprovozněné).
Děkuji všem za rady a trpělivost.
- David Matějka
- Moderator | 6445
pokud nepouzivas NDBT (tedy „magicke“ table), ale pises pouze sql, i tak muzes pouzit fetchPairs, aniz bys menil zavislosti:
public function getDum() {
return $this->db->query("SELECT id_domy, ulice FROM domy ORDER BY id_domy")->fetchPairs("id_domy", "ulice");
}
- Oli
- Člen | 1215
@Dark0ne dám ti pár snad dobrých rad do začátku :-)
- Využívej DI (dependency
injection). Má to hned 3 přínosy (má jich víc, tyhle mě napadly na
první dobrou)
- Nemusíš se starat o závislosti takto vložených závislostí (doplní se samy)
- Zahlásí ti to chybu, pokud se budeš snažit vytvořit objekt, který
potřebuje ke své funkčnosti něco co nemůže najít. Takže pokud by jsi
chtěl třeba vytvořit presenter, který potřebuje
FlatModel
, ale nepředal mu ho, tak to spadne. Pokud by jsi to vytvářel tímnew
operátorem, tak ti to spadne až ve chvíli, kdy se dostaneš na action, ve které tu třídu vytváříš. ⇒ dřív odhalíš chybu v kódu. - Přehledně na jednom místě vidíš všechny závislosti,
které třída má. Představ si, že píšeš třídu, která má
6 závislostí a všechny vytváříš pomocí
new
. A teď tu třídu chceš použít v jiným projektu. Asi víš kam mířím…
- Nepoužívej
$this->context
! Vytváří to skryté závislosti viz bod 1.
Ten tvůj presenter by šel přepsat velice jednoduše například takhle:
namespace App\Presenters;
use Nette,
App\Model,
Nette\Application\UI\Form;
/**
* Homepage presenter.
*/
class BytyPresenter extends BasePresenter
{
private $bytyModel;
private $data = null; //pridana promena pro edit
public function __construct(Model\BytyModel $bytyModel)
{
$bytyModel = $bytyModel;
}
public function renderDefault()
{
$this->template->byty = $this->bytyModel->getByty();
}
// ...
}
Řekl bych že to je výrazně kratší a přehlednější a o to v podstatě jde :-)
Editoval Oli (5. 5. 2015 23:02)