Zápis do db s vazební tabulkou (multiselect)

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

Ahoj,
dělám databázi obchodů a k těm obchodům bych potřeboval přiřazovat kategorie případně několik k jednomu obchodu.
Poprvé dělám s vazební tabulkou a potřeboval bych vědět jak do tabulky efektivně zapsat danná data včetně zápisu multiselect z formuláře.
Momentálně to řeším dvěma formuláři ale to mi přijde neefektivní z uživatelského hlediska.


CREATE TABLE `category` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `category_name` varchar(255) CHARACTER SET utf8 NOT NULL,
  `description` varchar(1000) CHARACTER SET utf8 NOT NULL,
  `parrent_id` int(11) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;


CREATE TABLE `category_shops` (
  `shops_id` int(11) NOT NULL,
  `category_id` int(11) NOT NULL,
  KEY `shops_id` (`shops_id`),
  KEY `category_id` (`category_id`),
  CONSTRAINT `category_shops_ibfk_1` FOREIGN KEY (`shops_id`) REFERENCES `shops` (`id`),
  CONSTRAINT `category_shops_ibfk_2` FOREIGN KEY (`category_id`) REFERENCES `category` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;


CREATE TABLE `shops` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `shop_name` varchar(255) CHARACTER SET utf8 NOT NULL,
  `description` varchar(255) CHARACTER SET utf8 NOT NULL,
  `detail_description` varchar(1000) CHARACTER SET utf8 NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
	/**
	 * @return Form
	 */
	public function create()
	{
	$form = new Form;

    $form->addText('shop_name', 'Název obchodu')
			->setRequired('Zadejte prosím název obchodu.')
			->setAttribute('class', 'form-control')
      ->setOption('description', 'Např.: alza.cz, mall.cz, ...');

	$form->addText('description', 'Popis obchodu')
    	->setRequired('Zadejte prosím popis obchodu..')
			->setAttribute('class', 'form-control')
      ->setOption('description', 'Např.: Obchod abývající se prodejem elektroniky');

	$form->addTextArea('detail_description', 'Detailní popis obchodu')
			->setRequired('Vyplňte prosím detailní popis obchodu.')
			->setAttribute('class', 'form-control');

    $form->addMultiSelect('category', 'Kategorie')
      ->setItems($this->category->getCategoriesForForm())
      ->setAttribute('class', 'form-control');

	$form->addSubmit('send', 'Vytvořit nový obchod')
			->setAttribute('class', 'btn btn-lg btn-success btn-block');

	$form->onSuccess[] = array($this, 'formSucceeded');
		return $form;
	}

Prosím o radu jak složit dotaz nejde mi totiž do hlavy jak udělat jeden dotaz na databázi teď to řeším pomocí foreach ale s tím že na to mám zvláštní formulář a ukládám tedy do jedné tabulky ne do dvou jako je třeba v tomto případě.

Moc díky za radu

Mysteria
Člen | 797
+
+1
-

Já to řeším takto:

$values = $form->getValues(TRUE);
$categories = $values['category'];
unset($values['category']);
if ($shopID = $this->database->table('shops')->insert($values)) {
	foreach ($categories as $category) {
		$this->database->table('category_shops')->insert([
			'shops_id' => $shopID,
			'category_id' => $category
		]);
	}
} else { /* Nepodařilo se vložit obchod, takže žádné kategorie nebudeme přidávat */ }

Případně místo toho IFu by asi bylo lepší try catch a zachytávat nějakou DatabaseException či jak se to jmenuje. :)

Editoval Mysteria (1. 10. 2015 21:47)

kasparek
Člen | 43
+
0
-

Ahoj,
děkuju hodil jsem si to do modelu a funguje perfektně.

;)

kasparek
Člen | 43
+
0
-

@Mysteria

a jak řešíš výpis z databáze nějak jsem začal ale skládání těch dotazů docela nedávám (s jednou tabulkou je to snažší)

  public function getShopsToCategory($id){
    $query = array();
    $categoryID = $this->database->table(self::TABLE_NAME_CATEGORY)->where('category_ident', $id)->fetch();
    $shopIDS = $this->database->table(self::TABLE_CATEGORY_SHOPS_NAME)->where('category_id', $categoryID->id);
    if($shopIDS){
      foreach ($shopIDS as $shopID){
        $query[] = $this->database->table(self::TABLE_NAME_SHOP)->where('id', $shopID->shops_id);
      }
      return $query;
    } else {
      return FALSE;
    }
  }

prvním dotazem na $categoryID si zjistím jaké id má kategorie protože v $id dostanu shop_ident viz. tabulka výš

drhuhým dotazem na $shopIDS zjistím jaká id mají obchody ve vazební tabulce která už chci vypsat v tabulce ale už potom špatně skládám ten poslední dotaz a nevím zda správně plním to $query nebo co

Dík za radu

CZechBoY
Člen | 3608
+
+1
-

@kasparek Co vlastně chceš jako výsledek? Shop nebo category?

Kategorie z shopu:

$categories = $this->db->table('category')->where(':category_shops.shop.id', $idShop);
kasparek
Člen | 43
+
0
-

CZechBoY napsal(a):

@kasparek Co vlastně chceš jako výsledek? Shop nebo category?

Kategorie z shopu:

$categories = $this->db->table('category')->where(':category_shops.shop.id', $idShop);

potřeboval jsem obchody ale upravil jsem si ten dotaz koukám že jsem na to šel hodně dlouhou cestou

kolsi
Člen | 131
+
0
-

Ahoj, mám podobný dotaz, resp. jak u tohoto problému řešíte následnou editaci? Když mám k objektu seznam uživatelů, který následně edituju… smazat staré záznamy a pak vložit nové? Nebo si spočítat rozdíl, chybějící vymazat, nové doplnit? Existuje nějaké obecně správné efektivní řešení?

Teď to řeším jednoduše takto:

		$this->connection->beginTransaction();

		$res = $this->findById($id)->update($data);

		$this->connection->table("sales_user")->where("contract_id", $id)->delete();
		foreach ($users as $user_id) {
			$this->connection->table("sales_user")->insert(array(
				"contract_id" => $id,
				"user_id" => $user_id
			));
		}

		$this->connection->commit();
		return $res;