Spojení 2 tabulek pomoci Nette Database

Upozornění: Tohle vlákno je hodně staré a informace nemusí být platné pro současné Nette.
wicked
Člen | 290
+
0
-

Zdravím přátelé,

Prosím Vás o radu, mám 2 tabulky s daty zakazniku

1. zakaznici
Pole Typ Nulový Výchozí Komentáře
id int(10) Ne
firma varchar(255) Ano NULL
ic varchar(30) Ano NULL
dic varchar(30) Ano NULL
web varchar(100) Ano NULL
datum_ulozeni datetime Ano NULL

a 2. zakaznici_kontakty

Pole Typ Nulový Výchozí Odkazuje na Komentáře
id int(10) Ne
zakaznici_id int(10) Ne zakaznici → id
titul_pred varchar(70) Ano NULL
jmeno varchar(70) Ano NULL
prijmeni varchar(70) Ano NULL
titul_po varchar(70) Ano NULL
ulice varchar(255) Ano NULL
mesto varchar(70) Ano NULL
psc varchar(30) Ano NULL
telefon varchar(50) Ano NULL
mail varchar(80) Ano NULL
datum_ulozeni datetime Ano NULL
pozn varchar(255) Ano NULL

Obě tabulky jsou spolu spojeny cizím klíčem zakaznici_kontakty.zakaznici_id který směruje na zakaznici.id

Mám v šabloně akci na vytáhnutí dat z obou tabulek a následné plnění do formuláře.

public function actionUpravit($id) {
    // Najdeme zaznam
    $zakaznici = $this->zakaznici->findAll()->where('id', $id);
    // Pokud neni nalezen, presmeruji a vypisu zpravu
    if (!$zakaznici->count()) {
        $this->flashMessage("Zákazník nenalezen!", "alert alert-success");
        $this->redirect("default");
    }
    // Nacteme data
    $zakaznici = $zakaznici->fetch();
    dump($zakaznici);
    // Nastavime defaultni hodnoty do formulare a nahradime button
    $this["zakaznikForm"]->setDefaults($zakaznici);
    $this["zakaznikForm"]['send']->caption = "Uložit";
    // Dostaname data do sablony
    $this->template->zakaznici = $zakaznici;
}

Toto mi správně dostane všechny údaje z tabulky zakaznici a dosadí je

Když zadám

$zakaznici = $this->zakaznici->findAll()->where(':zakaznici_kontakty.zakaznici_id', $id);

Udělá to dotaz

SELECT `zakaznici`.*
FROM `zakaznici`
LEFT JOIN `zakaznici_kontakty` ON `zakaznici`.`id` = `zakaznici_kontakty`.`zakaznici_id`
WHERE (`zakaznici_kontakty`.`zakaznici_id` = '172')

Ale data nevypíše, respektivě vypíše pouze z tabulky zakaznici.
Chci se zeptat, co přehlížím?
Daří se mě vypsat buď dat ze zakaznici nebo zakaznici_kontakty ale aby se to spojilo a vypsalo to oboji najednou, to mě už nejde …

Děkuji

Editoval wicked (25. 8. 2014 10:38)

David Matějka
Moderator | 6445
+
0
-

https://doc.nette.org/…ase/explorer

Hlavní myšlenkou je načítání dat pouze z jedné tabulky a tak, aby se tyto dotazy pokládaly jen jednou. Data jsou načtena do ActiveRow instancí. Data z jiných tabulek připojených vazbami jsou načteny samostatnými požadavky – o to se stará samotná vrstva Database\Table.

pouzij related

wicked
Člen | 290
+
0
-

Ano, related používám v tabulce, která mi vypisuje všechna data

<tbody>
                    <tr n:foreach="$zakaznici as $z">
                        <td>{$z->id}</td>
                        <td>{if $user->identity->data["zakaznici_editace"] == "1"}<a n:href="upravit, $z->id">{else}<a n:href="zobrazit, $z->id" target="_blank">{/if}{$z->firma}</a></td>
                        <td>{$z->ic}</td>
                        <td>{$z->dic}</td>
                        {foreach $z->related('zakaznici_kontakty') as $z}
                            <td>{$z->jmeno}</td>
                            <td>{$z->prijmeni}</td>
                            <td>{$z->mesto}</td>
                            <td>{$z->telefon}</td>
                            <td>{$z->mail}</td>
                            <td>{$z->pozn}</td>
                        {/foreach}
                        {if $user->identity->data["zakaznici_prohlizeni"] == "1"}<td align="center"><a n:href="Projekty:vlozit, $z->id"><img src="{$basePath}/pic/vloz_zakaznika.png" alt="Vložit zákazníka do projektu" title="Vložit zákazníka do projektu"></a></td>{else}<td>-</td>{/if}
                        {if $user->identity->data["zakaznici_editace"] == "1"}<td align="center"><a n:href="upravit, $z->id"><img src="{$basePath}/pic/edit.gif" alt="Editovat uživatele" title="Editovat uživatele"></a></td>{else}<td>-</td>{/if}
                        {if $user->identity->data["zakaznici_prohlizeni"] == "1"}<td align="center"><a n:href="zobrazit, $z->id" target="_blank"><img src="{$basePath}/pic/detail.png" alt="Detail zákazníka" title="Detail zákazníka"></a></td>{else}<td>-</td>{/if}
                        {if $user->identity->data["zakaznici_editace"] == "1"}<td align="center"><a n:href="smazat!, $z->id" onClick="return dotaz();"><img src="{$basePath}/pic/delete.gif" alt="Smazat uživatele" title="Smazat uživatele"></a></td>{else}<td>-</td>{/if}
                    </tr>
                </tbody>

