|
php.net | support | documentation | report a bug | advanced search | search howto | statistics | random bug | login |
[2011-09-15 13:42 UTC] bs@php.net
Description: ------------ Basic functionality doesn't work because it seems as the GlobIterator might needs some changes to work with this commit: http://marc.info/?l=php-cvs&m=130188548616717 Test script: --------------- <?php $g = new \GlobIterator(__DIR__ . '/*'); do { $g->next(); } while($g->valid()); Expected result: ---------------- Empty output Actual result: -------------- PHP Fatal error: Uncaught exception 'LogicException' with message 'The parent constructor was not called: the object is in an invalid state ' in /private/tmp/x.php:6 Stack trace: #0 /private/tmp/x.php(6): SplFileInfo->_bad_state_ex() #1 {main} thrown in /private/tmp/x.php on line 6 Fatal error: Uncaught exception 'LogicException' with message 'The parent constructor was not called: the object is in an invalid state ' in /private/tmp/x.php:6 Stack trace: #0 /private/tmp/x.php(6): SplFileInfo->_bad_state_ex() #1 {main} thrown in /private/tmp/x.php on line 6 PatchesPull Requests
Pull requests:
HistoryAllCommentsChangesGit/SVN commits
|
|||||||||||||||||||||||||||||||||||||
Copyright © 2001-2025 The PHP GroupAll rights reserved. |
Last updated: Sun Oct 26 09:00:01 2025 UTC |
Not sure if this is the same issue, but I've experienced something very similar when extending SplFileObject (see Script 1 below). This might seem to be of very little importance, as no one would ever want to extend this class in that way. But with the introduction of traits this became a real problem, becouse using trait methods that share the same name with a SplFileObject method causes to throw the mentioned LogicException. This happens when the method is used in constructor prior to calling the parent constructor even if the trait method is aliased (see Script 2 below). Script 1: -------------- <?php class MyFileObject extends \SplFileObject { public function __construct($fname) { /** * This throws LogicException despite of that we have * overloaded the getRealPath method making it independent * of the object state. */ $new_fname = $this->getRealPath(); parent::__construct($fname); } public function getRealPath() { return '/tmp/foo.txt'; } } $f1 = new MyFileObject(__FILE__); Script 2 -------------- <?php trait NewFileTrait { public function getRealPath() { return __FILE__ . '.new'; } } class MyFileObject extends \SplFileObject { use NewFileTrait { /** * The method getRealPath is defined in SplFileObject, * so we'll use alias: */ NewFileTrait::getRealPath as newFileGetRealPath; } public function __construct($fname) { /** * This throws LogicException despite using aliased method. * This should not be happening, as we are not using any * methods of the SplFileObject class, just the aliased method * of our trait which happens to share the same name with * a SplFileObject method. */ $new_fname = $this->newFileGetRealPath(); parent::__construct($new_fname); } } $f1 = new MyFileObject(__FILE__);I can confirm what "[2012-03-19 21:24 UTC] maciej dot sz at gmail dot com" said in a more simplistic way. This class fails in my current version (PHP 5.3.14 (cli) (built: Jun 19 2012 07:35:36)) on $this->touchLockFile(...) As I really need $file before calling the parent constructor, I have no other option than making it static <?php /** * @author Iltar van der Berg <ivanderberg@hostnet.nl> */ class Lock extends \SplFileObject { /** * @param string $file_name * @param string $open_mode * @param Filesystem $filesystem * @param string $lock_directory */ public function __construct($file_name, $open_mode = 'r', Filesystem $filesystem = null, $lock_directory = '/var/lock') { $filesystem = $filesystem ?: new Filesystem(); $file = $this->touchLockFile($file_name, $lock_directory, $filesystem); parent::__construct($file, $open_mode); } /** * Returns true if the lock is placed, false if unable to * * @return boolean */ public function lock() { return $this->flock(LOCK_EX | LOCK_NB); } /** * Returns true if the lock is released * * @return bool */ public function release() { return $this->flock(LOCK_UN); } /** * Attempts to create a lock file for a given filename and directory * it will return a string if the file is touched * * @param string $file_name * @param string $lock_directory * @param Filesystem $filesystem * @return string */ private function touchLockFile($file_name, $lock_directory, Filesystem $filesystem) { $lock_file_path = explode('/', $file_name); $lock_file = array_pop($path); $path = empty($lock_file_path) ? "$lock_directory/$lock_file" : $lock_directory . implode('/', $lock_file_path); $lock_file = "$path/$lock_file.lock"; if(!$filesystem->exists($path) || !is_dir($path)) { $filesystem->mkdir($path, 0733); } // some modes create this file already, but we force it in // that way the lock file always exists no matter what mode $filesystem->touch($lock_file); return $lock_file; } } ?>I can confirm this unexpected result also for php54 and php55 Test script: --------------- <?php $path_to_files = sys_get_temp_dir(); // Next works as expected: no xml files found = no output foreach (new GlobIterator($path_to_files . '/*.xml') as $fileinfo) { echo $fileinfo->getFilename() . "\n"; } $it = new GlobIterator($path_to_files . '/*.xml'); // Expected result: count = 0 // Instead next line will crash php if no xml files are found if ($it->count()) { // do something... } ?>Confirm the bug Ubuntu Linux 13.10 3.11.0-17-generic x86_64 PHP 5.5.3-1ubuntu2.1 (cli) (built: Dec 12 2013 04:24:35) Copyright (c) 1997-2013 The PHP Group Zend Engine v2.5.0, Copyright (c) 1998-2013 Zend Technologies with Zend OPcache v7.0.3-dev, Copyright (c) 1999-2013, by Zend Technologies with Xdebug v2.2.3, Copyright (c) 2002-2013, by Derick RethansAdditionally I can not reproduce the original report: ----------------------------------------------------- <?php $g = new \GlobIterator(__DIR__ . '/*'); do { $g->next(); } while($g->valid()); ---------------------------------------------------- Works flawlessly for me. Using 5.5.15Able to reproduce error in 5.5.6 on Ubuuntu 14.04 $iterator = new GlobIterator('./someDir/*'); $iterator->count(); Where 'someDir' has not contents.Tested on PHP 5.3, 5.4, 5.5, 5.6 and 7.0 on OSX and Ubuntu. It fails the same on all of them. <?php error_reporting(E_ALL); ini_set('display_errors', '1'); $g = new \GlobIterator('/tmp/*.txt'); echo('Before: '.$g->count()."\n"); foreach ($g as $f) { } echo('After : '.$g->count()."\n"); If the glob expression matches at least one file it throws the exception on the second call to count() (line 9). If it doesn't match then it throws on the first call to count() (line 6). Not only count() throws the exception. All its methods do the same.