Vysvětlí někdo na jednoduchém příkladu jak pracovat s databází?
- wb2009
- Člen | 125
Zdravím, potřeboval bych, aby mně někdo navedl na správnou cestu. Jsem začátečník, ale už jsem s nette něco dělal, takže si troufám tvrdit, že ne zas tak úplný, nicméně pořád nějak nechápu práci s databází.
V čistým PHP jsem byl zvyklý si to dělat vše po svém a ne asi úplně správně a nejlépe a nejbezpečněji, proto jsem přešel k nette, ale hrozně mě tady matou ty tutoriály. Jednak tu je Dibi a Nette\database, což jak jsem tak pochopil těží hlavně z NotORM. Jenomže možná právě čeho je moc, toho je příliš a já v tom mám guláš a to pořádnej.
Takže k mému problému vytvořil jsem si v databazi jednoduchou tabulku, kde budu ukládat nadpisy, obsahy a další věci ke každé mé stránce. Proč? Protože uživatelé to budou moci editovat.
No a teď bych chtěl vědět jak začít? Resp. Jak nejlépe začít? Resp.2. Jakou nejdřívě zvolit databazi? Dibi nebo Nette\Databaze? Asi bych byl spíše pro nette\database.
Takže potřebuji pomoc co vše potřebuji k tomu, abych například na moji úvodní stránku vysypal z databaze nadpis a obsah? Děkuji za nakopnutí a rady a pomoc…
- JuniorJR
- Člen | 181
Zjednodušený příklad pro Nette\Database (normálně by si data tahal skrz konkrétní model).
public function renderTest($id = NULL)
{
if ($id == NULL) {
$this->redirect('Foo:bar');
}
// get content of page with the given id
$page = $this->context->database->table('page')
->where('id', $id)
->fetch();
if (!$page) {
$this->redirect('Foo:bar');
}
$this->template->page = $page;
}
V šabloně pak např.:
<h1>{$page->header}</h1>
<p>{$page->body}</p>
Editoval JuniorJR (4. 6. 2012 22:38)
- motorcb
- Člen | 552
wb2009: Také používám Nette database a jsem spokojen.
Má výhodu, že složitější dotaz si v ní můžeš napsat stejným
zůsobem jako v NotORM.
Začni tutoriálem na https://doc.nette.org/cs/quickstart
Ten ti dá pro začátek hodně a nebudeš muset otravovat tady na foru
základníma věcma :)
- Jan Tvrdík
- Nette guru | 2595
wb2009 wrote:
Dibi nebo Nette\Databaze?
dibi považuji v současnosti za mnohem lepší volbu, obzvláště, pokud začínáš.
- wb2009
- Člen | 125
Zdravím, tak jsem si s tím, včera pohrál a podařilo se, už tahám data z db do šablony.
Navíc zdá se, že začínám i chápat tu logiku. Nette\Database se zdá velice šikovná.
Tak a teď mne opravte, jestli se mýlím. Vytvořil jsem si tedy funkci:
public function renderUvodniInformace()
{
// get content of page with the given id
$page = $this->context->database->table('obsahstranek')
->where('id', 1)
->fetch();
$this->template->page = $page;
}
Která teda mi vytáhne z databáze ten řádek, kde je id=1 a pak to pomocí $this->template.. předávám do šablony.
Má otázka tedy zní, jestli chápu model správně, že nejlepší by bylo si všechny tyto funkce do modelu vytvořit a pak to z něj tedy tahat? DO presenteru si tu funkci tedy natáhnu jak? Úplně jednoduše, nebo v tom jen vidím zbytečnou složitost, která není. Každopádně moc děkuji, teď když už chápu logiku MVP, dokážu tahat věci z databáze, poradím si s presentery, tak se mi to Nette líbí ještě víc :)
- vvoody
- Člen | 910
Ano, najlepsie je tuto funkciu presunut do modelu, cize by vyzerala takto:
public function getPage($id)
{
// get content of page with the given id
return $this->context->database->table('obsahstranek')
->where('id', $id)
->fetch();
}
a presenter uz len
public function renderUvodniInformace()
{
$this->template->page = $this->context->nazovModelu->getPage(1);
}
s tym ze model musis mat zaregistrovany ako sluzbu v configu, preto si ho potom mozes vybrat z contextu
- wb2009
- Člen | 125
Tak nakonec mám problém, už jsem to přesunul do toho modelu a fungovalo to. Nevím proč, ale najednou to nefunguje…Píše to:
Service ‚obsahstranek‘: Parameter $table in Method Nette\Database\Table\Selection::__construct() is missing
model mám:
<?php
use Nette\Database\Connection,
Nette\Database\Table\Selection;
class Obsahstranek extends Selection
{
public function getPage($id)
{
// get content of page with the given id
return $this->context->database->table('obsahstranek')
->where('id', $id)
->fetch();
}
}
v presenter pak mám:
<?php
namespace FrontModule;
class OskolePresenter extends \BasePresenter {
public function renderUvodniInformace()
{
$this->template->page = $this->context->obsahstranek->getPage(1);
}
}
a v configu to mám zaregistrovaný takto:
...
database:
default:
dsn: '%database.driver%:host=%database.host%;dbname=%database.dbname%'
user: %database.user%
password: %database.password%
services:
database: @Nette\Database\Connection
obsahstranek: Obsahstranek
authenticator: Authenticator( @database::table(users) )
...
díky za rady.
- JuniorJR
- Člen | 181
Mělo by pomoci:
services:
database: @Nette\Database\Connection
obsahstranek: Obsahstranek( 'obsahstranek', @database )
authenticator: Authenticator( @database::table(users) )
Jde o to, že ty tam nepředáváš požadované parametry pro vytvoření instance třídy Obsahstranek, viz. api.
Další chybu máš zde:
public function getPage($id)
{
// nelze se odkazat na context, ten je dostupny pouze z presenteru
return $this->context->database->table('obsahstranek')
->where('id', $id)
->fetch();
// navrh reseni
// return $this->where('id', $id)->fetch();
}
Editoval JuniorJR (6. 6. 2012 20:53)
- wb2009
- Člen | 125
děkuji, ale teď mi to hází chybu v latéčku:
Cannot read an undeclared property Obsahstranek::$nadpis
ale v laté to volám klasicky podle presenteru tedy:
....
<h1>{$page->nadpis}</h1>
<div class="obsah">{$page->obsah}</div>
....
Netuším :/
edit: zapomněl jsem fetch, takže už to funguje, díky.
Editoval wb2009 (6. 6. 2012 20:52)
- wb2009
- Člen | 125
Ještě tu mám jeden problém.
Jde o to, že když jsem volal tu funkci, tak jsem dostával jeden řádek, ale
teď mám další funkci
<?php
class Kontaktyskoly extends Selection
{
public function getKontakty($id)
{
// get content of page with the given id
return $this->where('typ', $id);
}
}
no a v presenteru mám:
public function renderAdresaKontakty()
{
$this->template->adresa = $this->context->adresaskoly->getAdresa(1);
$this->template->reditel = $this->context->kontaktyskoly->getKontakty(1);
$this->template->statut = $this->context->kontaktyskoly->getKontakty(2);
}
no a v latte mám:
</table>
<hr />
<h3>Ředitelství školy:</h3>
<table>
{foreach $reditel as $neco}
<tr>
<th>{$neco->pozice}</th>
<td>{$neco->tit_jmeno_prijmeni}</td>
</tr>
<tr>
<th>Telefon:</th>
<td>{$neco->telefon}</td>
</tr>
<tr>
<th>Fax/záznamník:</th>
<td>{$neco->fax_zaznamnik}</td>
</tr>
<tr>
<th>Email:</th>
<td>{$neco->email}</td>
</tr>
{/foreach}
</table>
<h3>Statutární zástupci:</h3>
<table>
{foreach $statut as $neco2}
<tr>
<th>{$neco2->pozice}</th>
<td>{$neco2->tit_jmeno_prijmeni}</td>
</tr>
<tr>
<th>Telefon:</th>
<td>{$neco2->telefon}</td>
</tr>
<tr>
<th>Fax/záznamník:</th>
<td>{$neco2->fax_zaznamnik}</td>
</tr>
<tr>
<th>Email:</th>
<td>{$neco2->email}</td>
</tr>
{/foreach}
</table>
jde mi o to, že když jsem chtěl dostávat jeden řádek, použil jsem v modelu fetch(), ale když jsem chtěl více řádků, pak sem fetch z modelu odstranil. A po přidání dalšího řádku v presenteru toho samého, ale s jiným id, kde se vrátí pouze 1 vysledek, to nefunguje…nějaká rada? :)
Jinak já se to tady z toho příspěvku postupně naučím … :D
díky
- JuniorJR
- Člen | 181
Definuj slovo „nefunguje“. Jestli nebude problém v tom, že ten selection používáš jako službu a v tom případě se vrací pořád ta samá instance té služby.
Jinak pro získání všech záznamů by mělo stačit (jelikož ten model implementuješ jako hotový selection):
$this->template->adresa = $this->context->adresaskoly;
Pokud by si chtěl vracet při každém volání modelu novou instanci, zaregistruj třídu jako továrnu v configu.
Editoval JuniorJR (6. 6. 2012 22:44)
- JuniorJR
- Člen | 181
Když ji registruješ jako továrnu, tak ji musíš jako továrnu také volat, viz. dokumentace:
$this->template->adresa = $this->context->createAdresaskoly();
Editoval JuniorJR (6. 6. 2012 22:57)
- wb2009
- Člen | 125
Tak ještě jednou…
v configu mám:
common:
parameters:
database:
driver: mysql
host: localhost
dbname: lhs
user: root
password:
php:
date.timezone: Europe/Prague
# session.save_path: "%tempDir%/sessions"
# zlib.output_compression: yes
nette:
container:
debugger: yes
session:
expiration: '+ 14 days'
database:
default:
dsn: '%database.driver%:host=%database.host%;dbname=%database.dbname%'
user: %database.user%
password: %database.password%
services:
database: @Nette\Database\Connection
authenticator: Authenticator( @database::table(users) )
factories:
obsahstranek: Obsahstranek( 'obsahstranek', @database )
adresaskoly: Adresaskoly( 'adresaskoly', @database )
kontaktyskoly: Kontaktyskoly( 'kontaktyskoly', @database )
production < common:
development < common:
v modelu mám(třeba model adresakontakty):
<?php
use Nette\Database\Connection,
Nette\Database\Table\Selection;
class Adresaskoly extends Selection
{
public function getAdresa($id)
{
// get content of page with the given id
return $this->where('id', $id)
;
}
}
a v presenteru mám:
<?php
namespace FrontModule;
class OskolePresenter extends \BasePresenter {
public function renderUvodniInformace()
{
$this->template->page = $this->context->createPage(1);
}
public function renderAdresaKontakty()
{
$this->template->adresa = $this->context->createAdresa(1);
$this->template->reditel = $this->context->createKontakty(1);
$this->template->statut = $this->context->createKontakty(2);
}
}
a píše mi to chybu, že nemám definovanou metodu: Call to undefined method SystemContainer::createAdresa().
Je možný, že tam už mám někde chybu, z toho jak to pořád opravuju a
předělávám…budu vděčný za cokoliv…
díky
- bojovyletoun
- Člen | 667
to a to jsi
četl?
Máš tam jiné názvy u „$this->context->Adresa“ a factories:
adresaSkoly
jenom takový nápad k těm třídám Adresaskoly. Pokud je nebudeš rozšiřovat, pak jejich existence je „zbytečná“, neboť metoda getAdresa() je nahraditelná metodou Nette\Database\Table\Selection::find()
Jak taková konfigurace může vypadat?
common:
nette:
database:
a:
dsn: sqlite:%appDir%/sites.db
factories:
db: @nette.database.a #jen alias
sites:
factory: @db::table(sites) #eq $context->nette->database->table('sites')
news:
factory: @db::table(news)
services:
texy:
class: CTexy(/img,%wwwDir%/img)
Editoval bojovyletoun (7. 6. 2012 19:01)
- wb2009
- Člen | 125
Děkuji, nakonec jsem to vyřešil podle quickstartu, kde je toto:
class Tasks extends Selection
{
public function __construct(\Nette\Database\Connection $connection)
{
parent::__construct('task', $connection);
}
}
a pak se to vlastně všechno děje přes presenter. A tak to udělám i já. A pak přes foreach to zobrazím v latte.
Každopádně děkuji.