Spatne určená cizí tabulka, jde si rucne nadefinovat strukturu databáze
- murdej
- Člen | 26
Ahoj,
občas se mi stává že se nette databaze netrefí když nacucává řádek
z cizí tabulky
$jabko->hruska
$jabko->ref('hruska')
Pokud zadám i sloupec s cizím klíčem tak už funguje
$tabulkaA->ref('hruska', 'hruskaId)
Věčinou si to plete tabulky se stejným začátkem názvu (jabko, jabkoHruska). Cizí klíče jsem kontroloval, používám innodb tabulky, temp jsem zkoušel promáznout.
Dá se ručně nadefinovat struktura DB?
- murdej
- Člen | 26
vvoody napsal(a):
murdej napsal(a):
Dá se ručně nadefinovat struktura DB?
Čo ti v tom bráni? Dôležité je ju navrhnúť tak aby použitá Reflecion správne určovala väzby.
Navrženou ji mám dobře, problém je v tom Reflection dělá občas chyby. Takže přeformuluji dotaz:
Dá se nette database vnutit rucne napsana struktura db aby nepoužíval reflection ke zjišťování?
- nanuqcz
- Člen | 822
vvody: murdej to asi myslel tak, že by chtěl NetteDB nějak přímo vnutit informace o tom, jak struktura DB vypadá.
Taky se mi totiž občas stává, že přestože používám Innodb a cizí klíče mám správně nastavené, tak se na některé cizí tabulky přes tečkovou/dvojtečkovou notaci nedostanu. (Bohužel jsem nepřišel na žádný konkrétní postup, jak tuto chybu cíleně způsobit, tak jsem o tom ani nepsal. Navíc u mě se to projevuje na jednom větším projektu, který ani neběží na nejaktuálnějším Nette.)
- vvoody
- Člen | 910
Tak keď vám nevyhovuje discovered reflection tak si ju treba ohnúť. Ak nechápete jej pravidlám tak uveďte reálny príklad, čiže sql dump tabuliek a kód ktorý vyhadzuje výnimku alebo nepracuje tak ako by ste chceli. Rád poradím, keď budem toho schopný. Najlepšie je to na vašom kóde a nie na hruškách a jabĺčkách ;)
murdej napsal(a):
Dá se nette database vnutit rucne napsana struktura db aby nepoužíval reflection ke zjišťování?
Áno dá, nette reflection nepoužije ak v selectoch nejoinujes a väzobné dáta získavaš pomocou funkcií ref a related tak, že vždy uvedieš oba parametre.
- murdej
- Člen | 26
Toto je kus kódu který dělal problémy:
// Načtu záznam z tabulky productSell
$productSell = $this->context->productSells->find(1);
// Toto vrátí správný záznam z tabulky product
$product = $product->ref('product', 'productId');
// Toto vrátí záznam z packageProduct
$product = $productSell->product;
Takže je to trochu jinak než jsem psal v prvním příspěvku, vypadá to že si to plete tam kde jsou stejné konce názvů tabulek, ne začátky.
Edit: Dělalo to problémy i u tečkové notace u where ale ten kus kódu už nemám přepsal jsem ho. Ale příčina bude podle mě stejná jako u toho kódu výše.
Db dump:
CREATE TABLE `packageProduct` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`packageId` int(10) unsigned NOT NULL,
`productId` int(10) unsigned NOT NULL,
`amount` double DEFAULT NULL,
`fromCredit` tinyint(1) NOT NULL,
`priceCredit` decimal(10,0) DEFAULT NULL,
`priceDirect` decimal(10,0) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `fk_packageProduct_package1_idx` (`packageId`),
KEY `fk_packageProduct_product1_idx` (`productId`),
CONSTRAINT `fk_packageProduct_package1` FOREIGN KEY (`packageId`) REFERENCES `package` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION,
CONSTRAINT `fk_packageProduct_product1` FOREIGN KEY (`productId`) REFERENCES `product` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_czech_ci;
CREATE TABLE `product` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(200) COLLATE utf8_czech_ci NOT NULL,
`description` text COLLATE utf8_czech_ci NOT NULL,
`price` decimal(10,0) NOT NULL,
`enabled` tinyint(1) NOT NULL,
`customerOnly` tinyint(1) NOT NULL,
`packageId` int(10) unsigned DEFAULT NULL,
`productId` int(10) unsigned DEFAULT NULL,
`isCategory` tinyint(1) NOT NULL,
`position` int(10) unsigned NOT NULL,
PRIMARY KEY (`id`),
KEY `fk_product_package1_idx` (`packageId`),
KEY `fk_product_product1_idx` (`productId`),
CONSTRAINT `fk_product_package1` FOREIGN KEY (`packageId`) REFERENCES `package` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION,
CONSTRAINT `fk_product_product1` FOREIGN KEY (`productId`) REFERENCES `product` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_czech_ci;
CREATE TABLE `productSell` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`productId` int(10) unsigned NOT NULL,
`prepaidId` int(10) unsigned DEFAULT NULL,
`packageProductId` int(10) unsigned DEFAULT NULL,
`directpaidId` int(10) unsigned DEFAULT NULL,
`priceDirectpaid` decimal(10,0) DEFAULT NULL,
`priceCredit` decimal(10,0) DEFAULT NULL,
`productAmount` decimal(10,0) DEFAULT NULL,
`utSell` int(10) unsigned NOT NULL,
`createUserId` int(10) unsigned NOT NULL,
`cancelUserId` int(10) unsigned DEFAULT NULL,
`cancelUt` int(10) unsigned DEFAULT NULL,
`cancelNote` text COLLATE utf8_czech_ci,
PRIMARY KEY (`id`),
KEY `fk_productSell_product1_idx` (`productId`),
KEY `fk_productSell_prepaid1_idx` (`prepaidId`),
KEY `fk_productSell_packageProduct1_idx` (`packageProductId`),
KEY `fk_productSell_directPaid1_idx` (`directpaidId`),
KEY `createUserId` (`createUserId`),
KEY `cancelUserId` (`cancelUserId`),
CONSTRAINT `fk_productSell_prepaid1` FOREIGN KEY (`prepaidId`) REFERENCES `prepaid` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION,
CONSTRAINT `productSell_ibfk_1` FOREIGN KEY (`packageProductId`) REFERENCES `packageProduct` (`id`),
CONSTRAINT `productSell_ibfk_2` FOREIGN KEY (`productId`) REFERENCES `product` (`id`),
CONSTRAINT `productSell_ibfk_3` FOREIGN KEY (`directpaidId`) REFERENCES `directpaid` (`id`),
CONSTRAINT `productSell_ibfk_4` FOREIGN KEY (`createUserId`) REFERENCES `user` (`id`),
CONSTRAINT `productSell_ibfk_5` FOREIGN KEY (`cancelUserId`) REFERENCES `user` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_czech_ci;
Editoval murdej (18. 2. 2013 7:01)
- redhead
- Člen | 1313
Řekl bych, že problém bude tady
Pokud reflexe objeví ty sloupce v pořadí
[packageProductId, productId]
tak vrátí
packageProduct
místo product
. Jestli to je bug,
nevím, v Nette\Database se vyzná snad jen @hrach :D
EDIT: nepodařilo se mi to ale reprodukovat. I když změním pořadí
sloupců, tak je vždy první productId
a až pak
packageProductId
(samozřejmě mažu cache).
Editoval redhead (18. 2. 2013 15:55)
- hrach
- Člen | 1838
Nette Database aplikuje (jak spravně zminuje redhead) first-match. Nicméně, aby to mělo nějakou logiku, tak si všechny klíče řadí dle délky. Díky tomu je prostě jednoduché špatný resolve vyřešit tím, že uvedu delší matchovací část :)
V tomto konkrétním příkladu: to, že
$productSell->product;
matche packageProductId
opravdu vypada na chybu, protoze productId
je kratsi. Vzhledem
k tomu, ze redheadovi se to nepodarilo reprodukovat, tak si rikam, jestli
nebude problem jeste nekde u tebe. Jakou mas verzi nette?