Filter udajov z databazy podla vlastnosti

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

Caute

potreboval by som urobiť vlastný filter udajov z databazy:

proste mam mineral co ma vlastnosti: farba, lesk, tvrdost

a potrebujem aby ak napr. uzivatel za dal farba = zelena tak mu vypisalo mineraly, ktore su zelenej farby..
resp. zeleny a leskly tak vypise tie…

ako by som mal podla vas postupovat?

Vdaka

hAssassin
Člen | 293
+
0
-

no ze vseho nejdriv by to chtelo aspon uvest jestli pouzivas Nette Database nebo dibi, nebo neco jinyho. Pak uz to bude lehky. Teda taky by chtelo nahodit aspon naznak DB (jestli mas vlastnosti ve spesl tabulce nebo je mas vyjmenovany primo v tabulce mineralu, apod…).

cujan
Člen | 410
+
0
-

Pouzivam nette database a vlastnosti mam v samostatnych tabulkach a tie su prepojene cudzimi klucmi…

hAssassin
Člen | 293
+
0
-
class Mineral extends Repository {
	...
	public function filterByProperty($property, $value) {
		return $this->dbcomm->table('mineral')->where($property.'.name = ?', $value);
	}
	...
}

Psano z hlavy a mozna to sou bludy, uz je pozde a dlouho sem s NetteDB nedelal, ale principielne jde o dotaz zhruba takovyto:

SELECT * FROM mineral m JOIN color c ON m.id = c.material_id WHERE c.name = 'zelena'

A potom $property je nazev tabulky ‚color‘ a $value je hodnota podle ktery chces filtrovat, cili ‚zelena‘. Viz srovnani

echo
Člen | 134
+
0
-

hAssassin napsal(a):
Psano z hlavy a mozna to sou bludy, uz je pozde a dlouho sem s NetteDB nedelal, ale principielne jde o dotaz zhruba takovyto:

SELECT * FROM mineral m JOIN color c ON m.id = c.material_id WHERE c.name = 'zelena'

Přesně tomuhle se snaží Nette Database vyhnout. Místo join položí 2 dotazy. Stačí to vyzkoušet a číst dokumentaci https://doc.nette.org/cs/database#….

cujan
Člen | 410
+
0
-

cize ake dva dotazy? lebo zacinam v tom mat dost velky chaos? a ak potrebujem joinovat 3 tabulky?

enumag
Člen | 2118
+
0
-

NDB funguje tak že pokládá samostatný dotaz na každou tabulku ze které potřebuješ číst data. Automatické joiny vytváří pouze pokud je potřebuješ ve where podmínkách, ale takto vytvořené joiny slouží jen k filtrování výsledku a nikoli ke čtení dat (čtení můžeš vynutit klauzulí ->select('join_column.column'), ale to nedoporučuji). Výjimku z výše uvedeného tvoří agregace.

Takže ano, pro 3 tabulky položí 3 dotazy.

Editoval enumag (24. 1. 2013 10:45)

cujan
Člen | 410
+
0
-

cize tento join ako ma vyzerat?

<?php
SELECT * FROM mineral m JOIN color c ON m.id = c.material_id WHERE c.name = 'zelena'
?>
enumag
Člen | 2118
+
0
-

Teď když se dívám na ten tvůj dotaz tak problém bude možná jinde. Je sloupec material_id primárním klíčem tabulky color? Pokud ano tak máš imho chybný návrh databáze, FK by vždy měl ukazovat na PK té cizí tabulky. Mám pocit, že NDB jiný způsob ani nepodporuje (@hrach: můžeš potvrdit?).

cujan
Člen | 410
+
0
-

to bol len hypoteticky priklad, cize skutocna struktura mojich tabuliek
mineral(id(PK), nazov)
farba(id(PK), nazov)
mineralFarba(idMineral, idFarba) – ktoru farbu ma mineral, lebo jeden moze obsahovat viacero farieb

a cudzie kluce su idMineral ma mineral.id a idFarba na farba.id

a ja potrebujem dostat mineraly, ktore maju pridelenu urcitu farbu…

dikes

enumag
Člen | 2118
+
0
-

Ahááá tak to řeknu rovnou že tam máš M:N vazbu. :-D Na to je potřeba backjoin, teď jen zda si správně pamatuju tu dvojtečkovou syntax…

$connection->table('mineral')->where('mineralFarba:farba.nazov', $barva);

Editoval enumag (24. 1. 2013 13:08)

cujan
Člen | 410
+
0
-

super parada a ked mam tych vlastnosti ciacej ako ta farba tak sa bude len ten where retazit?
napr. ak podobne ako farbu evidujem aj lesk.

Vdaka

enumag
Člen | 2118
+
0
-

Buď řetězit nebo tomu where myslím můžeš předat pole:

$connection->table('mineral')->where([
	'mineralFarba:farba.nazov' => $barva,
	'mineralLesk:lesk.nazov' => $lesk,
]);
castamir
Člen | 629
+
0
-

Proč ta tečková a dvojtečková notace není v dokumentaci ?!?

