Trošku mimo nette – rada ohledně foreach

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

Ahoj,

úplně to nesouvisí s Nette, ale na jiná fóra nechodím, takže to aspoň tady zkusím :)

v šabloně vypisuji jidelní menu tahle:

{foreach $jidlo->where('den >=', $today)->order('den ASC') as $jidla}
    <div class="tabulka_jidelnilistek mezera">
        <h4>{$jidla->den}</h4>
        <table class="rezervace_jidel">
            <tr>
                <td class="prvni_sloupec">{$jidla->kategorie}</td>
                <td class="druhy_sloupec">{$jidla->nazev}</td>
                <td class="treti_sloupec">{if $jidla->veganska}<div class="cervenekolecko">Veg</div>{/if}</td>
                <td class="ctvrty_sloupec">{if $jidla->detoxikacni}<div class="cervenekolecko">BL</div>{/if}</td>
                <td class="paty_sloupec">{if $jidla->bezlepkova}<div class="cervenekolecko">DX</div>{/if}</td>
                <td class="sesty_sloupec"></td>
                <td class="sedmy_sloupec">{$jidla->cena}Kč</td>
            </tr>
        </table>
    </div>
{/foreach}

$today = je aktuální datum

to mě vyhodí takovýto výpis

Ale už strašně dlouho se snažím přijít na to, jak jednotlivé položky mám vypsat tak aby se zobrazovali co datum, to všechna jídla k němu do jednoho boxu …

Doufám, že se nezlobíte, že jsem to dal sem a napsal jsem to srozumitelně.

Předem děkuji za radu

Filip Procházka
Moderator | 4668
+
+1
-

Buďto upravíš vstupní data, abys iteroval dvouúrovňové pole, nebo si někam uložíš stav a „oddělovač“ budeš vkládat pouze pokud se změní datum.

Jako jednodušší bych viděl první variantu.

$this->template->jidelnicek = $connection
	->query("... WHERE den >= ? ORDER BY den ASC", $today)
	->fetchAssoc('den[]');

Tohle by mělo vytvořit požadovanou strukturu, dyštak si s tím pohraj, to zvládneš :) Má to stejnou syntax jako dibi::fetchAssoc, k tomu určitě něco vygooglíš.

<div class="tabulka_jidelnilistek mezera" n:foreach="$jidelnicek as $den => $jidla">
	<h4>{$den}</h4>
	<table class="rezervace_jidel">
		<tr n:foreach="$jidla as $jidlo">
			<td class="prvni_sloupec">{$jidlo->kategorie}</td>
			...
		</tr>
	</table>
</div>
Etch
Člen | 403
+
0
-

Mnoha způsoby… třeba:

{var $den = null}
{foreach $jidlo->where('den >=', $today)->order('den ASC') as $jidla}
	{if $den != $jidla->den}
    <div class="tabulka_jidelnilistek mezera">
        <h4>{$jidla->den}</h4>
	{/if}
        <table class="rezervace_jidel">
            <tr>
                <td class="prvni_sloupec">{$jidla->kategorie}</td>
                <td class="druhy_sloupec">{$jidla->nazev}</td>
                <td class="treti_sloupec">{if $jidla->veganska}<div class="cervenekolecko">Veg</div>{/if}</td>
                <td class="ctvrty_sloupec">{if $jidla->detoxikacni}<div class="cervenekolecko">BL</div>{/if}</td>
                <td class="paty_sloupec">{if $jidla->bezlepkova}<div class="cervenekolecko">DX</div>{/if}</td>
                <td class="sesty_sloupec"></td>
                <td class="sedmy_sloupec">{$jidla->cena}Kč</td>
            </tr>
        </table>
	{if $den != $jidla->den}
    </div>
	{/if}
{? $den = $jidla->den}
{/foreach}
wicked
Člen | 290
+
0
-

Etch napsal(a):

Mnoha způsoby… třeba:

To mě trošku rozhodilo koukej

Etch
Člen | 403
+
0
-

To je spíše o principu než o tom, že by to mělo být přímo použitelné… Záleží jak to přesně potřebuješ vypisovat. (Jinými slovy jsem tu podmínku blbě umístil do HTML. :D)

Editoval Etch (28. 12. 2014 20:30)

wicked
Člen | 290
+
0
-

Etch napsal(a):

To je spíše o principu než o tom, že by to mělo být přímo použitelné… Záleží jak to přesně potřebuješ vypisovat. (Jinými slovy jsem tu podmínku blbě umístil do HTML. :D)

Jsem z toho nějak uplně jelen …

Etch
Člen | 403
+
0
-

