Nefunkční nákupní košík – komponenta

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

Zdravím,
momentálně pracuji na svém prvním e-shopu v Nette a narazil jsem na tento problém.
Košík mám implementován jako vykreslitelnou komponentu (říká se tomu control, že? :)), která položky košíku drží v v session v poli $items. Pro přidání zboží do košíku používám následující (zjednodušený) handler

<?php
public function handleAdd($id, $count) {
	$product = $model->getProduct($id);
	$product->count = $count;

	$session = Environment::getSession(__CLASS__);
	$session->items[] = $product;
}
?>

Ve třídě ProductPresenter mám nadefinovaný tento formulář a jeho obslužnou funkci pomocí kterého bych chtěl přidávat zboží do košíku

<?php
protected function createComponent($name) {
       switch($name) {
            case 'buyForm':
                $form = new AppForm($this, $name);
                ...
                $form->onSubmit[] = array($this, 'buyFormSubmitted');
                return;
        default:
            parent::createComponent($name);
            return;
        }
    }

    public function buyFormSubmitted(AppForm $form) {
        $values = $form->getValues();
        $basket->link('add', $values['id'], $values['count']);
    }
?>

Bohužel při odeslání formuláře dojde k selhání a Laděnka oznámí Fatal Error: Call to a member function link() on a non-object. Z čehož jsem vydedukoval, že v době odeslání formuláře patrně ještě není vytvořena komponenta košíku, ale příliš tomu nerozumím.

Ještě dodám, že komponentu košíku vytvářím v BasePresenteru, kterého je ProductPresenter potomkem takto

<?php
public function beforeRender() {
	...
	$this->template->basket = $this->getComponent('basket');
	...
}
...
protected function createComponent($name) {
        switch ($name) {
	...
	case 'basket':
            $basket = new Basket($this, $name);
            $this->addComponent($basket, $name);
            return;
	...
}
?>

Děkuju za každou radu, už mi to leze na mozek :)

EDIT: Vůbec nevím, jestli je toto řešení správné, pokud ne, tak mne prosím uveďte na správnou cestu :)

Editoval miira (2. 6. 2009 22:13)

jasir
Člen | 746
+
0
-
<?php
    public function buyFormSubmitted(AppForm $form) {
        $values = $form->getValues();
        $basket->link('add', $values['id'], $values['count']);
    }
?>
  1. pomocí $basket->link('add', $values['id'], $values['count']); se zřejmě pokoušíš vyvolat metodu handleAdd(). Nicméně link() k tomu neslouží, link() slouží k tvorbě linků.
  2. $basket není definovaná. Potřebuješ komponentu získat pomocí getComponent()

Mohlo by to pak vypadat nějak takhle:

<?php
public function buyFormSubmitted(AppForm $form) {
   $values = $form->getValues();
   $basket = $this->getComponent('basket');
   $basket->handleAdd($values['id'], $values['count']);
}
?>

Jinak metody handleXXX() se většinou jmenují příjemci signálů (tedy linků), čili
malinko čuchám zmatek v této věci, doporučuji si přečíst dokumentaci životního cyklu presenteru – Signály a subrequesty
A doporučuji přenést formulář do samotné komponenty basket.

Editoval jasir (2. 6. 2009 22:31)

miira
Člen | 13
+
0
-

Děkuju, takhle rychlou reakci jsem vážně nečekal :-)

jasir napsal(a):

…malinko čuchám zmatek v této věci…

Zmatek v tom pořád mám – bylo by tedy správným řešením vytvořit v controlu nějakou metodu prepare, která by vykreslila ten nakupovací formulář?

Editoval miira (2. 6. 2009 22:47)

jasir
Člen | 746
+
0
-

Nějak takhle, z hlavy & copy paste z tvého kódu:

Basket control:

<?php
class Basket extends Control {

	public function createComponent($name) {
	 switch($name) {
            case 'buyForm':
                $form = new AppForm($this, $name);
                ...
                $form->onSubmit[] = array($this, 'buyFormSubmitted');
                return;
        default:
            parent::createComponent($name);
            return;
		  }
	}

	public function buyFormSumitted(AppForm $form)
	{
		$values = $form->getValues();

		$product = $model->getProduct($id);
	        $product->count = $count;

        	$session = Environment::getSession(__CLASS__);
	        $session->items[] = $product;

		$this->presenter->redirect('this'); //po submitu vzdy redirect
	}

	public function render()
	{
		$template = $this->getTemplate()
		$template->form = $this->getComponent('buyForm');
		$template->setFile('basket.phtml');
		$template->items = Environment::getSession(__CLASS__)->items;
		$template->render();
	}
}
?>

Basket.phtml:

<?php
{$form}
<h2>Obsah košíku</h2>
{foreach $items as $item}
	Položka: {$item}<br>
{/foreach}
?>

Presenter:

<?php
	public function renderShop() {
		$this->template->basket = $this->getComponent('basket')
	}

	protected function createComponent($name) {
		switch ($name) {
	        ...
        	case 'basket':
	            	$basket = new Basket($this, $name);
	            	//$this->addComponent($basket, $name); TOTO tam být nemusí :)
	            	return;
		default:
			parent::createComponent($name)

       }
}
?>

shop.phtml

<?php
{$basket->render()}
?>

Editoval jasir (2. 6. 2009 23:06)

miira
Člen | 13
+
0
-

Myslím, že už do toho začínám pronikat. Někdy je dobře mířená rada lepší než stokrát číst manuál, díky moc! :)