Nette 3.0 na PHP 8.1: Return type of Nette\Application\Routers\RouteList::offsetGet($index) should either

Václav Mašín
Člen | 35
+
0
-

Zdravím,

na PHP 8.0 mi jede jeden starší projekt, který bych teď rád postupně aktualizoval na novější verze PHP+Nette. Momentální verze balíků vypadají takto:

$ php81 /usr/bin/composer show
dg/adminer-custom             1.28.2   Customization for Adminer, the best database management tool written in PHP.
guzzlehttp/guzzle             7.5.0    Guzzle is a PHP HTTP client library
guzzlehttp/promises           1.5.2    Guzzle promises library
guzzlehttp/psr7               2.4.3    PSR-7 message implementation that also provides common utility methods
latte/latte                   2.11.6   ☕ Latte: the intuitive and fast template engine for those who want the most secure PHP sites. Introduces context-sensitive escaping.
league/oauth2-client          2.6.1    OAuth 2.0 Client Library
nette/application             3.0.8    🏆 Nette Application: a full-stack component-based MVC kernel for PHP that helps you write powerful and modern web applications. Write less, have cleaner code and your work will bring you joy.
nette/bootstrap               3.0.2    🅱 Nette Bootstrap: the simple way to configure and bootstrap your Nette application.
nette/caching                 3.1.4    ⏱ Nette Caching: library with easy-to-use API and many cache backends.
nette/component-model         3.0.3    ⚛ Nette Component Model
nette/database                3.0.7    💾 Nette Database: layer with a familiar PDO-like API but much more powerful. Building queries, advanced joins, drivers for MySQL, PostgreSQL, SQLite, MS SQL Server and Oracle.
nette/di                      3.0.14   💎 Nette Dependency Injection Container: Flexible, compiled and full-featured DIC with perfectly usable autowiring and support for all new PHP features.
nette/finder                  2.5.4    🔍 Nette Finder: find files and directories with an intuitive API.
nette/forms                   3.0.7    ?? Nette Forms: generating, validating and processing secure forms in PHP. Handy API, fully customizable, server & client side validation and mature design.
nette/http                    3.1.7    🌐 Nette Http: abstraction for HTTP request, response and session. Provides careful data sanitization and utility for URL and cookies manipulation.
nette/mail                    3.1.10   📧 Nette Mail: handy email creation and transfer library for PHP with both text and MIME-compliant support.
nette/neon                    3.3.3    🍸 Nette NEON: encodes and decodes NEON file format.
nette/php-generator           3.6.9    🐘 Nette PHP Generator: generates neat PHP code for you. Supports new PHP 8.1 features.
nette/robot-loader            3.4.2    🍀 Nette RobotLoader: high performance and comfortable autoloader that will search and autoload classes within your application.
nette/routing                 3.0.4    Nette Routing: two-ways URL conversion
nette/safe-stream             2.5.1    Nette SafeStream: provides isolation for thread safe manipulation with files via native PHP functions.
nette/schema                  1.2.3    📐 Nette Schema: validating data structures against a given Schema.
nette/security                3.0.6    🔑 Nette Security: provides authentication, authorization and a role-based access control management via ACL (Access Control List)
nette/tester                  2.4.3    Nette Tester: enjoyable unit testing in PHP with code coverage reporter. 🍏🍏🍎🍏
nette/utils                   3.2.9    🛠  Nette Utils: lightweight utilities for string & array manipulation, image handling, safe JSON encoding/decoding, validation, slug or strong password generating etc.
paragonie/random_compat       9.99.100 PHP 5.x polyfill for random_bytes() and random_int() from PHP 7
psr/http-client               1.0.1    Common interface for HTTP clients
psr/http-factory              1.0.1    Common interfaces for PSR-7 HTTP message factories
psr/http-message              1.0.1    Common interface for HTTP messages
ralouphie/getallheaders       3.0.3    A polyfill for getallheaders.
symfony/deprecation-contracts 2.5.2    A generic function and convention to trigger deprecation notices
tracy/tracy                   2.9.7    😎  Tracy: the addictive tool to ease debugging PHP code for cool developers. Friendly design, logging, profiler, advanced features like debugging AJAX calls or CLI support. You will love it.

