Chyba Tracy Creation of dynamic property Tracy\DefaultBarPanel::$cpuUsage is deprecated při update na 2.4

milanb
Člen | 64
+
0
-

Ahoj,
snažím se o update Nette z 2.3 na 2.4, jak je popsáno zde: https://doc.nette.org/…tions/to-2-4. PHP mám 8.2.4.
Updavil jsem toto v composer.json:

		"php": ">= 5.6",
		"nette/application": "2.4.*",
		"nette/bootstrap": "2.4.*",
		"nette/caching": "2.5.*",
		"nette/database": "2.4.*",
		"nette/di": "2.4.*",
		"nette/forms": "2.4.*",
		"nette/http": "2.4.*",
		"nette/security": "2.4.*",

		"nette/finder": "2.4.*",
		"nette/mail": "2.4.*",
		"nette/robot-loader": "2.4.*",
		"nette/safe-stream": "2.4.*",
		"nette/utils": "2.4.*",
		"latte/latte": "2.4.*",
		"tracy/tracy": "2.4.*",

Jiné změny jsmem nedělal.
Pak jsem spustil composer update -W --prefer-stable --prefer-dist: nejdřív –dry-run a pak opravdu.
No a pak jsem spustil aplikaci a Tracy mě vypsal stack s chybou: Creation of dynamic property Tracy\DefaultBarPanel::$cpuUsage is deprecated
Zdrojem je řádek v bootstrap.php: $configurator->enableDebugger(__APPDIR__ . '/log');
A nechápu, proč chybu způsobuje řádek 483 v Debugger.php: $info->cpuUsage = self::$cpuUsage;,
když jde o volání mězi třídami uvnitř knihovny Tracy.
Díky za pomoc.

Editoval milanb (1. 3. 20:47)

milanb
Člen | 64
+
0
-

Tak jsem udělal downgrade PHP na 8.0.30 a už ta chyba není, ale zase je jiná:
Ambiguous class Notes resolution; defined in D:\TEMP\_0repos\magnusys\app/..\vendor\nette\component-model\tests\bootstrap.php and in D:\TEMP\_0repos\magnusys\app/..\vendor\nette\di\tests\bootstrap.php.
Způsobuje ji řádek v bootstrap.php: $configurator->createRobotLoader()->addDirectory(__APPDIR__)->register();
Jinak jsem zatím v aplikaci nic neměnil, podle návodu na update na 2.4 jsem nenašel nic, co bych v kódu měl ručně měnit.
Začínám se ztrácet…

Editoval milanb (1. 3. 21:47)

Marek Bartoš
Nette Blogger | 1177
+
+2
-

Zajímavé, že ti to do teď fungovalo. Robot loader by měl načítat jenom tvé složky, ne vendor.

milanb
Člen | 64
+
0
-

Taky mězarzilo, že v tom výpisu chyby je cesta do vendor a tests/bootstrap.php. Ale fungovalo to. Chci jen udělat update Nette na co možná nejvyšší verzi a dělám to postupně dle návodu. Jediné, co jsem udělal, je vše v tomto vlákně pospané, a to je pouze změna composer.json a pak composer update. Ani ťuk víc.
Můžu klidně poslat celý log té chyby.

Editoval milanb (2. 3. 9:16)

Marek Bartoš
Nette Blogger | 1177
+
+2
-

Ne všechno je v upgrade guides. Dobře napsané aplikace se podle nich a deprecation notices aktualizovat dají, ale s aplikacemi sahající na (nezdokumentované) internals a obecně dělající nestandardní věci narazí na problémy.

Že robotloader načítá vendor má ale jednoduchou příčinu – museli jste si ho tam sami přidat. Sám vendor nenačítá. Nejspíš tedy konstanta __APPDIR__ neukazuje na složku /app, ale /.

Co se týče chyby popsané v úvodu – Nette 2.4 je kompatibilní s maximálně PHP 8.0, viz https://nette.org/en/maintenance
Chyba se ukazuje uvnitř knihovny jednoduše proto, že používala něco, co už v novějším PHP nefunguje.

milanb
Člen | 64
+
0
-

