Cannot read an undeclared property: SignUpFormFactory

XpresS
Člen | 4
+
0
-

Ahojte,
Som v nette úplne nový a už druhý deň sa neúspešne pokúšam spraviť registráciu cez DB

SignPresenter

protected function createComponentSignUpForm()
	{
		return $this->SignUpFormFactory->create(function () {
				$this->redirect('Homepage:');
			}
		);
	}

SignUpFormFactory.php

<?php

namespace App\Forms;

use App\Model;
use Nette;
use Nette\Application\UI\Form;


class SignUpFormFactory
{
	use Nette\SmartObject;

	const PASSWORD_MIN_LENGTH = 7;

	/** @var FormFactory */
	private $factory;

	/** @var Model\UserManager */
	private $userManager;


	public function __construct(FormFactory $factory, Model\UserManager $userManager)
	{
		$this->factory = $factory;
		$this->userManager = $userManager;
	}


	/**
	 * @return Form
	 */
	public function create(callable $onSuccess)
	{
		$form = $this->factory->create();
		$form->addText('username', 'Pick a username:')
			->setRequired('Please pick a username.');

		$form->addEmail('email', 'Your e-mail:')
			->setRequired('Please enter your e-mail.');

		$form->addPassword('password', 'Create a password:')
			->setOption('description', sprintf('at least %d characters', self::PASSWORD_MIN_LENGTH))
			->setRequired('Please create a password.')
			->addRule($form::MIN_LENGTH, null, self::PASSWORD_MIN_LENGTH);

		$form->addSubmit('send', 'Sign up');

		$form->onSuccess[] = function (Form $form, $values) use ($onSuccess) {
			try {
				$this->userManager->add($values->username, $values->email, $values->password);
			} catch (Model\DuplicateNameException $e) {
				$form['username']->addError('Username is already taken.');
				return;
			}
			$onSuccess();
		};

		return $form;
	}
}

Chybové hlásenie v Tracy:

**Nette\MemberAccessException

Cannot read an undeclared property App\Presenters\SignPresenter::$SignUpFormFactory.**

-- Chápem, že nemôže prečitať nedeklarovanú „vlastnosť“

Predom ďakujem za každú radu.

Editoval XpresS (25. 2. 2018 15:15)

Ondřej Kubíček
Člen | 494
+
+1
-

tipuji že v tom SignPresenteru tu SignUpFormFactory neinjectuješ, pro presenter je nejjednoduší tenhle způsob:

/** @var App\Forms\SignUpFormFactory @inject **/
public $SignUpFormFactory;
steelbull
Člen | 241
+
0
-

Skontroluj, či máš v presenteri SignUpFormFactory injectnuté. Či máš v commente @inject a či je SignUpFormFactory nastavené na public. Tiež, či ho máš továrničku zaregistrovanú v neone.

Neviem, či do create môžeš vkladať anonymnú funkciu.

Mal by si tam mať len: $this->SignUpFormFactory->create(); a presmerovanie môžeš urobiť priamo v komponente v metóde $form->onSuccess[] = function() {redirect…}

XpresS
Člen | 4
+
0
-

@steelbull pravda, mal som to dať priamo do FormSucceeded a bolo by pokoj, ale mám problem, že mi z dajakého dôvodu component so signUpForm neexistuje,

RegisterPresenter.php

<?php

namespace App\Presenters;

use Nette;
use Nette\Application\UI\Form;
use Nette\Security\Passwords;




class RegisterPresenter extends Nette\Application\UI\Presenter
{

    /**@var Nette\Database\context */
    private $database;

    public function __construct(Nette\Database\Context $database)
    {
        $this->database = $database;

    }


    protected function createComponentSignUpForm()
    {
        $form = new Form;
        $form->addEmail('email', 'E-mail')
              ->setRequired('Prosím vyplňte e-mail')
              ->addRule(function ($control) {
              return !$this->database->query('SELECT email FROM users WHERE email = ? LIMIT 1', $control->value)->fetch();
              }, 'Uživatel existuje');


        $form->addText('username', 'Uživatelské jméno:')
            ->setRequired('Prosím vyplňte své uživatelské jméno.')
            ->addRule(function ($control) {
              return !$this->database->query('SELECT username FROM users WHERE username = ? LIMIT 1', $control->value)->fetch();
              }, 'Uživatel existuje');

        $form->addPassword('password', 'Heslo:')
             ->setRequired('Prosím vyplňte své heslo.')
             ->addRule(Form::MIN_LENGTH, 'Minimální délka hesla je %d znaků', 1);


        $form->onSuccess[] = [$this, 'registrationFormSucceeded'];
        $form->addSubmit('send', 'Prihlásiť');


        return $form;
    }