No je pravda, že vzhledem k tomu, jak máš napsané to HTML tak by bylo výhodnější si dané pole předpřipravit jak píše @FilipProcházka. Navíc pokud je dostupné fetchAssoc tak je to nejjednoduší varianta.

Ten způsob s podmínkama se hodí pouze pokud máš HTML například následující:

{var $den = null}
{foreach $jidlo->where('den >=', $today)->order('den ASC') as $jidla}
  {if $den != $jidla->den}
    <div class="tabulka_jidelnilistek mezera">
        <h4>{$jidla->den}</h4>
	</div>
  {/if}
	<div>
        <table class="rezervace_jidel">
            <tr>
                <td class="prvni_sloupec">{$jidla->kategorie}</td>
                <td class="druhy_sloupec">{$jidla->nazev}</td>
                <td class="treti_sloupec">{if $jidla->veganska}<div class="cervenekolecko">Veg</div>{/if}</td>
                <td class="ctvrty_sloupec">{if $jidla->detoxikacni}<div class="cervenekolecko">BL</div>{/if}</td>
                <td class="paty_sloupec">{if $jidla->bezlepkova}<div class="cervenekolecko">DX</div>{/if}</td>
                <td class="sesty_sloupec"></td>
                <td class="sedmy_sloupec">{$jidla->cena}Kč</td>
            </tr>
        </table>
	</div>
{? $den = $jidla->den}
{/foreach}
wicked
Člen | 290
+
0
-

Etch napsal(a):

No je pravda, že vzhledem k tomu, jak máš napsané to HTML tak by bylo výhodnější si dané pole předpřipravit jak píše @FilipProcházka. Navíc pokud je dostupné fetchAssoc tak je to nejjednoduší varianta.

Ten způsob s podmínkama se hodí pouze pokud máš HTML například následující:

Takže mám předělat vytahování dat? A nějak zakomponovat fetchAssoc()? Jedu na Nette Database …

Etch
Člen | 403
+
0
-

Nepoužívám Nette Database, takže nemohu říci, jestli fetchAssoc podporuje (EDIT: podle API podporuje fetchAssoc). Pokud ano tak ho použij. Pokud ho nepodporuje, tak si můžeš dané pole připravit ručně.

$jidla = $jidlo->where('den >=', $today)->order('den ASC')->fetchAll();
$out = array();
foreach($jidla AS $jidlo){
	$out[$jidlo->den][] = $jidlo;
}
$this->template->jidla = $out;

a pak vypisuj jak popsal @FilipProcházka.

Editoval Etch (28. 12. 2014 21:11)

wicked
Člen | 290
+
0
-

Etch napsal(a):

Nepoužívám Nette Database, takže nemohu říci, jestli fetchAssoc podporuje (EDIT: podle API podporuje fetchAssoc). Pokud ano tak ho použij. Pokud ho nepodporuje, tak si můžeš dané pole připravit ručně.

$jidla = $jidlo->where('den >=', $today)->order('den ASC')->fetchAll();
$out = array();
foreach($jidla AS $jidlo){
	$out[$jidlo->den][] = $jidlo;
}
$this->template->jidla = $out;

a pak vypisuj jak popsal @FilipProcházka.

Ano podporuje, musel bych udělat komplet update …

Jinak vyřešil jsem to díky Vám takto

sablona:

<div class="tabulka_jidelnilistek mezera" n:foreach="$jidla as $den => $jidelnicek">
    <h4>{$den}</h4>
    <table class="rezervace_jidel">
        <tr n:foreach="$jidelnicek as $jidlo">
            <td class="prvni_sloupec">{$jidlo->kategorie}</td>
            <td class="druhy_sloupec">{$jidlo->nazev}</td>
            <td class="treti_sloupec">{if $jidlo->veganska}<div class="cervenekolecko">Veg</div>{/if}</td>
            <td class="ctvrty_sloupec">{if $jidlo->detoxikacni}<div class="cervenekolecko">BL</div>{/if}</td>
            <td class="paty_sloupec">{if $jidlo->bezlepkova}<div class="cervenekolecko">DX</div>{/if}</td>
            <td class="sesty_sloupec"></td>
            <td class="sedmy_sloupec">{$jidlo->cena}Kč</td>
        </tr>
    </table>
</div>

presenter:

$jidla = $this->jidla->findAll()->where('den >=', $this->today())->order('den ASC')->fetchAll();
        $out = array();
        foreach ($jidla AS $jidlo) {
            $out[$jidlo->den][] = $jidlo;
        }
        $this->template->jidla = $out;

Ještě jednou děkuji :)

