Největší záseky v Nette – drobnosti, na kterých se dá viset i několik hodin

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

Všichni to známe. Někde přebývá nebo chybí jeden, dva znaky. Kde je malé písmeno, má být velké. A podobně. Chyby, které člověk snadno přehlídne a stráví na tom někdy i hodiny, než na to přijde.

<!-- velké písmeno na začátku názvu komponenty, skóre: asi 8 hodin (kdysi v začátcích s Nette),
chování: komponenta neexistuje, ačkoliv v presenteru je nadefinovaná -->
{control myComponent} <!-- funguje -->
{control MyComponent} <!-- nefunguje -->
<!-- mezera před tečkou, chování: část za mezerou se tiše ignoruje -->
{_'firstPart'.$secondPart} <!-- funguje -->
{_'firstPart' . $secondPart} <!-- nefunguje -->
// chybějící "[]", skóre: asi 2 h, chování: nezavolá se callback po úspěšném odeslání formuláře
$myForm->onSuccess[] = $presenter->myFormSucceeded; // funguje
$myForm->onSuccess = $presenter->myFormSucceeded; // nefunguje

Máte další podobné kousky?

Editoval chikeet (7. 3. 2015 7:02)

Jan Tvrdík
Nette guru | 2595
+
+2
-

Díky za sepsání, kouknu, jestli by se s tím nedalo něco dělat.

Vojtěch Dobeš
Gold Partner | 1316
+
+6
-

{_'firstPart' . $secondPart} by mělo fungovat ve 2.3.

enumag
Člen | 2118
+
+11
-
  1. Nebylo by lepší komponenty s velkým prvním písmenem prostě zakázat a házet výjimku?
  2. Viz co napsal Vojta.
  3. Pokud jde o eventy, asi by se dala přidat výjimka při volání eventu pokud ta property není pole a neimplementuje ArrayAccess (to kvůli Kdyby\Events).
Zax
Člen | 370
+
+1
-

Já se před pár dny totálně zamotal do trochu složitější továrny na komponentu a hrozně se divil, proč pořád dostávám error bad gateway :-D

Zjednodušeně můj kód vypadal cca takto:

function createComponentCarousel() {
	$control = $this->carouselFactory->create();
	$control->onSomething[] = function() {
		$this['carousel']->doSomethingElse();
	};
	return $control;
}

Kód tý továrny byl mnohem delší a tak můj mozek postupně vypustil informaci, že pracuji v továrně pro komponentu „carousel“ a vůbec mi nedošlo, že místo $this['carousel'] (neboli $this->getComponent('carousel')) bych měl zavolat prostě $control. Kód se hezky zacyklil a přestalo to fungovat. Asi dvě hodiny jsem do toho zíral, zkoušel různě přepisovat anonymní funkce apod. pak jsem si odskočil na oběd a když jsem se vrátil, tak mi to hned docvaklo.

Jojo, někdy ty nejmenší problémy jsou ve skutečnosti ty největší…

F.Vesely
Člen | 369
+
+2
-

To ja se zasekl na tomto:

function actionEdit($id){
	...
	$this['form']->setValues($array);
}

...

function formSucceeded($form, $values){
	...
	$this->em->flush();
	$this->redirect('this');
}

Zkusim to a data se nezmenila. Podivam se do Tracy na dotazy a jelikoz pouzivam Doctrine, tak tam nebyl zadny update. Nejdrive jsem tedy podezrival Doctrine, ale po chvilce jsem zjistil, ze Doctrine dostava stara data. Tak jsem prochazel a debugoval Nette Form, nechapal jsem, proc http data maji nova data, ale ve values jsou stara. Nakonec jsem si ve vedlejsim okne otevrel druhy Presenter, kde to fungovalo a porovnaval jsem. Nyni tu mam na papire velkym pismem napsane, ze setValues() != setDefaults().

ali
Člen | 342
+
+1
-

Tak sem prispeju dneska jednu zajimavou perlicku

zjednoduseny model

namespace App\Model;

use Nette\Security\User;

...

