Ako preniesť email po registrácii z Factory do presenteru do flashMessage

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

Zdravím už celý deň si láme hlavu nad tým ako preniesť z forms->SignUpFormFactory do presenteru AccountsPresenter tak aby po odoslaní formulára keď nabehne flashMessage za zobrazil email užívateľa ktorý registráciu vykonal?

Nefunkčné a jemu podobné kódy končia vždy chybou!

$sEmail->addText('[' . $this->signUpFactory->email . ']');
$sEmail->addText('[' . $this->signUpFactory->values['email'] . ']');
JZechy
Člen | 161
+
+2
-

Jelikož voláš továrnu a né samotný formulář.

Nejlepší asi bude použít události, kdy si ve formuláři vytvoříš třeba atribut onAfterRegistration, a v presenteru pak jenom tomuto atributu předáš odkaz na nějakou funkci, co vše zpracuje (jako když formuláři dáváš třeba onSuccess).

Ve formuláři pak onAfterRegistration zavoláš jako metodu a předáš tomu jako parametr registrační email, který můžeš v presenteru zpracovat jak chceš.

SontoEremo
Člen | 341
+
0
-

JZechy napsal(a):

Jelikož voláš továrnu a né samotný formulář.

Nejlepší asi bude použít události, kdy si ve formuláři vytvoříš třeba atribut onAfterRegistration, a v presenteru pak jenom tomuto atributu předáš odkaz na nějakou funkci, co vše zpracuje (jako když formuláři dáváš třeba onSuccess).

Ve formuláři pak onAfterRegistration zavoláš jako metodu a předáš tomu jako parametr registrační email, který můžeš v presenteru zpracovat jak chceš.

Ďakujem za odpoveď…
Skúšam to ale nejak neviem čo dosadiť do onAfterRegistration
teda v SignUpFormFactory doplním

public function onAfterRegistration($values) {
		return $this->values->email;
	}

a potom v AccountsPresenter vytiahnem

$this->signUpFactory->onAfterRegistration()

vyhadzuje Accessing methods as properties via $obj->onAfterRegistration is deprecated in

Oli
Člen | 1215
+
0
-

To se dělá trochu jinak. v SignUpForm si na konec zpracování formuláře dáš:

// property
public $onAfterRegistration = [];

// ...

public function process(Form $form, $values)
{
	// ...
	$this->onAfterRegistration($values);
}

A v presenteru potom

public function createComponentForm()
{
	$form = $this->signUpFactory->create();
	$form->onAfterRegistration[] = function($values) {
		$this->flashMessage($values->email);
		$this->redirect('Some:destination', $values->id);
	};
	return $form;
}

Editoval Oli (6. 10. 2016 22:24)

JZechy
Člen | 161
+
0
-

Tak trošku prakticky… Událost nastavíš při vytváření komponenty. Přímo v té komponentě (to, co vrací signUpFactory), si pak na libovolné místě zavoláš tu událost, třeba já v té komponentě na vhodném místě volám $this->onAfterCommit($guestbook).

<?php
// Takto vytvářím formulář v nadřazené komponentě.
// Zavolám továrničku, co mi vrátí instanci třídy, která vytváří a vykresluje formulář.
protected function createComponentGuestbookForm() {
	$component = $this->guestbookFormFactory->create();
	$component->onAfterCommit[] = $this->formSended;

	return $component;
}

public function formSended() {
	$this->flashMessage($this->t("forms.guestbook.messages.sended"), "success");
	$this->entries = [];

	$this->redrawControl("guestbook");
}

// V GuestbookForm (to, co vrátí továrnička) pak běžně zpracovávám formulář, kdy volám událost onAfterCommit.
public function processForm(\Nette\Application\UI\Form $form) {
	$values = $form->getValues();
	$ok = true;

	$this->getDbUtils()->begin();
	try {
		// ...
		$this->getDbUtils()->commit();
	} catch(\Exception $e) {
		$this->getDbUtils()->rollback();
		$ok = false;
		$this->catchException($e, $this);
	}

	if($ok) {
		$this->onAfterCommit(); // Zde volám tu událost.
	}
}
?>

Tvá signUpFactory je jenom továrnička, co ti z create() vrátí tu komponentu, nesnaž se na ní volat něco, co patří komponentě.