Podle vyžadovaných verzí u všech Nette balíků (všude je uvedeno min. PHP 7.1–7.2, žádné omezení na max. 8.0 jsem nikde neviděl) bych tedy čekal, že aplikace by v tomto stavu měla bez problémů jet i na PHP 8.1. Nicméně tomu tak není, protože vyhazuje chybu:

Return type of Nette\Application\Routers\RouteList::offsetGet($index) should either be compatible with ArrayAccess::offsetGet(mixed $offset): mixed, or the #[\ReturnTypeWillChange] attribute should be used to temporarily suppress the notice search

Chápu nebo dělám někde něco špatně? Rád bych pochopil, jak přesně to verzování přes composer přesně funguje.

Díky.

Šaman
Člen | 2668
+
0
-

Asi by to chtělo vidět i composer.json, jinak je to střelba od boku. Nemáš tam sekci config > platform?
Btw. aktuální Nette nemá Finder, ten se přesunul do Utils. Ale co jsem koukal na jeho závislosti, tam by problém být neměl.

Václav Mašín
Člen | 35
+
0
-

Šaman napsal(a):

Asi by to chtělo vidět i composer.json, jinak je to střelba od boku. Nemáš tam sekci config > platform?
Btw. aktuální Nette nemá Finder, ten se přesunul do Utils. Ale co jsem koukal na jeho závislosti, tam by problém být neměl.

Díky za reakci. composer.json vypadá takto:

{
	"name": "nette/sandbox",
	"description": "The sandbox is a pre-packaged Nette Framework project, basic configured structure for your application.",
	"homepage": "https://nette.org",
	"type": "project",
	"license": ["BSD-3-Clause", "GPL-2.0", "GPL-3.0"],
	"authors": [
		{
			"name": "David Grudl",
			"homepage": "https://davidgrudl.com"
		},
		{
			"name": "Nette Community",
			"homepage": "https://nette.org/contributors"
		}
	],
	"require": {
		"php": ">=7.4.0",
		"nette/application": "3.0.8",
		"nette/bootstrap": "3.0.2",
		"nette/caching": "3.1.4",
		"nette/database": "3.0.7",
		"nette/di": "3.0.14",
		"nette/finder": "2.5.4",
		"nette/forms": "3.0.7",
		"nette/http": "3.1.7",
		"nette/mail": "3.1.10",
		"nette/robot-loader": "3.4.2",
		"nette/safe-stream": "^2.3",
		"nette/security": "3.0.6",
		"nette/utils": "^3.1",
		"latte/latte": "^2.4",
		"tracy/tracy": "^2.4",
		"dg/adminer-custom": "^1.9",
		"league/oauth2-client": "^2.6"
	},
	"require-dev": {
		"nette/tester": "^2.0"
	},
	"minimum-stability": "stable",
	"config": {
		"platform": {
			"php": "7.4"
		}
	}
}

Ta sekce config/platform tam tedy je. Po pravdě netuším, jaký je tady její význam…

Pavel Kravčík
Člen | 1202
+
0
-

Řekneš composeru, že na „serveru“ máš 7.4. Takže i když budeš mít lokálně třeba PHP8.4 pokusí se nainstalovat pouze závislosti, které budou fungovat na 7.4. Pokud to smažeš bude si to composer automaticky brát z defaultního PHP. (Zjistit můžeš pomocí php -v)

Václav Mašín
Člen | 35
+
0
-

Pavel Kravčík napsal(a):

Řekneš composeru, že na „serveru“ máš 7.4. Takže i když budeš mít lokálně třeba PHP8.4 pokusí se nainstalovat pouze závislosti, které budou fungovat na 7.4. Pokud to smažeš bude si to composer automaticky brát z defaultního PHP. (Zjistit můžeš pomocí php -v)

OK, chápu. Nicméně i když tedy zkusím tu verzi změnit na 8.0 a následně i na 8.1 (mezitím pokaždé s „composer update“), tak ta chyba pořád přetrvává.

Aktuálně mám composer.json:

