Bug #81551 [Com]: SplFileObject::fgets( does not advance line pointer after SplFileObject::seek()

From: Date: Fri, 22 Oct 2021 12:33:42 +0000
Subject: Bug #81551 [Com]: SplFileObject::fgets( does not advance line pointer after SplFileObject::seek()
References: 1  Groups: php.bugs 
Request: Send a blank email to php-bugs+get-237335@lists.php.net to get a copy of this message
Edit report at https://bugs.php.net/bug.php?id=81551&edit=1 ID: 81551 Comment by: lucasfbustamante at gmail dot com Reported by: lucasfbustamante at gmail dot com Summary: SplFileObject::fgets( does not advance line pointer after SplFileObject::seek() Status: Feedback Type: Bug Package: SPL related Operating System: Unix PHP Version: 8.0.12 Assigned To: cmb Block user comment: N Private report: N New Comment: Is this expected? https://3v4l.org/s4ZKA <?php $file = new SplTempFileObject(); for ($i = 0; $i < 100; $i++) { $file->fwrite("Foo $i\n"); } $file->seek(50); echo json_encode(array( array('triggerNext' => $file->next(), 'line' => $file->key(), 'contents' => trim($file->current())), array('triggerNext' => $file->next(), 'line' => $file->key(), 'contents' => trim($file->current())), array('triggerNext' => $file->next(), 'line' => $file->key(), 'contents' => trim($file->current())), ), JSON_PRETTY_PRINT); ?> Results: PHP 8.0.1+ [ { "line": 51, "contents": "Foo 50" }, { "line": 52, "contents": "Foo 51" }, { "line": 53, "contents": "Foo 52" } ] PHP 5.1 - 8.0.0: [ { "line": 51, "contents": "Foo 51" }, { "line": 52, "contents": "Foo 52" }, { "line": 53, "contents": "Foo 53" } ] Previous Comments: ------------------------------------------------------------------------ [2021-10-21 22:21:08] lucasfbustamante at gmail dot com I see the consistency this bugfix aims to provide between rewind (or starting from zero) and seek: https://3v4l.org/HBTeF It still escapes me why "Line" is 0 at "Foo 1", but either way, it's consistent with the old implementation so it won't cause bugs in my application. I can replace all my usage of fgets() with current() and next() instead, so that key() will remain consistent after rewind() or seek() with all PHP versions: https://3v4l.org/WYrig ------------------------------------------------------------------------ [2021-10-21 21:45:34] lucasfbustamante at gmail dot com I understand what's happening now, and the reasoning behind the change. However, this makes it very difficult for distributed libraries to have a comprehensive PHP version constraint. If you use the SPLFileObject and depend on seek() and key(), you either have to pick PHP 8 or PHP 5~7, because they have the same API but operates differently. Taking the WordPress environment for instance (I am a WordPress plugin developer, my distributed library is a WordPress plugin), PHP 8.0 is used by only 1.5% of the websites to this date: https://wordpress.org/about/stats/ I dislike the fact that PHP broke backwards compatibility for a function that exists and returns this same result since PHP 5.3, especially considering that this was introduced in a minor patch version bump, so PHP 8.0.0 will operate in a substantially different way than, say, PHP 8.0.1 or 8.1. ------------------------------------------------------------------------ [2021-10-21 20:37:41] requinix@php.net Looks correct to me. Change the lines to get a better picture of what's happening. https://3v4l.org/33lsI key() returns the current line number, which should be the same at the "beginning" of the line (eg, after a seek or rewind) as it is at the "end" of the line (after an fgets). The line number increments according to iterator semantics, which say that the key/current doesn't change until a call to next() - or, in this case, if you try to continue reading beyond the current location using another call to fgets. Before the bug fix: - Rewinding returns key=0, fgets=line 0, key=0 - Seeking to 50 would return key=50, fgets=line 51, key=51 After the bug fix: - Rewinding returns key=0, fgets=line 0, key=0 - Seeking to 50 returns key=50, fgets=line 50, key=50 ------------------------------------------------------------------------ [2021-10-21 19:34:40] lucasfbustamante at gmail dot com Description: ------------ While fixing https://bugs.php.net/bug.php?id=62004, PHP 8.0.1 probably introduced a bug, where after using SplFileObject::seek($line), the first subsequent call to SplFileObject::fgets() does not increase the line pointer. Test script: --------------- $file = new \SplTempFileObject(); for ($i = 0; $i < 100; $i++) { $file->fwrite("Foo\n"); } $file->seek(50); var_dump($file->key()); var_dump($file->fgets()); var_dump($file->key()); var_dump($file->fgets()); var_dump($file->key()); // https://3v4l.org/bX3E0 Expected result: ---------------- I expect that using SplFileObject::fgets() will consistently increment the line pointer by one. Actual result: -------------- The first call to SplFileObject::fgets() after calling SplFileObject::seek($line) will not increment the lint pointer. Subsequent calls will. ------------------------------------------------------------------------ -- Edit this bug report at https://bugs.php.net/bug.php?id=81551&edit=1

« previous php.bugs (#237335) next »