Skip to content

Instantly share code, notes, and snippets.

@dfreerksen
Created August 17, 2012 16:19
Show Gist options
  • Save dfreerksen/3380322 to your computer and use it in GitHub Desktop.
Save dfreerksen/3380322 to your computer and use it in GitHub Desktop.
PHP Curl helper class (PHP 5.2+)
<?php
class Curl {
/**
* cURL request method
*
* @var string
*/
static protected $_method = 'GET';
/**
* cURL URL
*
* @var string
*/
static protected $_url = '';
/**
* cURL data params
*
* @var string
*/
static protected $_params = array();
/**
* cURL options
*
* @var array
*/
static protected $_options = array();
/**
* cURL user agent
*
* @var array
*/
static protected $_agent = 'ground(ctrl) engine';
/**
* cURL response
*
* @var object
*/
static protected $_response = null;
/**
* GET request
*
* @param string $url
* @param array $params
* @param array $options
* @return mixed
*/
static public function get($url = '', $params = array(), $options = array()) {
return static::make($url, $params, $options, 'GET');
}
/**
* POST request
*
* @param string $url
* @param array $params
* @param array $options
* @return mixed
*/
static public function post($url = '', $params = array(), $options = array()) {
return static::make($url, $params, $options, 'POST');
}
/**
* PUT request
*
* @param string $url
* @param array $params
* @param array $options
* @return mixed
*/
static public function put($url = '', $params = array(), $options = array()) {
return static::make($url, $params, $options, 'PUT');
}
/**
* DELETE request
*
* @param string $url
* @param array $params
* @param array $options
* @return mixed
*/
static public function delete($url = '', $params = array(), $options = array()) {
return static::make($url, $params, $options, 'DELETE');
}
/**
* Make request
*
* @param string $url
* @param array $params
* @param array $options
* @param string $method
* @return Curl
*/
static public function make($url = '', $params = array(), $options = array(), $method = null) {
// Set request method
if ($method) {
static::$_method = $method;
}
// Explode the URL to get the URL params
$url_split = explode('?', $url);
// Request URL is everything before the ? (if it exists)
static::$_url = $url_split[0];
// If there were URL params, add it to the params array
static::$_params = array_merge(static::$_params, static::_queryString($url), (array) $params);
// Set the passed options
static::_options($options);
// Return the instance
return new static(static::$_url, static::$_params, static::$_options, static::$_method);
}
/**
* Add multiple options
*
* @param array $options
* @return Curl
*/
public function options($options = array()) {
static::_options($options);
return $this;
}
/**
* Add single option
*
* @param string $key
* @param string $value
* @return Curl
*/
public function option($key = '', $value = '') {
static::_option($key, $value);
return $this;
}
/**
* Request method
*
* @param string $method
* @return Curl
*/
public function method($method = null) {
static::$_method = $method;
return $this;
}
/**
* User agent
*
* @param string $agent
* @return Curl
*/
public function agent($agent = '') {
if ($agent) {
return $this->option('CURLOPT_USERAGENT', $agent);
}
return $this;
}
/**
* Proxy helper
*
* @param string $url
* @param int $port
* @return Curl
*/
public function proxy($url = '', $port = 80) {
return $this->options(array(
'CURLOPT_HTTPPROXYTUNNEL' => true,
'CURLOPT_PROXY' => $url.':'.$port
));
}
/**
* Custom header helper
*
* @param string $header
* @param string $content
* @return Curl
*/
public function httpHeader($header, $content = null) {
$header = ($content) ? $header.':'.$content : $header;
return $this->option('CURLOPT_HTTPHEADER', $header);
}
/**
* HTTP login helper
*
* @param string $username
* @param string $password
* @param string $type
* @return Curl
*/
public function httpLogin($username = '', $password = '', $type = 'ANY') {
return $this->options(array(
'CURLOPT_HTTPAUTH' => constant('CURLAUTH_'.strtoupper($type)),
'CURLOPT_USERPWD' => $username.':'.$password
));
}
/**
* Proxy login helper
*
* @param string $username
* @param string $password
* @return Curl
*/
public function proxyLogin($username = '', $password = '') {
return $this->option('CURLOPT_PROXYUSERPWD', $username.':'.$password);
}
/**
* SSL helper
*
* @param bool $verify_peer
* @param int $verify_host
* @param string $path_to_cert
* @return Curl
*/
public function ssl($verify_peer = true, $verify_host = 2, $path_to_cert = null) {
if ($verify_peer) {
$options = array(
'CURLOPT_SSL_VERIFYPEER' => true,
'CURLOPT_SSL_VERIFYHOST' => $verify_host,
'CURLOPT_CAINFO' => $path_to_cert
);
}
else {
$options = array(
'CURLOPT_SSL_VERIFYPEER' => false
);
}
return $this->options($options);
}
/**
* Execute request
*
* @return Curl
* @throws CurlException
*/
public function call() {
// cURL is not enabled
if ( ! $this->_isEnabled()) {
throw new CurlException(__CLASS__.': PHP was not built with cURL enabled. Rebuild PHP with --with-curl to use cURL.');
}
// Request method
$method = (static::$_method) ? strtoupper(static::$_method) : 'GET';
// Unrecognized request method?
if ( ! in_array($method, array('POST', 'GET', 'PUT', 'DELETE'))) {
throw new CurlException(__CLASS__.': Unrecognized request method of '.static::$_method);
}
return $this->_execute($method);
}
/**
* Alias for call();
*
* @return Curl
*/
public function execute() {
return static::call();
}
/**
* Execute request
*
* @param string $method
* @return Curl
*/
private function _execute($method) {
// Method specific options
switch ($method) {
case 'GET' :
// Append GET params to URL
static::$_url .= '?'.http_build_query(static::$_params);
// Set options
static::options('CURLOPT_HTTPGET', 1);
break;
case 'POST' :
// Set options
static::options(array(
'CURLOPT_POST' => true,
'CURLOPT_POSTFIELDS' => static::$_params
));
break;
case 'PUT' :
// Set options
static::options(array(
'CURLOPT_PUT' => true,
'CURLOPT_HTTPHEADER' => array('Content-Type: '.strlen(static::$_params)),
'CURLOPT_POSTFIELDS' => static::$_params
));
break;
case 'DELETE' :
// Set options
static::option('CURLOPT_CUSTOMREQUEST', 'DELETE');
static::option('CURLOPT_POSTFIELDS', static::$_params);
break;
}
// Set timeout option if it isn't already set
if ( ! array_key_exists('CURLOPT_TIMEOUT', static::$_options)) {
static::option('CURLOPT_TIMEOUT', 30);
}
// Set returntransfer option if it isn't already set
if ( ! array_key_exists('CURLOPT_RETURNTRANSFER', static::$_options)) {
static::option('CURLOPT_RETURNTRANSFER', true);
}
// Set failonerror option if it isn't already set
if ( ! array_key_exists('CURLOPT_FAILONERROR', static::$_options)) {
static::option('CURLOPT_FAILONERROR', true);
}
// Set user agent option if it isn't already set
if ( ! array_key_exists('CURLOPT_USERAGENT', static::$_options)) {
static::option('CURLOPT_USERAGENT', static::$_agent);
}
// Only set follow location if not running securely
if ( ! ini_get('safe_mode') && ! ini_get('open_basedir')) {
// Ok, follow location is not set already so lets set it to true
if ( ! array_key_exists('CURLOPT_FOLLOWLOCATION', static::$_options)) {
static::option('CURLOPT_FOLLOWLOCATION', true);
}
}
// Initialize cURL request
$ch = curl_init(static::$_url);
// Can't set the options in batch
if ( ! function_exists('curl_setopt_array')) {
foreach (static::$_options as $key => $value) {
curl_setopt($ch, $key, $value);
}
}
// Set options in batch
else {
curl_setopt_array($ch, static::$_options);
}
// Execute
$response = new stdClass();
$response->result = curl_exec($ch);
$response->info = curl_getinfo($ch);
$response->error = curl_error($ch);
$response->error_code = curl_errno($ch);
// Reset the options
static::$_options = array();
// Close cURL request
curl_close($ch);
return $response;
}
/**
* Add multiple options
*
* @param array $options
*/
static private function _options($options = array()) {
foreach ((array)$options as $key => $value) {
static::_option($key, $value);
}
}
/**
* Add single option
*
* @param string $key
* @param string $value
*/
static private function _option($key = '', $value = '') {
if (is_string($key) && ! is_numeric($key)) {
$key = constant(strtoupper($key));
}
// Custom header
if ($key == CURLOPT_HTTPHEADER) {
static::$_options[$key][] = $value;
}
// Not a custom header
else {
static::$_options[$key] = $value;
}
}
/**
* Get query string from URL
*
* @param $uri
* @return array
*/
static private function _queryString($uri) {
$query_data = array();
$query_array = html_entity_decode(parse_url($uri, PHP_URL_QUERY));
if ( ! empty($query_array)) {
$query_array = explode('&', $query_array);
foreach($query_array as $val) {
$x = explode('=', $val);
$query_data[$x[0]] = $x[1];
}
}
return $query_data;
}
/**
* Check if cURL is enabled
*
* @return bool
*/
private function _isEnabled() {
return function_exists('curl_init');
}
}
class CurlException extends Exception { }
require_once('Curl.php');
$params = array(
'include_entities' => false,
'include_rts' => false,
'screen_name' => 'dfreerksen',
'count' => 2
);
$twitter = Curl::get('https://api.twitter.com/1/statuses/user_timeline.json', $params)
->call();
//$twitter = Curl::get('https://api.twitter.com/1/statuses/user_timeline.json?include_entities=false&include_rts=false&screen_name=dfreerksen&count=2')
//->call();
var_dump( $twitter->result );
var_dump( $twitter->info );
var_dump( $twitter->error );
var_dump( $twitter->error_code );
@bmcminn
Copy link