wicked
Člen | 290
+
0
-

Rád bych obnovil toto téma, ale pro změnu s jiným dotazem … Doufám, že najdu dobrou duši s radou :)

Mám presenter, který vypisuje jídla na určitý den (jak jsme řešili výše) ale teď přemýšlím, jak řešit objednávku jídel?

Když kouknete sem jde mi o to, abych po vyplnění kusů jídel dostal jako výstup toho formuláře počet jídel k danému dni->jídlu

Napadlo mě nějak předávat id toho jídla, ale vůnec nevím jak to propojit s formulářek …

Zatím mám „základ“ takto

šablona:

{block content}
    {form objednavkaForm}
        <div class="nadpis_jidelnilistek">REZERVACE JÍDEL</div>
        <div class="tabulka_jidelnilistek mezera" n:foreach="$jidla as $den => $jidelnicek">
            <h4>{$den}</h4>
            <table class="rezervace_jidel">

                <tr n:foreach="$jidelnicek as $jidlo" {if $iterator->isLast()} class="bezpruhu"{/if}>
                    <td class="prvni_sloupec">{$jidlo->kategorie}</td>
                    <td class="druhy_sloupec">{$jidlo->nazev}</td>
                    <td class="treti_sloupec">{if $jidlo->veganska}<div class="cervenekolecko">Veg</div>{/if}</td>
                    <td class="ctvrty_sloupec">{if $jidlo->detoxikacni}<div class="cervenekolecko">BL</div>{/if}</td>
                    <td class="paty_sloupec">{if $jidlo->bezlepkova}<div class="cervenekolecko">DX</div>{/if}</td>
                    <td class="sesty_sloupec">{$jidlo->cena},-Kč</td>
                    <td class="sedmy_sloupec">{input pocet}</td>
                </tr>
            </table>
        </div>

        {input odeslat}

    {/form}
{/block}

Presenter:

class MenuPresenter extends HomepagePresenter {

    /** @var \App\Model\JidlaModel @inject */
    public $jidla;

    public function renderDefault() {
        $jidla = $this->jidla->findAll()->where('den >=', $this->today())->order('den ASC')->fetchAll();
        $out = array();
        foreach ($jidla as $jidlo) {
            $out[$jidlo->den][] = $jidlo;
        }
        $this->template->jidla = $out;
    }

    // Dnesni datum
    public function today() {
        return date('d. m. Y');
    }

    public function createComponentObjednavkaForm() {
        $form = new Form();
        $form->addText('pocet', '')
                ->setType('number')
                ->setDefaultValue('0')
                ->addRule(Form::INTEGER, 'Musí být číslo!');
        $form->addSubmit('odeslat', 'Odeslat objednávku')
                ->setAttribute('id', 'odeslat');


        // call method signInFormSucceeded() on success
        $form->onSuccess[] = $this->objednavkaFormSucceeded;
        return $form;
    }

    public function objednavkaFormSucceeded($form){
        $values = $form->getValues();
        dump($values);
    }

}

Ale prosím, jak bych mohl řešit to, abych jako výstup z toho formuláře měl kompletní přehled objednávky? Počet jídel, jídlo?

Mockrát děkuji … :)

wicked
Člen | 290
+
0
-

Nikoho prosím nic nenapadá?

trejjam
Backer | 65
+
0
-

Koukni na low-level formuláře

Btw doporučuju přidat k těm zkratkám nějaký title.

wicked
Člen | 290
+
0
-

Zrovna tohle jsem před chvilkou studoval … jedine co mě ještě mate je to, že pro každou položku dostavam výpis takto

X ⇒ Y kde x je pocet iteraci (0 – X) a Y je spravna hodnota z formulare …

Ale cekam, ze reseni bude nejspise zde …

Editoval wicked (29. 12. 2014 22:48)

wicked
Člen | 290
+
0
-

Asi budu potřebovat ještě bližší dokopnutí … prosím…

trejjam
Backer | 65
+
0
-

Zkus něco takového

{block content}
    {form objednavkaForm}
        <div class="nadpis_jidelnilistek">REZERVACE JÍDEL</div>
        <div class="tabulka_jidelnilistek mezera" n:foreach="$jidla as $den => $jidelnicek">
            <h4>{$den}</h4>
            <table class="rezervace_jidel">

                <tr n:foreach="$jidelnicek as $jidlo" n:class="$iterator->isLast()?bezpruhu">
                    <td class="prvni_sloupec">{$jidlo->kategorie}</td>
                    <td class="druhy_sloupec">{$jidlo->nazev}</td>
                    <td class="treti_sloupec"><div n:if="$jidlo->veganska" class="cervenekolecko" title="Jídlo vhodné pro vegetariány">Veg</div></td>
                    ...
                    <td class="sedmy_sloupec"><input type="hidden" name="jidloId[]" value="{$jidlo->id}"><input type="number" min="0" name="jidloPocet[]"></td>
                </tr>
            </table>
        </div>

        {input odeslat}

    {/form}
{/block}