public function __construct(User $user)
{
  $this->user = $user;
	...

Tracy: Cannot use Nette\Security\User as User because the name is already in use

Po hodinovem zkoumani kde je chyba sem prepsal model a zacalo to normalne fungovat.. dal jsem neresil

public function __construct(\Nette\Security\User $user)
{
  $this->user = $user;
	...

.. po cca mesici jsem se k tomu dneska vratil a az dneska me trklo, ze v namespace App\Model uz mam tridu User :-)

David Grudl
Nette Core | 8228
+
+2
-

Jo, tohle je hrubá prasárna PHP…

enumag
Člen | 2118
+
+8
-

A co je ještě horší, PHP to někdy nechá projít a ten Fatal Error nevyhodí. Pak ti ta chyba vyskočí někdy později když pracuješ na něčem úplně jiném.

Imho by to ten Fatal Error ani nemělo způsobovat, samozřejmě s výjimkou případu kdy ta konfliktní třída je ve stejném souboru.

chikeet
Člen | 160
+
+7
-

Tak se mi dnes povedlo v latte:

<a href="{$entity->getOrderUrl()">Objednat</a>

Vtip je v chybějící složené závorce za getOrderUrl(). Výsledek: The connection was reset. Úplně největší sranda je, že když si toho nevšimnete, tak apache občas spadne a občas ne a to i beze změny v šabloně. Latte plugin to bohužel nezvýrazní jako chybu, tak se to blbě hledá. Třeba se bude někomu hodit.

David Grudl
Nette Core | 8228
+
+11
-

chikeet napsal(a):

<!-- velké písmeno na začátku názvu komponenty, skóre: asi 8 hodin (kdysi v začátcích s Nette),
chování: komponenta neexistuje, ačkoliv v presenteru je nadefinovaná -->
{control myComponent} <!-- funguje -->
{control MyComponent} <!-- nefunguje -->

Pokud je komponenta definovaná s velkým písmenem, např. pomocí $this['MyComponent'] = ..., bude fungovat i {control MyComponent}. Každopádně příští verze Nette bude vyhazovat výjimku Component with name 'MyComponent' does not exist, did you mean 'myComponent'?.

<!-- mezera před tečkou, chování: část za mezerou se tiše ignoruje -->
{_'firstPart'.$secondPart} <!-- funguje -->
{_'firstPart' . $secondPart} <!-- nefunguje -->

To se mi nezdá, z pohledu Latte v tom není žádný rozdíl a musí fungovat obojí stejně.

// chybějící "[]", skóre: asi 2 h, chování: nezavolá se callback po úspěšném odeslání formuláře
$myForm->onSuccess[] = $presenter->myFormSucceeded; // funguje
$myForm->onSuccess = $presenter->myFormSucceeded; // nefunguje

Doplnil jsem, aby to vyhodilo výjimku.

CZechBoY
Člen | 3608
+
+2
-

Zajímavá je taky konstrukce v Latte:
{if !empty(mojePromennaBezDolaru)}...{/if}, kdy Latte doplní okolo stringu apostrofy.
Já potom můžu hledat hodiny :-)

Michal Hlávka
Člen | 190
+
+1
-

Já se docela dost zarazil nad tímhle. Posílám do šablony pole

$data = ['foo' => 'bar']

V šabloně mám $data|getFoo

Filter mám napsaný takhle

public static function getFoo(array $data) {
	return $data['foo'];
}

V šabloně pak tedy použiju

{if $data|getFoo == 'asnifdisafniefniweiof'}Tahle podmínka mi projde{/if}

Editoval emptywall (7. 10. 2015 16:02)

Michal Hlávka
Člen | 190
+
-1
-

Doplním ještě o jeden příspěvek, zůstaneme u stejného příkladu, který jsem uváděl předtím.

Tohle mi Latté bez problému uzná

{if $data|getFoo())))))))))))))))) =========== 'asnifdisafniefniweiof'}Tahle podmínka mi projde{/if}

Editoval emptywall (7. 10. 2015 16:08)

David Grudl
Nette Core | 8228
+
0
-

tohle Latte zatím neumí

