Loop the PHP Code Until Statement Is True - php

I'm using two API keys to receive the data. That's because provider have some daily quota limit. If quota exceeds the daily limit, 403 error is returned from the server.
I used $http_response_header to check the response from the server. But the problem is that when response returned isn't 200, e.g the API key used exceeds the daily limit, the code should execute again so that another API key is picked randomly. Here's the code I'm using:
$keys = array('1stkey','2ndkey');
$key_r = array_rand($keys);
$yt_key = $keys[$key_r];
$data = file_get_contents("https://example.com/data&key=$yt_key");
if (strpos($http_response_header[0], "200")) {
echo $data;
}
else{
echo 'No';
}

You can create a function of this code, and just re-run the function when the response is not 200. Something like this maybe?
function getAPIData() {
$keys = array('1stkey','2ndkey');
$key_r = array_rand($keys);
$yt_key = $keys[$key_r];
$data = file_get_contents("https://example.com/data&key=$yt_key");
if (strpos($http_response_header[0], "200")) {
echo $data;
}
else {
getAPIData();
}
}
Like #Jaquarh says, you might want to change max_execution_time also. Have a look here and see what works for you.

I've created perfect solution, check this:
$api = array('1st key','2nd key');
$k = array_rand($api);
$api_key_yt = $api[$k];
$total_api=count($api);
for ($loop=0;$loop<=$total_api;$loop++) {
$api_key_yt=$api[$loop];
$request2 = "https://example.com/?data&key=$api_key_yt";
$response = file_get_contents($request2);
$jsonobj = json_decode($response);
if (isset($jsonobj->items)) {break;} else {unset($jsonobj);}
}
print_r($jsonobj);

Please try this
$data = null;
do {
$keys = array('1stkey','2ndkey')
$key_r = array_rand($keys);
$yt_key = $keys[$key_r];
$data = file_get_contents("https://example.com/data&key=$yt_key");
} while ($data == null);

Related

How to solve the memory increase in the render () loop of cakephp2

Currently, I am implementing the email sending function using Cakephp2.
This time we are implementing the email sending function with our own method without using CakeEmail, and we are loading the email template using render.
As a premise, this time we assume that we will deliver up to about 50,000 emails, and we can send the current 300 emails without any noticeable delay.
However, up to about 300 items can be sent 5 to 7 per second, but when it reaches about 1000, it will be sent once every 3 to 5 seconds.
Therefore, this time, I would like to make sure that I do not reduce the transmission speed of each mail.
Therefore, when checking the processing speed of each process, it was confirmed that the processing speed in the part executing render gradually increased, so the memory usage at the time of rendering may be a problem? I thought.
Please let me know if there is a cause or solution that increases memory usage by looping render.
function send()
{
$mails = $this->MailList->getSendMails();
foreach ($mails as $mail) {
if (!$this->saveTargetData($mail)) {
continue;
};
$limit = 300;
$offset = 0;
while ($targets = $this->MailDeliveryTarget->getTargets($mail,$limit,$offset)) {
foreach ($targets as $target) {
$result = $this->Sys->sendMailTemplate('reserved_mail',['input' => $input]);
if ($result) {
// success
} else {
// failure
}
}
unset($targets);
$offset += $limit;
}
}
}
function sendMailTemplate($tpl, $data = array())
{
$to = $this->getMailTo($tpl, $data);
$from = $this->getMailFrom($tpl, $data);
return $this->sendMail($to, $from, $this->getMailSubject($tpl, $data), $this->getMailBody($tpl, $data));
}
function getMailTo($tpl, $data)
{
return trim(convert_nl($this->_getMailTemplate($tpl."/to",$data), ""));
}
function _getMailTemplate($tpl, $data)
{
if (!is_file(dirname(dirname(dirname(__FILE__))).DS."Template".DS."mail".DS.str_replace("/", DS, $tpl).".txt")) {
return "";
}
$bk = array();
foreach (array("layout", "ext") as $v) {
$bk[$v] = $this->Controller->$v;
}
$bk_output = $this->Controller->response->body();
$this->Controller->layout = "";
$this->Controller->ext = ".txt";
$this->Controller->response->body("");
$this->Controller->set($data);
$this->Controller->mail_render = true;
$this->Controller->render("/".ltrim($tpl, "/"));
$out = $this->Controller->response->body();
$this->Controller->mail_render = false;
$this->Controller->response->body($bk_output);
foreach (array("layout", "ext") as $v) {
$this->Controller->$v = $bk[$v];
}
return $out;
}
Thank you.