{
	"name": "nette/sandbox",
	"description": "The sandbox is a pre-packaged Nette Framework project, basic configured structure for your application.",
	"homepage": "https://nette.org",
	"type": "project",
	"license": ["BSD-3-Clause", "GPL-2.0", "GPL-3.0"],
	"authors": [
		{
			"name": "David Grudl",
			"homepage": "https://davidgrudl.com"
		},
		{
			"name": "Nette Community",
			"homepage": "https://nette.org/contributors"
		}
	],
	"require": {
		"php": ">=8.1.0",
		"nette/application": "3.0.*",
		"nette/bootstrap": "3.0.*",
		"nette/caching": "3.1.*",
		"nette/database": "3.0.*",
		"nette/di": "3.0.*",
		"nette/finder": "2.5.4",
		"nette/forms": "3.0.*",
		"nette/http": "3.1.*",
		"nette/mail": "3.1.*",
		"nette/robot-loader": "3.4.*",
		"nette/safe-stream": "^2.3",
		"nette/security": "3.0.*",
		"nette/utils": "^3.1",
		"latte/latte": "^2.4",
		"tracy/tracy": "^2.4",
		"dg/adminer-custom": "^1.9",
		"league/oauth2-client": "^2.6"
	},
	"require-dev": {
		"nette/tester": "^2.0"
	},
	"minimum-stability": "stable",
	"config": {
		"platform": {
			"php": "8.1"
		}
	}
}

Jedině když změním verze těch „kmenových“ Nette balíků (application+boostrap atd.) na 3.1.*, tak se to jeví jako vyřešené (ta původní chyba se už neobjeví a vyskočí celkem dle očekávání nějaká jiná, ale to už je jiná věc).

Takže v podstatě řešení asi mám. Jen se snažím pochopit, proč aplikace na těch původních verzích balíků na PHP 8.0 jede a na PHP 8.1 ne, i když by tomu tak podle deklarovaných min. verzí být nemělo.

A nebo mi něco uniká (což je spíše ta pravděpodobnější varianta) a v tom případě bych se jen rád dozvěděl, co přesně.

Šaman
Člen | 2668
+
0
-

Ty jsi ale nedeklaroval minimální verzi. Tohle:

"nette/application": "3.0.8",

říká, že chceš přesně tuhle. A protože se v PHP 8.1 asi změnila definice ArrayHash tak, že má nyní otypovaný parametr, tak vyskočí ta deprecated chyba. (Tj. na produkčním serveru by to fungovalo, deprecated chyby se tam vypínají. Ale je dobře, že na @dev to máš povolené a aspon se pořešilo že někde něco nefunguje jak má.)

Václav Mašín
Člen | 35
+
0
-

Šaman napsal(a):

Ty jsi ale nedeklaroval minimální verzi. Tohle:

"nette/application": "3.0.8",

říká, že chceš přesně tuhle. A protože se v PHP 8.1 asi změnila definice ArrayHash tak, že má nyní otypovaný parametr, tak vyskočí ta deprecated chyba. (Tj. na produkčním serveru by to fungovalo, deprecated chyby se tam vypínají. Ale je dobře, že na @dev to máš povolené a aspon se pořešilo že někde něco nefunguje jak má.)

Aha, takže defakto ty informace o minimální verzi závislostí u balíků v composeru se vztahují k provozu v produkčním režimu? Že v kódu něco vyhazuje nějaké to deprecated varování se nepočítá. Pokud to je takto, tak to je přesně ta informace, která mi v hlavě chyběla – díky za vysvětlení.

Šaman
Člen | 2668
+
0
-

Nevím o čem mluvíš.
Když zadáš verzi bez dalších pomocných znaků, znamená to, že chceš přesně tu verzi.
Pak máš možnost:

"nette/application": "3.0.8",   # požadovaná verze
"nette/application": "~3.0.8",  # tilda říká, že se může změnit poslední číslo (takže projde 3.0.11, ale ne 3.1.0)
"nette/application": "^3.0.8",  # stříška říká, že se nesmí změnit první číslo (takže projde 3.2.9, ale ne 4.0)
"nette/application": "3.0.*",   # použije se nejvyšší verze 3.0.xxx
"nette/application": ">=3.0.8", # použije se nejnovější verze, minimálně 3.0.8 (ale klidně 5.2.0, pokud by existovala)

Tohle říká, že i když máš jinou verzi PHP, Composer ti má nainstalovat knihovny, jakoby jsi měl PHP 7.4. Používá se to, pokud na vývojovém počítači mám vyšší PHP (např. 8.2), ale na produkci je třeba stále 8.0 a chci používat stejné knihovny, jaké se nainstalují na produkčním serveru:

