NOVINKA! E-learningové kurzy umělé inteligence. Nyní AI za nejlepší ceny. Zjisti více:
NOVINKA – Víkendový online kurz Software tester, který tě posune dál. Zjisti, jak na to!

Diskuze: Nette nastavenie hodnot z tabulky

V předchozím kvízu, Online test znalostí PHP, jsme si ověřili nabyté zkušenosti z kurzu.

Aktivity
Avatar
Raiper34
Tvůrce
Avatar
Raiper34:16.8.2015 20:01

Zdar,

cely den sa paprem z Nette a za nic na svete nechapem tejto jeden veci... v presenteri vytvorim form

$form = (new EditovatUzivatelaForm($this->database, $this, $this->id))->createee();

potom v tej funkcii createee (test iba preto take prasacke pomenovanie...) urobim

$zaznam = $this->database->table('pouzivatelia')->get($this->id);
$form->setDefaults($zaznam->toArray());

Este tam nastavujem callback na prazdnu funkciu, ktoru chcem otom doplnit, ale otazka je, vykresli sa mi form uplne normalne ale ked nanho kliknem tak mi vyskoci chyba

Call to a member function toArray() on a non-object

Proste na ten riadok:

$form->setDefaults($zaznam->toArray());

Co vobec nechapem lebo pri kliknuti by sa ta funkcia nemala spustat a asi ani nespusta, a pri vykrelsovani sa spusta a funguje... som z toho na nervy uz :-D

Odpovědět
16.8.2015 20:01
Posledná vydaná hra: http://www.islandsoft.cz/index.php?art=hra-akcna-space-resistance
Avatar
d4rkw34v3r
Tvůrce
Avatar
Odpovídá na Raiper34
d4rkw34v3r:16.8.2015 20:27

Ukaz, jak vypada presenter a ta trida EditovatUziva­telaForm, protoze to resis dost podivne.

Editováno 16.8.2015 20:27
 
Nahoru Odpovědět
16.8.2015 20:27
Avatar
Odpovídá na Raiper34
Martin Konečný (pavelco1998):16.8.2015 20:51

Zdar,

obvykle je postup v Nette asi tak následující:

  1. Uděláš si továrničku (factory) na formuláře
use Nette\Security\User,
        Nette\Application\UI\Form;

class SignFormFactory
{

        private $user;

        // závislosti automaticky injectuje DI container

        /**
         * @param User
         */
        public function __construct(User $user)
        {
                $this->user = $user;
        }


        /**
         * @return Form
         */
        public function createSignIn()
        {
                $form = new Form();
                $form->addText("name", "Jméno")
                        ->setRequired("Nezadal jsi jméno");

                $form->addPassword("password", "Heslo")
                        ->setRequired("Nezadal jsi heslo");

                $form->addSubmit("login", "Přihlásit se");
                $form->onSuccess[] = $this->signInSucceeded;

                return $form;
        }


        /**
         * @param Form
         * @param \stdClass
         */
        public function signInSucceeded(Form $form, $values)
        {
                try {
                        // budeš mít nějaký autentikátor s metodou  authenticate(array $credentials)
                        $this->user->login($values->name, $values->password);
                } catch (Nette\InvalidArgumentException $e) {
                        $form->addError($e->getMessage());
                }
        }

}
  1. Tuto továrnu zaregistruješ do configu, aby mohla být injectována
services:
        - SignFormFactory

Díky tomu Nette dokáže automaticky injectovat všechny závislosti (např. objekt třídy Nette\Security\U­ser, který vyžaduješ v konstruktoru).

  1. V presenteru přidáš metodu na vytvoření komponenty
use Nette\Application\UI\Form;

class SignPresenter
{

        /**
         * @var SignFormFactory
         * @inject
         */
        public $signFormFactory;   // aby mohla být automaticky injektována do presenteru, musí být viditelnost public


        /**
         * @return Form
         */
        public function createComponentSignInForm()
        {
                $form = $this->signFormFactory->createSignIn();
                $form->onSuccess[] = function(Form $form) {
                        $p = $form->getPresenter();
                        $p->flashMessage("Byl jsi úspěšně přihlášen");
                        $p->redirect("User:overview");
                };

                return $form;
        }

}
  1. Vykreslíš komponentu v šabloně
{block content}

<h1>Přihlášení</h1>

{control signInForm}

{/block}

Dodatek:
Pokud chceš předávat formuláři defaultní data, je k tomu určena metoda action() v presenteru.

public function actionSignIn()
{
        // ke komponentě se dostaneš speciálním zápisem $this["nazev_komponenty"]
        $this["signInForm"]->setDefaults(array(
                "name" => "předvyplněné jméno"
        ));
}
Akceptované řešení
+20 Zkušeností
Řešení problému
Nahoru Odpovědět
16.8.2015 20:51
Aktuálně připravuji browser RPG, FB stránka - https://www.facebook.com/AlteiraCZ
Avatar
Jindřich Máca
Tvůrce
Avatar
Odpovídá na Raiper34
Jindřich Máca:16.8.2015 20:53