Editoval JZechy (6. 10. 2016 21:55)

Jan Mikeš
Člen | 771
+
0
-

Mohlo by to vypadat nějak takto:

class MyFormFactory {
	public $onUserRegistered = [];

	public function create()
	{
		// zde si vytvoříš formulář
		$form->onSuccess[] = [$this, "processForm"];
		return $form;
	}


	public function processForm($form, $values)
	{
		// logic

		$this->onUserRegistered($values->email);
	}
}


class MyPresenter {
	protected function createComponentRegisterForm()
	{
		$this->formFactory->onUserRegistered[] = function($email)
		{
			$this->flashMessage("Díky ti $email za registraci!");
		}

		return $this->formFactory->create();
	}
}

Ještě lepší než mít event přímo na factory by bylo lepší si veškerou logiku registrace přesunout do samostatné třídy, která bude registraci obsluhovat a event mít tam:

MyRegisterService {
	public $onRegister = [];

	public function register($email, $password)
	{
		// logic

		$this->onRegister($email);
	}
}

class MyFormFactory {
	public function processForm($form, $values)
	{
		$this->registerService->register($values->email, $values->email);
	}
}


class MyPresenter {
	protected function createComponentRegisterForm()
	{
		$this->registerService->onUserRegistered[] = function($email)
		{
			$this->flashMessage("Díky ti $email za registraci!");
		}

		return $this->formFactory->create();
	}
}
Jan Mikeš
Člen | 771
+
+2
-

@Oli máš tam chybku, navěšuješ handler eventu na form, ale property je u factory ;)
edit: za předpokladu, že to není ještě obaleno do komponenty, která má v sobě další createComponent() kde tvoří formulář

Editoval Lexi (6. 10. 2016 22:09)

Jan Mikeš
Člen | 771
+
+1
-

Rád bych ti ukázal ještě jeden přístup, který hojně využívám a myslím si, že pro tuto situaci je úplně ideální. Pokud ti jdě opravdu pouze o redirect a flashmessage, eventy mohou být trošku overkill, ty se podle mě hodí na složitější problémy, nebo pokud budeš chtít mít více handlerů.

Jedná se o předávání callbacku přímo do továrničky formuláře skrze create() metodu:

class MyFormFactory {
	public function create(callable $callback)
	{
		// sestavení formu
		$form->onSuccess[] = function($form, $values) use ($callback) {
			$this->processForm($form, $values, $callback);
		};
		return $form;
	}


	public function processForm($form, $values, $callback)
	{
		// registrace ... atd

		if ($form->isValid()) {
			$callback($values->email);
		}
	}
}


class MyPresenter {
	protected function createComponentRegisterForm()
	{
		return $this->formFactory->create(function($email){
			$this->flashMessage("Děkujeme ti $email za registraci");
			$this->redirect("Homepage:");
		});
	}
}
SontoEremo
Člen | 341
+
0
-

Ďakujem chlapci za odpovede a pomoc…
cez noc to budem skladať dokopy, ale opýtam sa Vás takto je dobre na prihlasovania a registráciu používať forms zo sandboxu z nette 2.4 alebo je dobré spraviť Jeden Presenter teda AccountPresenter a v ňom riešiť registráciu a prihlasovanie keďže to budem používať len na jednom mieste a nikde inde to už nebudem prenášať?

Jan Mikeš
Člen | 771
+
+2
-

@SontoEremo doporučuji se učit a zkoušet používat best practicess hned od začátku, vytvářet si services na cokoliv, snažit se dodržovat SRP a nemít žádnou business logiku v presenterech → tu přesouvat pryč a presentery používat pouze pro volání services a obsluhu samotné aplikace (request+response) a předávání dat do šablon.

Pokud se to budeš snažit dělat všeude, časem to pro tebe bude úplná automatika a ani ti to nepřijde, navíc tu jsou nástroje jako PHPStorm, které ti hooodně usnadní práci a programování je pak jedna báseň ;).

Jsem velkým zastáncem DDD, zkus si přečíst nějaké knížky/články, za mě doporučuji https://leanpub.com/ddd-in-php – drasticky změnila můj pohled na vývoj v PHP.

Editoval Lexi (6. 10. 2016 22:15)