enumag
Člen | 2118
+
0
-

Jedním z důvodů je, že ta dvojtečková notace se velmi pravděpodobně bude měnit. Na GitHubu už nějakou dobu visí hotový pull request, ale David se k tomu pokud vím ještě nevyjádřil…

Jinak místo dokumentace je k dispozici hrachova přednáška.

cujan
Člen | 410
+
0
-

Caves, funguje to aj s tym polom, len este jedna otazka, co s pripadom ak potrebujem vybrat mineraly podla viacerych farieb? napr. ten co obsahuje ciernu a zltu? resp. vsetky co obsahuju cervenu alebo zltu?

Editoval cujan (24. 1. 2013 22:26)

enumag
Člen | 2118
+
0
-
$connection->table('mineral')->where([
    'mineralFarba:farba.nazov' => [ $barva1, $barva2 ],
    'mineralLesk:lesk.nazov' => $lesk,
]);

Edit: Výše uvedený příklad je pro „nebo“, pro „a“ je to složité. Dá se to pomocí SqlLiteral a EXISTS ... AND EXISTS ....

Editoval enumag (24. 1. 2013 22:38)

cujan
Člen | 410
+
0
-

[ $barva1, $barva2 ] toto je AND alebo OR vdaka :-)

enumag
Člen | 2118
+
0
-

Viz výše, uvědomil jsem si to hned po odeslání a editoval původní příspěvek.

cujan
Člen | 410
+
0
-

Cau filter mi uz funguje, len by som sa chcel spytat na zopa vylepseni?

ako docielim aby ak zo select boxu vyberiem farbu tak sa mi hned na stranke pregeneroval zozonam mineralov bez toho aby sa mi ten vzber v tom select boxe stratil … take daco ako vyber vysledkov niekde na pozadi (interaktivne – podobne ako ked napr. pisem v google nieco vo vyhladavaci a internaktivne sa mi zobrazuju vysledky)

dufam ze som to napisal aspon trocha zrozumitelne :-)

vdaka

enumag
Člen | 2118
+
0
-

Najdi si v dokumentaci ajax a snippety. :-)

cujan
Člen | 410
+
0
-

oki dikes za nasmerovanie…

cujan
Člen | 410
+
0
-

je nutne na spracovanie ajaxu pouzivat javascript? resp. nieco doinstalovat?

enumag
Člen | 2118
+
0
-

Ne nic takového. V prohlížeči běží JavaScript, který na pozadí odesílá asynchronní požadavky na server (ajax). Server požadavek dostane úplně stejně jako každý jiný, jen s nějakou hlavičkou navíc která umožňuje Nette ajax detekovat a zachovat se podle toho.

EDIT: Budeš potřebovat doplněk pro zpracování odpovědí. V současnosti je asi nejlepší ten od @Vojty Dobeše.

Editoval enumag (25. 1. 2013 12:07)

cujan
Člen | 410
+
0
-

No tak som zacals ajaxom :)
so startovacieho prikladu som si skopiroval .js subor

<?php
jQuery.ajaxSetup({
    cache: false,
    dataType: 'json',
    success: function (payload) {
        if (payload.snippets) {
            for (var i in payload.snippets) {
                $('#' + i).html(payload.snippets[i]);
            }
        }
    }
});

// odesílání odkazů
$('a.ajax').live('click', function (event) {
    event.preventDefault();
    $.get(this.href);
});

// odesílání formulářů
$('form.ajax').live('submit', function (event) {
    event.preventDefault();
    $.post(this.action, $(this).serialize());
});
?>

nasledne som ho nalinkoval v @layout.latte podla navodu

potom som potrebny formular pomocu ktoreho chcem filtrovat mineraly obalil do tagu {snippet}

<?php
{snippet}
{form filterForm}
<table>

     <tr>
	<th>{label vonkajsiVzhlad/}</th>
	<td>{input vonkajsiVzhlad}</td>
     </tr>
     <tr>
        <th>{label farba/}</th>
	<td>{input farba}</td>
    </tr>
    <tr>
	<th>{label tvrdostOd/}</th>
	<td>{input tvrdostOd}</td>
    </tr>
    <tr>
	<th>{label tvrdostDo/}</th>
	<td>{input tvrdostDo}</td>
    </tr>
    <tr>
	<th>{label vryp/}</th>
	<td>{input vryp}</td>
    </tr>


    <tr>
        <th>{label lesk/}</th>
	<td>{input lesk}</td>
    </tr>
    <tr>
	<th>{label priepustnostSvetla/}</th>
	<td>{input priepustnostSvetla}</td>
    </tr>
    <tr>
        <th>{label create/}</th>
        <th>{input create}</th>
    </tr>
</table>
{/form}
{/snippet}
?>

len tu som sa sekol, stratil a nechapem ako mam postupovat dalej, ak chcem aby ak zmenim hociktoru polozku vo forme nech sami pregeneruje vysledna tabulka s vyseldkami (tuto v popisoch neuvadzam)

vdaka