PHP Classes and Curl - php

To my smartest friends, I googled and tried everything. I am sure that this is just the late night not letting me see/understand the problem. I should mention that I am still in the process of switching to OOP from functional, and I this is my first time I was able to have curl enabled. :( So, feel free to critique any bad practices also..
<?php
class urlValidation
{
public $content;
public $validUrl;
public function __construct($validUrl)
{
$this->content = $content;
$this->validUrl = $validUrl;
$this->getContents();
}
public function getContents()
{
$this->curlHandler = curl_init($this->validUrl);
curl_setopt($this->curlHandler, CURLOPT_NOBODY, false);
curl_setopt(CURLOPT_RETURNTRANSFER, false); //changing false to true is the answer!
$this->content = curl_exec($this->curlHandler);
curl_close($this->curlHandler);
}
}
?>
called from
$suggestUrl = 'http://www.google.com';
$validate = new urlValidation($suggestedUrl);
For all of the best of me, I cannot figure out why $this->content prints to the screen without being called. I just simply want that returned HTML to be stored in a variable and not returned/printed/appended to the document.

PHP documentation explains it all ;)
curl_exec returns TRUE on success or FALSE on failure. However, if the CURLOPT_RETURNTRANSFER option is set, it will return the result on success, FALSE on failure.
So before $this->content = curl_exec($this->curlHandler); you need to add this
curl_setopt($this->curlHandler, CURLOPT_RETURNTRANSFER, true);

Related

Alternative of file_get_contents function

I am trying to get json data from https://nepse-data-api.herokuapp.com/data/todaysprice.
I use file_get_contents() function but I got below error msg
Message: require(): https:// wrapper is disabled in the server
configuration by allow_url_fopen=0
Now my problem is I am using shared hosting so allow_url_fopen = 1 is not possible.
How can I get the data from above url.
In localhost this code is working properly, Here is my code
$url = 'https://nepse-data-api.herokuapp.com/data/todaysprice';
$raw = file_get_contents($url);
$data = json_decode($raw);
In case you’re using PHP to retrieve data from a certain server you probably came across the problem that it may work for you but a client complained about lots of errors. It’s pretty likely that you’ve relied on the fact that allow_url_fopen is set to true. This way you can put pretty much anything – local path or a URL – into function calls like include or maybe simplexml_load_file.
If you’d like to get around this problem you can advice your client to make the necessary changes in his php.ini file. Most of the time this isn’t an option because the hosting company decided to disable this feature for security reasons. Since almost everybody got cURL installed we can use this to retrieve data from another web server.
Implementation
I’ll present a wrapper that helps you loading an XML file. It uses simplexml_load_file if allow_url_fopen is enabled. If this feature is disabled it employs simplexml_load_string and cURL. If none of this works we’ll throw an exception because we weren’t able to load the data.
class XMLWrapper {
public function loadXML($url) {
if (ini_get('allow_url_fopen') == true) {
return $this->load_fopen($url);
} else if (function_exists('curl_init')) {
return $this->load_curl($url);
} else {
// Enable 'allow_url_fopen' or install cURL.
throw new Exception("Can't load data.");
}
}
private function load_fopen($url) {
return simplexml_load_file($url);
}
private function load_curl($url) {
$curl = curl_init($url);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
$result = curl_exec($curl);
curl_close($curl);
return simplexml_load_string($result);
}
}
//For Json
class JsonWrapper {
public function loadJSON($url) {
if (ini_get('allow_url_fopen') == true) {
return $this->load_fopen($url);
} else if (function_exists('curl_init')) {
return $this->load_curl($url);
} else {
// Enable 'allow_url_fopen' or install cURL.
throw new Exception("Can't load data.");
}
}
private function load_fopen($url) {
$raw = file_get_contents($url);
$data = json_decode($raw);
return $data;
}
private function load_curl($url) {
$curl = curl_init($url);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
$result = curl_exec($curl);
curl_close($curl);
$data = json_decode($result);
return $data;
}
}
The code is pretty simple, create an instance of the given class and call the loadXML method. It’ll call the right private method which finally loads the XML. Loading some XML is just an example, you can use this technique with e.g. include or require too.

cURL function returning false in simple GET request