{if $data|getFoo …

Takže | je operátor bitové OR z PHP http://php.net/….bitwise.php

Je fakt, že by to mělo vyhodit výjimku.

Michal Hlávka
Člen | 190
+
0
-

David Grudl napsal(a):

tohle Latte zatím neumí

{if $data|getFoo …

Takže | je operátor bitové OR z PHP http://php.net/….bitwise.php

Je fakt, že by to mělo vyhodit výjimku.

To je sice fakt, ale jako začátečník, který si čerstvě přečetl dokumentaci, jsem to bral jako výraz pro použití filtru a nedošlo mi, že to bere jako operátor.

Lukes
Silver Partner | 68
+
0
-

David Grudl napsal(a):

tohle Latte zatím neumí

{if $data|getFoo …

Takže | je operátor bitové OR z PHP http://php.net/….bitwise.php

Je fakt, že by to mělo vyhodit výjimku.

No zase je blbost vyhazovat výjimku při bitovém ORu v podmínce. Ono sem tam se to může hodit… Takže by se to mělo omezit jen na to, když je to očividně filtr…

David Grudl
Nette Core | 8228
+
+9
-

To s tím bitovým OR jsem škrtnul, nejde o bitový OR, ale o to, že makra jako {if} modifikátory nepoužívají a tudíž je ignorují. Upravil jsem to, aby to místo ignorování vyhodilo varování nebo výjimku.

CZechBoY
Člen | 3608
+
+1
-
{if $cond}
 ...
{else if $cond2}
 ...
{else}
 ...
{/if}

se přeloží jako

if ($cond) {
 ...
} else {
 ...
} else {
 ...
}

Nešlo by přidat možnost použít i makro {else if}?

Pavel Kravčík
Člen | 1196
+
+3
-

{elseif} funguje. {else if} by mělo házet warning místo makra.

looky
Člen | 99
+
+11
-

CZechBoY napsal(a):

Nešlo by přidat možnost použít i makro {else if}?

Spíš by to chtělo „Unknown macro {else if}, did you mean {elseif}?“ :)

David Grudl
Nette Core | 8228
+
+11
-

@looky done

potapnik
Člen | 127
+
+1
-

Tak se přidávám s aktualitou, která mě stála dvě hodiny času a nakonec to byla jenom drobnost. Testuju Testerem následující (je to hodně ořezaný):

<?php

$response = Json::decode($rawResponse);

$testPeak = [
	'item' => 'amount',
	'peak' => 1000
]

Assert::contains($testPeak, $response);

?>

A Tester hlásí chybu. Fajn, zapnu laděnku, nechám projet testy a otevřu si v logu Exception. A koukám na to jako vejr. Ty pole by se měly rovnat, sedí to. Čísla jsou stejný. (…hodina, dvě zkoušení všeho možného…) A pak zjistím, že ta peak hodnota v JSONU je float, ale v laděnce po rozkliknutí parametrů funkce vypadá jako int (tedy bez dvou 0 za desetinnou čárkou).

David Kudera
Člen | 455
+
+1
-

@potapnik A tobě tester nevytvořil soubory *.actual a *.expected? V nich by to mělo jít vidět ihned na první pohled totiž.

Editoval David Kudera (19. 10. 2015 11:32)

David Grudl
Nette Core | 8228
+
+8
-

@potapnik Tester to IMHO zobrazuje správně, tedy jako 1000.0, například v souborech .actual a .expected, jak zmiňuje @DavidKudera. Díky za upozornění na chybu v Tracy, při převodu do JavaScriptu to v tomto případě oseklo desetinnou čárku. Opraveno.

potapnik
Člen | 127
+
0
-

@DavidGrudl díky za tu opravu v Tracy :-) ano, v těch actual/expected je to správně, já errory v testech kontroluji přes Tracy, protože tam mám kompletní stav aplikace, a někdy se mi stává, že chyba není přímo v testu, ale kódu okolo něj a v tom případě je Tracy nenahraditelná :-) ještě jednou díky :-)

vvoody
Člen | 910
+
+2
-

Žiadny hodinový zásek, len proste vždy napíšem link na handler ako !delete namiesto delete!. Niekto ďalší okrem mňa? Poraďte nejakú memotechnickú pomôcku ako to písať vždy na prvý krát správne :D

greeny
Člen | 405
+
+16
-

