Skip to content

Conversation

@Sajid-al-islam
Copy link
Contributor

@Sajid-al-islam Sajid-al-islam commented Oct 19, 2025

Fixes #57357

Fixes serialization errors when using PHP 8.4 property hooks in Eloquent models. When models with property hooks a serialized, Laravel throws: serialize(): "property_name" returned as member variable from __sleep() but does not exist.

Property hooks create virtual properties without actual storage. The current __sleep() uses get_object_vars() which includes these virtual properties, causing serialization to fail.

Solution: Changed get_object_vars($this) to get_mangled_object_vars($this) in Model::__sleep(). This only returns properties with actual storage, excluding virtual property hooks.

Tests: Added comprehensive coverage in EloquentModelPropertyHooksTest.php for getter hooks, setter hooks, multiple hooks, mixed properties, and queue scenarios.

@Sajid-al-islam Sajid-al-islam marked this pull request as draft October 19, 2025 12:10
@Sajid-al-islam Sajid-al-islam marked this pull request as ready for review October 19, 2025 12:39
@crynobone crynobone marked this pull request as draft October 19, 2025 13:15
@Sajid-al-islam
Copy link
Contributor Author

Hello, @crynobone Is there any dependency?
as far as I checked, the failed test case is not related to any code changes

here is the error

Need to get 1481 kB of archives.
After this operation, 7558 kB of additional disk space will be used.
Get:1 file:/etc/apt/apt-mirrors.txt Mirrorlist [144 B]
Get:2 http://azure.archive.ubuntu.com/ubuntu noble/universe amd64 libjemalloc2 amd64 5.3.0-2build1 [256 kB]
Get:3 http://azure.archive.ubuntu.com/ubuntu noble/universe amd64 liblzf1 amd64 3.6-4 [7624 B]
Ign:4 http://azure.archive.ubuntu.com/ubuntu noble-updates/universe amd64 redis-tools amd64 5:7.0.15-1ubuntu0.24.04.1
Ign:5 http://azure.archive.ubuntu.com/ubuntu noble-updates/universe amd64 redis-server amd64 5:7.0.15-1ubuntu0.24.04.1
Ign:4 https://archive.ubuntu.com/ubuntu noble-updates/universe amd64 redis-tools amd64 5:7.0.15-1ubuntu0.24.04.1
Ign:5 https://archive.ubuntu.com/ubuntu noble-updates/universe amd64 redis-server amd64 5:7.0.15-1ubuntu0.24.04.1
Ign:4 https://security.ubuntu.com/ubuntu noble-updates/universe amd64 redis-tools amd64 5:7.0.15-1ubuntu0.24.04.1
Err:4 mirror+file:/etc/apt/apt-mirrors.txt noble-updates/universe amd64 redis-tools amd64 5:7.0.15-1ubuntu0.24.04.1
 404  Not Found [IP: 40.81.13.82 80]
Ign:5 https://security.ubuntu.com/ubuntu noble-updates/universe amd64 redis-server amd64 5:7.0.15-1ubuntu0.24.04.1
Err:5 mirror+file:/etc/apt/apt-mirrors.txt noble-updates/universe amd64 redis-server amd64 5:7.0.15-1ubuntu0.24.04.1
 404  Not Found [IP: 40.81.13.82 80]
E: Failed to fetch mirror+file:/etc/apt/apt-mirrors.txt/pool/universe/r/redis/redis-tools_7.0.15-1ubuntu0.24.04.1_amd64.deb  404  Not Found [IP: 40.81.13.82 80]
Fetched 264 kB in 1s (185 kB/s)
E: Failed to fetch mirror+file:/etc/apt/apt-mirrors.txt/pool/universe/r/redis/redis-server_7.0.15-1ubuntu0.24.04.1_amd64.deb  404  Not Found [IP: 40.81.13.82 80]
E: Unable to fetch some archives, maybe run apt-get update or try with --fix-missing?
Error: Process completed with exit code 100.

