Missing argument 3 for App\Forms\ResetFormFactory::App\Forms\{closure}()
- SontoEremo
- Člen | 341
Po pridaní premenných na mňa vyskočí Tracy
Missing argument 3 for
App\Forms\ResetFormFactory::App\Forms\{closure}()
Ako teda pridávať premenné do functions?
$form->onSuccess[] = function (Form $form, $email, $values, $token) use ($onSuccess) {
- Pavel Kravčík
- Člen | 1196
Success hádám předává jen 2 parametry. Tenhle zápis je nesmysl. A neduplikuj vlákna, když Ti David radil dobře.
- SontoEremo
- Člen | 341
Pavel Kravčík napsal(a):
Success hádám předává jen 2 parametry. Tenhle zápis je nesmysl. A neduplikuj vlákna, když Ti David radil dobře.
Môžeš mi prosím ta napísať kde mi David radil dobre na túto otázku? a kde je duplikátne vlákno?
- jiri.pudil
- Nette Blogger | 1032
Tady
ti David psal, že do druhého argumentu té funkce se předávají hodnoty
formuláře, tedy úplně totéž, co si o řádek níž získáváš přes
$form->getValues()
. Takže buďto:
$form->onSuccess[] = function (Form $form) {
$values = $form->getValues();
// ...
};
nebo
$form->onSuccess[] = function (Form $form, $values) {
// ...
};
Oběma způsoby dojdeš ke stejnému výsledku: ve $values
máš
odeslané hodnoty.
- SontoEremo
- Člen | 341
jiri.pudil napsal(a):
Tady ti David psal, že do druhého argumentu té funkce se předávají hodnoty formuláře, tedy úplně totéž, co si o řádek níž získáváš přes
$form->getValues()
. Takže buďto:$form->onSuccess[] = function (Form $form) { $values = $form->getValues(); // ... };
nebo
$form->onSuccess[] = function (Form $form, $values) { // ... };
Oběma způsoby dojdeš ke stejnému výsledku: ve
$values
máš odeslané hodnoty.
Ja to chápem preto som udával
$values = $form->getValue();
Ale ja potrebujem vedieť ako do
$form->onSuccess[] = function (Form $form, $values)
dopísať viac premenných $token, $mail, $atď…
- jiri.pudil
- Nette Blogger | 1032
Pokud je tam potřebuješ předat z vnějšího kontextu, použij k tomu
use
, stejně jako předáváš $onSuccess
:
// tu v tomto kontextu existují $onSuccess, $mail, $token
$form->onSuccess[] = function (Form $form, $values) use ($onSuccess, $mail, $token) {
// tu uvnitř můžeš navíc ještě přistupovat k $this
};
Více informací, pokud budou potřeba, můžeš najít v dokumentaci
- SontoEremo
- Člen | 341
jiri.pudil napsal(a):
Pokud je tam potřebuješ předat z vnějšího kontextu, použij k tomu
use
, stejně jako předáváš$onSuccess
:// tu v tomto kontextu existují $onSuccess, $mail, $token $form->onSuccess[] = function (Form $form, $values) use ($onSuccess, $mail, $token) { // tu uvnitř můžeš navíc ještě přistupovat k $this };
Více informací, pokud budou potřeba, můžeš najít v dokumentaci
Skúšal som vtedy to končí chybou Undefined variable: token nevie nájsť token ale keď to vkladam do function() tam to ide v pohode akurát tam viac nemôže byť.
- jiri.pudil
- Nette Blogger | 1032
Já ten první komentář myslel jako předpoklad. Pro lepší pochopení takto:
// tu v tomto kontextu MUSÍ EXISTOVAT $onSuccess, $mail, $token
Odkud se ten token bere?
Jinak bych ještě pro názornost doplnil, že parametry toho callbacku skutečně nijak neovlivníš, neb je určuje a předává ten, kdo ji volá, což je v tomhle případě Form
- SontoEremo
- Člen | 341
@jiri.pudil
Odkud se ten token bere?
z userManageru
public function selectToken($token) {
return $this->database->table(self::TABLE_NAME)->where(self::COLUMN_TOKEN, $token)->fetch();
}
Editoval SontoEremo (10. 1. 2017 16:12)
- David Matějka
- Moderator | 6445
Ten token, ktery tam chces, je predpokladam nejaky retezec. Kde vznika? to je nejaky parametr v presenteru?
- SontoEremo
- Člen | 341
Mysteria napsal(a):
Nepotřebuješ náhodou dostat do toho formuláře parametr z URL adresy?
@DavidMatějka @Mysteria
Ospravedlňujem sa ale celé som to doplietol.. namiesto toho aby som updatoval
$token v db som sa ho snažil vytiahnuť ale momentálne je token prázdny a ja
ho potrebujem naplňiť… takže tak.
Neviete ako aktualizovať pretože mne to furt vyhadzuje chybu
Call to a member function update() on boolean
public function updateToken() {
$update = $this->database->table(self::TABLE_NAME)->where(self::COLUMN_TOKEN, 'token')->fetch();
}
$selectToken = $this->userManager->updateToken('token');
$token = Random::generate(32);
$selectToken->update(array('token' => $token));
Editoval SontoEremo (10. 1. 2017 19:48)
- SontoEremo
- Člen | 341
@Mysteria
Takto to vysvetlím
Robím obnovenie hesla:
tak, že v tabuľke users mám token ktorý po registrácii musí užívateľ
aktívovať po aktivácii sa zmení na null a následne sa ďalší stĺpček
activation zmeni z no na yes… potom pri prihlásení kontrolujem či si
užívateľ aktivoval účet a či je activation yes tak ho prihlásim …
No a do toho tokenu ktorý je momentálne null chcem po správne zadanej emailovej adresy updatnúť token ktorý sa odošle na mail išlo mi o to aby sa najprv skontrolovalo či je email v db ak áno tak sa potom overí či je token null alebo už bol vygenerovaný ak áno vyhodím flashMessage, že už sa zažiadalo o heslo atď… ak token nie je null updatne sa tabuľka a vloží sa token…
Lenže ja som sa snažil ťahať tabulku či je token null alebo nie …
preto som to tam drbal…
Hádam som to vysvetlil aspoň pre pochopenie :)
- iguana007
- Člen | 970
Ale lidi tady chápou o co ti jde, problém je v tom, že ty pravděpodobně nerozumíš jejich radám.
Tj.: Když chceš nějaké metodě předávat parametr, tak jej musíš u té metody definovat. A pokud chceš ověřovat výsledek operace té metody, tak jej musíš vrátit, pomocí return.
Takže metoda updateToken by měla vypadat cca takto:
public function updateToken($token) {
return $this->database->table(self::TABLE_NAME)->where(self::COLUMN_TOKEN, $token)->fetch();
}
- SontoEremo
- Člen | 341
@iguana007
Keď si pozrieš 8 komentár od spodu mám to tak… ale ja neviem ako predať
z userMageru do ResetFormFactory funkciu updateToken().
napríklad
$addToken = $this->userManager->updateToken($token);
Vykočí Undefined variable: token
Ak vynechám $token
Missing argument 1 for App\Model\UserManager::updateToken(), called in
C:\xampp\htdocs\pagename\app\forms\ResetFormFactory.php on line 42 and
defined
Ak $token pridám a prídám ho aj do function
$form->onSuccess[] = function (Form $form, $email, $token) use ($onSuccess) {
Vyhodí to Missing argument 3 for
App\Forms\ResetFormFactory::App\Forms\{closure}()
Tak ako potom pridať parametre z userManageru do Factory alebo Presenteru?
- jiri.pudil
- Nette Blogger | 1032
@SontoEremo já to s tebou ještě zkusím :) vždyť sis ten
algoritmus vlastně celkem přesně popsal sám, a dokonce v něm máš
i napsáno, odkud se vezme $token
:
išlo mi o to aby sa najprv skontrolovalo či je email v db ak áno tak sa potom overí či je token null alebo už bol vygenerovaný ak áno vyhodím flashMessage, že už sa zažiadalo o heslo atď… ak token nie je null updatne sa tabuľka a vloží sa token…
Pojďme si to rozebrat:
išlo mi o to aby sa najprv skontrolovalo či je email v db
Ve
vedlejším vlákně jsi už doufám dospěl k fungující
matchEmail
, která ti vrátí:
- FALSE, pokud e-mail není v databázi → flashMessage, konec, není co řešit; nebo
- záznam o uživateli s daným e-mailem, říkejme mu třeba
$user
.
ak áno tak sa potom overí či je token null alebo už bol vygenerovaný
Z toho řádku, který dostaneš, přečti a zkontroluj token:
$user->token
. Tohle je ten tvůj $token
, od
kterého očekáváš, že se ti někde zčistajasna zjeví. Nezjeví; tady si
ho přečteš ze záznamu načteného z databáze.
ak áno vyhodím flashMessage, že už sa zažiadalo o heslo atď…
Spíš bych vygeneroval a poslal nový token, protože co když uživateli třeba jenom nedošel ten první e-mail? To už se nedostane do svého účtu?
ak token nie je null updatne sa tabuľka a vloží sa token…
Tady jsi myslel „ak token je null“, tj. ještě nebyl vygenerovaný.
V tom případě vygeneruj nový, ulož ho –
$user->update(['token' => $token])
– a pošli uživateli
e-mailem.
- SontoEremo
- Člen | 341
@JanMikeš ďakujem píšem si to do denníčka :)
@jiri.pudil zabudol som tam dopísať to že ako to mám už
urobené :) takže Ďakujem za rozsiahli opis ale už som to dal do
kopy len som to popísal dosť na prd za čo sa ospravedlňujem… ide mi stále
iba o jeden problém ku ktorému sa nemôžem ani za boha dopátrať.
ešte raz ti priložím problém ktorý ma trápy!
neviem ako predať z userMageru do ResetFormFactory funkciu updateToken().
napríklad
$addToken = $this->userManager->updateToken($token);
Vykočí Undefined variable: token
Ak vynechám $token
Missing argument 1 for App\Model\UserManager::updateToken(), called in
C:\xampp\htdocs\pagename\app\forms\ResetFormFactory.php on line 42 and
defined
Ak $token pridám a prídám ho aj do
function $form->onSuccess[] = function (Form $form, $email, $token) use ($onSuccess) {
Vyhodí to Missing argument 3 for
App\Forms\ResetFormFactory::App\Forms\{closure}()
Tak ako potom pridať parametre z userManageru do Factory alebo Presenteru?
- David Matějka
- Moderator | 6445
to je porad dokola. do onSuccess se predava $form
a
$values
. nic vic, nic min.
Kde je pritomna ta hodnota, kterou chces mit v $token
? nekde
jako parametr v presenteru?
- jiri.pudil
- Nette Blogger | 1032
Ty už z toho máš vlčí mlhu, tolik se soustředíš na jeden problém, až přehlížíš, že to je důsledek, a ne příčina, a že bys ten problém vůbec mít nemusel.
jiri.pudil napsal(a):
Z toho řádku, který dostaneš, přečti a zkontroluj token:
$user->token
. Tohle je ten tvůj $token, od kterého očekáváš, že se ti někde zčistajasna zjeví. Nezjeví; tady si ho přečteš ze záznamu načteného z databáze.
Líp už to vysvětlit nedokážu.
- SontoEremo
- Člen | 341
David Matějka napsal(a):
to je porad dokola. do onSuccess se predava
$form
a$values
. nic vic, nic min.
Ale to viem pre boha…
Takto aby sme to už absolútne nerozoberali
V userManager mám
napr.
public function theEmail($email) {
.....
}
public function nieco($volaco) {
....
}
public function nieco2($volaco2) {
....
}
a chcem to preniesť do NiecoFormFacory
a potrebujem to dostať sem tak aby bol výsledok
$form->onSuccess[] = function (Form $form, $email <- Toto už tu je viac sa nedá) use ($onSuccess) {
$addEmail = $this->userManager->theEmail($email)
$foo = $this->userManager->nieco($volaco);
$foo2 = $this->userManager->nieco2($volaco2);
Končí chybou Undefined variable: nieco
}
A ja neviem ako preniesť
$foo = $this->userManager->nieco($volaco);
$foo2 = $this->userManager->nieco2($volaco2);
do NiecoFormFacory
Editoval SontoEremo (11. 1. 2017 18:05)
- Mysteria
- Člen | 797
SontoEremo napsal(a):
@iguana007
Keď si pozrieš 8 komentár od spodu mám to tak… ale ja neviem ako predať z userMageru do ResetFormFactory funkciu updateToken().
Ne, tohle je špatně. Žádná funkce se nikam nepředává, to co ty potřebuješ, je předat token, a v tom je rozdíl.
A teď k tomu, jak to udělat:
/** @var string */
private $token;
// Na tuhle akci bude směřovat link, který pošleš v tom emailu,
// takže v emailu bude něco jako example.com/sign/change-password/?token=123456789
public function actionChangePassword($token = NULL) {
$this->token = $token;
}
protected function createComponentChangePasswword() {
$form = new \Nette\Application\UI\Form;
$form->addEmail('email');
$form->addPassword('password');
$form->addSubmit('submit');
$form->onSuccess[] = function(\Nette\Application\UI\Form $form) {
$something = $this->userManager->updateToken($this->token);
};
}
Ale jak psal @Jan Mikeš tak tohle nemá nic společného se samotným Nette, tohle jsou klasické znalosti z objektově orientovaného programování. Snažit se používat Nette a neumět samotné OOP PHP je to samé jako snažit se psát knihu a neumět abecedu. A to není problém Nette, na tohle bys narazil u jakéhokoliv jiného frameworku, protože:
Když definuješ funkci a dáš jí tam parametr, tak je logické, že když ji budeš volat, tak jí ten parametr taky musíš dát (nebo ho udělat volitelný, ale to není tenhle případ), jinak to bude psát chybu. Druhá věc, když si v nějaké funkci vytvoříš proměnnou a chceš jí použít v jiné funkci, tak lokální proměnná tam samozřejmě nebude dostupná (viz Undefined variable: token) a musí to být třídní proměnná.
Každopádně zdá se mi že celkově ten proces resetování hesla řešíš nějak zvláště (možná se mi to jenom zdá). Tady ti dávám příklad, z jednoho staršího projektu, jak to je řešené tam:
// Uživatel zadá do formuláře svůj email, na který se mu pošle link pro změnu hesla
// $user je klasicky $form->values z presenteru a obsahuje položku email
public function forgottenPassword(\Nette\Utils\ArrayHash $user) {
if ($user = $this->database->table('user')->where('email = ?', $user->email)->fetch()) {
$this->database->table('forgotten_password')->insert([
'user_id' => $user->id,
'token' => $token = \Nette\Security\Passwords::hash(\Nette\Utils\Random::generate(60))
]);
$this->mailer->send((new \Nette\Mail\Message)
->setFrom('no-reply@example.com')
->addTo($user->email)
->setBody($this->link->link('Guest:Sign:forgottenPassword', ['email' => $user->email, 'token' => $token]))
);
} else throw new UserException('Invalid email', 3);
}
// Uživatel kliknul na link v emailu, ve kterém je v parametrech email + token
// $user obsahuje email z URL + token z URL (to, že ty to máš z formuláře je jedno, jenom při volání téhle metody v presenteru předáš data od jinud)
// Plus tady v téhle metodě heslo generuju náhodně a posílám mu na email (což dneska není považováno za bezpečné),
// ale upravit to na formulář je jednoduchý, stačí přepsat $password = \Nette\Utils\Random::generate(10) na $user->password
public function forgottenPasswordVerify(\Nette\Utils\ArrayHash $user) {
if ($forgottenPassword = $this->database->table('forgotten_password')->where('user.email = ?', $user->email)->fetch()) {
if ($forgottenPassword->token === $user->token) {
if ($forgottenPassword->timestamp > new \DateTime('-1 hour')) {
$this->database->table('user')->where('email = ?', $user->email)->update([
'password' => \Nette\Security\Passwords::hash($password = \Nette\Utils\Random::generate(10), ['cost' => 10])
]);
$forgottenPassword->delete();
$this->mailer->send((new \Nette\Mail\Message)
->setFrom('no-reply@example.com')
->addTo($user->email)
->setBody('New password: ' . $password)
);
} else throw new UserException('Invalid timestamp', 5);
} else throw new UserException('Invalid token', 4);
} else throw new UserException('Invalid email', 3);
}
Editoval Mysteria (11. 1. 2017 18:09)
- SontoEremo
- Člen | 341
@Mysteria KONEČNE
Veľmi pekne Ďakujem ty si pán :) (v dobrom zmysle slova)
Ďakujem aj za kód budem sa z toho učiť :)
/** @var string */
private $nieco;
/** @var string */
private $nieco2;
$this->nieco
a
$this->nieco2
To je to o čo som sa snažil celý čas veľmi pekne ti Ďakujem
Problém vyriešený
Samozrejme aj ostatným :)
- SontoEremo
- Člen | 341
@Mysteria
Ďakujem za kód prechádzam krok po kroku avšak som sa zasekol na
// $user obsahuje email z URL + token z URL (to, že ty to máš z formuláře je jedno, jenom při volání téhle metody v presenteru předáš data od jinud)
if ($forgottenPassword = $this->database->table('forgotten_password')->where('user.email = ?', $user->email)->fetch()) {
if ($forgottenPassword->token === $user->token) {
......
}
}
Spravujem to v NewpasswordFormFactory ako to myslíš předáš data
od jinud? mám si to v userManager vytiahnuť?
napr.
public function selectEmai($email) {
return $this->database->table(self::TABLE_NAME)->where('email', $email)->fetch();
}
a predať ho do NewpassFormFactory?
if ($forgottenPassword = $this->userManager->selectEmai($this->email)) {
.....
}
Lebo stále je hodnota NULL
- Mysteria
- Člen | 797
To je myšleno tak, že já tu metodu volám přímo z action metody presenteru, protože už tam nemám formulář na zadání nového hesla, ale heslo mu generuju, takže to mám nějak takto:
public function actionCompleteChangePassword($email, $token) {
$this->userManager->forgottenPasswordVerify(['email' => $email, 'token' => $token]);
}
Ty když tam máš formulář, tak to budeš mít nějak takto (psáno z hlavy):
protected function createComponentPickNewPasswword() {
$form = new \Nette\Application\UI\Form;
$form->addEmail('email');
$form->addPassword('password');
$form->addSubmit('submit');
$form->onSuccess[] = function(\Nette\Application\UI\Form $form) {
$values = $form->values;
$values->token = $this->token;
$this->userManager->forgottenPasswordVerify($values);
};
}