Načtení prvků formuláře přes foreach

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

Snažím se vytvořit továrničku na formulář, který bude obsahovat seznam odkazů a u nich checkboxy. Tyto odkazy mám uložené v poli $odkazy a formulář se bez problémů vypíše, ale po odesláí formuláře se data ztratí.

<?php
	foreach($odkazy as $klic => $odkaz){
		$form->addHidden("odkaz_".$klic, $odkaz);
		$form->addCheckbox("check_".$klic, $odkaz);
	}
?>

Když zkusím do továrničky vložit prvek bez použití foreach, tak se také zobrazí a po odeslání jsou data z formuláře v pořádku:

<?php
	$form->addHidden("odkaz_"."1", $odkazy[1]);
	$form->addCheckbox("check_"."1", $odkazy[1]);
?>

Nevíte si s tím někdo rady?

hrach
Člen | 1834
+
0
-

podivej se na addContainer

Ladis-s
Člen | 53
+
0
-

hrach napsal(a):

podivej se na addContainer

Díky za radu, to je určitě efektivnější řešení.
Ale pořád to dělá stejný problém.
Když dám následující kód, tak po odeslání formuláře dostanu prázdné pole.

<?php
$form->addContainer('odkazy');
foreach($odkazy as $klic => $odkaz){
	$form['odkazy']->addHidden($klic, $odkaz);
}
?>

S tímto použitím vše funguje

<?php
$form->addContainer('odkazy');
$form['odkazy']->addHidden(1, $odkazy[1]);
?>
redhead
Člen | 1313
+
0
-

A vytváří se tyto pole i po submitnutí? Něco mi říká, že po submitu máš pole $odkazy prázdné a formulář pak neví, které hodnoty vlastně jsou jeho.

Nebo pošli víc kódu.

Ladis-s
Člen | 53
+
0
-

redhead napsal(a):

A vytváří se tyto pole i po submitnutí? Něco mi říká, že po submitu máš pole $odkazy prázdné a formulář pak neví, které hodnoty vlastně jsou jeho.

Nebo pošli víc kódu.

Právě, že se nevytváří i po submitnutí. Načtení toho pole trvá trošku déle, tak jsem doufal, že stačí, když jsou hodnoty uložené v tom formuláři.
Teď to mám tak, že pole načítám v továrničce. Předtím jsem ho zkušel načítat v render, ale stejně to nepomohlo.
Kde bych ho tedy měl zpracovat, abych k němu měl přístup i po submitnutí?

redhead
Člen | 1313
+
0
-

Pošli celý (relativně k problému) kód.

Ladis-s
Člen | 53
+
0
-

redhead napsal(a):

Pošli celý (relativně k problému) kód.

<?php
	protected function createComponentOdkazyForm($name)
    {
		$form = new AppForm($this, $name);

		include_once('../libs/simple_html_dom.php');

		$id_webu = $this->request->params['id_webu'];
		$link = WebModel::URLWebu($id_webu);

		// načte HTML kód cílového linku
		$html = file_get_html($link);

		$odkazy = array(); // odkazy na podstránky
		$e = $html->find('a');
		for($i=0 ; $i<sizeof($e) ; $i++){
			// vybere pouze odkazy mirici na vlastni domenu
			// porovna nalezeny odkaz s adresou webu / vybere pouze domenu
			if( str_replace("www.","", parse_url( $e[$i]->href , PHP_URL_HOST)) == str_replace("www.","", parse_url( $link , PHP_URL_HOST)) ){
				// rozparsuji URL
				$path = parse_url($e[$i]->href);
				// vytahu z URL pouze relativni cestu bez parametru
				$pathinfo = pathinfo($path['path']);

				// možné koncovky stránek
				$extensions = array("", "htm", "html", "php", "php5", "asp");

				if(!isset($pathinfo['extension']))$pathinfo['extension']="";
				// zkontroluje, jestli daný odkaz má koncovku stránky
				if( in_array($pathinfo['extension'], $extensions) ){
					if( !in_array($e[$i]->href, $odkazy) ) {
						array_push($odkazy, $e[$i]->href);
					}
				}
			}
		}
		$html->clear();

		$form->addHidden('id_webu',$this->request->params['id_webu']);
		$form->addHidden('pocet',sizeof($odkazy));

		$form->addContainer('odkazy');

		foreach($odkazy as $klic => $odkaz){
			$form['odkazy']->addHidden($klic, $odkaz);
			$form['odkazy']->addCheckbox($klic, $odkaz);

		}

        $form->addSubmit('send', 'Přidat');

        $form->onSubmit[] = array($this, 'odkazyFormSubmitted');
    }

    public function odkazyFormSubmitted($form)
    {
		$data = $form->getValues();

		print_r($data['odkazy']);
		exit;

		// vlozi do databaze
		$id_stranky = StrankaModel::insert($data);

		$this->flashMessage("Stránka \"".$data['nazev']."\" byla úspěšně přidána.");

	$this->redirect('SpravaStranek:default', array('id_webu' => $data['id_webu']) );

	}