@vvoody taky jsem to občas dělal, jednoduchá pomůcka – „zařveš“ na Nette, ať něco udělá (signál). Taky voláš „Smaž!“ a ne „!Smaž“

Pavel Janda
Člen | 977
+
0
-

Zdravím,

zajímavou chybovou hlášku:

Fatal Error

Class 'Templatea9636150a3bb8db31dd1bbff601c03aa' not found

vyhodí Latte, pokud mám vypnutou cache a zapomenu v

n:class="$var ? class, bla buu"

Editoval Pavel Janda (5. 11. 2015 10:37)

ic
Člen | 430
+
+1
-

Zapomenuté ukončení řetězce v latte dělá docela špatně idenfitikovatelné problémy {var $lol = 'text} nebo {dump 'text} způsobí to, že server neodpoví … nevrátí ani třeba chybu 500… prostě nic. Takže prohlížeč uživateli řekne, že je server úplně nedostupný ERR_CONNECTION_RESET.

ic
Člen | 430
+
0
-

@DavidMatějka jáj, to je zase tohle… pardon. Mám to zazáložkované, ohvězdičkované a stejně na často narážím :)

David Grudl
Nette Core | 8228
+
+2
-
David Grudl
Nette Core | 8228
+
+4
-
iNviNho
Člen | 352
+
0
-

Dneska som cez hodinu sa snažil prísť na to, prečo injectnuty interface je null

<?php
/* @var \App\Interfaces\IImageService @inject */
public $iImageService;
// a následne volanie
$image $this->iImageService->create($client["logo"]);
?>

Chyba je v injectovaný, chýba tam druhá hviezdička naa začiatku

Editoval iNviNho (13. 11. 2015 12:05)

David Grudl
Nette Core | 8228
+
+3
-

@iNviNho na to se dá použít Code Checker.

Tomáš Votruba
Moderator | 1114
+
+1
-

@iNviNho Z tvého zápisu je to opravdu těžké najít. Pokud bys používal blokový zápis, je to vidět hned.

/*
 * @var \App\Interfaces\IImageService
 * @inject
 */
public $iImageService;
Šaman
Člen | 2665
+
0
-

A ještě existuje jeden ukazatel, který napoví, že něco není v pořádku. Pokud používáš vhodné IDE, tak zápis @var Type v phpDoc anotaci ti zajistí napovídání. Pokud ti něco špatně napovídá, nebo nenapovídá vůbec, je pravděpodobně někde chyba.
Jinak tohle ani tak moc nesouvisí s Nette, tohle je univerzální. S jednou hvězdičkou je to běžný komentář, se dvěma je to phpDoc anotace. Když o tom ale teď přemýšlím, nebylo by špatné, kdyby to IDE uměly detekovat a pro anotaci použily jiné barvy, než pro komentář. Aspoň NetBeans to neumí. Ale napovídá správně.


Jen pro zajímavost mám další na první pohled špatně objevitelnou chybu, takovou specialitku. Používám speciální rozložení klávesnice CSHack, která umí pomocí kombinace kláves napsat i typografické znaky. A pod mezerníkem je i nedělitelná mezera a jednou za čas se mi ji podaří napsat místo normální. PHP ji ale nebere jako mezeru, takže v opticky zcela prostém a bechybném kódu mi vyhodí chybu. Naštěstí to IDE podrhne, ale mimo IDE je to prakticky neobjevitelné. Jestli máte nějakého opravdu úhlavního nepřítele programátora, tak mu pár mezer nahraďte nedělitelnýma (nebo mínusy pomlčkama, ale tam je drobný rozdíl v délce). Ale pozor – je to už tak evil, že z toho klesá karma a umírají koťátka…

David Grudl
Nette Core | 8228
+
0
-

@Šaman můžeš na to přidat filtr do Code checkeru, že mimo komentáře a řetězce se můžou vyskytovat jen znaky v rozsahu 32–127, je to na pár řádků.

Pavel Macháň
Člen | 282
+
+1
-

Šaman napsal(a):

