Databázové závislosti a vytiahnutie udajov
- StanlieK
- Člen | 28
Ahojte,
potrebujem pomôcť s databázovou závislosťou. Mám 3 tabuľky – znacky,
modely, auta. Znacky obsahuju nazvy tabuliek id a znacka. Potrebujem zistiť,
ako nastaviť kľúč v tabuľke auta na znacka_id, aby som mohol z tejto
tabuľky ťahať aj znacky, na základe toho znacka_id v tabuľke auta.
Týmto spôsobom {$auto->znacky->znacka}.
Moje SQL na vytvorenie tabuliek:
DROP TABLE IF EXISTS `znacky`;
CREATE TABLE `znacky` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`znacka` varchar(100) NOT NULL,
PRIMARY KEY (`id`),
KEY `id` (`id`,`znacka`)
) ENGINE=InnoDB AUTO_INCREMENT=13 DEFAULT CHARSET=utf8;
DROP TABLE IF EXISTS `modely`;
CREATE TABLE `modely` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`model` varchar(100) NOT NULL,
`znacka_id` int(10) unsigned NOT NULL,
PRIMARY KEY (`id`),
KEY `fk_znacka` (`znacka_id`),
KEY `id` (`id`,`model`),
CONSTRAINT `fk_znacka` FOREIGN KEY (`znacka_id`) REFERENCES `znacky` (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=11 DEFAULT CHARSET=utf8;
DROP TABLE IF EXISTS `auta`;
CREATE TABLE `auta` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`znacka_id` int(10) unsigned NOT NULL,
`model_id` int(10) unsigned NOT NULL,
`motor` varchar(50) NOT NULL,
`karoseria` varchar(50) NOT NULL,
`prevodovka` int(1) NOT NULL,
`palivo` int(1) NOT NULL,
`rok_vyroby` varchar(50) NOT NULL,
`km` varchar(50) NOT NULL,
`popis` varchar(255) NOT NULL,
PRIMARY KEY (`id`),
KEY `fk_znacky` (`znacka_id`),
KEY `fk_modely` (`model_id`),
CONSTRAINT `fk_znacky` FOREIGN KEY (`znacka_id`) REFERENCES `znacky` (`id`),
CONSTRAINT `fk_modely` FOREIGN KEY (`model_id`) REFERENCES `modely` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
A môj kód v AutaRepository a HomepagePresente:
//AutaRepository
class AutaRepository extends Repository
{
public function findCars(){
return $this->findAll()->where('znacka_id LIKE ?', '%%')->order('id ASC');
}
}
//HomepagePresenter
public function renderDefault() {
$this->template->auta = $this->autaRepository->findCars();
}
Ako to mám prosím upraviť aby som neťahal len z tabuľky autá takto {$auto->znacka_id}, ale aby som mohol potiahnuť namiesto znacka_id, názov tejto značky. Predpokladám, že to bude nejaká chyba v mojom SQL a tých kľúčoch a indexoch. Ako to mám upraviť prosím.
Editoval StanlieK (7. 4. 2013 15:05)
- Šaman
- Člen | 2666
$auto->znacka->znacka
Není důležitý název tabulek (i když pro jistotu doporučuji používat
jednotné číslo – odpadnou některé starosti), důležité je pole
znacka_id
.
Offtopic:
- Název metody
findCars()
nijak neinvokuje, že se hledají podle značky, doporučuji upravit na jednoznačnější název. TřebafindByZnacka()
, protože to, že hledáš mezi auty je jasné z toho, že to voláš na AutaRepository. - Doporučuji taky používat anglické názvy i pro tabulky a proměnné,
jink ti pak vznikají takové názvy, jako
findAutaByZnacka()
a to je trochu fuj.
- StanlieK
- Člen | 28
Hej, názvy tabuliek nie je problém upraviť, ale ja mám skôr ťažkú hlavu z toho, ako nastaviť tie kľúče medzi tabuľkami v DB, aby keď použijem.
class AutaRepository extends Repository
{
public function findByCars(){
return $this->findAll()->order('id ASC');
}
}
a
//HomepagePresenter
public function renderDefault() {
$this->template->auta = $this->autaRepository->findByCars();
}
Aby som v HomePage/deafult.latte vedel použiť {$auto->znacka->znacka} na vytiahnutie názvu z tabuľky znacka, podľa hodnoty znacka_id z tabuľky auta.
- Šaman
- Člen | 2666
A to $auto->znacka->znacka
ti teď nefunguje? (Já
v klíčích problém nevidím.)
Aha, už vidím druhý problém, ta find
metoda ti vrací kolekci,
nikoliv jeden záznam. Musíš si to v šabloně foreachnout. Jestli je
problém jinde, tak ho líp popiš, protože jinak nevím, kde hledat
brouka.
Výpis modelu ti funguje? Jestli jo a značka ne, tak pošli kód šablony.
Opět offtopic – osvědčilo se mi mít get
metody které
vrací jediný záznam a find
metody pro kolekce. Pak vím, že
výsledek find
metody musím fetchovat,get
nemusím.
Editoval Šaman (7. 4. 2013 17:10)
- StanlieK
- Člen | 28
OK, takže ten výpis za pomoci $auto->znacka->znacka som rozchodil, pretože to bola čisto moja chyba a v šablóne som písal $auto->znacky->znacka …
A teraz potrebujem pomôcť ešte s jedným problémom. Potrebujem, aby po odoslaní formulára sa upravil sql dotaz tak, aby to hľadalo podľa hodnôt z formulára. Resp. ako tieto hodnoty z formulára predať tomuto dotazu. Povedzme, že mám v AutaRepository toto:
public function findCars() {
return $this->findAll()->where('znacka_id LIKE ?','%%')->where('model_id LIKE ?','%%')->where('palivo LIKE ?','%%')->where('prevodovka LIKE ?','%%')->order('id ASC');
}
Ako spraviť aby miesto ‚%%‘, boli premenné z formulára, ktorý je v HomepagePresenter spravený takto. Alebo kam mám ten dotaz umiestniť, aby mi to vypísalo na úvodnej stránke hľadané záznamy na základe odoslaného formuláru?
Formulár:
<?php
/**
* Homepage presenter.
*/
class HomepagePresenter extends BasePresenter
{
public $znackyRepository;
public $modelyRepository;
public $autaRepository;
protected function startup() {
parent::startup();
$this->znackyRepository = $this->context->znackyRepository;
$this->modelyRepository = $this->context->modelyRepository;
$this->autaRepository = $this->context->autaRepository;
\DependentSelectBox\DependentSelectBox::register('addDSelect');
\DependentSelectBox\JsonDependentSelectBox::register('addJSelect');
}
protected function beforeRender() {
DependentSelectBox\JsonDependentSelectBox::tryJsonResponse($this);
}
public function renderDefault() {
$this->template->auta = $this->autaRepository->findCars();
}
protected function createComponentForm() {
$form = new Nette\Application\UI\Form;
$form->setMethod('GET');
$znackyPairs = $this->znackyRepository->findAll()->order('znacka ASC')->fetchPairs('id', 'znacka');
$form->addSelect('znacka', 'Značka', $znacka = array('0' => 'Nezáleží', $znackyPairs));
$self = $this;
$form->addDSelect('model', 'Model', $form['znacka'], function($form) use ($self) {
$v = $form['znacka']->getValue();
$modelsPairs = $self->modelyRepository->findBy(array('znacka_id' => $v))->order('model ASC')->fetchPairs('id', 'model');
if ($v == '0'){
$modelyPairs = $self->modelyRepository->findAll()->order('model ASC')->fetchPairs('id', 'model');
return array ('0' => 'Nezáleží', $modelyPairs);
}
else {
return array('0' => 'Nezáleží', $modelsPairs);
}
});
$form->addSelect('palivo', 'Palivo', $palivo = array(
'' => 'Nezáleží',
'1' => 'Diesel',
'2' => 'Benzín',
'3' => 'LPG',
'4' => 'Hybrid',
)
);
$form->addSelect('prevodovka', 'Prevodovka', $prevodovka = array(
'' => 'Nezáleží',
'1' => 'Manuálna',
'2' => 'Automatická',
)
);
//$presenter = $this;
if($this->isAjax()) {
$form['model']->addOnSubmitCallback(function() use($self) {
$self->invalidateControl('formSnippet');
});
}
$form->addSubmit('vyhladat', 'Vyhľadať');
return $form;
}
}
Ako to mám upraviť, aby to predalo premenné scriptu v AutaRepository. Alebo ako to riešiť, aby mi po odoslaní formulára na Homepage zobrazilo výsledky?
Ďakujem za pomoc.
- Šaman
- Člen | 2666
Na znacky
vs. znacka
jsem upozorňoval v prvním
přispěvku, ale asi jsem to písmenko málo zdůraznil. Vysvětlení je
v něm, nejde o název tabulky, ale jméno sloupce.
Předání proměnné řeš normálně přes parametry funkce, tedy třeba
$cars->findCar('skoda', 'fabia');
. To není věc Nette, stejně
jako problém pokud na daném kritériu nezáleží.
Ve findCar($znacka, $model)
budeš volat normálně
->where("znacka LIKE ?","%$znacka%");
Editoval Šaman (7. 4. 2013 19:27)