php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Request #48079 Provide a way to serialize classes to include files
Submitted: 2009-04-26 14:02 UTC Modified: 2009-04-28 12:58 UTC
From: php at prog dot hu Assigned:
Status: Not a bug Package: Feature/Change Request
PHP Version: 5.3.0RC1 OS:
Private report: No CVE-ID: None
View Add Comment Developer Edit
Welcome! If you don't have a Git account, you can't do anything here.
You can add a comment by following this link or if you reported this bug, you can edit this bug over here.
(description)
Block user comment
Status: Assign to:
Package:
Bug Type:
Summary:
From: php at prog dot hu
New email:
PHP Version: OS:

 

 [2009-04-26 14:02 UTC] php at prog dot hu
Description:
------------
This entry is about a feature request for a way to serialize/export complete class structures to include files. 

The purpose of this extensions would be to enable template systems, configuration intensive frameworks, etc. to use a persistent object storage which can take advantage of present opcode accelerators (eAccelerator, mmcache, etc), and thus avoid the overhead of classical parsing of serialized objects.

Classical serialize()/unserialize() gets very slow when the serialized state grows large (>100KB), and is also a waste of CPU with mostly static serialized objects, as it forces PHP to parse the serialized string over and over (even when it's more effective than direct PHP source parsing). The solution to this problem could be to provide a way to export complete objects and object structures (also including circular or back+forth references) to PHP include files, which then in turn - when stored in the file system - could be easily re-instantiated at any point without the need of a re-parse if an accelerator is present in the system. (Even if an accelerator isn't present, the overhead of parsing a var_export-style object-construction shouldn't be lot worser than parsing the output of serialize(), and shouldn't result in significantly larger output).

Currently PHP provides no integral means to to such an export (var_export() fails on circular references and too deep object nesting), and even though this can be circumvented from custom PHP code (with a lot of tricks, like casting an object to an array to be able to enumerate all it's members, including hidden ones, and usage of reflection API to get the actual value of hidden member fields), there's practically no way to re-instantiate the class in/from the generated source (include), as the standard constructor can't be avoided/circumvented when re-instantiating an object, making it impossible to load an object state directly back into memory.

To solve the problem PHP should provide a way to statically instantiate a class with predefined member field values (much like the __set_state() magic method, but _without the need of define this method in each classes_, and also without the method calling the "normal" constructor used for in-code instantiation, which defeats the purpose of serialization). This method the could be used in the generated include files to re-instantiate the class and restore it's state as it was when it was serialized. Circular references can be easily resolved with late-binding in the include, so practically the var_export() style can be preserved (with extra fixup code added after the basic construction of the object-hierarchy skeleton, to resolve the circular references). 

The extra method wouldn't open up any new security vulnerabilities and affect the object integrity (by avoiding the standard constructor and thus theorethically enabling to set all kind of inconsistent values in member fields accross the objects), as the input of unserialize() can be manipulated too anyway, so construction of possibly invalid object states and creation of objects with arbitrary member field values is already possible even without this special method/function I'm asking for.


Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2009-04-27 08:25 UTC] johannes@php.net
You can use the Serializeable interface or __sleep/__wakeup o do everything you want
 [2009-04-28 12:58 UTC] php at prog dot hu
The purpose of the extension I'm proposing is to avoid the overhead of (re)parsing classic serialized strings, and enabling the use of opcodes caches (if present), by storing the object state in native PHP code, instead of the format used by serialize()/deserialize() (which is not native code, and thus cannot be opcode-cached, and needs to be re-parsed every time the object is loaded back). Now you recommend me to use serialize/deserialize? How does that make sense?

Also __sleep() and __wakeup() is irrelevant for the problem I described, as the problem I'm having is that you can't "construct" (allocate space for) an object instance of a specific class (for the purpose of restoring its state from previously stored values) without calling the constructor in the first place. The latter is a problem because calling the regular constructor would require passing parameters you can't deduce from the object's state in general, thus preventing use of it in a dynamic object persistance framework. Also the constructor might execute operations that aren't desired in the case when the object is not really constructed for the first time, but loaded back from a persistent storage. That's why unserialize() doesn't call the constructor either when creating the object.

This problem has nothing to do with __sleep() and __wakeup() which are called prior to and after serialization, but only _after the object instance has been allocated and its properties were restored_. The latter one is the problem I'm trying to solve, but it seems impossible with current PHP constructs (except deserialize() which is what I'm trying to circumvent).
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Fri Apr 26 13:01:28 2024 UTC