A ještě existuje jeden ukazatel, který napoví, že něco není v pořádku. Pokud používáš vhodné IDE, tak zápis @var Type v phpDoc anotaci ti zajistí napovídání. Pokud ti něco špatně napovídá, nebo nenapovídá vůbec, je pravděpodobně někde chyba.
Jinak tohle ani tak moc nesouvisí s Nette, tohle je univerzální. S jednou hvězdičkou je to běžný komentář, se dvěma je to phpDoc anotace. Když o tom ale teď přemýšlím, nebylo by špatné, kdyby to IDE uměly detekovat a pro anotaci použily jiné barvy, než pro komentář. Aspoň NetBeans to neumí. Ale napovídá správně.

@Šaman PhpStorm má jinou barvu pro komentář a jinou pro anotace viz IMG (sorry za velikost img :D … retina)

Editoval Pavel Macháň (14. 11. 2015 17:52)

Šaman
Člen | 2665
+
+1
-

Pavel Macháň napsal(a):

@Šaman PhpStorm má jinou barvu pro komentář a jinou pro anotace viz IMG (sorry za velikost img :D … retina)

Tak se omlouvám za dezinformaci. NetBeans sice nezvýrazní celou phpDoc sekci, ale anotace zýrazní (defaultně tak, že je vypíše tučné). Dá se nastavit i výraznější rozlišení. Pokud se zapomene druhá hvězdička, tak k žádnému zvýraznění anotačních keywords nedojde.

David Matějka
Moderator | 6445
+
0
-

@PavelMacháň u jednoradkovych to bohuzel nerozlisuje :(

Pavel Macháň
Člen | 282
+
0
-

David Matějka napsal(a):

@PavelMacháň u jednoradkovych to bohuzel nerozlisuje :(

@DavidMatějka Jseš si jistý? IMG1 IMG2

Editoval Pavel Macháň (14. 11. 2015 18:46)

Šaman
Člen | 2665
+
0
-

Pavel Macháň napsal(a):

David Matějka napsal(a):

@PavelMacháň u jednoradkovych to bohuzel nerozlisuje :(

@DavidMatějka Jseš si jistý? IMG1 IMG2

Ale na tom druhém obrázku jsou dva komentáře. Jak to, že je to zeleně (i jen s jednou hvězdičkou)?

David Matějka
Moderator | 6445
+
+1
-

@PavelMacháň no vzdyt jo, u IMG2 mas jen 1 * a je to zvyrazneny jak phpdoc

@Šaman vypada to, ze to rozlisuje dle toho, jestli je tam @

fizzy
Backer | 49
+
+2
-

Dost casto sa mi stava, ze premena z cyklu foreach mi prepise nejaku hodnotu z presenteru.

Priklad:

1. mam layout v ktorom je menu s kategoriami a vypisujem ich

{foreach $categories as $category} ... {/foreach}

2. mam nejaku podstranku pre kazdu kategoriu, v presenteri si samozrejme nastavim

$this->template->category = $nejakaKategoria;

a v sablone si vobec neuvedomi clovek, ze v layoute je uz taka premenna pouzita :D takze mi to vypise poslednu kategoriu z menu a nie kategoriu na ktorej aktualne sa nachadzam :D

Mozno by bolo dobre implementovat nejake upozornenie, nestalo sa mi to prvy krat. Mal niekto podobny problem?

CZechBoY
Člen | 3608
+
0
-

@fizzy Proč vlastně máš seznam kategorií a ještě konkrétní kategorii v jedné šabloně?
Jinak já většinou v cyklu používám jednopísmenné názvy proměnných a v presenteru si předávám celý název, takže se mně to moc často nestává, resp. vůbec.

David Matějka
Moderator | 6445
+
0
-

@fizzy jo, taky se mi to parkrat stalo. ze strany latte bych to asi neosetroval, spise zacni pouzivat komponenty, pak je snazsi se temto chybam vyhnout :)

Šaman
Člen | 2665
+
+11
-

V tomhle směru mi vadí jen proměnná $user. Že si framefork zabere takhle běžné slovo proměnnou, to si myslím, že není slušné. Takže:

{foreach $categories as $category} ... {/foreach} <!-- funguje -->
{foreach $users as $user} ... {/foreach} <!-- způsobuje velké WTF pokud se někde jinde tím nette $userem pracuje -->