Class FormFactory needed by $formFactory in __construct() not found. Check type hint and ‚use‘ statements. sea

iDome89
Člen | 27
+
0
-

Ahoj,
snažím se vytvořit továrnu na Formuláře abych mohl použít bootstrap ve svém projektu, ale nechapu 100% jak to funguje. Službu mám zaregistrovanou v configu ale pořád mi vyskakuje chybová hláška. Chtěl bych to hlavně pochopit, protože z dokumentace to nechápu na 100%.

<?php

namespace App\Forms;

use Nette;
use Nette\Application\UI\Form;


final class FormFactory
{
    use Nette\SmartObject;

    /**
     * @return Form
     */
    public function create()
    {
        $form = new Form;
        $renderer = $form->getRenderer();
        $renderer->wrappers['controls']['container'] = null;
        $renderer->wrappers['pair']['container'] = 'div class="form-group"';
        $renderer->wrappers['pair']['.error'] = 'has-danger';
        $renderer->wrappers['control']['container'] = 'div';
        $renderer->wrappers['label']['container'] = 'div class="col-form-label"';
        $renderer->wrappers['control']['description'] = 'span class=form-text';
        $renderer->wrappers['control']['errorcontainer'] = 'span class=form-control-feedback';
        $renderer->wrappers['control']['.error'] = 'is-invalid';

        $renderer->wrappers['error']['container'] = 'div class="alert alert-danger"';
        $renderer->wrappers['error']['item'] = 'p"';

        foreach ($form->getControls() as $control) {
            $type = $control->getOption('type');
            if ($type === 'button') {
                $control->getControlPrototype()->addClass(empty($usedPrimary) ? 'btn btn-primary' : 'btn btn-secondary');
                $usedPrimary = true;
            } elseif (in_array($type, ['text', 'textarea', 'select'], true)) {
                $control->getControlPrototype()->addClass('form-control');
            } elseif ($type === 'file') {
                $control->getControlPrototype()->addClass('form-control-file');
            } elseif (in_array($type, ['checkbox', 'radio'], true)) {
                if ($control instanceof Nette\Forms\Controls\Checkbox) {
                    $control->getLabelPrototype()->addClass('form-check-label');
                } else {
                    $control->getItemLabelPrototype()->addClass('form-check-label');
                }
                $control->getControlPrototype()->addClass('form-check-input');
                $control->getSeparatorPrototype()->setName('div')->addClass('form-check');
            }
        }
        return $form;
    }
}
?>
<script>
parameters:


application:
	errorPresenter: Error
	mapping:
		*: App\*Module\Presenters\*Presenter


session:
	expiration: 14 days


services:
	router: App\Router\RouterFactory::createRouter
	- App\Forms\FormFactory
</script>
nightfish
Člen | 519
+
0
-

Službu mám zaregistrovanou v configu ale pořád mi vyskakuje chybová hláška.

Jaká chybová hláška ti vyskakuje? Jakým způsobem a kde továrnu voláš? (EDIT: aha, koukám, že jsem přehlédl chybovou hlášku v názvu diskuse).

Editoval nightfish (2. 9. 2019 20:01)

Martk
Člen | 661
+
0
-

A použití? Podle hlášky chceš FormFactory namísto App\Forms\FormFactory

iDome89
Člen | 27
+
0
-

Martk napsal(a):

A použití? Podle hlášky chceš FormFactory namísto App\Forms\FormFactory

Pouziti, jako tovarnu na tvorbu Formu bych jí chtěl.

Martk
Člen | 661
+
0
-

Myslel jsem to tak, ať tady pošleš celý kód, kde vyžaduješ onu FormFactory v konstruktoru

iDome89
Člen | 27
+
0
-

Martk napsal(a):

Myslel jsem to tak, ať tady pošleš celý kód, kde vyžaduješ onu FormFactory v konstruktoru

Momentálně mám jen část kódu, snažím se předělat předchozí presenter kde byl původní form, ve form tvořen pomocí továrny.
Hlavně moc nechápu jak se použivají továrny.

<?php

declare(strict_types=1);

namespace App\Presenters;

use Nette\Application\UI;

class HomepagePresenter extends UI\Presenter
{
     /** @var Nette\Database\Context */
     /** @var \FormFactory @inject */

     private $database;
     public $formFactory;

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

// tuto část potřebuju pozměnit //