Napadlo mě použít relater, ale jak to udělat, aby mě to naplnilo formulář správnými daty? Proto to řeším takto v presenteru

wicked
Člen | 290
+
0
-

Opravdu nikdo neporadí jak sloučit 2 tabulky na úrovni presenteru pomocí nette database tak abych k danému id dostal daně záznamy z obou tabulek?

David Matějka
Moderator | 6445
+
0
-

wtf? to jako kdyz bude mit zakazik vice zaznamu v te druhe tabulce, tak do bude pridavat sloupce?
nebo mas jen spatne navrzenou databazi?

jinak related pro vytazeni tech kontaktu muzes pouzit i v presenteru.

Editoval matej21 (25. 8. 2014 18:43)

wicked
Člen | 290
+
0
-

Related jsem v presenteru zkoušel použít, ale asi špatně…

Ano zákazník může mít více řádků v tabulce zákazníci_kontakty které se v default všechny vypisou.

Po kliknutí na Edit chci načíst data k danému id z obou tabulek a vypsat do formu pro editaci.

Nevím jak jinak navrhnout db, myslel jsem, že takto je ok.

Editoval wicked (25. 8. 2014 18:55)

David Matějka
Moderator | 6445
+
0
-

ok, v tom pripade je struktura asi ok, jen to vypisovani do tabulky hodne debilni :)

v presenteru normalne pomoci foreach($z->related('zakaznici_kontakty') as $kontakt).. projdes kontakty a dosadis je do formulare (asi replicator pouzivas, ne?)

wicked
Člen | 290
+
0
-

matej21 napsal(a):

ok, v tom pripade je struktura asi ok, jen to vypisovani do tabulky hodne debilni :)

v presenteru normalne pomoci foreach($z->related('zakaznici_kontakty') as $kontakt).. projdes kontakty a dosadis je do formulare (asi replicator pouzivas, ne?)

Ne, zatím jsem replicator ještě nepoužil/nepoužíval…

V presenteru ale $z musím nahradit za $zakaznici, ne?

Jak myslíš dosazovani do tabulky debilní? Já myslel, že takto se to má používat…

David Matějka
Moderator | 6445
+
0
-

mam na mysli tu html tabulky, konkretne kod

{foreach $z->related('zakaznici_kontakty') as $z}
                  <td>{$z->jmeno}</td>
                  <td>{$z->prijmeni}</td>
                  <td>{$z->mesto}</td>
                  <td>{$z->telefon}</td>
                  <td>{$z->mail}</td>
                  <td>{$z->pozn}</td>
              {/foreach}

ze se budou pridavat sloupce dle poctu zaznamu v te tabulce..

wicked
Člen | 290
+
0
-

Jo to musím ještě dořešit, přidávají se blbě sloupce, má se přidávat komplet záznam = řádek…

Jinak related v presenteru projít klasický foreach a pak setDefaultsna formulář? Když kouknes na ten můj action kde načítám data a nastavují je do editu, jak by jsi to zakomponovat?

Jinak tu html tabulku musím dopravit, takhle nefunguje dobře.

David Matějka
Moderator | 6445
+
0
-

no nevim, jak vypada tvuj form, tak ti neporadim. ale proste projdes ve foreach-y a nastavis hodnoty na jednotlive containery (v replicatoru nebo jak to mas reseny)

wicked
Člen | 290
+
0
-

matej21 napsal(a):

no nevim, jak vypada tvuj form, tak ti neporadim. ale proste projdes ve foreach-y a nastavis hodnoty na jednotlive containery (v replicatoru nebo jak to mas reseny)

Ten form není ničím zvláštní …

