====== PHP RFC: Add OOP methods to Curl objects ====== * Version: 0.1 * Date: 2024-02-14 * Author: Sara Golemon, pollita@php.net * Status: Under Discussion * First Published at: http://wiki.php.net/rfc/curl-oop ===== Introduction ===== As part of the [[https://github.com/php/php-tasks/issues/6|Resource to object conversion project]], the cURL resource types were converted to objects with the release of PHP 8.0 . Currently, those objects are still opaque types for holding and managing the underlying libcurl types, and do not offer any APIs for use by script authors. ===== Proposal ===== This RFC aims to add OOP interfaces to the cURL extension, primarily by aliasing free functions to matching methods in the `CurlHandle`, `CurlMultiHandle`, and `CurlShareHandle` classes. Additionally, this RFC aims to make a handful of changes to the behaviors and return values of some methods in the interest of presenting a more objects-style API. ==== Exceptions ==== Four new exceptions will be introduced. A top level `CurlException` to cover all cURL exception types, plus three specific exceptions as children of `CurlException`: `CurlHandleException`, `CurlMultiException`, and `CurlShareException`. ==== CurlHandle ==== The `CurlHandle` class will be expanded as follows: /** * @strict-properties * @not-serializable */ final class CurlHandle { /** * Behaves similarly to `curl_init(?string $uri = null): \CurlHandle`, * however this constructor implicitly sets CURLOPT_RETURNTRANSFER == true. */ public function __construct(?string $uri = null) {} /** @alias curl_errno */ public function errno(): int {} /** @alias curl_error */ public function error(): string {} /** @alias curl_strerror */ static public function strerror(int $code): string {} /** @alias curl_escape */ public function escape(string $str): string {} /** @alias curl_unescape */ public function unescape(string $str): string {} /** * @throws CurlHandleException * * Similar to `curl_exec(\CurlHandle $ch): string|bool`, * but never returns False, since errors are promoted to exceptions. */ public function exec(): string|true {} /** @alias curl_pause */ public function pause(int $flags): int {} /** @alias curl_reset */ public function reset(): void {} /** @alias curl_getinfo */ public function getInfo(?int $option = null): mixed {} #if LIBCURL_VERSION_NUM >= 0x073E00 /* Available since 7.62.0 */ /** @alias curl_upkeep */ public function upkeep(): bool {} #endif /** * Varies from curl_setopt() to allow fluent chaining. * @throws CurlHandleException */ public function setOpt(int $option, mixed $value): \CurlHandle {} /** * Returns self to match setOpt() behavior. * @throws CurlHandleException */ public function setOptArray(array $option): \CurlHandle {} } ==== CurlMultiHandle ==== The `CurlMultiHandle` class will be expanded as follows: /** * @strict-properties * @not-serializable */ final class CurlMultiHandle { /** * Returns self for fluent calling. * @throws CurlException. */ public function addHandle(\CurlHandle $handle): \CurlMultiHandle {} /** * Returns self for fluent calling. * @throws CurlException. */ public function removeHandle(\CurlHandle $handle): \CurlMultiHandle {} /** * Returns self for fluent calling. * @throws CurlException. */ public function setOpt(int $option, mixed $value): \CurlMultiHandle {} /** @alias curl_multi_errno */ public function errno(): int {} /** @alias curl_multi_error */ public function error(): ?string {} /** @alias curl_multi_strerror */ public function strerror(int $error_code): ?string {} /** * Returns TRUE if still running, FALSE otherwise. * @param int $still_running * @throws CurlException. */ public function exec(&$still_running): bool {} /** @alias curl_multi_getcontent */ static public function getContent(\CurlHandle $handle): ?string {} /** * @alias curl_multi_info_read * @param int $queued_messages * @return array|false * @refcount 1 */ public function infoRead(&$queued_messages = null): array|false {} /** @alias curl_multi_select */ public function select(float $timeout = 1.0): int {} } ==== CurlShareHandle ==== The `CurlShareHandle` class will be expanded as follows: /** * @strict-properties * @not-serializable */ final class CurlShareHandle { /** @alias curl_share_errno */ public function errno(): int {} /** @alias curl_share_error */ public function error(): ?string {} /** @alias curl_share_strerror */ static public function strerror(): ?string {} /** * Returns self for fluent calling. * @throws CurlException. */ public function setOpt(int $option, mixed $value): \CurlShareHandle {} } ==== New Functions ==== To make the functional API more consistent (and provide functions for the OOP implementation to alias), the following two additional functions will be added (psuedo-implementation shown): function curl_multi_error(CurlMultiHandle $multi_handle): ?string { $errno = curl_multi_errno($multi_handle); return $errno ? curl_multi_strerror($errno) ? NULL; } function curl_share_error(CurlShareHandle $share_handle): ?string { $errno = curl_share_errno($share_handle); return $errno ? curl_share_strerror($errno) ? NULL; } ===== Backward Incompatible Changes ===== No breaking changes for script code. Extensions will note small changes in intialization performed by `object_init_ex(return_value, curl_ce);` as now `curl_easy_init()` and other initialization happens in `curl_object_create` rather than deferring to constructor/curl_init(). ===== Proposed PHP Version(s) ===== 8.4.0 ===== Unaffected PHP Functionality ===== Script code written for the original cURL functional API will not be impacted. ===== Proposed Voting Choices ===== Straight yes/no. ===== Patches and Tests ===== Each existing unit test will be reviewed and duplicated as appropriate to cover the OOP version of the API. * Work in progress: https://github.com/php/php-src/pull/13394 Note that as a work in progress this may not 100% match the proposal above until it is complete. ===== Implementation ===== TBD ===== References ===== TBD ===== Rejected Features ===== TBD