Vyhledání výsledku podle parametrů z jiné tabulky

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

Zdravím, už asi druhý den si lámu hlavu s jednou věcí. Chtěl bych si nechat zobrazit záznamy z jedné tabulky podle parametru z druhé. Pokud jsem hledat správně tak se tomuto říká spojování tabulek. Našel jsem několik témat zde na fóru, ale bohužel se mi to nepodařilo zprovoznit.

Vytvořil jsem si tento kód:

$products_id = $this->orderRepository->getProduct()->where('order_id', $id);
foreach($products_id as $product_id){
    $products[] = $this->orderRepository->getProduct_table()->where('id', $product_id->product_id);
    $this->template->product = $products;
};

$products_id mi vybere id produktu z jedné tabulky a ještě pouze záznamy, které odpovídají danému $id. Dejme tomu, že v $products_id mám načteny 2 id produktů, které pomocí toho foreache chci zobrazit. Toto řešení bohužel nefunguje protože mi to zobrazuje chybu s tím, že nemůže nalézt jednotlivé sloupce, které volám v šabloně.

Díky za pomoc :D

Eda
Backer | 220
+
0
-

Nevím, jestli chápu tvé databázové schéma správně, ale v Nette\Database by to mělo být nějak takto:

$this->template->products = $this->db->table('products')->where('order_id', $orderId);

(Samozřejmě je nanejvýše vhodné tento kód zabalit do nějaké funkce v repository.)
…a pak v šabloně jen:

{foreach $products as $product}
	<div>{$product->title}</div>
	...
{/foreach}

Editoval Eda (8. 5. 2013 11:35)

quiced
Člen | 85
+
0
-

Pochopil jsi mě trochu špatně, ono se to i špatně vysvětluje.

Touto částí kódu:

$products_id = $this->orderRepository->getProduct()->where('order_id', $id);

si vyberu id produktů z jedné tabulky, ale těch ID je několik např. 1,2.

Potom potřebuju z druhé tabulky vybrat příslušné produkty a poslat je do šablony. Myslel jsem, že by to mohlo jít takto:

foreach($products_id as $product_id){
    $products[] = $this->orderRepository->getProduct_table()->where('id', $product_id->product_id);
    $this->template->product = $products;
};

ale jak už jsem psal v prvním příspěvku háže mi to chybu o neexistujícím sloupci v databázi i přesto, že tam ten sloupec je.

David Matějka
Moderator | 6445
+
0
-

muzes ukazat schema databaze?

quiced
Člen | 85
+
0
-

Určitě tady je: http://i44.tinypic.com/1nzfvc.png

V tabulce order_product ve sloupci product_id jsou id produktů podle kterých se vybírají produkty v tabulce products.

David Matějka
Moderator | 6445
+
0
-

koukam, ze tam nemas nadefinovane cizi klice. kdyz si je nadefinujes, bude ti stacit zhruba takovyhle dotaz:

$this->orderRepository->getProduct_table()->where('order_product:order_id', $orderId);
//ve vyvojove verzi nette pak takhle
$this->orderRepository->getProduct_table()->where(':order_product.order_id', $orderId);

(pripadne pokud mas nejaky duvod nepouzivat klice nebo pouzivat myisam, tak prejmenuj tabulku products na product a pouzi conventional reflection misto discovered a melo by to fungovat snad taky)

nebo to muzes provest pomoci dvou dotazu:

$products_id = $this->orderRepository->getProduct()->where('order_id', $id)->select('product_id');
$this->orderRepository->getProduct_table()->where('id', $products_id);

do where muzes jako parametr totiz dat i Nette\Database\Table\Selection, potom se provede ten dotaz odpovidajici selection a vezmou se hodnoty toho sloupecku product_id (je definovan v ->select(), pokud by nebyl, bral by se PK) a tyto hodnoty se daji do noveho dotazu do id IN(1,2,3..)

Eda
Backer | 220
+
0
-
  • tabulky převeď na uložiště InnoDB, pokud už takové nejsou
  • proč je jedna tabulka v množném čísle a jedna v jednotném? Doporučuju sjednotit
  • nadefinuj si správně cizí klíče mezi tabulkami (to zajistí, že Nette\Database bude vědět, jak tabulky přijoinovat = pak se už o to nemusíš starat)
  • pak použij tento kód:
$this->template->products = $this->db->table('products')
	->where(':order_product.order_id', $orderId); // ve verzi 2.0.x pak 'order_product:order_id'

V šabloně pak již budeš mít k dispozici proměnnou $products s produkty požadované objednávky.

Tak Matěj byl rychlejší :-)

Editoval Eda (8. 5. 2013 13:28)

quiced
Člen | 85
+
0
-

Můžu se ještě zeptat jak vyřešit to když chci provázat id z tabulky products, který má auto increment a product_id z tabulky order_products(přejmenoval jsem ji), který auto increment nemá?

Díky za rady :D

Eda
Backer | 220
+
0
-

V takové situaci bys měl mít cizí klíč ze sloupce product_id v tabulce order_products ukazující na sloupec id v tabulce products. Vůbec nevadí, že id má autoincrement.

Koukám, že používáš Adminer. Tam se dá přidat cizí klíč jednoduše pomocí odkazu v přehledu sloupců tabulky „přidat cizí klíč“…

quiced
Člen | 85
+
0
-

Jak přidat cizí klíč na to jsem přišel a obráceně to funguje, ale není potom problém v tom kódu

$this->template->products = $this->db->table('products')
    ->where(':order_product.order_id', $orderId);

když je tam tabulka products a ten cizí klíč bude u order_products?

a ještě jedna věc, nette database si podle toho cizího klíče sama propojí id produktu s product_id ?

aktuálně mi to píše chybu „No reference found for $products->order_products“

Ještě jednou díky za pomoc

quiced
Člen | 85
+
0
-

Tak už jsem na to přišel :D podlě předchozího příspěvku, protože to co posílal Eda má v sobě chybu místo order_product.order_id tam bude order_product:order_id pak už to jede.

Ještě jednou díky, zase jsem se něco nového naučil :D.

Eda
Backer | 220
+
0
-

Ano, jestli používáš verzi 2.0.x tak je to opravdu: order_product:order_id. Ve vývojové verzi je to ale už dle nové syntaxe: :order_product.order_id. Tohle jsem ale psal do komentu, takže chyba tam nebyla :-)

Nicméně, hlavně, že už je to vyřešené :-)