Největší záseky v Nette – drobnosti, na kterých se dá viset i několik hodin
- David Grudl
- Nette Core | 8228
fizzy napsal(a):
Dost casto sa mi stava, ze premena z cyklu foreach mi prepise nejaku hodnotu z presenteru.
Taky se mi to párkrát stalo, zkusil jsem přidat varování a uvidíme, jak se to osvědčí.
(tyjo… už jsem tím našel chybu v jednom projektu :-) )
Šaman napsal(a):
Že si framefork zabere takhle běžné slovo proměnnou, to si myslím, že není slušné. Takže:
Framework ji nepoužívá a tedy ani nezabírá.
- Šaman
- Člen | 2665
David Grudl napsal(a):
Šaman napsal(a):
Že si framefork zabere takhle běžné slovo proměnnou, to si myslím, že není slušné. Takže:
Framework ji nepoužívá a tedy ani nezabírá.
Aha, ok. Takže se můžeme spolehnout na to, že framework používá jen
proměnné s podtržitkem? (_presenter
, _control
) a
že pokud by to vyžadoval framework, tak si zavede svůj
_user
?
I když stále to neřeší to, že ve výpisu uživatelů, nebo na jeho detailu (což je skoro v každém projektu) nemohu použít
{foreach $users as $user} ... {/foreach}
ani přiřadit v presenteru $this->template->user
, aniž
bych tím neporušil defaultní chování, se kterým mohou ostatní
programátoři počítat. Teoreticky se to týká všech „obsazených“
proměnných, ale u těch ostatních jsem ještě nikdy nenarazil na kolizi
(control
, presenter
, netteHttpResponse
,
netteCacheStorage
, baseUri
, basePath
,
flashes
a ten user
).
@DavidGrudl: Jak to řešíš třeba na výpisu uživatelů, nebo na
detailu uživatele? Přepíšeš tu defaultní proměnnou, nebo používáš
něco jako $myUser
, což mi přijde ošklivé řešení? Nebo
doporučuješ úplně jinou cestu? V tomhle jsem si zatím nedokázal najít
best practise, se kterým bych byl spokojený.
- David Grudl
- Nette Core | 8228
Co vím, tak používá jen podtržítkové proměnné a netteCacheStorage.
{foreach ... as $user}
jsem asi nikdy nepoužil.
- Šaman
- Člen | 2665
CZechBoY napsal(a):
Předávání User do šablony.
https://api.nette.org/…ory.php.html#90
Jestli to je odpověď na Davidovo „Framework ji nepoužívá a tedy ani
nezabírá.“, tak on asi opravdu mluví jen o nepoužívání. Tedy, pokud si
toho usera přepíšu, tak framework bude fungovat dál. Problém nastane, pokud
někde dál budu třeba testovat, zda je $user->isLoggedIn()
,
ale to už je tak trochu moje chyba.
Ale stejně na to opakovaně narážím. Vzhledem k
sandboxu/web-projectu
a veškeré dokumentaci nechci tu proměnnou
přepisovat (většina programátorů s ní počítá a většinou si myslí
i že je to nativní chování Nette) – kdybych ji přepsal, zadělal bych
na big WTF. A pokud zároveň pracuji třeba s pravou entitou
User
, tak pro ni musím vymýšlet zvláštní jméno a stejně pak
často omylem napíšu $this->user
a myslím tím tu entitu.
- ic
- Člen | 430
Začal jsem používat pojmenování proměnných tvořených foreachem jako
$item
. A postupem času si na to docela zvykl. Nebylo to
z důvodu vyhnutí se problému s náhodným přejmenováním nějaké
proměnné, ale prostě z lenosti, když mi to IDE ten cyklus takto napovídá,
tak to použiji a s přejmenováváním si už hlavu nedělám :) . Pak vím,
že mám v tom cyklu $iterator
a $item
a je to
takové … všude pěkně stejné.
{foreach $foo as $item}
.
.
.
Problém jedině, když je třeba více vnořených cyklů, což ale není zase tak často… pak si to tedy pojmenuji nějak hezky.
- Pavel Kravčík
- Člen | 1196
{if $article}
<div class="page-header">
<h1 n:block="title">{$article->title}</h1>
{<small>{$article->date|date:'d.m.Y'}</small>}
</div>
<div class="perex">
{$article->perex}
</div>
<div class="text">
{$article->text}
</div>
{else}
Hlavní článek není zadán
{/if}
Pěkná chvilka, když n:block ignoruje if. :)
Editoval Pavel Kravčík (6. 12. 2015 22:20)
- Michal Hlávka
- Člen | 190
Latte – pokud přistupuju k sloupci v databázi, který nabývá hodnoty null, sloupec neexistuje a vyhodí vyjímku
- Eda
- Backer | 220
Právě jsem se dost zasekl na jedné věci a vzpomněl jsem si na tohle vlákno, tak třeba s tím půjde něco udělat :-)
Jde o použití generované továrny, která má metodu create s jedním parametrem, který pak má předat do konstruktoru vytvářené komponenty.
config.neon:
catalogSearchRendererControlFactory: ICatalogSearchRendererControlFactory
Interface pro továrnu:
interface ICatalogSearchRendererControlFactory extends IRendererFactory
{
/**
* @param SearchResult $searchResult
* @return CatalogSearchRendererControl
*/
public function create(SearchResult $searchResult);
}
Komponenta:
class CatalogSearchRendererControl extends AbstractControl
{
/**
* @param SearchResult $result
*/
public function __construct(SearchResult $result)
{
...
}
}
Když takový kód spustím, dostanu od laděnky nadělení v podobě
chyby:
`Nette\DI\ServiceCreationException:
Service ‚catalogSearchRendererControlFactory‘: Service of type SearchResult
needed by CatalogSearchRendererControl::__construct() not found. Did you
register it in configuration file?`
Chyba je samozřejmě v tom, že název proměnné v rozhraní pro továrnu neodpovídá názvu parametru v konstruktoru, takže Nette si to „nematchne“, a tak se snaží ten argument autowirovat. Samozřejmě ho ale nenajde, takže to spadne.
Ta hláška ale není moc návodná.
Všechno se to děje v compile-time. Nestálo by za to tam přidat nějaký check na podchycení těchto situací? Co dělal jsem si miniprůzkum a nejsem sám, kdo se na tom někdy zasekl.
- Felix
- Nette Core | 1245
Eda napsal(a):
Chyba je samozřejmě v tom, že název proměnné v rozhraní pro továrnu neodpovídá názvu parametru v konstruktoru, takže Nette si to „nematchne“, a tak se snaží ten argument autowirovat. Samozřejmě ho ale nenajde, takže to spadne.
Ta hláška ale není moc návodná.
Všechno se to děje v compile-time. Nestálo by za to tam přidat nějaký check na podchycení těchto situací? Co dělal jsem si miniprůzkum a nejsem sám, kdo se na tom někdy zasekl.
Nedavno se mi stala podobna chyba a netusil jsem cim to je.
U me to bylo klasickym form
vs fomr
.
interface FooControlFactory
{
/**
* @param Form $form
* @return FooControl
*/
public function create(Form $form);
}
class FooControl
{
/**
* @param Form $form
*/
public function __construct(Form $fomr)
{
}
}
- David Matějka
- Moderator | 6445
https://forum.nette.org/…ikace-modely
mohlo by tam byt explicitne napsano, ze konstruktor je private, hlaska
Class App\Modules\SMSModule\Models\SMSModel used in service ‚SMSModel‘ not found or is not instantiable.
svadi spise k tomu, ze budu hledat, proc to tu tridu nenaslo
- Casper
- Člen | 253
Issue už tady bylo před rokem, zajímavý je komentář od enumaga.
Editoval Casper (1. 3. 2016 10:13)
- CZechBoY
- Člen | 3608
Tak jsem zjistil další zajímavost a to při přidávání routy.
$router[] = new Route('<presenter>/<action>[/<id]');
Všimne si někdo chyby, kvůli které Nette vygeneruje url např.
/homepage/default?id=1
, místo očekávaného
/homepage/default/1
?
Ano, chybějící zobáček „>“ za to může.
- Michal Hlávka
- Člen | 190
Pokud filter metoda nic nevrací, vypíše se, že filter není definovaný, i když je a Nette ho zavolalo. Celou dobu koukám na to, proč není definovaný, ale pak jenom zjistím, že switch nemám v plném rozsahu a tudiž mi nic nevrací.
- David Grudl
- Nette Core | 8228
Croc napsal(a):
emptywall napsal(a):
Latte – pokud přistupuju k sloupci v databázi, který nabývá hodnoty null, sloupec neexistuje a vyhodí vyjímku
Přesně, tohle mě taky dosti potrápilo… A né jednou…
Pokud má hodnotu NULL, vrátí NULL a nevyhazuje výjimky.
- ali
- Člen | 342
Davide, kdyz je filter zaveden pres config takto, tak ano
latte.latteFactory:
setup:
- addFilter(NULL, [App\Service\Filters(), loader])
class Filters
{
public static function loader(string $filter)
{
return (method_exists(__CLASS__, $filter) ? call_user_func_array([__CLASS__, $filter], array_slice(func_get_args(), 1)) : NULL);
}
- David Grudl
- Nette Core | 8228
Teď tomu nerozumím, míchají se tu sloupce v databázi s filtry v Latte.
Takže pokud má sloupec hodnotu NULL, databáze rozhodně nevyhodí výjimku, že sloupec neexistuje. Reaguji na https://forum.nette.org/…ekolik-hodin?p=2
ad Latte: pokud loader filtru vrací NULL, tak se zkusí další loader
v pořadí, což je příčina https://forum.nette.org/…ekolik-hodin?p=2.
Hraje tu roli názvosloví, nebavíme se o filtru, ale o loaderu,
o návratové hodnotě loaderu. Sice je možné, aby loader vrátil hodnotu a
ta se brala jako výsledek filtru, ale loader by měl především filtr
načíst, tedy zavolat addFilter
, třeba kvůli výkonnosti.
A filtr klidně může vracet NULL.
Takže config bych upravil na:
latte.latteFactory:
setup:
- addFilter(NULL, [Filters(@self), loader])
a loader na:
class Filters
{
private $latte;
public function __construct(Latte\Engine $latte)
{
$this->latte = $latte;
}
public function loader(string $filter)
{
if (method_exists(__CLASS__, $filter)) {
$this->latte->addFilter($filter, [__CLASS__, $filter]);
}
}
- Michal Hlávka
- Člen | 190
@DavidGrudl asi jsme se jenom nepochopili – http://i.imgur.com/Q27ompb.jpg
Edit: až teď mi dochází, že tu každej motá jedno téma s druhým.
Editoval emptywall (29. 6. 2016 13:03)
- Michal Hlávka
- Člen | 190
David Grudl napsal(a):
Croc napsal(a):
emptywall napsal(a):
Latte – pokud přistupuju k sloupci v databázi, který nabývá hodnoty null, sloupec neexistuje a vyhodí vyjímku
Přesně, tohle mě taky dosti potrápilo… A né jednou…
Pokud má hodnotu NULL, vrátí NULL a nevyhazuje výjimky.
Teď jsem to zkoušel a je to jak říkáš. Už si přesně nepamatuju jak se mi to v té době povedlo, ale vím, že to tak bylo. Zkusím to příště víc rozepsat co pro to všechno člověk musí udělat. :-)