Jak vytáhnout data z db na základě selectBoxu

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

Ahoj,
vytvářím si vlastní jednoduchej datagrid, kterej vytáhne data z databáze a na základě vybraného selectBoxu zobrazí výpis (ajax zatím nepotřebuju, ale do budoucna ho tam chci taky). Myšlenka je, že v modelu bude dotaz do db, kterej mi vytáhne IDčko a na jeho základě vypíše data. Koukal jsem na již hotové datagridy, hledal na fóru, ale nikde jsem nenašel nic co bych využil.

Zatím mám tohle:

Komponenta, která vykreslí formulář a zatím vypíše id kategorie

public function createComponentArticleMenu() {

	$form = new Form();
	$form->addSelect('category','Kategorie', $this->articles->getCategory()->fetchPairs('id','category_name'));
	$form->addSubmit('submit', 'Zobrazit');
	$form->onSuccess[] = $this->articleMenuSuceeded;
	return $form;

    }

    public function articleMenuSuceeded($form) {

	$values = $form->getValues();
	$category = $values->category;
	echo $category;

Tohle funguje, ale chtěl bych, aby to bylo schopné dynamicky zjistit jaké id (selectBox) jsem vybral a podle toho to ty data vypsalo, zatím vypíše jen id kategorie. Pořád se mi v hlavě objevuje if, ale nevím jak ověřit, které id bylo vybráno jinak než napevno ifem a nechci to tam nadrátovat napevno (když přidám kategorii do db, tak bych musel připsat další prvek do pole). Tzn. array (1,2,3,4 …) nechci.

Výsledek by měl být → vyberu prvek ze selectBoxu, kliknu na Zobrazit a dole se mi vypíše to co patří do dané kategorie.

Mohl by mě někdo prosím popostrčit?

Díky.

Ještě doplním šablonu, která se stará o zobrazení:

block content}
<br /> <br />
<div class="article_main">Posledních 10 příspěvků: <br /><br />
    {control articleMenu}
 <br /> <br />
 <table class="table-article-create">
	<thead>
		<tr>
			<th>ID</th>
			<th>Název</th>
			<th>Text</th>
			<th>Autor</th>
			<th>Datum</th>
			<th>Kategorie</th>
		</tr>
	</thead>
	<tbody>
	    <tr n:foreach = "$articles as $article">

    <td>{$article->id}</td>
    <td>{$article->title}</td>
    <td>{$article->content}</td>
    <td>{$article->author}</td>
    <td>{$article->datetime}</td>
    <td>{$article->category}</td>
 </tr>
</tbody>
 </table>
</div>

</div>
{/block}
Mysteria
Člen | 797
+
0
-

Normálně ve formuláři přesměruj na stejnou stránku a přidaj jako parametr to IDčko ze selectboxu a zpracuj to v render / action metodě.

public function articleMenuSuceeded($form) {
	$this->redirect('this', ['categoryID' => $form->values->category]);
}

public function renderSomething($categoryID) {
	$this->template->articles = !empty($categoryID) ?
		$this->articleRepository->getByCategoryId($categoryID) :
		$this->articleRepository->getAll();
}

Editoval Mysteria (29. 6. 2014 22:29)

Freestyler
Člen | 50
+
0
-

Díky, ale nešlo by to trochu víc rozepsat. První funkci chápu, ta mi hodí ID do url, ale to zpracování mi jasný není vůbec, zvlášt zápis otazníku a dvojtečky a co to má vlastně dělat, co k tomu mám dopsat.

Mysteria napsal(a):

Normálně ve formuláři přesměruj na stejnou stránku a přidaj jako parametr to IDčko ze selectboxu a zpracuj to v render / action metodě.

public function articleMenuSuceeded($form) {
	$this->redirect('this', ['categoryID' => $form->values->category]);
}

public function renderSomething($categoryID) {
	$this->template->articles = !empty($categoryID) ?
		$this->articleRepository->getByCategoryId($categoryID) :
		$this->articleRepository->getAll();
}
Majkl578
Moderator | 1364
+
+1
-

Freestyler napsal(a):

zvlášt zápis otazníku a dvojtečky a co to má vlastně dělat

To je ternární operátor, zkrácený zápis if (...) { ... } else { ... }, to jsou základy PHP a nepatří na tohle fórum.

Freestyler
Člen | 50
+
0
-

Pardon, jsem zase o něco chytřejší.

Nicméně to nic neřeší. Problém přetrvává a ten kód nefunguje, tak jak bych chtěl. Možná je problém jen v dotazu.

Tohle je funkce z modelu, která mi vypíše tabulku „category“ (ale možná úplně zbytečně)

public function getCategory() {

	return $this->database->table('category');

}

