Problém při spojování tabulek v Nette\Database\Table\Selection

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

Narazil jsem na docela podivný problém. Mám tabulky

CREATE TABLE languages (
	id integer NOT NULL auto_increment,
	name varchar(255) NOT NULL,
	...
	PRIMARY KEY (id)
);

CREATE TABLE serials (
	id integer NOT NULL auto_increment,
	language_id integer NOT NULL,
	...
	PRIMARY KEY (id),
	CONSTRAINT FOREIGN KEY (language_id) REFERENCES languages(id)
);

Používám DiscoveredReflection, který podle všeho správně analyzoval vazby a klíče. Usuzuji tak z toho, že něco jako dump(DiscoveredReflection->structure) vypadá takto:

array(3) {
   primary => array(2) {
      serials => "id" (2)
      languages => "id" (2)
   }
   hasMany => array(1) {
      languages => array(1) {
         serials => "language_id" (11)
      }
   }
   belongsTo => array(1) {
      serials => array(4) {
         language_id => "languages" (9)
      }
   }
}

A teď chci udělat v modelu Serials něco jako

<?php
class Serials extends Nette\Database\Table\Selection {
	...
	public function view() {

		return $this->select('serials.*, languages.name AS language_name');
	}
	...
}
?>

Jako výsledek očekávám něco jako:

id | name     | language_id | language_name | ...
---+----------+-------------+---------------+----
 1 | Serial 1 |          cs |       čeština | ...
 2 | Serial 2 |          sk |    slovenčina | ...
...

Problém je v tom, že místo očekávaného seznamu hodnot se to zacyklí na vykonávání dotazu

SELECT CONSTRAINT_NAME, COLUMN_NAME, REFERENCED_TABLE_NAME, REFERENCED_COLUMN_NAME
FROM information_schema.KEY_COLUMN_USAGE
WHERE TABLE_SCHEMA = DATABASE() AND REFERENCED_TABLE_NAME IS NOT NULL AND TABLE_NAME = 'serials'

načež to spadne po uplynutí maximálního času pro běh skriptu. Pokud odstraním languages.name AS language_name z dotazu, vše proběhne bez problémů (ale pochopitelně bez potřebného sloupce).

Můžete mi prosím někdo přiblížit v čem by mohl být zakopaný pes?

(Nette Framework 2.0.1 (revision 94abcaa released on 2012–02–29), PHP 5.3.10, MySQL 5.1.61)

theo
Člen | 57
+
0
-

Děkují za promptní (ne)odpověď na stupidně jednoduchou otázku…

Problémem je to, že moje tabulky se jmenují v množném čísle (serials, languages) a DiscoveredReflection bůhví proč hledá název tabulky pomocí srovnávání názvu tabulky s názvem odkazujícího sloupce namísto toho, aby poměrně logicky hledala v názvu odkazující tabulky (viz. zde: https://api.nette.org/…ion.php.html#130)… No nic…

Řešením pro mě v tomto případě bylo vytvoření vlastní databázové reflexe, která je potomkem DiscoveredReflection a která před tím, než předá rodiči ke zpracování název klíče jej převede do jednotného čísla (lidově řečeno uřeže ‚s‘, ‚es‘, ‚ies‘, případně další řetězce z konce názvu tabulky, naštěstí si to už stripos() uvnitř rodičovské metody přežvýká). Podle mého je to sice na hranici hacku, nicméně na nic lepšího jsem prostě nepřišel. Moje databázová reflexe vypadá přibližně takto:

<?php

class MyReflection extends DiscoveredReflection {
	...
	public function getBelongsToReference($table, $key) {

		$key   = $this->singelize($key);

		return parent::getBelongsToReference($table, $key);
	}

	public function getHasManyReference($table, $key) {

		$key   = $this->singelize($key);

		return parent::getHasManyReference($table, $key);
	}

	protected function singelize($key) {

		return preg_replace('/^(.*?)(s|es|ies)$/i', '$1', $key);
	}

}

?>