Alexander Lisachenko has floated an RFC proposal to extend PHP's Foreign Function Interface (FFI) with opt-in mapping of C struct types to userland PHP classes.

The current FFI implementation wraps all C values—strings, objects, primitive pointers—in a single final FFI\CData class. This uniform type maintains flexibility but prevents static analysis tools and IDEs from type-checking struct fields, and instanceof operations cannot work on mapped types. FFI binding generators currently work around this limitation by shipping stub classes, IDE metadata files, and analyzer plugins, yet the result remains weaker than native support.

Lisachenko's proposal introduces an options array to FFI::cdef() that accepts a classmap configuration, mapping C type names to PHP class names:

```php $ffi = FFI::cdef($code, $lib, options: [ 'classmap' => [ 'zend_string' => \My\Engine\ZendString::class, ], ]); ```

When a type is registered, every FFI handle created for it—from FFI::new(), FFI::cast(), struct-field reads, or function returns—becomes an instance of the mapped class. This enables get_class() to return the correct type, instanceof checks to work, and native parameter and return type declarations to be enforced.

The implementation remains local to ext/ffi with zero overhead when unused. Object storage stays the same zend_ffi_cdata structure with shared handlers; only the class entry pointer changes. The only breaking change is that FFI\CData becomes extendable for registered classes. All changes are backward compatible and opt-in.

The proposal also mentions an optional typemap for custom marshalling callbacks (from_cdata/to_cdata), though the author seeks feedback on whether to include that feature in a first iteration.

Lisachenko maintains the z-engine framework, which already emulates these semantics in userland, providing a real-world test bed. He targets PHP 8.6 and volunteers to implement the feature if feedback is positive.