Class FormFactory needed by $formFactory in __construct() not found. Check type hint and ‚use‘ statements. sea
- iDome89
- Člen | 27
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>
- iDome89
- Člen | 27
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
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
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
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
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
Mabar napsal(a):
Celá ta třída je nějaká rozbitá. Pro získání závislostí se používá buď
__construct()
, neboinject*
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
Mabar napsal(a):
Celá ta třída je nějaká rozbitá. Pro získání závislostí se používá buď
__construct()
, neboinject*
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
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
Š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
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.
- Šaman
- Člen | 2667
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)