I am working on this for 2 hours and just can't figure out what's wrong. I am making a cURL get request with just the URL (with parameters) and the response is expected to be some kind of access_token in JSON format but I am continually getting an error: the curl_exec() function is returning false. The URL is alright because directly pasting the prepared URL to the browser address bar gives the appropriate access_token. You may need to know that I am making a graph API (Facebook) request. Here is some code:
private function getAccessToken() {
$uri = $this->prepareTokenUri(); // getting the uri
echo "<strong>$uri</strong><br/>"; // printing the uri for debugging purpose
$this->setCurlToGet($uri); // explained below
$response = curl_exec($this->curl);
echo "<b>Here Goes Response</b>";
var_dump($response); // boolean false
$response = json_decode($response, true);
$this->token_expires = $response['expires_in'];
$this->token_type = $response['type'];
return $response['access_token'];
}
The function setCurlToGet() just does the following:
// call this function only when making a GET request
private function setCurlToGet($url) {
$this->unsetCurl();
$this->curl = curl_init();
curl_setopt($this->curl, CURLOPT_URL, $url);
curl_setopt($this->curl, CURLOPT_RETURNTRANSFER, true);
return $this->curl;
}
and the unsetCurl() method is as follows:
private function unsetCurl() {
if(!is_null($this->curl)) {
curl_close($this->curl);
$this->curl = null;
}
}
I have var_dumped() everything, the cURL resource variable ($this->curl) and it is actually a curl resource variable. The call to curl_exec() is returning false and I just can't figure out why. Again, I would like to repeat that there is nothing wrong with the URL because when the printed url (in the line echo "<strong>$uri</strong><br/>";) is copied and pasted in browser's address bar, result is an access_token that I need.
In case you wanted to see the pattern of URI that prepareTokenUri() is preparing:
https://graph.facebook.com/v2.3/oauth/access_token?client_id={my-appid}&redirect_uri={response-handler-script-uri}&client_secret={app-secret-code}&code={a-long-code}
The quick fix:
Add these lines to your setCurlToGet function in same area as other curl_setopt methods.
curl_setopt($this->curl, CURLOPT_SSL_VERIFYHOST, 0);
curl_setopt($this->curl, CURLOPT_SSL_VERIFYPEER, 0);
The only issue with this is that if someone is able to make dns go to their server, instead of facebook as expected from url, that you are not verifying that it is indeed facebook.
So if you are worried about that, the proper fix:
1) Download cacert.pem from https://curl.haxx.se/ca/cacert.pem
2) Add the following line to php.ini, with correct path of where you put the above file
curl.cainfo=/path/to/cacert.pem
3) Reload apache service

How do I show a specific tweet? (with PHP/jQuery)