@Sajid-al-islam Sajid-al-islam marked this pull request as ready for review October 19, 2025 13:56
@macropay-solutions
Copy link

@Sajid-al-islam We see you are at least the 3rd one to attempt this change.
All previous attempts were rejected.
Our questions are:

  • What impact will have this increase in the serialized object string that now will contain also private and protected properties?
  • Does it worth it for a happy flow of using property hooks directly into the model (that will work only if there are no clashes between the names of the actual model properties and the properties that are defined by the developer). The active record is not a Symfony entity.

@Sajid-al-islam
Copy link
Contributor Author

@macropay-solutions
Previous attempts rejected because of failing test cases

  • There is NO increase in serialized string size or change in behavior.
    Both get_object_vars() and get_mangled_object_vars() return the same properties when called from inside the class (via $this). The difference is:
    get_object_vars($this) - returns properties + property hooks (virtual)
    get_mangled_object_vars($this) - returns ONLY actual properties (no virtual hooks)
    We're not adding private/protected properties. We're just removing virtual properties.

  • Yes, because the current code is broken for a valid PHP 8.4 feature, and the fix has zero impact on existing code. And property hooks can't clash with actual properties—that's enforced by PHP itself. If there's a clash, PHP throws an error at parse time, not runtime.

@macropay-solutions
Copy link

macropay-solutions commented Oct 20, 2025

@Sajid-al-islam

Both get_object_vars() and get_mangled_object_vars() return the same properties when called from inside the class (via $this). The difference is:
get_object_vars($this) - returns properties + property hooks (virtual)
get_mangled_object_vars($this) - returns ONLY actual properties (no virtual hooks)

Thank you.

that's enforced by PHP itself. If there's a clash, PHP throws an error at parse time, not runtime.

Yes and this is making php attribute hooks in active record just a happy flow usage (coupled with the fact that arrays are not fully supported either). But that is not a stopper for this PR. Laravel is full of happy flows.EE

UPDATE

class A {
    public $public = 1;
    protected $protected = 2;
    private $private = 3;
}

class B extends A {
    private $private = 4;

    public function showVars() {
        var_dump(get_object_vars($this));
        var_dump(get_mangled_object_vars($this));
    }
}
echo '<pre>';
$obj = new B();
$obj->dynamic = 5;
$obj->showVars();

DEPRECATED Creation of dynamic property B::$dynamic is deprecated on line number 17
array(4) {
["public"]=>
int(1)
["protected"]=>
int(2)
["private"]=>
int(4)
["dynamic"]=>
int(5)
}
array(5) {
["public"]=>
int(1)
["*protected"]=>
int(2)
["Aprivate"]=>
int(3)
["Bprivate"]=>
int(4)
["dynamic"]=>
int(5)
}

@Sajid-al-islam

Both get_object_vars() and get_mangled_object_vars() return the same properties when called from inside the class (via $this). The difference is:
get_object_vars($this) - returns properties + property hooks (virtual)
get_mangled_object_vars($this) - returns ONLY actual properties (no virtual hooks)

It looks that the results are not exactly the same.

@Sajid-al-islam
Copy link
Contributor Author

Sajid-al-islam commented Oct 20, 2025

@macropay-solutions

You're right, my bad, get_mangled_object_vars() includes parent class private properties with prefixes. However, this doesn't negatively impact Laravel models since they don't use conflicting private properties across inheritance. The real issue is property hooks causing crashes, which this fixes. Although get_mangled_object_vars properly preserves inherited properties during serialization, As all the old test cases passed from laravel framework, I think it can be merged, let's see what Tyler has to say.

@taylorotwell
Copy link
Member

I don't think we're really thinking this through - we're just hoping this works and crossing our fingers. I need someone to really dig into it deeply and give a considered solution (even if it is this solution) that is well explained.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Error serialised with php8. 4 Hooks

4 participants