Návrh tabuliek pre viacjazykový web + query

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

Zdravím,
potreboval by som poradiť. Robím si web kde by som chcel aj viacjazyčnú podporu (en, sk). Na preklad šablóny a textov som použil komponentu kdyby/translator a teraz ešte by som chcel vyriešiť aj preklad údajov ťahaných z DB (zatiaľ to skúšam aplikovať len na novinky, ak by to išlo, tak aj na zvyšok webu).
Chcel by som použiť nasledovnú štruktúru: 4. Additional Translation Table Approach
Takže mám vytvorené nasledujúce tabuľky:

CREATE TABLE `news` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `title` varchar(128) NOT NULL,
  `body` text NOT NULL,
  `date` datetime NOT NULL,
  `users_id` int(11) unsigned NOT NULL,
  PRIMARY KEY (`id`),
  KEY `users_id` (`users_id`),
  CONSTRAINT `users_id` FOREIGN KEY (`users_id`) REFERENCES `users` (`id`)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8;

CREATE TABLE `languages` (
  `code` char(2) NOT NULL,
  `name` varchar(20) NOT NULL,
  PRIMARY KEY (`code`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

CREATE TABLE `news_translation` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `news_id` int(11) unsigned NOT NULL,
  `language_code` char(2) NOT NULL,
  `title` varchar(128) NOT NULL,
  `body` text NOT NULL,
  PRIMARY KEY (`id`),
  KEY `translation_id` (`news_id`),
  KEY `language_code` (`language_code`),
  CONSTRAINT `translation_id` FOREIGN KEY (`news_id`) REFERENCES `news` (`id`),
  CONSTRAINT `language_code` FOREIGN KEY (`language_code`) REFERENCES `languages` (`code`)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8;

Podľa príkladu by som mal vytvoriť asi nasledujúcu query na výber podľa jazyka:

$sql = "SELECT news.*, news_translation.title, news_translation.body
        FROM `news` p
        INNER JOIN `news_translation` ON news.id = news_translation.news_id
        WHERE news.id = 1 AND news_translation.language_code = '$current_language'";

Zatiaľ som si spravil len malý test, či vlastne dokážem spraviť inner join. Takže som si vytiahol len jednu novinku a skúsil, či prepínaním jazykov to bude robiť to čo má. Nasledujúci kód mi funguje presne ako chcem:

public function newsOnLanguage($lang) {
		return $this->database->table('news_translation')->where('language_code = ?', $lang)->where('news_id = news.id')->fetch();
	}

Toto mi vyhodí nasledujúcu query v debugbare:

SELECT `news_translation`.`id`, `news_translation`.`title`, `news_translation`.`body`
FROM `news_translation`
INNER JOIN `news` ON `news_translation`.`news_id` = `news`.`id`
WHERE (`language_code` = ?) AND (`news_id` = `news`.`id`)

následne v presentri mam:

public function renderSingle() {
		$this->template->myNews = $this->newsRepository->newsOnLanguage($this->translator->getLocale());
	}

Avšak podľa toho príkladu vyššie by som to mal mať opačne, čiže vyberať tabuľku news a zvyšok z news_translation, ale opačne mi to nefunguje a taktiež mi nefunguje ani $myNews->users->username.

Potreboval by som poradiť ako by to celé malo vyzerať na základe toho príkladu z linku vyššie, asi stačí len nejak správne zostaviť výber z DB.
Ďakujem

Editoval NiNu (13. 12. 2013 21:57)

Oli
Člen | 1215
+
0
-

Ahoj,
nějak nechápu význam té tanulky news_translation. V ní i v news máš title i body. Máš tam teda duplicitní informace.

Já to používám bez té jedné tabulky a mám teda:
news: id, title, body, date, …, language_id. S tím, že id+language_id jsou unique
language: id, name

dotaz potom vypadá

$row = $this->db->table('news')->getPrimary(1);
$row->title;
$row->language->name;

PS. podle toho jak to máš v tom dotazu by mělo jít vytáhnout uživatele jako

$myNews->news->users->username;
NiNu
Člen | 31
+
0
-

Ano viem, že je tam tá duplicita, tú si nevšímajte, najskôr som chcel vyskúšať, či to bude fungovať potom v news tie duplicity title a body samozrejme vymažem, keďže tam už budú nepotrebné, no zatiaľ mi to nefunguje tak ako chcem.
Snažím sa o tento návrh:

tabuľky aj s FK mám, už potrebujem len správne zostaviť not-orm query

Oli
Člen | 1215
+
0
-

Nejjedonuší řešení je něco jako

$row = $this->repository->table('app_product_translation')->where('product_id = ? && language_code = ?', $id, $langCode);

$row->title;
$row->product->price;
$row->language->name;
// ...

Jediné co si nejsem jistej je, s tím language_code jestli ho to bude umět takhle najít. Já vždy používal someFK_id.

NiNu
Člen | 31
+
0
-

@Oli: Diky moc, takto mi to už funguje a je to docela jednoduché. Ja som namiesto toho hľadal zložité riešenie cez inner join a jeho zostavenie v nette. Teraz mi už ide aj ten preklad noviniek z DB. Ešte poriešim tamto aj menu a mám celý web preložený.
Diky moc.