    protected function createComponentCalculationForm(): UI\Form
    {
        $supplierList = $this->database->table("suppliers")->fetchPairs("id", "supp_name");
        $form = new UI\Form;
        $form->addSelect('supplier', 'Dodavatel:',$supplierList);
        $form->addText('quantity', 'Počet kusů:')
             ->setRequired()
             ->setHtmlType('number');
        $form->addText('price', 'Cena v Kč:')
             ->setRequired()
             ->setHtmlType('number');
        $form->addSubmit('calculate', 'Spočítat');
        $form->onSuccess[] = [$this, 'calculatePrice'];
        $form->addTextArea('result')
             ->setHtmlAttribute('class', 'totalPrice')
             ->setHtmlAttribute('readonly');
        return $form;
    }
    public function calculatePrice(UI\Form $form, \stdClass $values){
        $values=$form->getValues();
        $price= $values->price;
        $selectedSupp=$values->supplier;
        $quantity=$values->quantity;
        $modifier=$this->database->fetch('SELECT percentage FROM prices WHERE supplier_id = ? AND max >= ? AND min <= ?', $selectedSupp, $quantity, $quantity);
        $total=round($price + ($price / 100)* $modifier->percentage);
        return $form['result']->setValue("$quantity Ks, $total Kč + DPH");

    }

}
?>

Editoval iDome89 (2. 9. 2019 21:04)

artemevsin
Člen | 61
+
0
-

V té třídě v konstruktoru používáš \FormFactory, musíš použit \App\Forms\FormFactory. Teď ti to hledá třídu FormFactory v globálním namespace, ale (pravděpodobně) tu třídu máš v \App\Forms

<?php

declare(strict_types=1);

namespace App\Presenters;

use Nette\Application\UI;

class HomepagePresenter extends UI\Presenter
{
     /** @var Nette\Database\Context */
     /** @var \App\Forms\FormFactory @inject */

     private $database;
     public $formFactory;

     public function __construct(\Nette\Database\Context $database, \App\Forms\FormFactory $formFactory)
     {
         $this->database = $database;
     }
?>

Editoval artemevsin (2. 9. 2019 21:14)

iDome89
Člen | 27
+
0
-

artemevsin napsal(a):

V té třídě v konstruktoru používáš \FormFactory, musíš použit \App\Forms\FormFactory. Teď ti to hledá třídu FormFactory v globálním namespace, ale (pravděpodobně) tu třídu máš v \App\Forms

<?php

declare(strict_types=1);

namespace App\Presenters;

use Nette\Application\UI;

class HomepagePresenter extends UI\Presenter
{
     /** @var Nette\Database\Context */
     /** @var \App\Forms\FormFactory @inject */

     private $database;
     public $formFactory;

     public function __construct(\Nette\Database\Context $database, \App\Forms\FormFactory $formFactory)
     {
         $this->database = $database;
     }
?>

Pokud to upravím tak, tak mi to hází jinou hlášku :

Nette\DI\ServiceCreationException

Service ‚01‘: Class App/Forms/FormFactory not found

Marek Bartoš
Nette Blogger | 1280
+
0
-

Service ‚01‘: Class App/Forms/FormFactory not found

Třída nenalezena – nejspíš ji nenajde autoloader. U robotloaderu je třeba smazat cache, u composer classmapy udělat dump, u composer psr-4 musí sedět struktura složkaXnamespace (předpokládám, že používáš výchozí variantu, robotloader, takže zkus smazat cache)

Též máš chybu ve třídě

/** @var Nette\Database\Context */
/** @var \App\Forms\FormFactory @inject */

private $database;
public $formFactory;

správně je to takto

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

/** @var \App\Forms\FormFactory @inject */
public $formFactory;

Anotace vždy k proměnné, které se týkají.

Editoval Mabar (2. 9. 2019 22:05)

Marek Bartoš
Nette Blogger | 1280
+
0
-

Celá ta třída je nějaká rozbitá. Pro získání závislostí se používá buď __construct(), nebo inject* metoda, nebo @inject anotace. Ty tam teď máš jak inject, tak konstruktor a ještě v konstruktoru nepřiřazuješ proměnou.

Udělej si službu a pořiď si phpstorm. Pomůže ti odhalit hromady chyb.

iDome89
Člen | 27
+
0
-

Mabar napsal(a):

Celá ta třída je nějaká rozbitá. Pro získání závislostí se používá buď __construct(), nebo inject* metoda, nebo @inject anotace. Ty tam teď máš jak inject, tak konstruktor a ještě v konstruktoru nepřiřazuješ proměnou.

Udělej si službu a pořiď si phpstorm. Pomůže ti odhalit hromady chyb.

Díky moc za pomoc a rady, kouknu se jakmile se dostanu k PC doma, pořád mám problém pochopit DI tak to zkouším do kola.

iDome89
Člen | 27
+
0
-

Mabar napsal(a):

Celá ta třída je nějaká rozbitá. Pro získání závislostí se používá buď __construct(), nebo inject* metoda, nebo @inject anotace. Ty tam teď máš jak inject, tak konstruktor a ještě v konstruktoru nepřiřazuješ proměnou.

Udělej si službu a pořiď si phpstorm. Pomůže ti odhalit hromady chyb.

PhpStorm jsem si sehnal, ale stale mam problem přesto že mi přijde že mám vše v pořádku, Nechápu proč mi to nevidí class FormFactory..

<?php

declare(strict_types=1);

namespace App\Presenters;

use Nette\Application\UI;
use Nette\Forms;

class HomepagePresenter extends UI\Presenter
{
     private $database;
     public $formFactory;

