====== PHP RFC: Deprecate FFI non-static methods ======
* Version: 0.2
* Date: 2024-06-21
* Author: Chopins, chopins.xiao@gmail.com
* Target version: PHP 8.4
* Status: Draft
* First Published at: https://wiki.php.net/rfc/ffi-non-static-deprecated
===== Introduction =====
**FFI::new(), FFI::type(), FFI::cast()** support static and non-static access, which is very confusing. This issue has been proposed to be amended in the RFC that has already been adopted. However, the RFC proposal and actual implementation is to mark static access as deprecated, which will further confuse and ugliness of the FFI function API. Here's why:
1. Because the method of calling a class method through an FFI instance is the way to access C functions, and this method is mixed with the access of PHP class methods.
$a = FFI::cdef($def);
$a->new(); //This PHP class method is not a C function
$a->new2(); //This is a C function
2. If you can't statically call FFI::new() and other functions, it will cause some PHP code to be very complicated and inefficient.
$a1 = FFI::cdef()->new('int'); //statically is deprecated, complex and ugly code
$a2 = FFI::new('int'); //current allowed
3. The name of the C library function is occupied, resulting in a vague concept
$b = FFI::cdef('int cast(long a);', 'third-party.so');
$b->cast($a); //This is a call to FFI::cast(), which is ambiguous.
===== Proposal =====
It is recommended to add a **FFICDef** class to access the handle as a C function. **FFI::cdef()** returns an instance of **FFICDef** instead of an instance of the **FFI** class. For the **FFI::new()**, **FFI::type()**, and **FFI::cast()** methods, the last parameter is added to receive the **FFICDef** instance. This is how FFI's API behavior becomes uniform and less confusing.
After the change, the method signature is as follows:
final class FFI\CDef {}
public static FFI::cdef(string $code = "", ?string $lib = null): FFI\CDef
public static FFI::new(FFI\CType|string $type, bool $owned = true, bool $persistent = false, FFI\CDef $cdef = null): ?FFI\CData
public static FFI::cast(FFI\CType|string $type, FFI\CData|int|float|bool|null &$ptr, FFI\CDef $cdef = null): ?FFI\CData
public static FFI::type(string $type, FFI\CDef $cdef = null): ?FFI\CType
During the transition phase, the class **FFI\CDef** instance will provide **FFI\CDef::new(),FFI\CDef::cast(),FFI\CDef::type()** three non-static methods for the transition, but will deprecated error is reported. As follows:
PHP Deprecated: Calling FFI->new() or FFI\CDdef->new() non-statically is deprecated
PHP Deprecated: Calling FFI->cast() or FFI\CDdef->cast() non-statically is deprecated
PHP Deprecated: Calling FFI->type() or FFI\CDdef->type() non-statically is deprecated
===== Backward Incompatible Changes =====
Since non-static calls are marked as stale, they will result in a stale prompt being received for versions less than PHP 8.3. If PHP 9.0 removes non-static calls to FFICDef::new(), FFICDef::cast(), FFICDef::type(), it will result in an error in the unadapted program.
===== Proposed PHP Version(s) =====
PHP 8.4
===== Impact on extensions =====
FFI
===== Open Issues =====
https://github.com/php/php-src/issues/8554
===== Implementation =====
Implementation reference https://github.com/php/php-src/pull/8585