Souhlasím s d4rkw34v3r, opravdu to řešíš dost podivně. Nicméně ta chyba je způsobena následující příčinou:

  • Kliknutí na formulář ho odešla na stejnou stránku.
  • Aby mohl být formulář správně zvalidován a předán do funkce pro jeho zpracování, tak se musí znovu zkonstruovat. Přeci si nebudeš držet jeho instanci pro každého uživatele, který s ním zrovna pracuje. Ne, Ty si ho znova zhotovíš, doplníš do něj odeslané hodnoty a pak ho předáš k dalšímu zpracování.
  • A samozřejmě, aby vše bylo konzistentní, tak se formulář vytváří úplně stejným způsobem jako při jeho vytvoření pro stránku, pouze se pak již nerenderuje.

Vualá, tady je Tvoje druhé volání metody createee(), které nevíš odkud se vzalo. A samozřejmě když ho pak voláš podruhé, pravděpodobně se mu předává špatné $this->id, poté následné volání databáze s neplatným ID vrátí hodnotu false a jak už jsi asi pochopil, false není objekt, tudíž na něj nemůžeš logicky volat metodu toArray(). A jsme doma! :D

Co se týče správného řešení, na to bych musel vidět mnohem více kódu, ale obecný postup zde již dobře popsal Martin Konečný (pavelco1998). :)

Editováno 16.8.2015 20:56
 
Nahoru Odpovědět
16.8.2015 20:53
Avatar
Raiper34
Tvůrce
Avatar
Raiper34:16.8.2015 22:09

Tak ja to mam cca tak ako napisal Martin... ale stale akosi nechapem kde je ta chyba, predsa id som predal konstuktoru a v tom objekte je ulozene to id stale neprepisuje sa nic a ked sa znovu zavola mal by tam byt stale to iste idcko. Ja to potrebuje iba na to aby som dal do formu defaulne hodnoty z databaze...

Nahoru Odpovědět
16.8.2015 22:09
Posledná vydaná hra: http://www.islandsoft.cz/index.php?art=hra-akcna-space-resistance
Avatar
Jindřich Máca
Tvůrce
Avatar
Odpovídá na Raiper34
Jindřich Máca:16.8.2015 22:14

Tak to se dělá přesně tak, jak psal Martin Konečný (pavelco1998).

Pokud chceš předávat formuláři defaultní data, je k tomu určena metoda action() v presenteru.

public function actionSignIn()
{
        // ke komponentě se dostaneš speciálním zápisem $this["nazev_komponenty"]
        $this["signInForm"]->setDefaults(array(
                "name" => "předvyplněné jméno"
        ));
}
 
Nahoru Odpovědět
16.8.2015 22:14
Avatar
Raiper34
Tvůrce
Avatar
Raiper34:16.8.2015 23:59

No ale aj tak mi to nefunguje :/ V editovanie Presenter mam

protected function createComponentEditovanieForm()
        {
                $form = (new EditovatUzivatelaForm($this->database))->createee();
                return $form;
        }

        public function actionEditovanieForm()
        {
                $zaznam = $this->database->table('pouzivatelia')->get($this->id);
                $this["EditovatUzivatelaForm"]->setDefaults($zaznam->toArray());
                $this["EditovatUzivatelaForm"]->id = $this->id;
        }

teraz mi to nenaplni ani to id cez public atributu na skusku co som urobil...

Nahoru Odpovědět
16.8.2015 23:59
Posledná vydaná hra: http://www.islandsoft.cz/index.php?art=hra-akcna-space-resistance
Avatar
Jindřich Máca
Tvůrce
Avatar
Odpovídá na Raiper34
Jindřich Máca:17.8.2015 0:36

No, jelikož ta metoda action*() by se měla vztahovat k akci presenteru, kde voláš ten formulář a ne k tomu formuláři samotnému... :-D

Zrovna tuhle problematiku jsem už 2x řešil v tutoriálu pro Nette, který zde aktuálně píšu. Nechci se nijak propagovat, ale myslím, že jeho přečtení by Ti opravdu pomohlo. :) Konkrétně se to řeší v tomto díle http://www.itnetwork.cz/…administrace. Je zde přímo ukázka editačního formuláře pro články a jak ho naplnit výchozími hodnotami. K článku jsou navíc i kompletní zdrojové kódy ke stažení. ;)

 
Nahoru Odpovědět
17.8.2015 0:36
Avatar
Raiper34
Tvůrce
Avatar
Raiper34:17.8.2015 12:29

