PHPackages                             jshensh/php-curl-class - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [HTTP &amp; Networking](/categories/http)
4. /
5. jshensh/php-curl-class

ActiveLibrary[HTTP &amp; Networking](/categories/http)

jshensh/php-curl-class
======================

PHP HTTP client, based on cURL

1.0.0(5mo ago)532.8k↓50%18[1 issues](https://github.com/jshensh/php-curl-class/issues)GPL-3.0-or-laterPHPPHP &gt;=5.6

Since Mar 23Pushed 5mo ago4 watchersCompare

[ Source](https://github.com/jshensh/php-curl-class)[ Packagist](https://packagist.org/packages/jshensh/php-curl-class)[ RSS](/packages/jshensh-php-curl-class/feed)WikiDiscussions master Synced 1mo ago

READMEChangelogDependenciesVersions (23)Used By (0)

Custom Curl (嗯懒得取名字)
====================

[](#custom-curl-嗯懒得取名字)

对 PHP 自带 curl 的一个简单的封装，支持链式操作。

安装
--

[](#安装)

```
composer require jshensh/php-curl-class
```

使用示例
----

[](#使用示例)

### GET 方法

[](#get-方法)

```
use CustomCurl\Client;

$curlObj = Client::init('http://cn.bing.com/search?q=php')->exec();

if (!$curlObj->getStatus()) {
    throw new \Exception('Curl Error', $curlObj->getCurlErrNo());
}

var_dump($curlObj->getHeader(), $curlObj->getCookies(), $curlObj->getBody(), $curlObj->getInfo());
```

### POST 方法

[](#post-方法)

```
use CustomCurl\Client;

$curlObj = Client::init('http://www.w3school.com.cn/example/php/demo_php_global_post.php', 'post')
    ->set('postFields', ['fname' => 'jshensh'])
    ->exec();

if (!$curlObj->getStatus()) {
    throw new \Exception('Curl Error', $curlObj->getCurlErrNo());
}

var_dump($curlObj->getHeader(), $curlObj->getCookies(), $curlObj->getBody(), $curlObj->getInfo());
```

### POST 上传文件

[](#post-上传文件)

```
use CustomCurl\Client;

$curlObj = Client::init('http://127.0.0.1/examples/example_server.php', 'post')
    ->set('postFields', [
        'fname'    => 'jshensh',
        'files[0]' => new CURLFile('./README.md'),
        'files[1]' => new CURLFile('LICENSE')
    ])
    ->set('postFieldsBuildQuery', false)    // postFieldsBuildQuery 设置为 True 时，将对 postFields 进行 http_build_query，避免出现跨语言无法 POST 数据的问题。如需上传文件则需要将该项设置为 False。
    ->exec();

if (!$curlObj->getStatus()) {
    throw new \Exception('Curl Error', $curlObj->getCurlErrNo());
}

var_dump($curlObj->getHeader(), $curlObj->getCookies(), $curlObj->getBody(), $curlObj->getInfo());
```

### PUT 方法，传输 JSON 数据

[](#put-方法传输-json-数据)

```
use CustomCurl\Client;

$curlObj = Client::init('http://lab.imjs.work/server.php', 'put')
    ->set('postFields', ['fname' => 'jshensh']) // 可以传入数组
    ->set('postFields', '{"fname": "jshensh"}') // 也可以直接传入 json 字符串
    ->set('postType', 'json')
    ->exec();

if (!$curlObj->getStatus()) {
    throw new \Exception('Curl Error', $curlObj->getCurlErrNo());
}

var_dump($curlObj->getHeader(), $curlObj->getCookies(), $curlObj->getBody(), $curlObj->getInfo());
```

### 手动设置 Cookie

[](#手动设置-cookie)

```
use CustomCurl\Client;

$cookieJar = [];
$curlObj = Client::init('http://example.com')
    ->cookieJar($cookieJar)   // 设置 CookieJar，类似于 CURLOPT_COOKIEJAR，可在多次交互过程中自动存取 Cookies
    ->setCookie('a', 'b')     // 设置 Cookie，Key => Value
    ->clearCookies()          // 清空之前设置的所有 Cookie
    ->setCookie('b', 'c')     // 重新设置 Cookie，Key => Value
    ->exec();

if (!$curlObj->getStatus()) {
    throw new \Exception('Curl Error', $curlObj->getCurlErrNo());
}

var_dump($curlObj->getHeader(), $curlObj->getCookies(), $curlObj->getBody(), $curlObj->getInfo());
```

### Cookie 字符串/数组

[](#cookie-字符串数组)

```
use CustomCurl\Client;

$curlObj = Client::init('http://example.com')
    ->setCookie('a', 'b')             // 设置 Cookie，Key => Value
    ->setCookies('b=c; c=d')          // 传入字符串设置 Cookie，之前设置的 cookie 失效
    ->setCookies('d=e; c=f', true)    // 传入字符串追加设置 Cookie，Key 相同的 cookie 将会被覆盖
    ->setCookies(['e' => 'f'], true)  // 传入数组追加设置 Cookie，只允许传入一维数组
    ->setCookies(['e' => ['f', 'g']]) // 传入二维数组将忽略
    ->setCookies('dsjdhs')            // 传入不合法字符串将忽略
    ->exec();

if (!$curlObj->getStatus()) {
    throw new \Exception('Curl Error', $curlObj->getCurlErrNo());
}

var_dump($curlObj->getHeader(), $curlObj->getCookies(), $curlObj->getBody(), $curlObj->getInfo());
```

### Header

[](#header)

```
use CustomCurl\Client;

$curlObj = Client::init('http://example.com/api')
    ->setHeader('X-PJAX', 'true')                         // 设置 Header，Key => Value
    ->clearHeaders()                                      // 清空之前设置的所有 Header
    ->setHeader('X-Requested-With', 'XMLHttpRequest')     // 设置 Header，Key => Value
    ->exec();

if (!$curlObj->getStatus()) {
    throw new \Exception('Curl Error', $curlObj->getCurlErrNo());
}

var_dump($curlObj->getHeader(), $curlObj->getCookies(), $curlObj->getBody(), $curlObj->getInfo());
```

### 自定义 CurlOpt

[](#自定义-curlopt)

```
use CustomCurl\Client;

$headerSize = -1;

$curlObj = Client::init('http://example.com')
    ->setCurlOpt(CURLOPT_SSL_VERIFYPEER, false)                                   // CURLOPT_SSL_VERIFYPEER，默认值 True
    ->setCurlOpt(CURLOPT_SSL_VERIFYHOST, 0)                                       // CURLOPT_SSL_VERIFYHOST，默认值 2
    ->setCurlOpt(CURLOPT_NOBODY, false)                                           // CURLOPT_NOBODY，默认值 False
    ->setCurlOpt(CURLOPT_HEADER, true)                                            // CURLOPT_HEADER，默认值 True
    ->setCurlOpt(CURLOPT_ENCODING, '')                                            // CURLOPT_ENCODING，默认值 ''
    ->setCurlOpt(CURLOPT_SSLCERT, dirname(__FILE__) . '/client.crt')              // CURLOPT_SSLCERT，SSL 双向认证证书路径
    ->setCurlOpt(CURLOPT_SSLKEYPASSWD, '')                                        // CURLOPT_SSLKEYPASSWD，证书需要的密码
    ->setCurlOpt(CURLOPT_SSLCERTTYPE, 'PEM')                                      // CURLOPT_SSLCERTTYPE，证书的类型，支持的格式有 "PEM" (默认值), "DER" 和 "ENG"
    ->setCurlOpt(CURLOPT_SSLKEY, dirname(__FILE__) . '/client.key')               // CURLOPT_SSLKEY，SSL 双向认证证书的私钥
    ->setCurlOpt(CURLOPT_SSLKEYPASSWD, '')                                        // CURLOPT_SSLKEYPASSWD，CURLOPT_SSLKEY 私钥的密码
    ->setCurlOpt(CURLOPT_SSLKEYTYPE, 'PEM')                                       // CURLOPT_SSLKEYTYPE，私钥的加密类型，支持的密钥类型为 "PEM"(默认值)、"DER" 和 "ENG"
    ->setCurlOpt(CURLOPT_WRITEFUNCTION, function($ch, $data) use (&$headerSize) { // CURLOPT_WRITEFUNCTION，下载时的回调函数，通常用于反向代理即时传输数据
        $info = curl_getinfo($ch);
        if ($headerSize < $info['header_size']) {
            $headerSize = $info['header_size'];
            if ($data === "\r\n") {
                $headerSize += 2;
            }
            header($data, false);
        } else {
            echo $data;
        }
        ob_flush();
        flush();
        return strlen($data);
    })
    ->exec();

if (!$curlObj->getStatus()) {
    throw new \Exception('Curl Error', $curlObj->getCurlErrNo());
}

var_dump($curlObj->getHeader(), $curlObj->getCookies(), $curlObj->getBody(), $curlObj->getInfo());
```

### 并发请求

[](#并发请求)

```
use CustomCurl\Client;

$cookieJar = [];

$multiCurl = Client::multi([
    'test6' => Client::init('http://127.0.0.1/examples/example_server.php')->cookieJar($cookieJar),
    'test4' => Client::init('http://127.0.0.1/examples/example_server.php')->cookieJar($cookieJar),
    'test3' => Client::init('http://127.0.0.1/examples/example_server.php')->cookieJar($cookieJar),
    'test1' => Client::init('http://127.0.0.1/examples/example_server.php')->cookieJar($cookieJar),
    'test9' => Client::init('http://127.0.0.1/examples/example_server.php')->cookieJar($cookieJar),
    'test8' => Client::init('http://127.0.0.1/examples/example_server.php')->cookieJar($cookieJar),
], ['concurrency' => 3]);

foreach ($multiCurl as $k => $curlObj) {
    var_dump($k, $curlObj->getStatus(), $curlObj->getHeader(), $curlObj->getCookies(), $curlObj->getBody(), $curlObj->getInfo());
}

var_dump($cookieJar);

$multiCurl = Client::multi([
    Client::init('http://127.0.0.1/examples/example_server.php')->cookieJar($cookieJar),
    Client::init('http://127.0.0.1/examples/example_server.php')->cookieJar($cookieJar),
]);

foreach ($multiCurl as $k => $curlObj) {
    var_dump($k, $curlObj->getStatus(), $curlObj->getHeader(), $curlObj->getCookies(), $curlObj->getBody(), $curlObj->getInfo());
}

var_dump($cookieJar);
```

设置项
---

[](#设置项)

```
use CustomCurl\Client;

$curlObj = Client::init('http://cn.bing.com')
    ->set('referer', 'http://google.com')       // 设置 HTTP REFERER
    ->set('ignoreCurlError', 1)                 // 忽略 Curl 错误，默认值 False
    ->set('timeout', 1)                         // CURLOPT_TIMEOUT，单位秒，默认值 5
    ->set('reRequest', 1)                       // 遇到错误时重新尝试的次数，默认值 3
    ->set('postFields', ['fname' => 'jshensh']) // POST 提交参数，数组
    ->set('postType', 'json')                   // 提交方式，可选 ['form', 'json', 'string']，默认值 'form'
    ->set('followLocation', 1)                  // CURLOPT_FOLLOWLOCATION，默认值 False
    ->set('autoRefer', 1)                       // CURLOPT_AUTOREFERER，默认值 True
    ->set('maxRedirs', 1)                       // CURLOPT_MAXREDIRS，默认值 3
    ->set('userAgent', 'Mozilla')               // CURLOPT_USERAGENT
    ->set('postFieldsBuildQuery', false)        // POST 时是否 build 成字符串传递，默认值 true
    ->set('postFieldsMultiPart', true)          // POST 时是否以 multipart/form-data 传递，优先级高于 postFieldsBuildQuery，默认值 false
    ->exec();

if (!$curlObj->getStatus()) {
    throw new \Exception('Curl Error', $curlObj->getCurlErrNo());
}

var_dump($curlObj->getHeader(), $curlObj->getCookies(), $curlObj->getBody(), $curlObj->getInfo());
```

杂项
--

[](#杂项)

### 多次请求同一地址

[](#多次请求同一地址)

```
use CustomCurl\Client;

$curlObj1 = Client::init('http://cn.bing.com')
                ->set('referer', 'http://google.com');

$curlObj2 = clone $curlObj1;

$curlObj1 = $curlObj1->setHeader('X-PJAX', 'true')->exec();
$curlObj2 = $curlObj2->setHeader('X-Requested-With', 'XMLHttpRequest')->exec();

if (!$curlObj1->getStatus()) {
    throw new \Exception('Curl Error', $curlObj1->getCurlErrNo());
}

var_dump($curlObj1->getHeader(), $curlObj1->getCookies(), $curlObj1->getBody(), $curlObj1->getInfo());

if (!$curlObj2->getStatus()) {
    throw new \Exception('Curl Error', $curlObj2->getCurlErrNo());
}

var_dump($curlObj2->getHeader(), $curlObj2->getCookies(), $curlObj2->getBody(), $curlObj2->getInfo());
```

### 代理

[](#代理)

```
use CustomCurl\Client;

$curlObj = Client::init('http://example.com')
    ->set('proxy', '127.0.0.1')                    // 代理地址
    ->set('proxyPort', 8080)                       // 代理端口，默认 8080
    ->set('proxyUserPwd', '[username]:[password]') // 代理用户名密码，默认不设置
    ->set('proxyType', CURLPROXY_HTTP)             // 代理类型，可选 [CURLPROXY_HTTP, CURLPROXY_SOCKS4, CURLPROXY_SOCKS5, CURLPROXY_SOCKS4A, CURLPROXY_SOCKS5_HOSTNAME]，默认 CURLPROXY_HTTP，传入常量，不要加引号
    ->exec();

if (!$curlObj->getStatus()) {
    throw new \Exception('Curl Error', $curlObj->getCurlErrNo());
}

var_dump($curlObj->getHeader(), $curlObj->getCookies(), $curlObj->getBody(), $curlObj->getInfo());
```

### 设置全局配置

[](#设置全局配置)

```
use CustomCurl\Client;

Client::setConf('timeout', 3);                            // CURLOPT_TIMEOUT，单位秒，默认值 5
Client::setConf('reRequest', 1);                          // 遇到错误时重新尝试的次数，默认值 3
Client::setConf('maxRedirs', 1);                          // CURLOPT_MAXREDIRS，默认值 3
Client::setConf('ignoreCurlError', 1);                    // 忽略 Curl 错误，默认值 False
Client::setConf('followLocation', 1);                     // CURLOPT_FOLLOWLOCATION，默认值 True
Client::setConf('referer', 'http://google.com');          // 设置 HTTP REFERER
Client::setConf('userAgent', 'Mozilla');                  // 设置 User-Agent
Client::setConf('customHeader', ['X-PJAX: true']);        // 设置 Header，要求传入数组
Client::setConf('sendCookies', 'a=b; b=c');               // 设置 Cookies，要求传入一维数组或者字符串
Client::setConf('autoRefer', 1);                          // CURLOPT_AUTOREFERER，默认值 True
Client::setConf('postType', 'json');                      // 提交方式，可选 ['form', 'json', 'string']，默认值 'form'
Client::setConf('proxy', '127.0.0.1');                    // 代理
Client::setConf('proxyPort', 8080);                       // 代理端口
Client::setConf('proxyUserPwd', '[username]:[password]'); // 代理用户名密码
Client::setConf('proxyType', CURLPROXY_HTTP);             // 代理方式
Client::setConf('postFieldsBuildQuery', false);           // POST 时是否 build 成字符串传递，默认值 true
Client::setConf('postFieldsMultiPart', true);             // POST 时是否以 multipart/form-data 传递，优先级高于 postFieldsBuildQuery，默认值 false
// 以上为所有可修改的全局配置项

$curlObj = Client::init('http://lab.imjs.work/server.php')
    ->set('userAgent', 'Test') // 在当前会话中覆盖预设值
    ->exec();

if (!$curlObj->getStatus()) {
    throw new \Exception('Curl Error', $curlObj->getCurlErrNo());
}

var_dump($curlObj->getHeader(), $curlObj->getCookies(), $curlObj->getBody(), $curlObj->getInfo());

$curlObj1 = Client::init('http://lab.imjs.work/server.php')->exec();

if (!$curlObj1->getStatus()) {
    throw new \Exception('Curl Error', $curlObj1->getCurlErrNo());
}

var_dump($curlObj1->getHeader(), $curlObj1->getCookies(), $curlObj1->getBody(), $curlObj1->getInfo());

Client::resetConf('userAgent'); // 恢复 userAgent 参数为默认值

$curlObj2 = Client::init('http://lab.imjs.work/server.php')->exec();

if (!$curlObj2->getStatus()) {
    throw new \Exception('Curl Error', $curlObj2->getCurlErrNo());
}

var_dump($curlObj2->getHeader(), $curlObj2->getCookies(), $curlObj2->getBody(), $curlObj2->getInfo());

Client::resetConf(); // 恢复全部参数为默认值

$curlObj3 = Client::init('http://lab.imjs.work/server.php')->exec();

if (!$curlObj3->getStatus()) {
    throw new \Exception('Curl Error', $curlObj3->getCurlErrNo());
}

var_dump($curlObj3->getHeader(), $curlObj3->getCookies(), $curlObj3->getBody(), $curlObj3->getInfo());
```

### 设置全局 CurlOpt 配置项

[](#设置全局-curlopt-配置项)

```
use CustomCurl\Client;

Client::setCurlOptConf(CURLOPT_SSL_VERIFYPEER, false);  // CURLOPT_SSL_VERIFYPEER，默认值 True
Client::setCurlOptConf(CURLOPT_SSL_VERIFYHOST, 0);      // CURLOPT_SSL_VERIFYHOST，默认值 2
Client::setCurlOptConf(CURLOPT_ENCODING, 'gzip');       // CURLOPT_ENCODING，默认值 ''
// 以上为所有可修改的全局 CurlOpt 配置项

$curlObj = Client::init('http://lab.imjs.work/server.php')
            ->setCurlOpt(CURLOPT_ENCODING, '') // 在当前会话中覆盖预设值
            ->exec();

if (!$curlObj->getStatus()) {
    throw new \Exception('Curl Error', $curlObj->getCurlErrNo());
}

var_dump($curlObj->getHeader(), $curlObj->getCookies(), $curlObj->getBody(), $curlObj->getInfo());

$curlObj1 = Client::init('http://lab.imjs.work/server.php')->exec();

if (!$curlObj1->getStatus()) {
    throw new \Exception('Curl Error', $curlObj1->getCurlErrNo());
}

var_dump($curlObj1->getHeader(), $curlObj1->getCookies(), $curlObj1->getBody(), $curlObj1->getInfo());

Client::resetCurlOptConf(CURLOPT_ENCODING); // 恢复 CURLOPT_ENCODING 为默认值

$curlObj2 = Client::init('http://lab.imjs.work/server.php')->exec();

if (!$curlObj2->getStatus()) {
    throw new \Exception('Curl Error', $curlObj2->getCurlErrNo());
}

var_dump($curlObj2->getHeader(), $curlObj2->getCookies(), $curlObj2->getBody(), $curlObj2->getInfo());

Client::resetCurlOptConf(); // 恢复全部 CurlOpt 配置为默认值

$curlObj3 = Client::init('http://lab.imjs.work/server.php')->exec();

if (!$curlObj3->getStatus()) {
    throw new \Exception('Curl Error', $curlObj3->getCurlErrNo());
}

var_dump($curlObj3->getHeader(), $curlObj3->getCookies(), $curlObj3->getBody(), $curlObj3->getInfo());
```

### 设置请求签名（以微信支付为例）

[](#设置请求签名以微信支付为例)

```
class Client extends \CustomCurl\Client
{
    public function sign($mchid, $serialNo, $privateKey)
    {
        $urlParts = parse_url($this->url);
        $canonicalUrl = ($urlParts['path'] . (!empty($urlParts['query']) ? "?{$urlParts['query']}" : ""));
        $timestamp = time();
        $method = strtoupper($this->method);
        $nonce = bin2hex(random_bytes(16));
        $body = $this->conf['postFields'] ? http_build_query($this->conf['postFields']) : '';
        $message = "{$method}\n{$canonicalUrl}\n{$timestamp}\n{$nonce}\n{$body}\n";

        var_dump($message, $privateKey);

        $rawSign = null;
        openssl_sign($message, $rawSign, $privateKey, 'sha256WithRSAEncryption');
        $sign = base64_encode($rawSign);

        $token = sprintf('WECHATPAY2-SHA256-RSA2048 mchid="%s",nonce_str="%s",timestamp="%d",serial_no="%s",signature="%s"', $mchid, $nonce, $timestamp, $serialNo, $sign);

        return $this->setHeader('Authorization', $token);
    }
}

$pKey = setHeader('Accept', 'application/json')
    ->sign('166*******', '****************************************', $pKey)
    ->exec();

if (!$curlObj->getStatus()) {
    throw new \Exception('Curl Error', $curlObj->getCurlErrNo());
}

var_dump($curlObj->getHeader(), $curlObj->getCookies(), $curlObj->getBody(), $curlObj->getInfo());
```

Laravel / Lumen 支持
------------------

[](#laravel--lumen-支持)

### ApiDebugger

[](#apidebugger)

ApiDebugger 是一个简单的类似 Postman 的单页接口调试工具。

CustomCurl 起初只是一个服务端的 Curl 封装，由于在随后的使用过程中发现，我们一般都用它来模拟请求其他业务的接口，甚至是[搭建反向代理](https://github.com/jshensh/phpReverseProxy)，于是就产生了对反向代理接口进行调试的需求，作为并不喜欢使用 Postman 的我就写了这个工具（后端狗用上世纪 jQuery 码的东西，不要笑）。

因为浏览器限制，在一般情况下 ApiDebugger 只能调试当前域名下的所有资源，但我们可以通过在被调试目标上添加 `Access-Control-Allow-Origin` 等 Header 或者使用反向代理解决问题。

#### 开始使用

[](#开始使用)

一般情况下，只要在 `routes/web.php` 中加入以下代码即可使用

```
if (env('APP_DEBUG')) {
    Route::get('/debugger', function () {
        return view('CustomCurl::ApiDebugger');
    });
}
```

我们可以向 view 传递以下数据

```
return view('CustomCurl::ApiDebugger', [
    'loginUrl'  => '',                     // 登录接口的 url，接口需要以 json 格式返回 token
    'loginForm' => [                       // 登录表单
        [
            'key'         => 'username',
            'label'       => 'Username',
            'placeholder' => 'Username',
            'value'       => 'admin',
            'type'        => 'text'        // dom 的类型，可选值 [number, email, text, number, password, hidden, html]
        ],
        [
            'key'         => 'password',
            'label'       => 'Password',
            'placeholder' => 'Password',
            'value'       => 'password',
            'type'        => 'password'
        ],
        [
            'type' => 'html',
            'html' => 'test'        // 当 type 为 html 时，需要传入 html 的内容
        ],
    ],
    'apiListUrl' => '/apilist',            // api 列表接口
    'loginToken' => "data['access_token']" // 登录接口返回的 token 下标
]);
```

#### 预置 Api 列表

[](#预置-api-列表)

向 `app/Http/Controller` 目录发布 `ApiListController.php`

```
php artisan vendor:publish --tag=ApiDebugger
```

在之前的基础上继续设置路由

```
if (env('APP_DEBUG')) {
    Route::get('/debugger', function () {
        return view('CustomCurl::ApiDebugger');
    });
    Route::get('/apilist', [\App\Http\Controllers\ApiListController::class, 'index']);
}
```

由于 Lumen 不支持 `vendor:publish` 操作，请手动将 [ApiListController.php](https://github.com/jshensh/php-curl-class/blob/master/src/FrameworkSupport/Laravel/Http/Controller/ApiListController.php) 复制至对应目录

#### 注册 Provider

[](#注册-provider)

由于 Lumen 不具备 Laravel 的 Discovered Package 功能，所以我们在使用 Lumen 时，需要手动注册 Provider。

请向 `/bootstrap/app.php` 中 `Register Service Providers` 代码段中添加以下代码

```
$app->register(CustomCurl\FrameworkSupport\Laravel\Providers\LoadViewsProvider::class);
```

版权信息
----

[](#版权信息)

Custom Curl 遵循 GPL-3.0 开源协议发布，并提供免费使用。

版权所有 Copyright © 2018 - 2021 by jshensh ()

All rights reserved。

更多细节参阅 [LICENSE](LICENSE)

###  Health Score

47

—

FairBetter than 94% of packages

Maintenance72

Regular maintenance activity

Popularity33

Limited adoption so far

Community13

Small or concentrated contributor base

Maturity57

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~82 days

Recently: every ~409 days

Total

22

Last Release

154d ago

Major Versions

0.0.21 → 1.0.02025-12-16

PHP version history (3 changes)0.0.1PHP ^5.6 || ^7.1

0.0.21PHP ^5.6 || ^7.0

1.0.0PHP &gt;=5.6

### Community

Maintainers

![](https://www.gravatar.com/avatar/46924d17eb78863323996e3abdcba2ca6053fd07487155be474d86ae78f6235f?d=identicon)[jshensh](/maintainers/jshensh)

---

Top Contributors

[![jshensh](https://avatars.githubusercontent.com/u/11555188?v=4)](https://github.com/jshensh "jshensh (103 commits)")

---

Tags

httpclientcurlhttp clientweb service

### Embed Badge

![Health badge](/badges/jshensh-php-curl-class/health.svg)

```
[![Health](https://phpackages.com/badges/jshensh-php-curl-class/health.svg)](https://phpackages.com/packages/jshensh-php-curl-class)
```

###  Alternatives

[aplus/http-client

Aplus Framework HTTP Client Library

2161.6M1](/packages/aplus-http-client)[zoonman/pixabay-php-api

PixabayClient is a PHP HTTP client library to access Pixabay's API

3354.7k](/packages/zoonman-pixabay-php-api)[e-moe/guzzle6-bundle

Integrates Guzzle 6 into your Symfony application

11259.2k](/packages/e-moe-guzzle6-bundle)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