"config": {
		"platform": {
			"php": "7.4"
		}
	}

S produkčním režimem Composer nijak nesouvisí. Psal jsem to proto, že ačkoliv ti to píše deprecated hlášku, tak samotná verze je nejspíš stále kompatibilní. Na serveru s hlášením deprecated a notice hlášek ro zařve (typicky vývojové PC). Na produkci chceš mít naopak tyhle chyby nízké závažnosti potlačené a jen je potichu zalogovat.

Václav Mašín
Člen | 35
+
0
-

Řeším čistě jen ten zdánlivý rozpor v tom, že je verze Nette 3.0 prezentovaná jako funkční s PHP 8.1, ale já tady narážím na tu „deprecated“ hlášku. Chápu už nicméně, že problém je čistě jen v tom u mě zapnutém vyhazování výjimek, když se narazí na něco, co je „deprecated“ a že tedy jinak Nette 3.0 na PHP 8.1 bez problémů funkční je.

Což jsem si teď i přímo sám potvrdil, když jsem podle https://doc.nette.org/cs/migrations do bootstrap.php zkusmo přidal:

error_reporting(~E_USER_DEPRECATED); // tady jsem tedy musel dát z nějakého důvodu ~E_DEPRECATED - s ~E_USER_DEPRECATED to nefungovalo

a voilá – aplikace najednou normálně běží.

Takže tímto svůj dotaz považuji za zodpovězený – ještě jednou díky za pomoc!

Šaman
Člen | 2668
+
0
-

Funkční ano (s vypnutou Tracy to poběží správně a nic nespadne), ale s deprecated hláškama počítej. A to i dopředně – pokud se plánuje něco změnit (naposledy to byly názvy konstant apod.), tak se kvůli kompatibilitě udělá kompatibilní změna (jsou tam konstanty dvojího názvu, nové i staré) a ty staré vyhazují deprecated hlášku, že od příští major verze tento kód nebude podporovaný s odkazem na nový zápis.

E_DEPRECATED vs E_USER_DEPRECATED – jedno používá jádro, druhé si vyhazuji sám, ale pokud nechci NOTICE, nebo DEPRECATED úroveň hlášek, tak vždy vyloučím obě verze (USER i bez). Vlastně pořádně nevím, proč jsou dvě. A z hlavy taky nevím, kterou používá Nette. Ta hláška, kterou to začalo, je od samotného PHP, to používá E_DEPRECATED.

Václav Mašín
Člen | 35
+
0
-

Jasně, určitě „deprecated“ hlášky nehodlám ignorovat.

Tady v tomto konkrétním případě to tedy po upgrade na Nette 3.1 už tuto hlášku nevyhazuje.

Marek Bartoš
Nette Blogger | 1306
+
0
-

že je verze Nette 3.0 prezentovaná jako funkční s PHP 8.1

Já tady vidím něco jiného https://nette.org/en/maintenance#…

m.brecher
Generous Backer | 898
+
0
-

@VáclavMašín

v PHP 8.1 vyhazuje: Return type of Nette\Application\Routers\RouteList::offsetGet($index) should either be compatible ......

tedy jinak Nette 3.0 na PHP 8.1 bez problémů funkční je.

Tady v tomto konkrétním případě to tedy po upgrade na Nette 3.1 už tuto hlášku nevyhazuje.

Problém je způsoben tím, že Nette 3.0 vyžaduje verzi PHP v rozsahu 7.1 až 8.0, takže PHP 8.1 nepodporuje jak správně upozornil @MarekBartoš odkazem do dokumentace Nette. Takže buďto nechat PHP na verzi 8.0, nebo upgradovat Nette na 3.1. Ale Ty Jsi na to vlastně už přišel sám :).

Václav Mašín
Člen | 35
+
0
-

Marek Bartoš napsal(a):

že je verze Nette 3.0 prezentovaná jako funkční s PHP 8.1

Já tady vidím něco jiného https://nette.org/en/maintenance#…

Aha, díky, tuto stránku (resp. tam tu tabulku dole) jsem jaksi úplně přehlédl.

Koukal jsem tuším jen na vyžadované verze PHP u dotyčných balíků na packagist.org, kde jsem žádné omezení v tomto smyslu neobjevil, což mě očividně svedlo na scestí.