Pro čtení by mělo fungovat něco jako:

$jidloId=$form->getHttpData($form::DATA_TEXT, 'jidloId[]'); //podívej se, zda je i typ DATA_NUMBER/INT/etc
$jidloPocet=$form->getHttpData($form::DATA_TEXT, 'jidloPocet[]');

$jidloObjednavka=array_combine($jidloId, $jidloPocet);

Editoval trejjam (30. 12. 2014 0:06)

wicked
Člen | 290
+
0
-

trejjam napsal(a):

Zkus něco takového

{block content}
    {form objednavkaForm}
        <div class="nadpis_jidelnilistek">REZERVACE JÍDEL</div>
        <div class="tabulka_jidelnilistek mezera" n:foreach="$jidla as $den => $jidelnicek">
            <h4>{$den}</h4>
            <table class="rezervace_jidel">

                <tr n:foreach="$jidelnicek as $jidlo" n:class="$iterator->isLast()?bezpruhu">
                    <td class="prvni_sloupec">{$jidlo->kategorie}</td>
                    <td class="druhy_sloupec">{$jidlo->nazev}</td>
                    <td class="treti_sloupec"><div n:if="$jidlo->veganska" class="cervenekolecko" title="Jídlo vhodné pro vegetariány">Veg</div></td>
                    ...
                    <td class="sedmy_sloupec"><input type="hidden" name="jidloId[]" value="{$jidlo->id}"><input type="number" min="0" name="jidloPocet[]"></td>
                </tr>
            </table>
        </div>

        {input odeslat}

    {/form}
{/block}

Pro čtení by mělo fungovat něco jako:

$jidloId=$form->getHttpData($form::DATA_TEXT, 'jidloId[]'); //podívej se, zda je i typ DATA_NUMBER/INT/etc
$jidloPocet=$form->getHttpData($form::DATA_TEXT, 'jidloPocet[]');

$jidloObjednavka=array_combine($jidloId, $jidloPocet);

Ano ano :) Dostanu ID jidel a k nim jejich počet :-) Ted už jenom zpracuji :)

DĚKUJI MNOHOKRÁT! :-)

wicked
Člen | 290
+
0
-

Jen bych se chtěl ještě ujistit, je toto zpracování v pořádku? Nebo bych měl něco upravit?

public function objednavkaFormSucceeded($form) {
        // Dostaneme hodnoty
        $jidloId = $form->getHttpData($form::DATA_TEXT, 'jidloId[]');
        $jidloPocet = $form->getHttpData($form::DATA_TEXT, 'jidloPocet[]');

        // Hodnoty do 1 pole
        $jidloObjednavka = array_combine($jidloId, $jidloPocet);

        // Projdeme hodnoty a rozdelime ve foreach
        foreach ($jidloObjednavka as $jidlo => $ks) {
            if ($ks) {
                try {
                    // Nastavime sessions
                    $session = $this->getSession('objednavka');
                    $session->polozkyObjednavka[] = array(
                        "jidlo" => $jidlo,
                        "pocet" => $ks
                    );
                    $this->flashMessage('Objednávka byla úspěšně zpracována!', 'alert alert-success');
                    $this->redirect('this');
                } catch (Exception $ex) {
                    $form->addError('Při ukládání se vyskytla chyba: ' . $ex);
                    if ($ex instanceof \Nette\Application\AbortException) {
                        throw $ex;
                    }
                }
            }
        }
    }

Děkuji :)

EDIT: Tak něco je blbě, uloží mě to jenom 1. zaznam, ale ne všechny postupně …

Editoval wicked (30. 12. 2014 14:15)

matopeto
Člen | 395
+
0
-

Ulozi sa ti iba jeden, pretoze hned po prvom robis redirect :)

wicked
Člen | 290
+
0
-

matopeto napsal(a):

Ulozi sa ti iba jeden, pretoze hned po prvom robis redirect :)

Prosím Tě a jak bych to měl rozšířit pro všechny?

matopeto
Člen | 395
+
0
-

Das ho az za ten foreach.

wicked
Člen | 290
+
0
-

matopeto napsal(a):

Das ho az za ten foreach.

… jasně … jsem blb … sorry a děkuji :)