Ukládání do více tabulek v jednu chvíli
- Muhal
- Člen | 4
Zdravím, zatím jenom tak s Nette blbnu. Možná se to netýká ani tak přímo Nette, jako samotného MVP.
Zajímalo by mě, jaký je nejlepší způsob ukládání dat z formuláře do více tabulek zároveň. Když to uvedu bodově na příkladu uživatelských profilů:
- Mám tabulku
user
, kde jsou základní informace o uživateli důležité k přihlášení a dalšímu fungování v aplikaci - Potom je tu tabulka
profile
, kde jsou doplňující informace – jméno a popis uživatele. S uživatelem je spojená indexemuser_id
- Dále tabulky
avatar
,profile_contact
acontact_kind
, ty už jsou pro teď nepotřebné.
No a jde o to, že si najednou vůbec nejsem jistý, jakým způsobem zapisovat hodnoty např. registračního formuláře do těchto tabulek zaráz tak, abych si pokud možno nezprasil kód. Samotný formulář mám napsaný takto:
<?php
public function createComponentProfileForm()
{
$form = new AppForm();
$form->addText('login', 'Username:')
->addRule(Form::FILLED, 'Please provide an username.');
$form->addText('email', 'E-mail:')
->addRule(Form::FILLED, 'Please provide an e-mail.')
->addRule(Form::EMAIL, 'Please provide valid e-mail.');
$form->addPassword('password', 'Password:')
->addRule(Form::FILLED, 'Please provide a password.');
$form->addSelect('role', 'Level:', array('registered' => 'Registered', 'editor' => 'Editor', 'admin' => 'Admin'))
->skipFirst('Select user level')
->addRule(Form::FILLED, 'Please select user level');
$form->addText('name', 'Name:');
$form->addTextArea('description', 'Description:');
$form->addSubmit('save', 'Save');
$form->onSubmit[] = callback($this, 'profileFormSubmitted');
return $form;
}
?>
Můžu si v modelu udělat na vložení jednu metodu a v ní potom konkrétně vybrat, které hodnoty kam uložit, ale to se mi zdá právě blbě, „neuniverzální“. Nebo můžu mít na každou tabulku v modelu zvlášť vkládací metodu, ale to se mi taky nějak nezdá. Takže otázka – můžete se podělit o nějaký svůj ukázkový model řešící takto navrhlé tabulky?
Tabulky:
Btw. Když už píšu, lze při vkládání do tabulky zjistit id právě vloženého záznamu, když je sloupec id auto_increment? Díky.
- iguana007
- Člen | 970
Já jsem zrovna nedávno řešil podobnou věc a udělal jsem to vše v jedné metodě v modelu.
Měl jsem případ, kdy ukládám nový projekt a k němu vytvářím
i novou kategorii v článcích a do ní několik článků a to vše
tolikrát, kolik je v systému nastavených jazyků (přes foreach).
Poslední id zjistíš takto:
https://forum.dibiphp.com/…st-insert-id
- Foowie
- Člen | 269
// tvorba formu
$form = new AppForm($this, $name);
$userContainer = $form->addContainer("user");
$userContainer->addText("login", "Login");
...
$profileContainer = $form->addContainer("profile");
$profileContainer->addText("name", "Name");
...
// po submitu
$values = $button->getForm()->getValues();
$userValues = $values["user"];
$profileValues = $values["profile"];
dibi::query("UPDATE user SET %a", $userValues);
dibi::query("UPDATE profile SET %a", $profileValues);
Tady máš nástřel jak by to mohlo vypadat …
PS: Neříkám že je to nějak propracovaný návrh, ale je to rychlé .)
Editoval Foowie (27. 7. 2010 12:46)
- Bernard Williams
- Člen | 207
Nazdárek,
@Foowie: Jak v takto navrženém modelu kontroluješ chyby a ošetřuješ výjimky?
@Muhal: V čem si, prosím tě, generoval to schéma tabulku? Viděl jsem to tu už několikrát, ale nikde jsem nezjistil ten program.
Děkuji
Bernard
Editoval Bernard Williams (27. 7. 2010 13:50)
- Foowie
- Člen | 269
... model
if(validační chyba)
throw new ModelException("Popis chyby");
try {
db::beginTransaction();
try {
velmi_nebezpečná_instrukce
} catch(JináVýjimka $x) {
throw new ModelException("Popis chyby");
}
db::commit();
} catch(ModelException $e) {
db::rollback();
throw $e;
}
on submit:
try {
MujModel->upravHodnoty($button->getForm()->getValues());
$this->flashMessage("Všechno OK");
invalidateControl / redirect
} catch(ModelException $e) {
$this->flashMessage($e->getMessage());
invalidateControl...
}
Ve skutečnosti je to ještě trošku jinak ale pro přehlednost nějak takhle ;)
- koprkuba
- Člen | 24
Ahoj, mám takovýhle problém:
Mám dvě tabulky:
Objednavky(`id_objednavky` auto_increment, `id_zakaznika`); PK = `id_objednavky`;
Obsah_objednavky(`id_objednavky`,`id_produktu`,`pocet_kusu`); FK = `id_objednavky`=>`Objednavky.id_objednavky`;
Pokud zákazník vytvoří objednávku tak se vytvoří řádek v tabulce
Objednavky
kde je id_objednavky
automaticky
inkrementováno a jeho zákaznické ID.
Chtěl bych pak vložit dalších x (počet produktů v košíku) řádků
s tím, že by id_objednavky
z tabulky Objednavky
bylo stejné jako to id_objednavky
v
Obsah_objednavky
.
Zkoušel jsem to takhle, ale laděnka mi vyhodila error:
Cannot retrieve last generated ID.
na řádku 392.
Line 385: * @return int
Line 386: * @throws DibiException
Line 387: */
Line 388: public function getInsertId($sequence = NULL)
Line 389: {
Line 390: $this->connected || $this->connect();
Line 391: $id = $this->driver->getInsertId($sequence);
Line 392: if ($id < 1) throw new DibiException('Cannot retrieve last generated ID.');
Line 393: return (int) $id;
Line 394: }
Line 395:
Line 396:
Line 397:
Line 398: /**
Line 399: * Retrieves the ID generated for an AUTO_INCREMENT column. Alias for getInsertId().
Zde je můj kód:
$objednavky_model = new Objednavky();
$objednavky_model->insert(array('id_zakaznika' => $userID));
$id_objednavky = dibi::insertId();
$kosik = new Kosik();
$items = $kosik->getContent();
$obsahObjednavky_model = new ObsahObjednavky();
foreach ($items as $key => $item) {
$data = array(
'id_objednavky' => $id_objednavky,
'id_produktu' => $key,
'pocet_kusu' => $item->count
);
$obsahObjednavky_model->insert($data)->execute();
}
díky moc
EDIT: Vloží mi to do Obsah_objednavky
pouze jeden řádek (ten
první produkt z košíku)
Editoval koprkuba (30. 12. 2010 18:44)
- cuga
- Člen | 210
@koprkuba: u Obsah_objednavky ti chybi neco jako Polozka_id, ktera by mela mit nastavene autoincrement…
jinak kdyz koukam na atributy tabulek, tak pokud jsi opravdu vypsal vsechny, doporucoval bych ti u polozky objednavky jeste evidovat cenu… protoze cena u produktu se muze v case menit, ale ceny v objednavkach by ti meli zustavat nemenne
- koprkuba
- Člen | 24
@cuga: super díky za radu, už to funguje. BTW bude to fungovat
i v případě, že by 2 uživatelé zadali požadavek ve stejný čas a
došlo by ke kolizi takové, že by uživatel A vytvořil řádek v tabulce
Objednávky
(potom by se z nějakého důvodu zpozdil) pak by
uživatel B vytvořil řádek do Objednávky
i řádky do
Obsah_objednavky
a až potom by uživatel A vytvořil řádky do
Obsah_objednavky
?
P.S. samozřejmě vypsal jsem jen to důležité jinak si v db. držím daleko více údajů včetně data a cen, právě proto, že mohou být produkty ve slevě atp.