?>
redhead
Člen | 1313
+
0
-

Tak mé postřehy:

  • rozhodně parsování toho html, ať už to děláš pročkoliv, dát do nějakého modelu. Tady je to fuj fuj.
  • pokud to trvá déle (což je asi logické), můžeš si to výsledné pole cachovat (na straně modelu – na model vždy jenom zavoláš metodu, která vrátí buď nové pole z parsování, pokud není v cache, anebo pole z cache a tím se zbavíš náročné operace parsování)
  • dáváš dvěma prvkům stejné jména $klic (u hidden a checkboxu; docela se divím, že to neřve). Měl bys je odlišit třeba 'hidden_'.$klic a 'check_'.$klic (nebo něco podobného, to je na tobě)

Další chyby jsem nenašel. Zkus si třeba dumpnout to pole $odkazy. Ať už při normálním zobrazení nebo při odeslání v něm musí být stejné elementy.

Editoval redhead (16. 9. 2010 12:07)

Patrik Votoček
Člen | 2221
+
0
-

Fuj! include_once('../libs/simple_html_dom.php'); používej RobotLoader

Fuj! $id_webu = $this->request->params['id_webu']; používej (když už musíš) $this->getParam(‚id_webu‘);

Fuj! celkově takovéhle věci do továrničky nepatří hoď si to do speciálních metod nejlépe modelu (mluvím o tom parsování).

Ladis-s
Člen | 53
+
0
-

S Nette začínám stejně jako MVC, tak v tom mám trochu guláš.
parsování jsem hodil teda do modelu, takže továrnička je takto:

<?php
protected function createComponentOdkazyForm($name)
    {
		$form = new AppForm($this, $name);

		$id_webu = $this->getParam('id_webu');
		$link = WebModel::URLWebu($id_webu);
		$odkazy = StrankaModel::nactiStranky($link);

		$form->addHidden('id_webu',$id_webu);
		$form->addHidden('pocet',sizeof($odkazy));

		$form->addContainer('odkazy');

		foreach($odkazy as $klic => $odkaz){
			$form['odkazy']->addCheckbox("check_".$klic, $odkaz);
		}

        $form->addSubmit('send', 'Přidat');

        $form->onSubmit[] = array($this, 'odkazyFormSubmitted');
    }
?>

Po submitnutí forruláře to zpracovávám takto:

<?php
 public function odkazyFormSubmitted($form)
    {

		$data = $form->getValues();
		$link = WebModel::URLWebu($data['id_webu']);
		$odkazy = StrankaModel::nactiStranky($link);

		// prida datum pridani
		$ulozit = array();
		$ulozit['datum_pridani'] = new DateTime();

		print_r($data['odkazy']);
		exit;

		// vlozi do databaze
		$id_stranky = StrankaModel::insert($data);

		$this->flashMessage("Stránka \"".$data['nazev']."\" byla úspěšně přidána.");

	$this->redirect('SpravaStranek:default', array('id_webu' => $data['id_webu']) );

	}
?>

Stále nefukční. Nějak nechápu ten princip. Když formulář generuji, tak to tam jednotlivé prvky v pořádku vygeneruje, tzn. při odeslání formuláře by se měly hodnoty těch prvků odeslat. Nebo to chápu špatně?

Jinak za rady ohledně kódu díky, upravím si to.

redhead
Člen | 1313
+
0
-

Nemyslel jsem, že to pole $odkazy máš tvořit i v submit metodě. Tam to pole stejně nikde nepoužíváš. Šlo mi o to, že ta továrnička se provede v obou requestech (a v obou musí vygenerovat stejný formulář), proto jsem myslel to dumpnutí pole $odkazy (v továrničce) – uvidíš jesli se generuje stejný formulář, stejné prvky podle stejného pole $odkazy.

A kdyžtak si dumpni celé pole $data (values z formuláře), jestli se ti odešlo i ty napevno daný data (id_webu, pocet)

Ladis-s
Člen | 53
+
0
-

