pronto.ee

Tomorrow will be cancelled due to lack of interest

PHP 8.0: Muudatus funktsioonis strrpos()

PHP

Nüüd kus PHP 7.x-i enam parketikõlbulikuks ei peeta ilmneb, et mitte kõik rakendused ei taha uuemate PHP versioonidega toimida. Mitte alati ei ole nende põhjus üheselt selge ning töö käigus ilmnevad siin ja seal pooldokumenteeritud muudatused mis võivad lohakale arendajale kaika valusal kombel kordaratesse torgata. Üheks selliseks funktsiooniks on strrpos().

Selleks, et asja olemusest aru saada tuleb vaadata kõigepealt funktsiooni signatuuri ja pöördumisväärtuseid. Php.net ütleb selles kohta nii:

strrpos(string $haystack, string $needle, int $offset = 0): int|false

Returns the position where the needle exists relative to the beginning of the haystack string (independent of search direction or offset).

Returns false if the needle was not found.

Enne PHP 8.0-t töötas see funktsioon nõnda, et kui $offset läks string piiridest välja (tavaliselt oli selle põhjuseks tühi $haystack) oli pöördumisväärtuseks false. Alates PHP 8.0-st on tulemuseks hoopis:

Fatal error:  Uncaught ValueError: strrpos(): Argument #3 ($offset) must be contained in argument #1 ($haystack)

Ehk siis tulemuseks on kriitiline viga ning koodi edasi töötlemine lõpetatakse. Ühest küljest on see halb, sest dokumentatsioon seda situatsioon ei kata. Teisest küljest on see mõistetav, sest strrpos() on lõppeks ikkagi funktsioon ning hea tava näeb PHP-s ette, et küllalt ressursimahukaid funktsioone ei kasutata tuvastamaks kas andmeid on võimalik töödelda või mitte. Igal juhul oleks korrektne lahendus kontrollida if lausega ega string juhtumisi pole tühi. Alternatiivse variandina võib try / catch-iga püüda kinni \ValueError ja jätkata nii nagu algne kood ette nägi. See viimane lahendus läheb loomulikult vastuolla heade tavadega, kuid teinekord on oluline lihtsalt kood käima saada.

Siinkohas oleks paslik märkida, et \ValueError on uuendus mis toodi sisse PHP 8.0-s. Ehk siis sellepüüdmine ei toimi varasemate PHP-dega. Kui kood peab olema ka tagurpidi ühilduv peaks kasutama kas \Exception-it või klassi polyfillimist:

if (!class_exists('\ValueError')) {
    class ValueError extends \Error {
    }    
}

Ahjaa, märkuseks niipalju veel, et kuigi algne teemapüstitus puudutas ühte konkreetset funktsiooni mõjutab see muudatus veel teisigi, näiteks strpos(), range(), array_rand() ja võib-olla midagi veel on samuti selles muudatusest mõjutatud.

Post a comment