bmcminn commented Oct 30, 2013

Line #476 when using html_entity_decode() forces my explicitly encoded ampersand char to be decoded which causes Line #484 to break due to a Undefined offset: 1 error.

Basically, I'm using OMDb API to capture relevant movie data for a given title, and this title requires an (encoded) ampersand be defined in the title, or URI variable t, otherwise the OMDb API resolves the ampersand as a URL var delimiter and request the movie "Love"... The ampersand gets decoded, and a corresponding = is never resolved.

Making my own cURL request worked just fine, but this is def a bug I'm looking into. Thoughts?

@pduda
Copy link

pduda commented Dec 12, 2013

Under which licences is this class available ?

@ivansklempej
Copy link

Hi,
in line 328 this should be correct way of building query
otherwise if no params passed it generates url with ? at the end and breaks some RestAPI services

328 $this->_url .= http_build_query($this->_params)? '?'.http_build_query($this->_params): '';

@marcincodes
Copy link

Can u add example how to login to page using your class?

@randronico
Copy link

randronico commented Jun 30, 2021

Hi,

First of all, thank you for this Helper class. It help me a lot recently. After using it, I found some bugs.

In this link https://gist.github.com/randronico/f3ad3aa7cec12e53a84b12abba66137c you have a patch with all changes (including comment from @bmcminn -> https://gist.github.com/dfreerksen/3380322#gistcomment-1220305)

Changelog:

  • use option method on switch case "GET" instead of options
  • Use CURLOPT_* constants as constants instead of encapsulate them with quotes, because option keys are not in string but in integers

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment