Alternative of file_get_contents function - php

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.

Related

Problems receiving POST variables from PHP

I have a function developed by PHP that at the moment all I want it to do is to return the value of the variable $_POST['token']
I tried:
public function actionGetuserbytoken() {
$data = json_decode(file_get_contents("php://input"), TRUE);
$id = $data['token'];
return $id;
}
Or I also just tried:
public function actionGetuserbytoken() {
return $_POST['token'];
}
I tried doing the POST with Insomnia to check what is going on:
I feel this is a very absurd question but I can't understand why I can't get the value of the POST in either of the two ways.
The php://input stream can only be read once per request. Yii is likely reading the payload before you can, which means that the body is empty when you read the data.
Instead of using php://input, try the following:
$data = json_decode(Yii::app()->request->getRawBody(), true);

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

PHP cURL - thread safe?

I wrote a PHP script which retrieved data via libcurl and processed it. It worked fine but for performance reasons I changed it to use dozens of workers (threads). The performance improved by more than 50 times, however now php.exe is crashing every few minutes and the faulting module listed is php_curl.dll. I do have prior experience with multi-threading in C, but haven't used it at all before in php.
I googled around and supposedly cURL is thread safe (as of 2001):
http://curl.haxx.se/mail/lib-2001-01/0001.html
But I can't find any mention of whether or not php_curl is thread safe.
In case it matters, I am running php from the command line. My setup is Win7 x64, PHP 5.5.11 Thread Safe VC11 x86, PHP pthreads 2.0.4 for PHP 5.5 Thread Safe VC11 x86.
Here is some pseudo code to show what I am doing
class MyWorker extends Worker
{
...
public function run()
{
...
while(1)
{
...
runCURL();
...
sleep(1);
}
}
}
function runCURL()
{
static $curlHandle = null;
...
if(is_null($curlHandle))
{
$curlHandle = curl_init();
curl_setopt($curlHandle, CURLOPT_RETURNTRANSFER, TRUE);
curl_setopt($curlHandle, CURLOPT_USERAGENT, "My User Agent String");
}
curl_setopt($curlHandle, CURLOPT_URL, "The URL");
curl_setopt($curlHandle, CURLOPT_POSTFIELDS, $data);
curl_setopt($curlHandle, CURLOPT_HTTPHEADER, $header);
curl_setopt($curlHandle, CURLOPT_SSL_VERIFYPEER, false);
$result = curl_exec($curlHandle);
...
}
Firstly, resource types are officially unsupported by pthreads; a curl handle is a resource, you therefore should not store curl handles in the object scope of pthreads objects, since they might become corrupted.
Making it easy
pthreads provides an easy way to use workers...
The easiest way to execute among many threads is to use the built in Pool class provided by pthreads:
http://php.net/pool
The following code demonstrates how to pool a bunch of requests in a few background threads:
<?php
define("LOG", Mutex::create());
function slog($message, $args = []) {
$args = func_get_args();
if (($message = array_shift($args))) {
Mutex::lock(LOG);
echo vsprintf("{$message}\n", $args);
Mutex::unlock(LOG);
}
}
class Request extends Threaded {
public function __construct($url, $post = []) {
$this->url = $url;
$this->post = $post;
}
public function run() {
$curl = curl_init();
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
curl_setopt($curl, CURLOPT_URL, $this->url);
if ($this->post) {
curl_setopt($curl, CURLOPT_POSTFIELDS, $this->post);
}
$response = curl_exec($curl);
slog("%s returned %d bytes", $this->url, strlen($response));
}
public function getURL() { return $this->url; }
public function getPost() { return $this->post; }
protected $url;
protected $post;
}
$max = 100;
$urls = [];
while (count($urls) < $max) {
$urls[] = sprintf(
"http://www.google.co.uk/?q=%s",
md5(mt_rand()*count($urls)));
}
$pool = new Pool(4);
foreach ($urls as $url) {
$pool->submit(new Request($url));
}
$pool->shutdown();
Mutex::destroy(LOG);
?>
Your specific task requires that you now process the data, you can either write this functionality into a design like the above ... or
Making it fancy
promises are a super fancy form of concurrency ...
Promises suit the nature of the task here:
First: Make a request
Then: Process response
The following code shows how to use pthreads/promises to make the same request and process responses:
<?php
namespace {
require_once("vendor/autoload.php");
use pthreads\PromiseManager;
use pthreads\Promise;
use pthreads\Promisable;
use pthreads\Thenable;
define("LOG", Mutex::create());
function slog($message, $args = []) {
$args = func_get_args();
if (($message = array_shift($args))) {
Mutex::lock(LOG);
echo vsprintf("{$message}\n", $args);
Mutex::unlock(LOG);
}
}
/* will be used by everything to report errors when they occur */
trait ErrorManager {
public function onError(Promisable $promised) {
slog("Oh noes: %s\n", (string) $promised->getError());
}
}
class Request extends Promisable {
use ErrorManager;
public function __construct($url, $post = []) {
$this->url = $url;
$this->post = $post;
$this->done = false;
}
public function onFulfill() {
$curl = curl_init();
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
curl_setopt($curl, CURLOPT_URL, $this->url);
if ($this->post) {
curl_setopt($curl, CURLOPT_POSTFIELDS, $this->post);
}
$this->response = curl_exec($curl);
}
public function getURL() { return $this->url; }
public function getPost() { return $this->post; }
public function getResponse() { return $this->response; }
public function setGarbage() { $this->garbage = true; }
public function isGarbage() { return $this->garbage; }
protected $url;
protected $post;
protected $response;
protected $garbage;
}
class Process extends Thenable {
use ErrorManager;
public function onFulfilled(Promisable $request) {
slog("%s returned %d bytes\n",
$request->getURL(), strlen($request->getResponse()));
}
}
/* some dummy urls */
$max = 100;
$urls = [];
while (count($urls) < $max) {
$urls[] = sprintf(
"http://www.google.co.uk/?q=%s",
md5(mt_rand()*count($urls)));
}
/* initialize manager for promises */
$manager = new PromiseManager(4);
/* create promises to make and process requests */
while (#++$id < $max) {
$promise = new Promise($manager, new Request($urls[$id], []));
$promise->then(
new Process($promise));
}
/* force the manager to shutdown (fulfilling all promises first) */
$manager->shutdown();
/* destroy mutex */
Mutex::destroy(LOG);
}
?>
Composer:
{
"require": {
"krakjoe/promises": ">=1.0.2"
}
}
Note that Request has hardly changed, all that has been added is somewhere to hold the response and a means to detect if the objects are garbage.
For details on garbage collection from pools, which applies to both examples:
http://php.net/pool.collect
The slog function exists only to make logged output readable
Making it clear
pthreads is not a new PDO driver ...
Many people approach using pthreads as they would approach using a new PDO driver - assume it works like the rest of PHP and that everything will be fine.
Everything might not be fine, and requires research: we are pushing the envelope, in doing so some "restrictions" must be placed upon the architecture of pthreads to maintain stability, this can have some strange side effects.
While pthreads comes with exhaustive documentation which mostly include examples in the PHP manual, I'm not able to attach the following document in the manual, yet.
The following document provides you with an understanding of the internals of pthreads, everyone should read it, it's written for you.
https://gist.github.com/krakjoe/6437782

PHP Classes and Curl

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);

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).

Categories