praca s databazou v komponente
- whitedeath
- Člen | 25
Nette Framework 2.0.1 (revision 94abcaa released on 2012–02–29)
PHP 5.3.9
Netbeans IDE 7.1
Ahoj, vytvoril som si takyto formular a umiestnil som si ho do komponentu. Debugger mi hadze chybu, ze context ako property nie je deklarovana. Rozumiem zhruba o co ide, ale neviem to vyriesit. Messages je model.
Tuto istu chybu mi vyhodilo ked som chcel v komponente pracovat s modelom, ale to som vyriesil tak, ze som ten dotaz poslal do konstruktora ako ActiveRow $dotaz
ale tuto mam aj insert aj select a to uz tato s ActiveRow nejde..
<?php
public function contactMessageFormSubmitted(Form $form)
{
$hasSentToday = $this->context->createMessages()
->select('id')
->where(array('ip_address' => $form->values->ip_address))
->where('created > DATE_SUB(NOW(), INTERVAL 1 DAY)')
->fetch();
if($hasSentToday['id'] == FALSE)
{
$this->context->createMessages()->insert(array(
'mlist_title' => $form->values->mlist_title,
'created' => new DateTime(),
'ip_address' => $form->values->ip_address,
'name' => $form->values->name,
'email' => $form->values->email,
'message' => $form->values->message
));
$this->flashMessage('Message has been sent', 'success');
$this->redirect('this');
}
else
{
$this->flashMessage('You have sent message today', 'alert');
$this->redirect('this');
}
}
?>
Dakujem!
- whitedeath
- Člen | 25
no podarilo sa mi to spojazdnit takto
<?php
protected function createComponentLetmetalk()
{
return new Letmetalk($this->context->createMessages());
}
?>
ale nejde mi ->flashMessage(), da sa to inac vyriesit ako posunut modul
v konstruktore?
a ten flashmessage moze byt nastavenim CSS? ale to sa mi nezda nejako…
- Etch
- Člen | 403
Pokud je „Messages“ model, tak by si ho asi měl mít definovaný spíš jako službu než jako factory.
config.neon
services:
messages:
class: \Models\Messages
factories:
letmetalk:
class: \Letmetalk
třída Letmetalk
class Letmetalk extends \Nette\Application\UI\Control{
private $messages;
public function __construct(\Models\Messages $messages){
parent::_construct();
$this->messages = $messages;
}
public function contactMessageFormSubmitted(Form $form){
$hasSentToday = $this->messages
->select('id')
->where(array('ip_address' => $form->values->ip_address))
->where('created > DATE_SUB(NOW(), INTERVAL 1 DAY)')
->fetch();
if($hasSentToday['id'] == FALSE){
$this->messages->insert(array(
'mlist_title' => $form->values->mlist_title,
'created' => new DateTime(),
'ip_address' => $form->values->ip_address,
'name' => $form->values->name,
'email' => $form->values->email,
'message' => $form->values->message
));
$this->flashMessage('Message has been sent', 'success');
$this->redirect('this');
}else{
$this->flashMessage('You have sent message today', 'alert');
$this->redirect('this');
}
}
}
V presenteru:
protected function createComponentLetmetalk(){
return $this->context->createLetmetalk();
}
Psáno z hlavy, takže za naprosto správnou funkčnost neručím.
ad FlashMessages: Ty by měli fungovat normálně, pokud budeš svojí
komponentu dědit od \Nette\Application\UI\Control
Editoval Etch (14. 3. 2012 3:26)
- whitedeath
- Člen | 25
Vdaka, tak ja to skusim.
Mal som ten preto ako factory, lebo sa ucim podla tutorialu co je tu na stranke a robim subezne tutorial a svoj vlastny projekt a takto sa snazim na jednom pochopit a na druhom vyskusat to svoje.
Neviem presne ake ma co vyhody: factory vs. service ale tipoval by som ze service je spustena stale? Hladam v tom nejaku analogiu so service v operacnom systeme, mam to tak chapat?
- Etch
- Člen | 403
Tak jeden ze zásadních rozdílů je ten, že služba vždy vrací stejnou instanci dané třídy, ale factory vždy vytváří novou.
config.neon
services:
foo:
class: \Foo
factories:
fooFactory:
class: \Foo
třída Foo:
class Foo extends Nette\Object{
public $data;
}
v presenteru:
$service = $this->context->foo;
echo $service->data; // tiskne: null
$service->data = 'data';
echo $service->data; // tiskne: 'data'
$service2 = $this->context->foo;
echo $service2->data; // tiskne: 'data'
$service2->data = 'nová data';
echo $service->data; // tiskne: 'nová data'
$foo = $this->context->createFooFactory();
echo $foo->data; // tiskne: null
$foo->data = 'data';
echo $foo->data; // tiskne: 'data'
$bar = $this->context->createFooFactory();
echo $bar->data; // tiskne: null
$bar->data = 'další data';
echo $bar->data; // tiskne: 'další data'
echo $foo->data; // tiskne: 'data'
U modelů většinou nepotřebujeme novou instanci dané třídy, ale stačí nám již jednou vytvořená instance, a proto se většinou definují jako služba. Factory se používá tam, kde vždy chceme novou instanci dané třídy. Továrnám lze navíc předávat parametry.
Doporučuji prostudovat dokumentaci.
Editoval Etch (14. 3. 2012 17:49)
- whitedeath
- Člen | 25
takze service vs. factory som pochopil :) ale do hlavy mi este nejdu tie
flashmesages.
v Letmetalk.php:
<?php
public function render()
{
$this->template->setFile(__DIR__ . '/letmetalk.latte');
$this->template->render();
}
?>
a ked do letmetalk.latte vlozim
<?php
<script>
$(document).ready(function(){
setTimeout(function() {
$('.flash').fadeOut('slow');
}, 2000);
});
</script>
<div n:foreach="$flashes as $flash" class="flash {$flash->type}">{$flash->message}</div>
?>
tak mi vypise messages, ale predtym som mal tieto riadky v @layout.latte, existuje tam nejaka hierarchia alebo akasi forma dedenia v sablonach? alebo musim vypisovat flashmessages globalne vo vseobecnosti a pre komponenty (ak v nich pouzivam vlastne latte) zvlast?
Dakujem za ochotu pomoct!
- Etch
- Člen | 403
Flash zprávy se ukládají globálně. Pokud budeš mít v layout.latte
<div n:foreach="$flashes as $flash" class="flash {$flash->type}">{$flash->message}</div>
tak se ti budou zobrazovat zprávy vyhozené jak v presenterech, tak v komponentách.
Doufám, že jsem tvou otázku pochopil dobře. Pokud ne, tak ji popřípadě krapet upřesni(přeformuluj).
- whitedeath
- Člen | 25
ano presne to som mal v layout.latte a neslo mi to, kym som to neskopiroval aj do letmetalk.latte, ktore je ulozene v app/components/letmetalk.latte teraz mi to uz ide, ale mam to v dvoch sablonach.
- whitedeath
- Člen | 25
este jedna drobnost:
ak mam Pages ako factory, tak viem robit taketo:
<?php
class HomepagePresenter extends BasePresenter
{
public function renderDefault()
{
// Upper content
$this->template->uppercontent = $this->context->createPages()
->where(array('plist_title' => 'uppercontent', 'hidden' => false, 'deleted' => false));
// Lower content
$this->template->quickexplantation = $this->context->createPages()
->where(array('plist_title' => 'lowercontent', 'title' => 'quickexplantation', 'hidden' => false, 'deleted' => false))
->fetch();
$this->template->ambitions = $this->context->createPages()
->where(array('plist_title' => 'lowercontent', 'title' => 'ambitions', 'hidden' => false, 'deleted' => false))
->fetch();
}
}
?>
ale ak dam pages ako service, tak pri druhom dotaze mi to vyhodi, ze false, tj, prazdny vysledok volania, ale podla Tvojho prikladu so sluzbami som pochopil, ze by to nemal byt problem. Ale ak je, tak potom mam problem aj s Messages, lebo tie chcem vyuzivat tiez podobnym sposobom. Da sa to vyriesit tak nejako, ze si spravim nejake metody v Modeli? napriklad $this->messages->getContact() a $this->messages->insertContact() a toto aj pre pages a podobne?
- whitedeath
- Člen | 25
No tak spravil som to cez service a pouzil som metody v service na volanie jednotlivych uloh. Napriklad ked chcem nejaku stranku tak to spravim v sluzbe Pages takto:
<?php
/**
* Vracia stranku
* @param string $plist_title: Plist
* @param string $title: Name
* @param bool $fetch: To fetch
* @return array
*/
public function getPage($plist_title = '', $title = '', $fetch = FALSE)
{
$where = array('hidden' => FALSE, 'deleted' => FALSE);
if($plist_title != '')
$where['plist_title'] = $plist_title;
if($title != '')
$where['title'] = $title;
$sql = $this->connection
->table($this->class)
->where($where);
if($fetch)
return $sql->fetch();
else
return $sql;
}
?>
- whitedeath
- Člen | 25
Btw. aj mne sa velmi paci dibi, ale som si myslel, ze to uz bude prilis velky chaos, keby som do nette montoval aj dibi. Existuju nejake najmenej bolestne cesty, ako to rozbehat? Nestrati sa tam potom nejaka ta myslienka nette? Napriklad ked robim taketo nieco:
<?php
$row = $this->users->where('username', $username)->fetch();
$salt = $this->salts->select('salt')->where('user_id', $row->id)->fetch();
?>
a cez dibi by som pisal nejake query, to je jedno ake, ale takto mam na to nejaku sluzbu a hentak by som mal query, neviem to je prehladnejsie alebo ci ide len o vlastne zvyky? Rad by som sa totiz naucil pouzivat nette tak, aby to bolo co najefektivnejsie a najrozumnejsie, pochopit principom a tak…
- Etch
- Člen | 403
Ohledně Dibi vs Nette\Database si přečti toto.
Zrovna ty příkazy, které si napsal, by se daly zapsat pomocí Dibi téměř stejně.
<?php
// Tvůj zápis
$row = $this->users->where('username', $username)->fetch();
// Dibi zápis
$row = $this->users->where('username = %s', $username)->fetch();
// Tvůj zápis
$salt = $this->salts->select('salt')->where('user_id', $row->id)->fetch();
// Dibi zápis
$salt = $this->salts->select('salt')->where('user_id = %i', $row->id)->fetch();
?>
To jestli budeš ve výsledku používat Dibi, \Nette\Database, NotORM, Doctrine nebo třeba Propel už záleží jenom na tobě a na tom, co ti více vyhovuje.