4

I'm trying to store an array of SplFileInfo instances in a cache with serialize command but the command throws this exception:

Exception' with message 'Serialization of 'SplFileInfo' is not allowed

Why is it not allowed?

Thanks!

Note: I'm just curious. The problem itself can be worked around.

MartyIX
  • 27,828
  • 29
  • 136
  • 207

2 Answers2

9

Objects based on Resources can't be serialized.

I guess I don't have to explain why (if you need the explanation tell me even if it's OT in this question)

Addendum

For @Charles that doesn't believe that SplFileInfo doens't store/open a new resource I have made a little test script.

If you run this:

new SplFileInfo('index.php');
$link=mysql_connect('localhost','root','');
echo $link;

The output is: Resource id #2

If you run this:

//new SplFileInfo('index.php');
$link=mysql_connect('localhost','root','');
echo $link;

The output is: Resource id #1.

dynamic
  • 46,985
  • 55
  • 154
  • 231
  • 1
    -1, factually incorrect. `SplFileInfo` *is not* based on a resource type (you might be thinking of [`SplFileObject`](http://us2.php.net/manual/en/class.splfileobject.php) instead), and failing to explain why resources can't be serialized doesn't help. – Charles Jun 05 '11 at 16:22
  • 1
    @yes, the fact that resources can't be serialized is very non-obvious to people that haven't worked with PHP. – Charles Jun 05 '11 at 16:36
  • @yes, I have been unable to duplicate your results showing that there's a resource handle being created by `SplFileInfo`. **Can you please post a more comprehensive, *verifiable* test case?** – Charles Jun 07 '11 at 18:19
  • 1
    @Charles: Actually running it again it's giving me not always the same results. Sometimes it returns `Resource id #1`, somtimes it returns `Resource id #2` So at this point I can't really say if splfileinfo always open a new handler or only under some circumstances – dynamic Jun 07 '11 at 18:22
5

SplFileInfo can not be serialized because the PHP team has marked it as unserializable. Really, this isn't surprising: The only actual data that a SplFileInfo object would contain would be the filename. Each method in the class is effectively a wrapper for the non-OO standard function that does the same thing. These method calls are resolved at call time, not when the object is created, so serializing the object would not capture the state of the file as it was at serialize time.

If you're trying to build a list of files to remember later, build the list from the file names.

If you're trying to build a list of files and their properties at a specific time, then grab those properties and store those instead of the object. * Please keep in mind that PHP caches the results of stat-based functions for you, so there's no overwhelming need to add another caching layer.


Here is the C file containing the underlying mechanisms for SplFileInfo and SplFileObject. The method SPL uses to open a file handle is called spl_filesystem_file_open. If you search the file, you will see four references to it. One is the function definition. One is in the constructor for SplFileObject. One is in the constructor for SplTempFileObject.

There are other references in there, when working with entities on the filesystem, of a definition called SPL_FS_FILE. A switch statement with SPL_FS_FILE as one of the conditions is the fourth and final spl_filesystem_file_open call. It's inside a function called spl_filesystem_object_create_type, which creates the actual internal structure that the various filesystem-based SPL objects work upon. Note that right above the SPL_FS_FILE case is a SPL_FS_INFO case, which handles SplFileInfo cases, and note how that code does not contain a filehandle open.

This is concrete proof that SplFileInfo does not contain a file handle resource.

The file also contains the code that prevents SplFileInfo from being serialized, by marking it as not serializable... without comment. Darn.


Debunking the resource issue even further at the PHP interactive prompt

[charles@duo ~/splfileinfo_test]$ touch a b c d e
[charles@duo ~/splfileinfo_test]$ php -a
Interactive shell

php > $fh_a = fopen('./a', 'r');
php > echo $fh_a; # should be 1
Resource id #2
php > # WHAT.
php > $fh_b = fopen('./b', 'r');
php > echo $fh_b; # should be ... uh ... 3 now?
Resource id #3
php > $fi_c = new SplFileInfo('./c');
php > $fh_d = fopen('./d', 'r');
php > echo $fh_d; # should be 4 if SplFileInfo has no internal resource
Resource id #4
php > exit
[charles@duo ~/splfileinfo_test]$ php -v
PHP 5.3.6 (cli) (built: Mar 19 2011 07:44:03)
Copyright (c) 1997-2011 The PHP Group
Zend Engine v2.3.0, Copyright (c) 1998-2011 Zend Technologies
    with Xdebug v2.1.0, Copyright (c) 2002-2010, by Derick Rethans
Charles
  • 50,943
  • 13
  • 104
  • 142
  • Actually you are wrong. SplFileInfo open a resource to a file and store it internally therefore it cannot be serialized. – dynamic Jun 05 '11 at 16:35
  • Cite your source. Perhaps you are thinking of [the `openFile` method](http://us2.php.net/manual/en/splfileinfo.openfile.php), which returns a [`SplFileObject`](http://us2.php.net/manual/en/class.splfileobject.php), which *would* open the file. `SplFileInfo` -- emphasis on the **`Info`** there -- is just a wrapper to file information functions, **none of which require that the file be opened.** – Charles Jun 05 '11 at 16:38
  • @charles: Editing my answer. Hang on. – dynamic Jun 05 '11 at 16:44
  • @yes, I have updated my answer with concrete evidence that `SplFileInfo` does not contain a file handle. – Charles Jun 05 '11 at 16:58
  • I wouldn't call `concrete evidence` also give me some time to study that .c. Also we went completly OT than the OP question – dynamic Jun 05 '11 at 17:02
  • @yes, indeed we have. I have also now updated my post with an example showing, using real code, that SplFileInfo **does** not increment the resource counter. I'm confused at how your example and mine differ. Can you please try the example code? – Charles Jun 05 '11 at 17:15