// Formular na pridani zakaznika
    public function createComponentZakaznikForm() {
        $form = new Form();
        // Nastavime inputy
        $form->addText('firma', 'Firma')
                ->setAttribute('class', 'form-control')
                ->setRequired('Firma musí být vyplněna!');
        $form->addText('ic', 'IČ')
                ->setAttribute('class', 'form-control');
        $form->addText('dic', 'DIČ')
                ->setAttribute('class', 'form-control');
        $form->addText('titul_pred', 'Titlu před jménem')
                ->setAttribute('class', 'form-control');
        $form->addText('jmeno', 'Jméno')
                ->setRequired('Jméno musí být vyplněno!')
                ->setAttribute('class', 'form-control');
        $form->addText('prijmeni', 'Přijmení')
                ->setRequired('Přijmení musí být vyplněno!')
                ->setAttribute('class', 'form-control');
        $form->addText('titul_po', 'Titul za jménem')
                ->setAttribute('class', 'form-control');
        $form->addText('ulice', 'Ulice')
                ->setRequired('Ulice musí být vyplněna!')
                ->setAttribute('class', 'form-control');
        $form->addText('mesto', 'Město')
                ->setRequired('Město musí být vyplněno!')
                ->setAttribute('class', 'form-control');
        $form->addText('psc', 'PČS')
                ->setRequired('PČS musí být vyplněno!')
                ->setAttribute('class', 'form-control');
        $form->addText('telefon', 'Telefon')
                ->setAttribute('class', 'form-control');
        $form->addText('mail', 'Email')
                ->setAttribute('class', 'form-control');
        $form->addText('web', 'Web')
                ->setAttribute('class', 'form-control');
        $form->addText('pozn', 'Poznámka')
                ->setAttribute('class', 'form-control');
        // Odesilaci tlacitko
        $form->addSubmit('send', 'Přidat zákazníka')
                ->getControlPrototype()
                ->class('btn btn-info');
        // Zavolame metodu usersFormSucceeded()po uspechu
        $form->onSuccess[] = $this->zakaznikFormSucceeded;
        // Set Twitter Bootstrap render
        $form->setRenderer(new BootstrapRenderer());
        return $form;
    }
David Matějka
Moderator | 6445
+
0
-

no prave ze by mel byt zvlastni – kdyz rikas, ze zakaznik muze mit vice kontaktu – takhle bys mohl editovat pouze jeden… koukni na replicator https://componette.org/search/?…

Editoval matej21 (25. 8. 2014 23:39)

wicked
Člen | 290
+
0
-

ale v te tabulce bude vypsan zakaznik a kontakt k nim (jak je vidno z te spatne html tabulky).

Já si vyberu pouze 1 kontakt k danému zákazníkovi, a ten edituji. Takže takto mi to právě stačí.

Můj problém byl to, že nemůžu dostat společná data ze 2 tabulek do 1 formu …

David Matějka
Moderator | 6445
+
0
-

ty v te tabulce nevypisujes radky pro jednotlive kontakty, ale pro jednotlive zakazniky..
jak chces, aby se to chovalo, kdyz bude mit zakaznik 2 kontakty?

wicked
Člen | 290
+
0
-

No chtěl bych, aby se přidal druhý řádek s info o zákazníkovi a kontaktu

proste zakaznik + kontakt je jeden radek, pod nim bude druhy kde bude zase zakaznik a další kontakt

kdyz kliknu na edit, edituji vesker info jak o zakaznikovi (firma, ic, dic, web) tak o kontaktu (jmeno, prijmeni, tel)

David Matějka
Moderator | 6445
+
0
-

tak to bude lepsi, kdyz jako „zaklad“ nebudes brat tu tabulku zakaznici, ale tabulku zakaznici_kontakty – tedy vyberes z ni data, vypises do tabulky, pomoci ref() ziskas data zakaznika, pri odkazovani na editaci pouzijes id kontaktu a ne id zakaznika…

wicked
Člen | 290
+
0
-

takze to otocit? Ja jak jsem studoval prave dokumetaci, prislo me nejlepsi backjoin …

Podari se me vypsat bud info ze zakazniku nebo z kontaktu ale nejde mi je spojit …

Takže to otočit a másto related použit ref?

wicked
Člen | 290
+
0
-

Jak nad tím přemýšlím je to ale has many ne?

zakaznik má několik kontaktu, takže forma zakaznici → zakaznici_kontakt by měla být správná a fungovat tam to related, akorád se mě to zaboha nedaří sprovnoznit v presenteru

wicked
Člen | 290
+
0
-

Když provedu

public function actionUpravit($id) {
        $zakaznici = $this->zakaznici->findAll()->where('zakaznici.id', $id)->fetch();

        foreach($zakaznici->related('zakaznici_kontakty') as $zakaznici)

        dump($zakaznici);

        $this["zakaznikForm"]->setDefaults($zakaznici);
        $this["zakaznikForm"]['send']->caption = "Uložit";
        // Dostaname data do sablony
        $this->template->zakaznici = $zakaznici;
    }

Položí to dotazy

SELECT *
FROM `zakaznici`
WHERE (`zakaznici`.`id` = '83')

a

SELECT *
FROM `zakaznici_kontakty`
WHERE (`zakaznici_kontakty`.`zakaznici_id` IN (83))

Ale zobrazi data jenom z tabulky zakaznici_kontakty

wicked
Člen | 290
+
0
-

Dal jsem vše do jedné tabulky „zakaznici“ tak jak to bylo předtím, než se zbytečně trápit

vvoody
Člen | 910
+
0
-

Pozerám že nikto nemal silu ti to napísať :D tak sa obetujem ja. V poslednej ukážke kódu si vo foreach prepisuješ pôvodnú premennú $zakaznici s riadkom z tabulky zakaznici.