PHP 8.0: CurlHandle
class objects replace curl handlers
One of the long-term goals in PHP is to convert resource
type to appropriate class objects. In PHP 8, the Curl functionality is transformed into class object based resources.
Resource to Object Migration PHP is gradually phasing out all
resource
types with class objects, and this migration is one step of the Resource to Object Migration plan.
Init functions return objects
Curl init functions curl_init
, curl_multi_init
, and curl_share_init
functions returned PHP resources prior to PHP 8. It was not possible enforce typing in those functions, or any other user-land functionality that used them.
From PHP 8, these functions return objects. You still have to use init functions to create these objects; it is not allowed to new CurlInit()
(or any other objects for that matter).
curl_init()
now returns a \CurlHandle
object
Prior to PHP 8, when you call curl_init()
, it returned a PHP resource
of type Curl
.
From PHP 8 and forward, curl_init
function returns an instance of \CurlHandle
class.
- /**
- * @return resource|false
- */
- function curl_init() {}
+ function curl_init(): \CurlHandle|false {}
final class CurlHandle {}
curl_multi_init()
now returns a CurlMultiHandle
object
Similar to curl_init()
in PHP 8, curl_multi_init()
now returns a \CurlMultiHandle
object instead of a resource
with type curl_multi
.
- /**
- * @return resource
- */
- function curl_multi_init() {}
+ function curl_multi_init(): \CurlMultiHandle {}
final class CurlMultiHandle {}
curl_share_init()
now returns a \CurlShareHandle
object
curl_share_init()
now returns a \CurlShareHandle
object instead of a resource
with type curl_share
.
- /**
- * @return resource
- */
- function curl_share_init() {}
+ function curl_share_init(): \CurlShareHandle {}
final class CurlShareHandle {}
All these newly added classes, CurlHandle
, CurlMultiHandle
, and CurlShareHandle
follow resource-to-object semantics.
-
Directly instantiating objects is not allowed. For example,
new CurlHandle
will result in an error:new CurlHandle(); new CurlMultiHandle(); new CurlShareHandle();
Cannot directly construct CurlHandle, use curl_init() instead in ... on line ... Cannot directly construct CurlMultiHandle, use curl_init() instead in ... on line ... Cannot directly construct CurlShareHandle, use curl_share_init() instead in ... on line ...
-
All classes are declared final. Extending them is not allowed:
class Foo extends CurlHandle {}
Class Foo may not inherit from final class (CurlHandle) in ... on line ...
-
No dynamic properties are allowed. Attempting to set a dynamic property will result in an error:
$ch = curl_init(); $ch->foo = 'Bar';
Cannot create dynamic property CurlHandle::$foo in ... on line ...
All curl_*
functions accept Curl*
objects instead of resources
PHP does not have a resource
type, so it was not possible to enforce a parameter or return type for any of the curl_
functions. This conveniently makes this resource
to Curl*
object transform not introduce backwards-incompatibilities.
is_resource()
returns false
on Curl*
objects
Because the Curl init function return values are standard PHP objects, is_resource
function returns false
which is the correct bahavior for that function.
This might break your existing code because it is common to check if the curl_init()
call was successful with a is_resource($handle)
call.
Note that in PHP 8 and in old versions, curl_(multi_|share_)init()
functions return false
on failed resource creation.
To make sure the code is compatible with both PHP 8 and older versions, you can change is_resource($handle)
calls with $handle !== false
calls.
$handle = \curl_init();
- if (!\is_resource($handle)) {
+ if ($handle === false) {
throw new \Exception();
}
curl_close
no longer closes the resource
Because Curl resources are now objects, Curl handles are closed when the object is no longer referenced, or explicitly destroyed.
You can still call curl_close($handle)
, but this function no longer has any effect.
In your existing code, you can explicitly unset()
the CurlHandle
object. PHP will automatically do it following standard object garbage collection mechanisms.
$handle = curl_init();
// ... use it ...
curl_close($handle);
+ unset($handle);
Backwards compatibility impact
Calling is_resource()
on Curl init function return values will now return false
, which breaks existing code. For cross-version compatibility, always use $handle === false
which will correctly evaluate in all PHP versions.
PHP has no resource
type declared in a way that you can enforce it in user-land code. This mitigates any possible typed functions.
Furthermore, curl_close
no longer effectively closes the Curl handler. Because the handlers are now objects, the resources will be destroyed during garbage collection, unless the handler is explicitly closed with an unset()
call. This unset()
call can be used in older PHP versions without breaking the functionality. See the example in curl_close
section above
It is not possible to backport this functionality to older PHP versions. This means that if you start to enforce CurlHandle
, CurlShareHandle
, and CurlShareHandle
types, that code will not work in older PHP versions.