     public function __construct(\Nette\Database\Context $database, \App\Forms\FormFactory $formFactory)
     {
         parent::__construct();
         $this->database = $database;
         $this->formFactory=$formFactory;

     }
?>
Šaman
Člen | 2667
+
+1
-

A co ti to teď píše za hlášku? Zkus to hodit někam, kde si můžm projít zdrojáky (GitHub) a napiš co to aktuálně hází za chybu. Někde je zakopán pes, ale já ho v těch nasílených kuseh kódu nevidím.

Jestli je to stále Nette\DI\ServiceCreationException Service ‚01‘: Class App/Forms/FormFactory not found, pak je to v nastavení RobotLoaderu, nebo v nějaké netradiční adresářové struktuře.

iDome89
Člen | 27
+
0
-

Šaman napsal(a):

A co ti to teď píše za hlášku? Zkus to hodit někam, kde si můžm projít zdrojáky (GitHub) a napiš co to aktuálně hází za chybu. Někde je zakopán pes, ale já ho v těch nasílených kuseh kódu nevidím.

Jestli je to stále Nette\DI\ServiceCreationException Service ‚01‘: Class App/Forms/FormFactory not found, pak je to v nastavení RobotLoaderu, nebo v nějaké netradiční adresářové struktuře.

Ano je to pořád ta stejná chyba, zkusim to hodit na github.

https://github.com/…89/NetteTest

Editoval iDome89 (3. 9. 2019 21:57)

Šaman
Člen | 2667
+
0
-

Zkusil jsem ten kód na localu a funguje. Teda, musel jsem si tam dát local.neon s databází a pak se mi to samozřejmě seklo na tom, že mi chybí patřiné tabulky v databázi. Ale to znamená, že aplikace už byla úspěšně sestavená.
Zkus vymazat cache.

iDome89
Člen | 27
+
0
-

Cache jsem vymazal už minimálně 3× když jsem to zkoušel, tak nevim uz kde hledat problém

Šaman
Člen | 2667
+
0
-

V tom local.neon máš jenom databázi? Nebo máš ho tam vůbec? Na GitHubu chybí. To je jediná změna, kterou jsem na tom sdíleném kódu dělal.

Jinak tu FormFactory bych dal jinam, než pod Presentery, ale to jen kvůli přehlednosti, na funkci to nemá vliv. RobotLoader ji tam musí bez problémů najít.

iDome89
Člen | 27
+
0
-

Ano, v local.neon mam jenom db a nic vic, nevim proč ho tam git nenatahal.

Šaman
Člen | 2667
+
+1
-

Jestli jsi to tahal přes git, tak ho nenatáhl kvůli .gitignore v rootu. V tom lokálním configu jsou hesla pro databázi a v případě více vývojářů může mít každý hesla jiná, tak nemá být verzován. (Je to složitější, ale ve zkratce to snad stačí. Prostě v tom local jsou věci, které mohou být na každém stroji nastavené jinak.) Když ho chceš verzovat, dělá se to tak, že verzuješ nějaký local.neon.example, kde je ukázáno, co všechno ma obsahovat. Ale bez hesel a bez citlivých informací. Při nasazení si ho programátor zkopíruje (nepřejmenuje, originál musí zůstat) na local.neon a doplní tam údaje podle sebe.

Většinou jsou v tom .gitignore i adresáře od NetBeans a PhpStorm (ona .idea) a vendor. I když zrovna co se vendoru týče, jsou argumenty i pro to ho verzovat, takže cajk.

Nicméně opakuji, že chybu v injectování FormFactory tam nevidím a při pokusu o spuštění mi naběhla Tracy už normálně do kódu HomepagePresenteru s tím, že nemůže v databázi najít nějakou tabulku. (Kterou jsem tam samozřejmě neměl. Pokud bys někdy chtěl opravdu sdílet aplikaci, přidej ještě verzovaný adresář alespoň s dumpem databáze s testovacími daty, pak lze i aplikaci rozběhnout). Tím chci říct, že aplikace se (na Windows10 + XAMPP) složila správně a fáze sestavování DI kontejeru proběhla bez chyby. Zkus si to natáhnout z toho GitHubu třeba do nového adresáře. Nevím, kde je chyba, ale vypadá to na něco mimo GitHub. Což je hlavně adresář Temp.

Editoval Šaman (4. 9. 2019 13:28)