PHP Fatal error: Uncaught Unirest\Exception: Bad URL

I'm trying to request a REST API using PHP Unirest.
The printed error is the following:
Bad URL, colon is first character
And my code:
<?php
require __DIR__ . '/../vendor/autoload.php';
use Unirest\Request as UniRequest;
use CurlFile;
if (isset($_POST['primeiro'])) {
$where = $_POST["where"];
$equal = $_POST["equal"];
$resultado = new pedidos;
$valores = $resultado->LogIgualA($where, $equal);
}
class pedidos {
function LogIgualA($where, $equal) {
$wsURL = "localhost:8080/public";
try {
$valores = UniRequest::get($wsURL."/visual/json_log/where=".$where."/equal=".$equal, $headers, null);
} catch (Exception $e) {
echo $e->getMessage();
}
$valoresAux = $valores->body;
$valores = [];
foreach($valoresAux as $z){
$ID = $z->ID;
$DateConnection = $z->DateConnection;
$TimeToServe = $z->TimeToServe;
$ClientIP = $z->ClientIP;
$CacheCode = $z->CacheCode;
$Bytes = $z->Bytes;
$Method = $z->Method;
$RequestProtocol = $z->RequestProtocol;
$RequestIP = $z->RequestIP;
$RequestPort = $z->RequestPort;
$RequestFolder = $z->RequestFolder;
$Auth = $z->Auth;
$RouteLeft = $z->RouteLeft;
$RouteRight = $z->RouteRight;
$ContentType = $z->ContentType;
}
return $valores;
}
}
The "isset($_POST['primeiro']" is when I click the button in HTML so it calls the function in PHP.
I really don't know how to use this...
You need to prepend a protocol like https://.
There are other people having the same issue where prepending the protocol fixed this... https://github.com/Azure/doAzureParallel/issues/44
URL is not http: localhost:8080/public
Also check that there is no malicious input in your $_POST vars and maybe you need to use urlencode() on the fields containing appropriate characters.

How to combine functions to get several types of information

I use the Youtube Api to get information about a single video. When I do a request with an url like:
https://www.googleapis.com/youtube/v3/videos?part=status,snippet,contentdetails&id=$videoID&key=$apikey
I get all the info which I need. The problem is that I can not find a way to combine the functions that I have to get the information in one go.
What I got so far:
function getDescription($videoID){
$apikey = "<MYKEY>";
$desc = file_get_contents("https://www.googleapis.com/youtube/v3/videos?part=snippet&id=$videoID&key=$apikey");
$description =json_decode($desc, true);
foreach ($description['items'] as $videodesc)
{
$description= $videodesc['snippet']['description'];
}
return $description;
}
function getPublishedAt($videoID){
$apikey = "<MYKEY>";
$pub = file_get_contents("https://www.googleapis.com/youtube/v3/videos?part=snippet&id=$videoID&key=$apikey");
$publish =json_decode($pub, true);
foreach ($publish['items'] as $published)
{
$publish= $published['snippet']['publishedAt'];
}
$publish = new DateTime($publish);
$publish = $publish->format('Y-m-d H:i:s');
return $publish;
}
echo "<br>Description: ";
echo getDescription("<VIDEO-ID>");
echo "<br>PublishedAt: ";
echo getPublishedAt("<VIDEO-ID>");
So, this code works, but I like to do ONE request to the api (using multiple parts in the url) and get the information.
Does anyone has a clue how to do this using one function only?
Ok, I found the answer myself:
$videoinfo = file_get_contents("https://www.googleapis.com/youtube/v3/videos?id=<video-id>&part=snippet,status,contentDetails,statistics&part=statistics&key=<api-key>");
$videoinfo =json_decode($videoinfo, true);
foreach ($videoinfo['items'] as $embed)
{
$emb= $embed['status']['embeddable'];
$license= $embed['status']['license'];
$duration= $embed['contentDetails']['duration'];
}
echo $emb;
echo $license;
echo $duration;
It's not a function, but this will do the tric :)

How to get "metric" and "element" names for PHP - Adobe Analytics

I am pulling a report using the Adobe API from Omniture.
Here is the full script :
<?php
include_once('/path/SimpleRestClient.php');
// Date
$end_date = date("Y-m-d",strtotime("-1 days"));
$start_date = date("Y-m-d",strtotime("-8 days"));
// Location of the files exported
$adobe_file = '/path/Adobe_'.$end_date.'.csv';
// List creation that will be updated with the fields and be put into my CSV file
$list = array
(
array('lasttouchchannel', 'product','visits','CTR(Clicks/PageViews)') // headers // ADD or DELETE metrics #
);
function GetAPIData($method, $data)
{
$username = "XXXX";
$shared_secret = "XXXX";
$postURL = "https://api3.omniture.com/admin/1.4/rest/?method=";
// Nonce is a simple unique id to each call to prevent MITM attacks.
$nonce = md5(uniqid(php_uname('n'), true));
// The current timestamp in ISO-8601 format
$nonce_ts = date('c');
/* The Password digest is a concatenation of the nonce, it is timestamp and your password
(from the same location as your username) which runs through SHA1 and then through a base64 encoding */
$digest = base64_encode(sha1($nonce . $nonce_ts . $shared_secret));
$rc = new SimpleRestClient();
$rc -> setOption(CURLOPT_HTTPHEADER, array("X-WSSE: UsernameToken Username=\"$username\", PasswordDigest=\"$digest\", Nonce=\"$nonce\", Created=\"$nonce_ts\""));
//var_dump($o);
$rc -> postWebRequest($postURL .$method, $data);
return $rc;
}
$method = 'Report.Queue';
$data ='
{
"reportDescription":
{
"reportSuiteID":"XXXX",
"dateFrom":"'.$start_date.'",
"dateTo":"'.$end_date.'",
"metrics":[{"id":"visits"},{"id":"instances"},{"id":"pageviews"}],
"elements":[{"id":"lasttouchchannel","top":"50000"}]
}
}';
/*
"date":"'.$date.'",
"dateTo":"'.$date.'",
"dateFrom":"'.$start_date.'",
"dateTo":"'.$end_date.'",
*/
$rc=GetAPIData($method, $data);
if($rc -> getStatusCode() == 200) // status code 200 is for 'ok'
{
$counter = 0;
do
{
if($counter>0){sleep($sleep = 120);}
$return = GetAPIData('Report.Get', $rc->getWebResponse());
$counter++;
}while($return -> getStatusCode() == 400 && json_decode($return->getWebResponse())->error == 'report_not_ready'); // status code 400 is for 'bad request'
//
$json=json_decode($return->getWebResponse());
foreach ($json->report->data as $el)
{
echo $el->name.":".$el->counts[0].":".$el->counts[1]."\n";
// Adding the data in the CSV file without overwriting the previous data
array_push($list, array($el->name, $el->name, $el->counts[0], ($el->counts[1])/($el->counts[2])));
}
}
else
{
echo "Wrong";
}
$fp = fopen($adobe_file, 'w');
foreach ($list as $fields)
{
// Save the data into a CSV file
fputcsv($fp, $fields);
}
fclose($fp);
?>
How can I get the names of the metrics and elements in order to use them in this script? There is no way. I searched with all the possible tags on google and nothing worked !
I need the metrics and elements for this part of the code :
$data ='
{
"reportDescription":
{
"reportSuiteID":"XXXX",
"dateFrom":"'.$start_date.'",
"dateTo":"'.$end_date.'",
"metrics":[{"id":"visits"},{"id":"instances"},{"id":"pageviews"}],
"elements":[{"id":"lasttouchchannel","top":"50000"}]
}
}';
I cannot find 'date' as an element which is crucial. I cannot find all the other metrics as well. In Google Analytics we had this link :
Google Analytics Query
but in Adobe there is not any. I want something like that :
"metrics":[{"id":"instances"},{"id":"impressions"}],
"elements":[{"id":"date","top":"50000"}]
You would json_decode() as $data contains a JSON string. For example:
$data ='
{
"reportDescription":
{
"reportSuiteID":"XXXX",
"dateFrom":"'.$start_date.'",
"dateTo":"'.$end_date.'",
"metrics":[{"id":"visits"},{"id":"instances"},{"id":"pageviews"}],
"elements":[{"id":"lasttouchchannel","top":"50000"}]
}
}';
$json = json_decode($data, true);
echo $json['reportDescription']['dateFrom'];
print_r($json['reportDescription']['metrics']);

PHP - Icecast info being updated on page