Tak v továrničce se pole $odkazy dumpne v pořádku, kdežto ve fci pro obsluhu potvrzeného formuláře je pole prázdná. Když dumpnu přímo $data, tak pevně nastavené hodnoty tam jsou.

Patrik Votoček
Člen | 2221
+
0
-

Moc nechápu kde je problém… V submit metodě nemá $odkazy = StrankaModel::nactiStranky($link); co dělat to se ti načte už v továrničce.

Btw pro dump se v Nette používá dump($val);.

PS: Necituj zbytečně celý předchozí příspěvek za*** se tím fórum (citaci jsem odstranil).

Ladis-s
Člen | 53
+
0
-

Z té submit metody jsem to vyhodil a na dump používám: Debug::dump($odkazy);
Už od začátku mám problém s tím, že když v továrničce načtu pole $odkazy a vypíšu si z něj nějaký prvek formuláře pomocí přímého indexu, např. $form->addHidden(‚odkaz‘,$odkazy[1]); , tak se v pohodě vygeneruje a při odeslání je uložen v poli $data, tak jak by to mělo být.
Ovšem když na to použiju foreach, nebo for cyklus, tak to záhadně nefunguje. I když ho nechám projít třeba jen jednu iteraci.

Ladis-s
Člen | 53
+
0
-

Nenapadá vás ještě něco? pořád se kolem toho motám a nemůžu to vyřešit.
Díky

arron
Člen | 464
+
0
-

Ladis-s napsal(a):

Nějak nechápu ten princip. Když formulář generuji, tak to tam jednotlivé prvky v pořádku vygeneruje, tzn. při odeslání formuláře by se měly hodnoty těch prvků odeslat. Nebo to chápu špatně?

Cele to funguje tak, ze Nette si pri odeslani nenecha podstrcit jen tak nejake hodnoty, ale kontroluje, jestli v tom formulari takove hodnoty opravdu ocekavas. Takze to, ze se neco ze stranky posle jeste vubec neznamena, ze se to ve formulari objevi. Cili napr. pokud pri zobrazeni formulare pridas nejaky checkbox, odesles jeho hodnotu, ale pri submitu ho uz do toho formulare nepridas, tak se Ti ani neobjevi v ->getValues(). Je to jednoduse proto, aby se ty hodnoty nedaly podvrhnout. Osobne bych asi hledal chybu nekde timto smerem…

Ladis-s
Člen | 53
+
0
-

Aha, tak to je asi ten problém. Takže je to někde v tom, že to pole $odkazy už není načtené ve fci pro zpracování formuláře.
Když se spouští tato obslužná fce, tak se ještě jednou volá továrnička?
Ale když nad tím přemýšlím, tak mi nejde dohlavy to co jsem psal v #14

arron
Člen | 464
+
0
-

Ladis-s napsal(a):

Aha, tak to je asi ten problém. Takže je to někde v tom, že to pole $odkazy už není načtené ve fci pro zpracování formuláře.

Anebo se do nej nactou nejake jine hodnoty. Nette si pak mysli, ze odeslane hodnoty jsou podvrh a tak je zahodi…

Když se spouští tato obslužná fce, tak se ještě jednou volá továrnička?

Nez se spusti obsluzna submit funkce, tak se zavola tovarnicka.

Ale když nad tím přemýšlím, tak mi nejde dohlavy to co jsem psal v #14

Jo, je to divny a rekl bych, ze ta chyba bude tak moc trivialni, ze se pak budeme divit, ze jsme to nevideli driv (a takove jsou nejhorsi)…

Ladis-s
Člen | 53
+
0
-

tak je to zajímavé, ale má to na svědomí to dlouhé načítání pole. Proč, to nevím.
Když jsem do modelu přidal použití keše, tak vše chodí jak má. Teď to při zobrazení potvrzeného formuláře vytáhne data z keše.
Tak díky za rady.

arron
Člen | 464
+
0
-

Osobne si myslim, ze v tom poli $odkazy bylo pri kazdem requestu neco jineho, a to, ze to s cache funguje me v tom tak trochu utvrzuje :-) Ale pokud to nemam na cem vyzkouset, tak je to samozrejme jenom dohad:-)

redhead
Člen | 1313
+
0
-

Jako bych #8 nepsal :D :D

arron
Člen | 464
+
0
-

redhead napsal(a):

Jako bych #8 nepsal :D :D

Nekdy je proste potreba vice slov ;-) Hlavne, jestli se to povedlo vyresit :-)