Tak další malý posun: Změnil jsem všechny dotčené verze na 2.4.* a spustil update roučně pro všechny tyto komponenty a na nich závislé:
composer update nette/mail nette/security nette/caching nette/database nette/finder nette/forms nette/http nette/utils nette/robot-loader nette/application nette/bootstrap nette/caching nette/di tracy/tracy latte/latte -W
A objevila se jiná chyba: Cannot use 'Object' as class name as it is reserved
A to už vůbec nechápu, protože v návodu update je uvedeno právě tohle:
Třídy frameworku teď místo dědění od Nette\Object používají novou traitu Nette\SmartObject
Tak proč v knihovně nette/utils v2.4.* je použito pořád Nette\Object?

milanb
Člen | 64
+
0
-

Marek Bartoš napsal(a):

Ne všechno je v upgrade guides. Dobře napsané aplikace se podle nich a deprecation notices aktualizovat dají, ale s aplikacemi sahající na (nezdokumentované) internals a obecně dělající nestandardní věci narazí na problémy.

Že robotloader načítá vendor má ale jednoduchou příčinu – museli jste si ho tam sami přidat. Sám vendor nenačítá. Nejspíš tedy konstanta __APPDIR__ neukazuje na složku /app, ale /.

Co se týče chyby popsané v úvodu – Nette 2.4 je kompatibilní s maximálně PHP 8.0, viz https://nette.org/en/maintenance
Chyba se ukazuje uvnitř knihovny jednoduše proto, že používala něco, co už v novějším PHP nefunguje.

Díky, to s PHP jsem pochopil a vrátil se na 8.0.30. To s __APPDIR__ je zavádějící, protože jeho hodnota je skutečně root celé aplikace, ale to fungovalo již s verzí Nette 2.3. Přesto ale můžu zkusit řádek změnit na:
$configurator->createRobotLoader()->addDirectory(__APPDIR__ . '/app')->register();

Ale jek píšu v předhozím komentáři, teď už ten problém nevidím, mám problém s Nette\Object v Nette\Utils 2.4.*…

Marek Bartoš
Nette Blogger | 1177
+
+1
-

Vyžaduj v Composeru verze ^2.4.0, dovolí to cokoli od 2.4.0, nižší než 3.0.0. Například nette/utils mají 2.5.* verze.

milanb
Člen | 64
+
0
-

Zdá se, že to pomohlo. Teď už to háže chyby jen v souborech aplikace v /app a níž.
Moc děkuji!

milanb
Člen | 64
+
0
-

Tak teď už bojuju jen z aplikací. Ta samozřejmě fungovala, ale s verzí Nette 2.5 se dějí věci…
Mám HomepagePresenter, který začíná takto:

class HomepagePresenter extends Nette\Application\UI\Presenter
{
	use BasePresenter;
    ...

BasePresenter začíná takto:

