Nefunkční generování továrničky

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

Ahoj mám problém s generování továrničky a fakt is nevím rady, dělám to podle tohoto návodu – https://doc.nette.org/…s/form-reuse
A můj kód, který jsem si upravil vypadá takto (trochu se liší od toho v tutorialu, ale myslím že to by problém být neměl)

CategoryForm:

class CategoryForm extends UI\Control {

    private $database;
    public $onCategorySave;

    public function __construct(Connection $database) {
        parent::__construct();
        $this->database = $database;
    }

    public function createComponentForm() {
        $form = new UI\Form;
        $form->addSubmit('send', 'Odeslat');
        $form->onSuccess[] = [$this, 'processForm'];

        return $form;
    }

    public function processForm($form) {
        $this->onCategorySave($this, $category);
    }

}

interface ICategoryFormFactory
{
    /** @return \CategoryForm */
    function create();
}

Presenter:

class HomepagePresenter extends BasePresenter {
    public $categoryFormFactory;

    public function __construct(ICategoryFormFactory $categoryFormFactory) {
        $this->categoryFormFactory = $categoryFormFactory;
    }

    protected function createComponentCategoryForm() {
        $control = $this->categoryFormFactory->create();
        $control->onCategorySave[] = function(CategoryControl $control, $category) {
            $this->redirect('this');
        };

        return $control;
    }

}

Config:

- App\Forms\ICategoryFormFactory

Moc Vám děkuji za rady. :)

h4kuna
Backer | 740
+
0
-

Nějaká exception by byla?
Jinak na první pohled CategoryForm a ICategoryFormFactory jsi uvedl v jednom bloku tak to máš asi v jednom souboru? Ale neuvedl jsi namespace tak jen hádám.

U rozhraní podle, kterýho se má generovat továrna máš v anotaci return namespace od rootu \CategoryForm

interface ICategoryFormFactory
{
    /** @return \CategoryForm */
    function create();
}

V configu

- App\Forms\ICategoryFormFactory

Odhaduji že by tam mělo být

- ICategoryFormFactory

Editoval h4kuna (6. 7. 2017 19:45)

lukasklekner
Člen | 24
+
0
-

h4kuna napsal(a):

Nějaká exception by byla?
Jinak na první pohled CategoryForm a ICategoryFormFactory jsi uvedl v jednom bloku tak to máš asi v jednom souboru? Ale neuvedl jsi namespace tak jen hádám.

U rozhraní podle, kterýho se má generovat továrna máš v anotaci return namespace od rootu \CategoryForm

interface ICategoryFormFactory
{
    /** @return \CategoryForm */
    function create();
}

V configu

- App\Forms\ICategoryFormFactory

Odhaduji že by tam mělo být

- ICategoryFormFactory

Díky za odpověď. Jo dobře omlouvám se zkusím všechno zodpovědět.
Takže mám to v jednom souboru.

Namespace: namespace App\Forms;

V configu jsem to předělal a aplikace mi vyhodila tuto chybu: Class ICategoryFormFactory used in service ‚28_ICategoryFormFactory‘ not found

CZechBoY
Člen | 3608
+
0
-

Tak to potom uveď @return CategoryForm, protože jsou nejspíš ve stejném namespace.

lukasklekner
Člen | 24
+
0
-

CZechBoY napsal(a):

Tak to potom uveď @return CategoryForm, protože jsou nejspíš ve stejném namespace.

Uvedl jsem @return CategoryForm:

interface ICategoryFormFactory
{
    /** @return CategoryForm */
    function create();
}
CZechBoY
Člen | 3608
+
0
-

a uz funguje? :-))

lukasklekner
Člen | 24
+
0
-

CZechBoY napsal(a):

a uz funguje? :-))

Promin jsem dement :D Nefunguje právě…

CZechBoY
Člen | 3608
+
0
-

jo počkej, tobě to píše jinou hlášku :D
musíš při registraci služby zadat fqdn – celé jméno třídy i s namespace – tzn. App\Forms\ICategoryFormFactory

lukasklekner
Člen | 24
+
0
-

CZechBoY napsal(a):

jo počkej, tobě to píše jinou hlášku :D
musíš při registraci služby zadat fqdn – celé jméno třídy i s namespace – tzn. App\Forms\ICategoryFormFactory

Ty jo ted mi to hlásí tudle chybu… Call to undefined method App\Forms\CategoryForm::render()

CZechBoY
Člen | 3608
+
0
-

No jasne… jak se ma ta komponenta vyrenderovat? Jestli ti staci jen form tak by melo stacit

echo $this['form']->render();
lukasklekner
Člen | 24
+
0
-

