[php-src] Issue #23328: SessionHandlerInterface create_sid()/validateId() warning depends on the order interfaces are listed in
[email protected] (nicolas-grekas)
| Newsgroups | php.bugs |
|---|---|
| Message-ID | <zmKpgYEaMsLkOvctjF9fO3Gnw6nTEhapVWtAuK16hkU@main.internal.php.net> |
Issue: https://github.com/php/php-src/issues/23328
Author: nicolas-grekas
### Description
The `create_sid()`/`validateId()` check added in 6901c87aeabf28cbb08dadc2ac64d1dabfdfdd3c depends on the order the interfaces are listed in, so a class that does implement `SessionIdInterface` and `SessionUpdateTimestampHandlerInterface` can still be reported as missing their methods.
The following code:
```php
<?php
abstract class A implements SessionHandlerInterface, SessionIdInterface, SessionUpdateTimestampHandlerInterface {}
abstract class B implements SessionIdInterface, SessionUpdateTimestampHandlerInterface, SessionHandlerInterface {}
```
Resulted in this output:
```
Warning: Class A implementing SessionHandlerInterface is missing the create_sid() method which will be required in PHP 9.0 in /tmp/iface-order.php on line 2
Warning: Class A implementing SessionHandlerInterface is missing the validateId() method which will be required in PHP 9.0 in /tmp/iface-order.php on line 2
```
But I expected this output instead:
```
```
`A` and `B` differ only in the order of the `implements` list, and both declare `create_sid()` and `validateId()` through the interfaces they implement.
`session_handler_interface_gets_implemented()` is registered as the `interface_gets_implemented` handler of `SessionHandlerInterface`, so it runs while that interface is being attached to the class. At that point the sibling interfaces have not been linked yet, so `class->function_table` only holds the methods the class declares itself:
```c
static int session_handler_interface_gets_implemented(zend_class_entry *self, zend_class_entry *class) {
if (!zend_hash_str_exists(&class->function_table, ZEND_STRL("create_sid"))) {
```
Listing `SessionIdInterface` before `SessionHandlerInterface` makes the abstract method present in time and the warning disappears, which is why `B` is silent.
Declaring the methods on the class itself also silences it, so this only affects classes that rely on the interfaces to declare them — abstract classes and interfaces meant to be implemented further down, where declaring the methods again would be redundant.
### PHP Version
```plain
PHP 8.6.0-dev (cli) (built: Aug 16 2026 17:43:53) (NTS DEBUG)
Copyright © The PHP Group and Contributors
Zend Engine v4.6.0-dev, Copyright © Zend by Perforce
with Zend OPcache v8.6.0-dev, Copyright ©, by Zend by Perforce
```
Built from 9f32f90ad35.
### Operating System
Ubuntu 24.04.4 LTS