	public function startUp()
	{
		parent::startUp();
		if (!defined('self::LOGIN_NOT_REQUIRED') && !$this->user->isLoggedIn()) {
			$this->redirect('Login:default');
			return;
		} else {
        ...

Ta podmínka zjednodušeně říká, že když nejsem přihlášen, přesměruj na Login.
LoginPresenter vypadá takto:

class LoginPresenter extends Nette\Application\UI\Presenter
{
	use BasePresenter;
	use \App\Control\LoginControl;

	const LOGIN_NOT_REQUIRED = TRUE;
	public function actionDefault() { $this->user->logout(); }
	public function renderDefault()	{ }
}

A LoginControl vyrábí login formulář. Ale k tomu to nikdy nedojde, protože dojde k zacyklení. V adrese prohlížeče to skončí tímto:
http://localhost:59029/login/login/login/login/login/login/login/login/login... až dojde k chybě Smyčka při přesměrování.
Čím to je? A proč se v adrese vrší ty loginy za sebou?
Neměl bych v takových situacích použít radši jen $this->forward('Login:default');, když nepřesměrovávám na jinou adresu a stále zůstávám v aplikaci?
Děkuji.

Editoval milanb (2. 3. 13:14)

David Grudl
Nette Core | 8152
+
+1
-

@milanb zkus mi nějak polopaticky vysvětlit, co znamená to self v defined('self::LOGIN_NOT_REQUIRED') a proč?

milanb
Člen | 64
+
0
-

OK. V LoginPresenter určuje hodnota LOGIN_NOT_REQUIRED, jestli je požadováno, aby byl člověk pro danou stránku (presenter) vyžadován. A není vyžadován u registračního presenteru, kde si uživatel teprve účet vytváří, a u login presenteru, kde je login dialog, takže ještě přihlášen není. Všechny ostatní stránky (presentery) potřebují, aby byl user zalogován.
self:: je kvalifikátor sebe sama (třídy). Odkazujete se na konstantu nebo statickou proměnnou definovanou ve stejné třídě. Klíčové slovo self se používá k přístupu k statickým členům třídy (statické proměnné, konstanty a metody) zevnitř třídy.
A protože je ta konstanta definována v LoginPresenter, který využívá i metody BasePresenter a v tom se také provádí ten test, tak nemusí být konstanta definována (když BasePresenter je užit v jiné třídě, než LoginPresenter, takže tam konstanta nedude), proto: if (!defined('self::LOGIN_NOT_REQUIRED').
P.S. Já ten kód sdědil, nepsal bych to tak, použil bych normální dědění, a ne use BasePresenter.

Editoval milanb (2. 3. 15:38)

David Grudl
Nette Core | 8152
+
+2
-

Mě zaráží, že globální funkce defined() si má poradit se self… Nečekal bych, že to vůbec bude fungovat, a jestli jo, mohlo se to i změnit mezi verzemi PHP, tak bych to asi prověřil.

milanb
Člen | 64
+
0
-

Aha, ok, zkusím. Díky.

milanb
Člen | 64
+
0
-

Udělal jsem z toho protected proměnnou, ale to nijak nepomoho. Pořád se ten redirect nějak správně neprovede, protože se z toho BasePresenteru nedokážu dostat dál, ani HomePagePresenter, natož LoginPresenter se nedostanou ani do konstruktoru. Chyba je v celé logice a taky to přesměrování nechápu, this je vždy HomePresenter, i kdyžjsempřesměrovsl do Login…

Editoval milanb (2. 3. 17:43)

milanb
Člen | 64
+
0
-

Tak nově se zdá být chyba někde tady při konstrukci formu:
$form->addSubmit('login', $l->login)->getControlPrototype()->setClass('btn btn-primary');
To způsobí, že ve vygenerováném form je <form action="/login/" method="post" id="frm-loginForm"> a to vůbec nezpůsobí volání
localhost/login, ale jen ‚/‘ a pak přidá další action="/login/login/" atd. další…
Když to v inspektoru ručně upravím na action="/login", tak se dostanu až do submit metody successLoginForm.

Editoval milanb (2. 3. 18:10)

m.brecher
Generous Backer | 765
+
-1
-

@milanb

defined('self::LOGIN_NOT_REQUIRED');

je asi lepší nahradit reflexí třídy, které jsou k tomu přímo určené, třeba takto:

$ro = new ReflectionObject($this);
$ro->hasConstant('LOGIN_NOT_REQUIRED');
milanb
Člen | 64
+
0
-

OK, zkusím. Díky.

David Grudl
Nette Core | 8152
+
+2
-

Že to dělá /login/login/login nejspíš značí, že se špatně detekuje base-path. Nedokážu takhle z hlavy poradit co z tím, jen přemýšlím nahlas.

m.brecher
Generous Backer | 765
+
0
-

@milanb

Zkus natvrdo vyloučit redirect z LoginPresenter-u:

místo:

if (!defined('self::LOGIN_NOT_REQUIRED') && !$this->user->isLoggedIn()) {
	$this->redirect('Login:default');
}

zkus:

if ($this->name !== 'Login' && !defined('self::LOGIN_NOT_REQUIRED') && !$this->user->isLoggedIn()) {
	$this->redirect('Login:default');
}
milanb
Člen | 64
+
0
-

David Grudl napsal(a):

Že to dělá /login/login/login nejspíš značí, že se špatně detekuje base-path. Nedokážu takhle z hlavy poradit co z tím, jen přemýšlím nahlas.

Asi to tak nějak bude, protože další problém, o kterém jsem zatím nepsal, je neschopnost načíst cokoliv z <site-root>/www, ani CSS, JS, nic. Použité jsou např. takto v šabloně: ¨<link rel="stylesheet" href="{$basePath}/www/less/magnus.css">.
Jak se basePath naplní, kdy a kde? Jen dodám, že Apache alias je nasměrován rovnou do <site-root>/www, kde načte index.php atd.
.htaccess mám zkopírovaný ze vzorového projektu nette/web-project, takže to by mělo být dobře. Přesto ani přímý přístup k nějakému zdroji nelze načíst, i když ho dám do adresy prohlížeče, např. http://localhost:51173/css/less/magnus.css nebo když na zkoušku umístím do <site-root>/www soubory index.html tak ani http://localhost:51173/index.html neprojde. Oboje skončí stejou chybou zobrazenou v Tracy: Cannot load presenter 'Magnus:Css', class 'App\MagnusModule\Presenters\CssPresenter' was not found..
Je nakonec to <site-root>/www/.htaccess špatně? Tady je:

Require all granted
# Disable directory listing for security reasons
<IfModule mod_autoindex.c>
	Options -Indexes
</IfModule>
# Enable pretty URLs (removing the need for "index.php" in the URL)
<IfModule mod_rewrite.c>
	RewriteEngine On
	# Uncomment the next line if you want to set the base URL for rewrites
	# RewriteBase /
	# Force usage of HTTPS (secure connection). Uncomment if you have SSL setup.
	# RewriteCond %{HTTPS} !on
	# RewriteRule .? https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
	# Permit requests to the '.well-known' directory (used for SSL verification and more)
	RewriteRule ^\.well-known/.* - [L]
	# Block access to hidden files (starting with a dot) and URLs resembling WordPress admin paths
	RewriteRule /\.|^\.|^wp- - [F]
	# Return 404 for missing files with specific extensions (images, scripts, styles, archives)
	RewriteCond %{REQUEST_FILENAME} !-f
	RewriteRule \.(pdf|js|mjs|ico|gif|jpg|jpeg|png|webp|avif|svg|css|rar|zip|7z|tar\.gz|map|eot|ttf|otf|woff|woff2)$ - [L]
	# Front controller pattern - all requests are routed through index.php
	RewriteCond %{REQUEST_FILENAME} !-f
	RewriteCond %{REQUEST_FILENAME} !-d
	RewriteRule . index.php [L]
</IfModule>
# Enable gzip compression for text files
<IfModule mod_deflate.c>
	AddOutputFilterByType DEFLATE text/html text/plain text/xml text/css application/javascript application/json application/xml application/rss+xml image/svg+xml
</IfModule>

Díky moc.

Editoval milanb (3. 3. 11:23)

nightfish
Člen | 474
+
+2
-

@milanb
Píšeš, že Apache je nasměrovaný do <site-root>/www, a zároveň že se např. na styly odkazuje přes {$basePath}/www/less/magnus.css. Pokud by opravdu platila ta první část, tak odkaz musí být {$basePath}/less/magnus.css.

  1. Nemáš náhodou v <site-root> ještě jeden .htaccess, který by dělal nějaké přesměrovávání/přepisování/podstrkávání do adresáře www?
  2. Co se stane, když v <site-root>/www/.htaccess odkomentuješ RewriteBase / a změníš to na RewriteBase /www/? (I kdyby to zafungovalo, tak chceš mít spíš správně nastavený Apache než používat tuto berličku…).
milanb
Člen | 64
+
0
-

m.brecher napsal(a):

@milanb

Zkus natvrdo vyloučit redirect z LoginPresenter-u:

místo:

if (!defined('self::LOGIN_NOT_REQUIRED') && !$this->user->isLoggedIn()) {
	$this->redirect('Login:default');
}

zkus:

if ($this->name !== 'Login' && !defined('self::LOGIN_NOT_REQUIRED') && !$this->user->isLoggedIn()) {
	$this->redirect('Login:default');
}

Ta část s if ($this->name !== 'Login' by mohla fungovat, ale problém je, že submit togo login okna vede na localhost/login/, tzn. i s tím lomítkem na konci, což asi .htaccess nějak vyhodnotí tak, že opět zavolá root /HomePreseneter. Problém už začítán tam, že v budování formu příkaz $form->addSubmit('login', $l->login) způsobí, že ve vygenerováném form je <form action="/login/" method="post", tzn.i s tím lomítkem na konci.A to netuším, proč…?

milanb
Člen | 64
+
0
-

nightfish napsal(a):

@milanb
Píšeš, že Apache je nasměrovaný do <site-root>/www, a zároveň že se např. na styly odkazuje přes {$basePath}/www/less/magnus.css. Pokud by opravdu platila ta první část, tak odkaz musí být {$basePath}/less/magnus.css.

  1. Nemáš náhodou v <site-root> ještě jeden .htaccess, který by dělal nějaké přesměrovávání/přepisování/podstrkávání do adresáře www?
  2. Co se stane, když v <site-root>/www/.htaccess odkomentuješ RewriteBase / a změníš to na RewriteBase /www/? (I kdyby to zafungovalo, tak chceš mít spíš správně nastavený Apache než používat tuto berličku…).

Rozumím, díky za snahu, ale to vede stále na stejný výsledek – error v Tracy: Cannot load presenter 'Magnus:Css', class 'App\MagnusModule\Presenters\CssPresenter' was not found. Teda když to zkouším takto: http://localhost:51671/less/magnus.css.
Ale ani změna v šabloně Latte nepomohla a všude, kde je použito {$basePath}/www/..., změna na {$basePath}/... taky ne.

ad. 1) V <site-root> mám ještě jeden .htaccess, ale ten obsahuje jen Require all denied dle vzoru v nette/web-project.

ad. 2) A když jsem odkomentoval RewriteBase / a změnil to na RewriteBase /www/, tak to nepomohlo.

Editoval milanb (3. 3. 11:45)

nightfish
Člen | 474
+
+3
-

milanb napsal(a):
Rozumím, díky za snahu, ale to vede stále na stejný výsledek – error v Tracy: Cannot load presenter 'Magnus:Css', class 'App\MagnusModule\Presenters\CssPresenter' was not found. Teda když to zkouším takto: http://localhost:51671/less/magnus.css.

A soubor <site-root>/www/less/magnum.css existuje a je přístupný Apachi? Protože podle pravidel, nastavených ve www/.htaccess, se všechny existující (CSS) soubory buď napřímo zobrazují, nebo se pro ně vrací (Apache) chybová stránka, takže k předání zpracování do index.php by vůbec nemělo dojít (a tedy by se ti pro CSS soubor neměla zobrazit Tracy).

Takže tímto směrem bych se ubíral. Asi by se hodilo zkontrolovat access_log a error_log Apache, jestli tam nenarazíš na něco zajímavého.

milanb
Člen | 64
+
0
-

Ne, v žádném logu není nic, co by na něco ukazovalo.

milanb
Člen | 64
+
0
-

OMG, tak chyba nenačítání těch CSS a JS úplně někde jinde a sice v lauch.json skriptu pro soupštění v prostředí VS Code.Když to spustím ručně pomocí php -S localhost:8000 -t ./www tak se načtou. Omouvám se, že jsem s tímto zdržoval.
Teď jdu zjistit, co všech shora až sem se tím spravilo…

milanb
Člen | 64
+
+1
-

Jestli můžu někomu prospět, kdo taky používá VS Code, tak správný launch.json vypadá takto:

{
  "version": "0.2.0",
  "configurations": [
    {
      "name": "Launch Built-in web server",
      "type": "php",
      "request": "launch",
      "runtimeArgs": [
        "-dxdebug.mode=debug",
        "-dxdebug.start_with_request=yes",
        "-S",
        "localhost:5001"
      ],
      "cwd": "${workspaceRoot}/www/",
      "serverReadyAction": {
        "pattern": "Development Server \\(http://localhost:([0-9]+)\\) started",
        "uriFormat": "http://localhost:%s",
        "action": "openExternally"
      }
    }
  ]
}

Port si samozřejmě lze změnit dle libosti. A stiskem F5 se spustí aplikace s debuggerem a otevře se okno prohlížeče s aplikací.
Ještě jednou děkuji a prosím, můžete toto vlákno zavřít, jestli se to tu vlastně vůbec tak nějak dělá.

Marek Bartoš
Nette Blogger | 1177
+
+2
-

Nevím, zda už tě to trklo, tak just in case – php built-in webserver je alternativa k Apache určená pro lokální vývoj. Takže žádná úprava .htaccess se ti nemohla projevit, nepoužívá se.

milanb
Člen | 64
+
0
-

Netrklo. Díky. A fakt, že celá aplikace funguje, je asi dán tím, že ve www ten server najde index.php, ne?
Ale jak bez .htaccess fungují všechna URL, když např. žádný soubor login.php ve www neexistuje?

Marek Bartoš
Nette Blogger | 1177
+
0
-

index.php je výchozí umístění. Když nenajde soubor ve www, tak se request nasměruje na něj.

Raději si nastav stejný webserver, který máš na serveru i pro lokální vývoj, aby se ti to chovalo stejně.

milanb
Člen | 64
+
0
-

OK, nastavím, mám tu XAMPP, tak to by mělo jít. Díky.

milanb
Člen | 64
+
0
-

Ahoj, díky moc všem za pomoc, už se i podařilo upgradovat z 2.3 na 3.1, už zbává jen kousek cesty k 3.2… :-)