I'm using a script from this site. This script works fine for me and it does what its need to do but I have one problem. When a track finishes on my Icecast server it doesn't get updates on the site. So if my song is 'Stole the show' than it says 'Stole the show' the page but when the song finished and e.g. 'Thinking out loud' starts the page still says 'Stole the show' on a refresh it will update. But how to make it so the page auto updates itself so the users doesn't have to refresh manually?
PHP
<?php
// include the class file
include( 'icecast.php' );
// instantiate class
$stream = new IceCast();
// set server and mount
$server = 'http://radio.finioxfm.com:8000';
$file = '/status.xsl';
// set the url
$stream->setUrl($server,$file);
// get status info
$radio = $stream->getStatus();
// assign array to variables
extract($radio);
// echo the status
echo $status.'<br/>';
// display more stats if ON AIR
if ($status=='ON AIR') :
echo $listeners.' listeners<br/>';
echo $title.'<br/>';
echo $genre.'<br/>';
for ($i=0; $i < 1; $i++) {
echo $now_playing['artist'].'<br/>';
echo $now_playing['track'].'<br/>';
}
endif;
?>
icecast.php script
<?php
class IceCast {
var $server = "http://radio.finioxfm.com:8000";
var $stats_file = "/status.xsl";
var $radio_info=array();
function __construct() {
// build array to store our Icecast stats
$this->radio_info['server'] = $this->server;
$this->radio_info['title'] = '';
$this->radio_info['description'] = '';
$this->radio_info['content_type'] = '';
$this->radio_info['mount_start'] = '';
$this->radio_info['bit_rate'] = '';
$this->radio_info['listeners'] = '';
$this->radio_info['most_listeners'] = '';
$this->radio_info['genre'] = '';
$this->radio_info['url'] = '';
$this->radio_info['now_playing'] = array();
$this->radio_info['now_playing']['artist'] = 'Unknown';
$this->radio_info['now_playing']['track'] = 'Unknown';
$this->radio_info['status'] = 'OFF AIR';
}
function setUrl($url,$file) {
$this->server=$url;
$this->stats_file=$file;
$this->radio_info['server'] = $this->server;
}
private function fetch() {
// create a new curl resource
$ch = curl_init();
// set the url
curl_setopt($ch,CURLOPT_URL,$this->server.$this->stats_file);
// return as a string
curl_setopt($ch,CURLOPT_RETURNTRANSFER,1);
// $output = the status.xsl file
$output = curl_exec($ch);
// close curl resource to free up system resources
curl_close($ch);
return $output;
}
function getStatus() {
$output=$this->fetch();
// loop through $output and sort arrays
$temp_array = array();
$search_for = "<td\s[^>]*class=\"streamdata\">(.*)<\/td>";
$search_td = array('<td class="streamdata">','</td>');
if(preg_match_all("/$search_for/siU",$output,$matches)) {
foreach($matches[0] as $match) {
$to_push = str_replace($search_td,'',$match);
$to_push = trim($to_push);
array_push($temp_array,$to_push);
}
}
if(count($temp_array)) {
//sort our temp array into our ral array
$this->radio_info['title'] = $temp_array[0];
$this->radio_info['description'] = $temp_array[1];
$this->radio_info['content_type'] = $temp_array[2];
$this->radio_info['mount_start'] = $temp_array[3];
$this->radio_info['bit_rate'] = $temp_array[4];
$this->radio_info['listeners'] = $temp_array[5];
$this->radio_info['most_listeners'] = $temp_array[6];
$this->radio_info['genre'] = $temp_array[7];
$this->radio_info['url'] = $temp_array[8];
if(isset($temp_array[9])) {
$x = explode(" - ",$temp_array[9]);
$this->radio_info['now_playing']['artist'] = $x[0];
$this->radio_info['now_playing']['track'] = $x[1];
}
$this->radio_info['status'] = 'ON AIR';
}
return $this->radio_info;
}
}
?>
First of all, I have to point out that you shouldn't use this script. It works by parsing the Icecast Status page, which we highly discourage, as it may change. For example in Icecast 2.4 we re-made the complete web interface, so chances are that this script breaks.
You should actually parse the XML Icecast provides at http://icecast.tld:8000/admin/stats. It contains everything you need. If you can't access Icecast's Admin page for some reason, you can use the JSON at http://icecast.tld:8000/status-json.xsl, which is there since Icecast 2.4 exactly for the purpose you describe.
To get the site display new metadata information without refreshing, you need to use an AJAX call which either loads directly the status-json.xsl and extracts the metadata and updates it on the page, or if you use the admin XML you need to write a PHP script which returns json, that you can fetch via AJAX and update accordingly.
A lot of people in the past have spoken about setting up node.js (if you have a server doing your streaming).
Personally I have gone with a jquery solution; which just compares the last fetched data with the live data every 10 seconds. That way it loads in almost 'real time'.
You can find my solution here broken down here http://www.radiodj.ro/community/index.php?topic=7471.0

Categories