Každopádně s tím předchozím kódem nefunguje, koukám do toho už tři hodiny a nic :(. Tak prosím ještě pořádne nakopnout.

Díky.

Majkl578 napsal(a):

Freestyler napsal(a):

zvlášt zápis otazníku a dvojtečky a co to má vlastně dělat

To je ternární operátor, zkrácený zápis if (...) { ... } else { ... }, to jsou základy PHP a nepatří na tohle fórum.

Mysteria
Člen | 797
+
0
-

Aby ti fungoval ten můj příklad, tak potřebuješ přidat do toho svého modelu ty dvě metody, co tam volám, takže zhruba takto:

// Vybere všechny články
public function getAll() {
	return $this->database->table('articles');
}
// Vybere pouze ty články, který patří do kategorie vybrané v tom selectboxu
public function getByCategoryId($categoryID) {
	return $this->database->table('articles')->where('category_id', $categoryID);
}

Pokud si ani tak nevíš rady, tak sem hoď komplet celej tvůj model + ten presenter.

Editoval Mysteria (30. 6. 2014 0:53)

Freestyler
Člen | 50
+
0
-

Píše mi to: „Missing argument 1 for getCategory“ :/.

HomepagePresenter

<?php

namespace AdminModule;

use Nette\Application\UI\Form;

/**
 * Homepage presenter.
 */
class HomepagePresenter extends BasePresenter
{

    /**
     * @var \App\Model\Articles
     * @inject
     */
     public $articles;


    public function beforeRender() {

        $this->template->articles = $this->articles->fetchAll();

    }


    public function createComponentArticleMenu() {

	$form = new Form();
	$form->addSelect('category','Kategorie', $this->articles->getCategory()->fetchPairs('id','category_name'));
	$form->addSubmit('submit', 'Zobrazit');
	$form->onSuccess[] = $this->articleMenuSuceeded;
	return $form;

    }

    public function articleMenuSuceeded($form) {

	 $this->redirect('this', ['categoryID' => $form->values->category]);


    }

    public function renderDefault($categoryId) {
    $this->template->articles = !empty($categoryId);
         $this->template->articles = !empty($categoryId) ?
      $this->articles->getCategory($categoryId) :
      $this->articles->fetchAll();
}

    }

Articles Model

<?php



namespace App\Model;

/**
 * Description of Articles
 *
 * @author Freestyler
 */
class Articles extends Base {



    public function fetchAll() {

	return $this->database->table('articles')
		    ->limit('10');
    }

    public function articleAdd() {


    }

    public function getCategory($categoryId) {


	return $this->database->table('articles')->where('category',$categoryId);


    }



}
Mysteria
Člen | 797
+
0
-

Tak samozřejmě, protože protože ve výpisu kategorií pro ten selectbox ve formuláři používáš u metodu bez toho parametru. Každopádně máš tam bordel i v názvech. Do modelu přidej třeba metodu

public function getArticleCategories() {
	return $this->database->table('category');
}

a tu použij v

$form->addSelect('category','Kategorie', $this->articles->getArticleCategories()->fetchPairs('id', 'category_name'));

Btw, pojmenovat si metodu, která ti vrací články dle jejich kategorie jako getCategory($categoryId) není moc ideální. Ten návrh getArticlesByCategory($categoryId) jsem nenavrhoval pro nic za nic. Samozřejmě na funkčnost to mít vliv nebude, ale až se na to koukneš za měsíc…

Freestyler
Člen | 50
+
0
-

Super, díky moc. Funguje přesně jak má.

Ještě bych potřeboval poradit s jednou věcí. V tabulce articles je sloupec categories, který je cizím klíčem propojen na tabulku categories, kde je id a name (např. úvod, program, fotogalerie etc.).

Snažím se aby ve výpisu článků nebylo id z tabulky articles ale name z tabulky categories. Myslel jsem, že když mám tabulky propojeny cizím klíčem, tak to bude sranda, ale nedaří se :(.

Toto vypíše bez problému id kategorie v které článek je, pokud to nahradím za „name“ (což je název sloupce v tabulce categories), tak to samozřejmě skončí chybou. Zkrátka nedaří se mi tahat z té tabulky data přes cizí klíč. Dokumentaci (konkrétně část table a selection jsem četl).

<td>{$article->categories}</td>

Pokud zkusím přistoupit přímo ke sloupci „name“ (což by mělo jít protože jsou propojeny klíčem), tak dostanu chybu Trying to get property of non object …

<td>{$article->categories->name}</td>

Díky.

Mysteria napsal(a):

Tak samozřejmě, protože protože ve výpisu kategorií pro ten selectbox ve formuláři používáš u metodu bez toho parametru. Každopádně máš tam bordel i v názvech. Do modelu přidej třeba metodu

public function getArticleCategories() {
	return $this->database->table('category');
}

a tu použij v

$form->addSelect('category','Kategorie', $this->articles->getArticleCategories()->fetchPairs('id', 'category_name'));

Btw, pojmenovat si metodu, která ti vrací články dle jejich kategorie jako getCategory($categoryId) není moc ideální. Ten návrh getArticlesByCategory($categoryId) jsem nenavrhoval pro nic za nic. Samozřejmě na funkčnost to mít vliv nebude, ale až se na to koukneš za měsíc…

Editoval Freestyler (30. 6. 2014 22:48)

Mysteria
Člen | 797
+
0
-

Jak se ti jmenuje ta tabulka na kategorie? Protože se „doprostřed“ nezadává název sloupečku přes který je to spojený, ale přímo název té tabulky.

$article->tableName->columnName

Pokud to ani pak nepůjde, tak dej SQL dump obou tabulek.

David Matějka
Moderator | 6445
+
0
-

nepouziva se nazev cilove tabulky, ale nazev spojovaciho sloupecku (respektive jeho cast)

nazev „categories“ pro ten sloupecek je tedy ponekud nestastny. Je lepsi pouzit category_id. Pote se necha pouzit $article->category.

Ale muzes pouzit metodu ref, konkretne $article->ref('categories')

vice v dokumentaci

Freestyler
Člen | 50
+
0
-

Ať použiju $article->ref(‚categories‘,‚categories_id‘)->name a nebo zkusím přistoupit přímo ke sloupečku přes
$article->categories->name tak dostanu „Trying to get property of non object“. Není problém že ty data předtím projíždím foreachem? Podle mě by to ale mělo fungovat, jinak platí ten kód co jsem tady psal už dříve.

Vytáhnu si data z db:

public function fetchAll() {
	return $this->database->table('articles')
		    ->limit('10');
    }

Injectu do proměnný articles

/**
     * @var \App\Model\Articles
     * @inject
     */
     public $articles;


    public function beforeRender() {

        $this->template->articles = $this->articles->fetchAll();

    }

A projedu foreachem:

<tr n:foreach = "$articles as $article">

    <td>{$article->id}</td>
    <td>{$article->title}</td>
    <td>{$article->content}</td>
    <td>{$article->author}</td>
    <td>{$article->datetime}</td>
    <td>{$article->ref('categories','categories_id')->name}</td>
  </tr>

Jinak SQL dump tabulky zde:

SET NAMES utf8;
SET foreign_key_checks = 0;
SET time_zone = '+02:00';
SET sql_mode = 'NO_AUTO_VALUE_ON_ZERO';

DROP TABLE IF EXISTS `articles`;
CREATE TABLE `articles` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `title` varchar(255) COLLATE utf8_bin NOT NULL,
  `content` text COLLATE utf8_bin NOT NULL,
  `categories_id` int(11) DEFAULT NULL,
  `datetime` datetime NOT NULL,
  `author` varchar(50) COLLATE utf8_bin NOT NULL,
  PRIMARY KEY (`id`),
  KEY `categories_id` (`categories_id`),
  CONSTRAINT `articles_ibfk_1` FOREIGN KEY (`categories_id`) REFERENCES `categories` (`id`) ON DELETE SET NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin;


DROP TABLE IF EXISTS `categories`;
CREATE TABLE `categories` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(50) COLLATE utf8_bin NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin;
Mysteria
Člen | 797
+
0
-

Nemáš tam nějakou záludnost typu, článek bez kategorie? Protože pak by to samozřejmě nefungovalo a musel by jsi to mít třeba takto:

{($category = $article->ref('categories','categories_id')) ? $category->name : 'Bez kategorie')}

matej21 napsal(a):
nepouziva se nazev cilove tabulky, ale nazev spojovaciho sloupecku (respektive jeho cast)

Díky za upřesnění, už moc dlouho využívám místo cizích klíčů konvenční pojmenování, kde ta část spojovacího sloupečku je vlastně název cílové tabulky. :)

Freestyler
Člen | 50
+
0
-

Samozřejmě jsem tam měl jeden článek bez kategorie a vůbec mi to nedošlo…

Díky moc!

Mysteria napsal(a):

Nemáš tam nějakou záludnost typu, článek bez kategorie? Protože pak by to samozřejmě nefungovalo a musel by jsi to mít třeba takto:

{($category = $article->ref('categories','categories_id')) ? $category->name : 'Bez kategorie')}

matej21 napsal(a):
nepouziva se nazev cilove tabulky, ale nazev spojovaciho sloupecku (respektive jeho cast)

Díky za upřesnění, už moc dlouho využívám místo cizích klíčů konvenční pojmenování, kde ta část spojovacího sloupečku je vlastně název cílové tabulky. :)