CZechBoY napsal(a):

No jasne… jak se ma ta komponenta vyrenderovat? Jestli ti staci jen form tak by melo stacit

echo $this['form']->render();

To mám přidat do metody redner ? V tý třídě CategoryForm ?

lukasklekner
Člen | 24
+
0
-

Hele tk už mi to hlásí chybu, že proměnná category neni deklarovaná

public function processForm($form) {
       $this->onCategorySave($this, $category);
   }

Což mi je jasný, ale moc nevím co s tím… Snažím se o vytvoření callbacku a dělám to jk jsem psal výše podle návodu, ale nejde to prostě… Snad pomůžete dík moc

Oli
Člen | 1215
+
0
-

No záleží, kde se má ta proměnná $category vzít? Z formuláře nebo z GET parametru? Je to idčko, ActiveRow nebo entita? Pokud je to z formuláře tak $form->category, pokud z presenteru, tak přes konstruktor (jesltiže bez toho nedává komponenta smysl) nebo přes setr metodu…

lukasklekner
Člen | 24
+
0
-

Oli napsal(a):

No záleží, kde se má ta proměnná $category vzít? Z formuláře nebo z GET parametru? Je to idčko, ActiveRow nebo entita? Pokud je to z formuláře tak $form->category, pokud z presenteru, tak přes konstruktor (jesltiže bez toho nedává komponenta smysl) nebo přes setr metodu…

Okej ted jsem fkt uplně mimo :D Nemohl by si mi napsat nějaký příklad jendoduchý na toto téma ? Zkrátka vůbec nechápu jak ten callback použít… Díky moc

Oli
Člen | 1215
+
0
-

Jsem na mobilu, tak snad postačí tohle https://doc.nette.org/…/smartobject#…. Případně to víc rozvedu, jestli to z toho nebude patrné :)

CZechBoY
Člen | 3608
+
0
-

Stačí vědět jak fungujou funkce a proměnný… Prostě ti neexistuje proměnná $category. Co v té proměnné má být? Kde se má vzít?

petrkasnal
Člen | 42
+
0
-

Díky moc všem už jsem to dokázal jsem blb… Ale mám ještě jeden dotaz šlo by to udělat bez interface – ICategoryFormFactory. Zkousil jsem to takhle:
CategoryForm:

class CategoryForm extends UI\Control {

    private $database;
    public $onCategorySave;

    public function __construct(Connection $database) {
        $this->database = $database;
    }

    public function render() {
        echo $this['form']->render();
    }

    public function createComponentForm() {
        $form = new UI\Form;
        $form->addSubmit('send', 'Odeslat');
        $form->onSuccess[] = [$this, 'processForm'];
        return $form;
    }

    public function processForm($form) {
        $this->onCategorySave();
    }

}

Presenter:

class HomepagePresenter extends BasePresenter {

    public $categoryForm;
    public $userManager;

    public function __construct(CategoryForm $categoryForm) {
        $this->categoryForm = $categoryForm;
    }

    public function createComponentCategoryForm() {
        $control = $this->categoryForm->createComponentForm();
        $control->onCategorySave[] = function() {
            $this->redirect('this');
        };

        return $control;
    }

}

Ale program mi vyhodil tuto chybu: Cannot read an undeclared property Nette\Application\UI\Form::$onCategorySave.

David Matějka
Moderator | 6445
+
+1
-

muzes si udelat pouze tovarnu na form, pak to ale uz nebude „formular jako komponenta“. kdyz chces form jako komponentu, tak ten interface (resp tovarnu) mit musis

Šaman
Člen | 2666
+
0
-

Ty lítáš v základech OOP a ještě se ti do toho motají věci specifické pro Nette.
V tomhle případě to ale s Nette nesouvisí – v presenteru si pomocí tovární metody vytvoříš nikoliv instanci CategoryForm, ale jen UI\Form (podívej se na kód createComponentForm()).
A ten UI\Form o nějaké $onCategorySave vůbec neví. Proto ta chyba.

Bez interface to jde, ale pak si musíš sám napsat tovární třídu pro vytvoření CategoryForm. Nebo nepoužívat továrnu a v metodě $homepagePresenter->createComponentCategoryForm() použít operátor new. (Nedoporučuje se, ale fungovat to bude.)

Ideální je se ale nejdřív seznámit s Nette tím, že budeš psát kód podle ukázek a teprve až je pochopíš, tak si zkoušet vlastní řešení.

petrkasnal
Člen | 42
+
0
-

Aha už mi je to jasnější díky moc za každou radu už to mám a funguje :) Děkuji