I want to embed a specific tweet on my page e.g http://twitter.com/myusername/status/123465678 I would also like to be able to show the latest of my tweets which have a specific tag.
I tried to do this with Twitter API CodeIgniter Library myself but I need to register my application with Oauth. This seems like overkill for embeding one tweet on a page.
I would prefer to do this with PHP but will probably need to settle for a jquery version. Can anyone point me towards a script that can do this?
thanks
$.ajax({
url: 'http://api.twitter.com/1/statuses/show/4190230693289984.json',
dataType: 'jsonp',
data: null,
success: function (data) {
// Do something with the data here.
// I am just logging the object to the console.
console.log(data);
}
});
The above fetches the json object for an individual tweet (http://twitter.com/CERN/status/4190230693289984). Note the use of 'jsonp' to allow the client's browser to access a different domain from yours. Refer to http://api.jquery.com/jQuery.ajax/ for further information.
I think you can consume a public feed without using Oauth. I haven't worked with it in a while, but this code worked for me at one time:
$url = "http://twitter.com/yourtwittername";
$h = curl_init($url);
curl_setopt($h,CURLOPT_POST,TRUE);
curl_setopt($h,CURLOPT_POSTFIELDS,$params);
curl_setopt($h,CURLOPT_RETURNTRANSFER,TRUE);
curl_setopt($h,CURLOPT_VERBOSE,1);
curl_setopt($h,CURLOPT_HTTPHEADER,array('Expect:'));
$response = json_decode(curl_exec($h));
$results = curl_getinfo($h); # to check for http response, etc.
curl_close($h);
// additional processing on response ...
I did this once using curl, you may have to enable it first in your php.ini
here is a class that could probably do the job for you
<?php
class TwitterGrub{
private $user;
private $password;
function __construct($user, $password) {
$this->user = $user;
$this->password = $password;
}
function setUser($user) {
$this->user = $user;
}
// same for password
function twitterCapture() {
$ch = curl_init("https://twitter.com/statuses/user_timeline.xml");
curl_setopt($ch, CURLOPT_HEADER, 1);
curl_setopt($ch,CURLOPT_TIMEOUT, 30);
curl_setopt($ch,CURLOPT_USERPWD,$this->user . ":" . $this->password);
curl_setopt($ch,CURLOPT_RETURNTRANSFER,1);
curl_setopt ($ch, CURLOPT_SSL_VERIFYPEER, 0);
curl_setopt ($ch, CURLOPT_SSL_VERIFYHOST, 0);
$result=curl_exec ($ch);
$data = strstr($result, '<?');
$xml = new SimpleXMLElement($data);
return $xml;
}
function twitterDisplay($twitNum = 2){
$xml = $this->twitterCapture();
for($i= 0; $i<$twitNum; $i++){
echo $xml->status[$i]->text;
}
}
Can't you just parse the public RSS?
You could use pure javascript, see http://twitter.com/goodies/widget_profile for a twitter profile widget. Then customize it to show only one tweet (or look at their js code :D).

how do I override php://input when doing unit tests

I'm trying to write a unit test for a controller using Zend and PHPUnit
In the code I get data from php://input
$req = new Zend_Controller_Request_Http();
$data = $req->getRawBody();
My code works fine when I test the real application, but unless I can supply data as a raw http post, $data will always be blank. The getRawBody() method basically calls file_get_contents('php://input'), but how do I override this in order to supply the test data to my application.
I had the same problem and the way I fixed it was to have the 'php://input' string as a variable that is settable at run time. I know this does not really apply directly to this question as it would require modifying the Zend Framework. But all the same it may be helpful to someone.
For example:
<?php
class Foo {
public function read() {
return file_get_contents('php://input');
}
}
would become
<?php
class Foo {
public $_fileIn = 'php://input';
public function read() {
return file_get_contents($this->_fileIn);
}
}
Then in my unit test I can do:
<?php
$obj = new Foo();
$obj->_fileIn = 'my_input_data.dat';
assertTrue('foo=bar', $obj->read());
You could try mocking the object in your unit tests. Something like this:
$req = $this->getMock('Zend_Controller_Request_Http', array('getRawBody'));
$req->method('getRawBody')
->will($this->returnValue('raw_post_data_to_return'));
Provided the $req->getRawBody() is, as you say, the same as file_get_contents('php://input')...
$test = true; /* Set to TRUE when using Unit Tests */
$req = new Zend_Controller_Request_Http();
if( $test )
$data = file_get_contents( 'testfile.txt' );
else
$data = $req->getRawBody();
Not a perfect solution, but similar to what I have used in the past when designing scripts to handle piped emails with great success.
Zend_Controller_Request_HttpTestCase contains methods for setting and getting various http request/responses.
For example:
$req = new Zend_Controller_Request_HttpTestCase;
$req->setCookie('cookie', 'TRUE');
$test = $this->controller->cookieAction($req);
$this->assertSame($test, TRUE);

Using PHPUnit to test cookies and sessions, how?

With PHPUnit it's quite easy to test raw PHP code, but what about code that heavily relies on cookies? Sessions could be a good example.
Is there a method that doesn't require me to setup $_COOKIE with data during my test? It feels like a hacky way of doing things.
This is a common problem with code, especially lagacy PHP code. The common technique used is to further abstract the COOKIE/SESSION variables in related objects and using inversion of control technique(s) to pull those dependencies into scope.
http://martinfowler.com/articles/injection.html
Now before you execute a test you would instantiate a mock version of a Cookie/Session object and provide default data.
I imagine, the same effect can be achieved with legacy code by simply overriding the super global value before executing the test.
Cheers,
Alex
I understand this is quite old, but I believe this needs to be updated as technology has improved since the original post. I was able to get sessions working with this solution using php 5.4 with phpunit 3.7:
class UserTest extends \PHPUnit_Framework_TestCase {
//....
public function __construct () {
ob_start();
}
protected function setUp() {
$this->object = new \User();
}
public function testUserLogin() {
$this->object->setUsername('test');
$this->object->setPassword('testpw');
// sets the session within:
$this->assertEquals(true, $this->object->login());
}
}
I found that I could use PHPUnit to test the behavior of the part of my website that relies heavily on sessions, through a combination of Curl and a cookie that passes the session id.
The following Curl class uses the CURLOPT_COOKIE option to pass a session parameter. The static variable $sessionid saves the session between different Curl calls. Further, sessions can be changed using the static function changeSession.
class Curl {
private $ch;
private static $sessionid;
public function __construct($url, $options) {
$this->ch = curl_init($url);
if (!self::$sessionid)
self::$sessionid = .. generateRandomString() ..;
$options = $options + array(
CURLOPT_RETURNTRANSFER => true,
CURLOPT_COOKIE => 'PHPSESSID=' . self::$sessionid);
foreach ($options as $key => $val) {
curl_setopt($this->ch, $key, $val);
}
}
public function getResponse() {
if ($this->response) {
return $this->response;
}
$response = curl_exec($this->ch);
$error = curl_error($this->ch);
$errno = curl_errno($this->ch);
$header_size = curl_getinfo($this->ch, CURLINFO_HEADER_SIZE);
$this->header = substr($response, 0, $header_size);
$response = substr($response, $header_size);
if (is_resource($this->ch)) {
curl_close($this->ch);
}
if (0 !== $errno) {
throw new \RuntimeException($error, $errno);
}
return $this->response = $response;
}
public function __toString() {
return $this->getResponse();
}
public static function changeSession() {
self::$SESSIONID = Practicalia::generateRandomString();
}
}
An example call
$data = array(
'action' => 'someaction',
'info' => 'someinfo'
);
$curl = new Curl(
'http://localhost/somephp.php',
array(
CURLOPT_POSTFIELDS => http_build_query($data)));
$response = $curl->getResponse();
And any subsequent Curl calls will automatically use the same session as the previous one, unless specifically Curl::changeSession() is called.

Categories