    public function registrationFormSucceeded($form, $values)
    {

        $values["password"] = Passwords::hash($values['password']);
        $values["role"] = 'registred';

        $this->database->table('users')->insert($values);

        $this->flashMessage('Byl jste zaregistrován', 'success');
        $this->redirect('Homepage:');}

    }

TRACY:

**  /* line 4 */ $_tmp = $this->global->uiControl->getComponent("signUpForm"); **
44:            if ($_tmp instanceof Nette\Application\UI\IRenderable) $_tmp->redrawControl(null, false);
45:            $_tmp->render();
46:            ?><p><a href="<?php echo LR\Filters::escapeHtmlAttr($this->global->uiControl->link("in")) ?>">Already have an account? Log in.</a></p>

Editoval XpresS (25. 2. 2018 15:34)

Ondřej Kubíček
Člen | 494
+
0
-

@steelbull ten callback v create samozřejmě může mít

@XpresS a co ti to napíše přesně za chybu? tady ten jednoduchý příklad musí fungovat, nevidím tam na první pohled nic špatně

steelbull
Člen | 241
+
0
-

Je tam viac vecí, ktoré by bolo potrebné upraviť. Aby Ti Di fungoval, musíš vytvoriť továrničku. V config.neon si ju musíš zaregistrovať a potom v presenteri pridať inject, ako Ti napísal Ondrej.

A potom môžeš upraviť formulár podľa môjho:
https://forum.nette.org/…vo-formulari

Napr. vo …formSucceded nemusíš posielať values, stačí form. Values získaš z form->getValues();

XpresS
Člen | 4
+
+1
-

@steelbull Zaregistroval som to dajako takto:

services:
	latte.latteFactory:
		setup:
			- setAutoRefresh(true)
	- App\Model\UserManager
	- App\Forms\FormFactory
	- App\Forms\SignUpFormFactory
	router: App\RouterFactory::createRouter

a pravda
$values = $form->getValues();

** @OndřejKubíček **
No ako píše mi to:
Component with name ‚signUpForm‘ does not exist, did you mean ‚signInForm‘?
Myslel / myslím, si že tréba registrovať ale neviem ako a ani kde..

steelbull
Člen | 241
+
+1
-

OK, zaregistroval si to spravne, problem je, ze si nevytvoril komponent.

Takze:

v presenteri pridaj property aj s commentom:

/** @var \App\Forms\ISignUpFormFactory @inject */
public $SignUpFormFactory

Uprav metodu:

protected function createComponentSignUpForm()
{
return $this->SignUpFormFactory->create();
}

A v komponente zmen nazov triedy z class SignUpFormFactory na SignUpForm

A v komponente za triedou vytvor tovarnicku aj s commentom

interface ISignUpFormFactory
{
/**
* create method.
* @return SignUpForm
*/
public function create();
}

A v config.neon zmen na:

- App\Forms\SignUpFormFactory

A to je vsetko.

XpresS napsal(a):

@steelbull Zaregistroval som to dajako takto:

services:
	latte.latteFactory:
		setup:
			- setAutoRefresh(true)
	- App\Model\UserManager
	- App\Forms\FormFactory
	- App\Forms\SignUpFormFactory
	router: App\RouterFactory::createRouter

a pravda
$values = $form->getValues();

** @OndřejKubíček **
No ako píše mi to:
Component with name ‚signUpForm‘ does not exist, did you mean ‚signInForm‘?
Myslel / myslím, si že tréba registrovať ale neviem ako a ani kde..

Editoval steelbull (25. 2. 2018 16:52)

XpresS
Člen | 4
+
0
-

Mohol by si byť konkretnejší k tým súborom ( ktorý, kde mám upraviť ) pretože som úplne mimo kde čo mám pridať snažím sa to naučiť ale je veľa vecí na mňa..

steelbull
Člen | 241
+
0
-

Chapem. Urob to, co som Ti napisal a pozri na ten moj formular. Uprav to podla neho.

V komponente musis mat triedu SignUpForm a tovarnicku ISignUpFormFactory

V neone musis mat – App\Forms\ISignUpFormFactory

V presenteri musis mat

/** @var \App\Forms\ISignUpFormFactory @inject */
public $SignUpFormFactory

a musis tam mat metodu
protected function createComponentSignUpForm()
{
return $this->SignUpFormFactory->create();
}

a v latte musis mat:
{component signUpForm}

To je vsetko

steelbull
Člen | 241
+
0
-

Funguje Ti to?