No nieco som urobil ale zase sa objavili ine problemy :-D btw maju sa aj form factory pomenovavat menoFormFactory? ako je to pri presenteroch menoPresenter? Lebo moje factory sa volaju iba menoForm

Nahoru Odpovědět
17.8.2015 12:29
Posledná vydaná hra: http://www.islandsoft.cz/index.php?art=hra-akcna-space-resistance
Avatar
Raiper34
Tvůrce
Avatar
Raiper34:17.8.2015 12:48

Este otazka, ked mam renderDefault, a ako hovoris ze by sa to malo stahovat k akii presneteru v tomto pripade actionDefault? Alebo som uplne mimo? :-D precital som 7 dielov tych nette clankov, ale stale som na tom mojom probleme zaseknuty :-D

Nahoru Odpovědět
17.8.2015 12:48
Posledná vydaná hra: http://www.islandsoft.cz/index.php?art=hra-akcna-space-resistance
Avatar
Raiper34
Tvůrce
Avatar
Raiper34:18.8.2015 15:05

Ten form mi nenajde ked sa snazim naplnit data :/
Toto mam

protected function createComponentEditovanieForm()
        {
                $form = (new EditovatUzivatelaForm($this->database))->createee();
                return $form;
        }

        public function actionDefault($id)
        {
                $zaznam = $this->database->table('pouzivatelia')->get($this->id);
                $this["EditovanieForm"]->setDefaults($zaznam->toArray());
                $this["EditovanieForm"]->id = $this->id;
        }

takto to amm zaregistrovane v config

services:
        authenticator: App\Model\Prihlasovanie
        router: App\Router::vytvoritRouter
        - App\Forms\EditovatUzivatelaForm

Co robim zle? Uz vobec neviem

Nahoru Odpovědět
18.8.2015 15:05
Posledná vydaná hra: http://www.islandsoft.cz/index.php?art=hra-akcna-space-resistance
Avatar
Jindřich Máca
Tvůrce
Avatar
Odpovídá na Raiper34
Jindřich Máca:18.8.2015 15:23

Pojmenování těchto tříd je asi čistě na Tobě. :) Já tam třeba to FormFactory většinou píšu. ;)

 
Nahoru Odpovědět
18.8.2015 15:23
Avatar
Jindřich Máca
Tvůrce
Avatar
Odpovídá na Raiper34
Jindřich Máca:18.8.2015 15:25

Ano, pochopil jsi to dobře, pokud se ten formulář vykresluje v default, tak by se to mělo vztahovat k actionDefault(). :)

 
Nahoru Odpovědět
18.8.2015 15:25
Avatar
Jindřich Máca
Tvůrce
Avatar
Odpovídá na Raiper34
Jindřich Máca:18.8.2015 15:29

Můžu se zeptat, kde bereš to $this->id ? Protože pokud nemáš nadefinovanou třídní proměnou $id a nenaplníš jí před vykonáním actionDefault(), v tomhle případě jedině v metodě startup(), tak to $this->id je v době, kdy ho tam voláš null. :D Tam by totiž mělo být jenom to $id, které dostáváš jako parametr té funkce actionDefault($id). :)

 
Nahoru Odpovědět
18.8.2015 15:29
Avatar
Raiper34
Tvůrce
Avatar
Raiper34:18.8.2015 15:57

To this ide je moja chyba hej, lebo v renderi som najprv naplnal to id tej tiredy a potom vyuzival, potom to hlasilo chybu zze aj action potrebuje mat tolko isto parametrov ako render... ale ono mi to robi to ze ten form nenajde, ze neexistuje taky form ked sa tam snazim predat data

Nahoru Odpovědět
18.8.2015 15:57
Posledná vydaná hra: http://www.islandsoft.cz/index.php?art=hra-akcna-space-resistance
Avatar
Jindřich Máca
Tvůrce
Avatar
Odpovídá na Raiper34
Jindřich Máca:18.8.2015 16:12

To bude asi tím, že název toho formuláře má začínat malým písmenem tj. editovanieForm, stejně jako když to píšeš to Latte makra control. ;)

 
Nahoru Odpovědět
18.8.2015 16:12
Avatar
Raiper34
Tvůrce
Avatar
Raiper34:18.8.2015 17:20

Nah diky :)

Nahoru Odpovědět
18.8.2015 17:20
Posledná vydaná hra: http://www.islandsoft.cz/index.php?art=hra-akcna-space-resistance
Děláme co je v našich silách, aby byly zdejší diskuze co nejkvalitnější. Proto do nich také mohou přispívat pouze registrovaní členové. Pro zapojení do diskuze se přihlas. Pokud ještě nemáš účet, zaregistruj se, je to zdarma.

Zobrazeno 17 zpráv z 17.