PHP Undefined Offset unless printed out - php

While trying to read data from a socket ran the following code through the interpreter:
function get_song_title($stream){
$song;
$sc_return = array();
$sc_return = explode("\r\n",$stream);
$song = $sc_return[4];
return $song;
}
This will succeed in getting the information I need 20% of the time maybe.
However when I do:
function get_song_title($stream){
$song;
$sc_return = array();
$sc_return = explode("\r\n",$stream);
echo $sc_return[4];
$song = $sc_return[4];
return $song;
}
it will succeed 100% of the time. Any method to print the array(or its elements) out will make it to work without a problem. If I simply to try return it or assign it the undefined offset 4 message comes up.
this also includes using print_r($sc_return); which will always succeed.
Any ideas why I would need to print the array element out for it to succeed all the time?

not sure about why you need echo / print out to work, but...
try to do
var_dump($sc_rturn);
to see what you are getting.
also to check for undefined index, you should do
isset($sc_return[4]);
also you can count your results using
count($sc_return);

Related

Can I retry file_get_contents() until it opens a stream?

I am using PHP to get the contents of an API. The problem is, sometimes that API just sends back a 502 Bad Gateway error and the PHP code can’t parse the JSON and set the variables correctly. Is there some way I can keep trying until it works?
This is not an easy question because PHP is a synchronous language by default.
You could do this:
$a = false;
$i = 0;
while($a == false && $i < 10)
{
$a = file_get_contents($path);
$i++;
usleep(10);
}
$result = json_decode($a);
Adding usleep(10) allows your server not to get on his knees each time the API will be unavailable. And your function will give up after 10 attempts, which prevents it to freeze completely in case of long unavailability.
Since you didn't provide any code it's kind of hard to help you. But here is one way to do it.
$data = null;
while(!$data) {
$json = file_get_contents($url);
$data = json_decode($json); // Will return false if not valid JSON
}
// While loop won't stop until JSON was valid and $data contains an object
var_dump($data);
I suggest you throw some sort of increment variable in there to stop attempting after X scripts.
Based on your comment, here is what I would do:
You have a PHP script that makes the API call and, if successful, records the price and when that price was acquired
You put that script in a cronjob/scheduled task that runs every 10 minutes.
Your PHP view pulls the most recent price from the database and uses that for whatever display/calculations it needs. If pertinent, also show the date/time that price was captured
The other answers suggest doing a loop. A combo approach probably works best here: in your script, put in a few loops just in case the interface is down for a short blip. If it's not up after say a minute, use the old value until your next try.
A loop can solve this problem, but so can a recursive function like this one:
function file_get_contents_retry($url, $attemptsRemaining=3) {
$content = file_get_contents($url);
$attemptsRemaining--;
if( empty($content) && $attemptsRemaining > 0 ) {
return file_get_contents_retry($url, $attemptsRemaining);
}
return $content;
}
// Usage:
$retryAttempts = 6; // Default is 3.
echo file_get_contents_retry("http://google.com", $retryAttempts);

Using Simple HTML DOM to extract an 'a' URL

I have this code for scraping team names from a table
$url = 'http://fantasy.premierleague.com/my-leagues/303/standings/';
$html = #file_get_html($url);
//Cut out the table
$FullTable = $html->find('table[class=ismStandingsTable]',0);
//get the text from the 3rd cell in the row
$teamname = $FullTable->find('td',2)->innertext;
echo $teamname;
This much works.. and gives this output....
Why Always Me?
But when I add these lines..
$teamdetails = $teamname->find('a')->href;
echo $teamdetails;
I get completely blank output.
Any idea why? I am trying to get the /entry/110291/event-history/33/ as one variable, and the Why Always Me? as another.
Instead do this:
$tdhtml = DOMDocument::loadHTML($teamdetails);
$link = $tdhtml->getElementsByTagName('a');
$url = $link->item(0)->attributes->getNamedItem('href')->nodeValue;
$teamdetails = $teamname->find('a')->href;
^^^^^^^^^---- never defined in your code
I also fail to see how your "works" code could possibly work. You don't define $teamname in there either, so all you'd never get is the output of a null/undefined variable, which is...no output all.
Marc B is right, I get that you don't have to initialize a variable, but he is saying you are trying to access a property of said variable:
$teamdetails = $teamname->find('a')->href;
^^^^^^^^^---- never defined in your code
This is essentially:
$teamname = null;
$teamname->find('a')->href;
The problem in your example is that $teamname is a string and you're treating it like a simple_html_dom_node

Calling php method from external function produces error

function KeepSamePage($text)
{
$sb_w = $oPdf->GetStringWidth($text);
$num_lines = explode("\n",$text);
$total = 0;
foreach($num_lines as $line)
{
$y = $oPdf->GetY();
$page_height = 11 * 25.4;
$this_width = $oPdf->GetStringWidth(strip_tags($line));
$extra_line = floor($this_width / $w);
$is_line = $this_width / ($w - 1);
$is_line = $this_width == 0 ? 1 + $extra_line : ceil($is_line) + $extra_line;
$total = $total + $is_line;
}
$sb_height = $total * 5;
if(($page_height - $y) < $sb_height){ $oPdf->AddPage(); }
}
KeepSamePage($signature_block);
I'm using FPDF and I'm creating a function to keep the signature page of a letter all on the same page. This checks to see if it would go to the next page and if soo, then it does an AddPage();
The issue I'm having is that when I don't have it in a function, it works perfectly, but when I put it within a function, I get errors when calling the methods in the class represented by $oPdf.
So, my question generally is this: Is it possible to have a regular function in PHP call a class method as I have below? If it is possible, what am I doing wrong?
ERROR GENERATED IS:
Fatal error: Call to a member function GetStringWidth() on a non-object in /home/jarodmo/public_html/cms/attorney_signature_block.php on line 18
Oh, and an explanation of my function just in case you're interested or someone else finds it.
Text has \n for new lines in it so the PDF will put the text of the signature block on the next line. Each new array element should be a new line, so I would need to multiply the number of lines by my line height, 5 in this case. (See $total * 5).
I check to see where we are on the page, find the difference between the page height and the Y position, then check that against the height of the signature block. If the signature block is bigger, then it wouldn't fit and I know we need a manual page break.
Also, because I do the explode with the \n to see the lines, I also have to check to make sure that none of the lines is still wider than the page otherwise it would word wrap and really be 2 lines (or more) where I was only counting it as 1 because it was just one array element. I know a signature block shouldn't have text wide enough to be on 2 lines, but I wrote this to be applicable for more than just signature blocks. I wanted to be able to call this function anywhere I wanted to make sure certain text stayed on the same page. Call the function, check the text I'm about to write to the PDF and move on knowing that the desired text would all be on the same page.
Thanks for all of the help and comments. SO is the best.
$oPdf
is not defined on your code. You need to define it, and maybe read PHP variable scope.
You are trying to access methods of the $oPdf object in your function, but your function has no idea what $oPdf is, thus, the error message.
you have to do something like this.
function KeepSamePage($text) {
$oPdf = new your_string_class();
$sb_w = $oPdf->GetStringWidth($text);
}
or
$oPdf = new your_string_class();
function KeepSamePage($text, $oPdf) {
$sb_w = $oPdf->GetStringWidth($text);
}
Try the following:
function KeepSamePage($text) {
global $oPdf;
…
}
The problem is, that the object is defined outside your function and you will have to allow your function to access it.
// Edit:
If you want to avoid global for whatever reason, you will have to pass your object to the function like this:
function KeepSamePage($text, $oPdf) {
…
// IMPORTANT! $oPdf has changed in this function, so you will have to give it back
return $oPdf;
}
You can call your function like this:
$oPdf = KeepSamePage($signature_block, $oPdf);
The advantage is, that you see in the main thread, that your function might has changed the object.
// Edit 2: I think, I was wrong on the edit1 in your case. As you pass the complete object to the function every change does apply to the object, so the changes will still be existant without giving back the result. If this was a variable that was defined in the main thread, you would have to give back the new value:
$a = 1;
function result1($a) {
++$a;
}
function result2($a) {
return ++$a;
}
echo $a."\n"; // 1
result1($a);
echo $a."\n"; // 1
$a = result2($a);
echo $a."\n"; // 2

PHP JSON and Twitter

<?
$Tweet = file_get_contents("http://api.twitter.com/1/statuses/user_timeline.json?screen_name=EdVizenor&count=1");
//$Tweet = explode(",",$Tweet);
/// If I explode and echo the $Tweet(3); i get .... "text":"mY LATEST TWEET"
var_dump(json_decode($Tweet,true));
?>
What I want to do is parse out the array via key. Something like:
echo $Tweet(text); /// but this does not work.
It would be helpful to know what the error is. The problem is that $Tweet(text) would be calling a function contained in $Tweet, since that variable is not a function, but an actual array, you actually just have to
<?php
// your code
$tweets = json_decode($Tweet,true);
echo $tweets[0]['text'];
Next time, be sure to include the error being thrown, it is very helpful for you to read and understand those!

Script dies, I'm not sure why

I'm trying to parse a 6,000 line 500 KB file into an array so I can import the data into our system. The problem is that the script stops executing somewhere between lines 3000-4000. There are no breaks in the code, we use it on other imports. Any ideas on why this might be happening and what I can do to prevent it?
/**
* Takes a seperated value string and makes it an array
* #param $delimiter string The delimiter to be seperated by, usually a comma or tab
* #param $string string The string to seperate
* #return array The resulting array
*/
public function svToArray ($delimiter, $string) {
$x = 0;
$rowList = array();
$splitContent = preg_split("#\n+#", trim($string));
foreach ($splitContent as $key => $value) {
$newData = preg_split("#".$delimiter."#", $value);
if ($x == 0) {
$headerValues = array_values($newData);
} else {
$tempRow = array();
foreach ($newData as $rowColumnKey => $rowColumnValue) {
$tempRow[$headerValues[$rowColumnKey]] = $rowColumnValue;
}
$rowList[] = $tempRow;
}
$x++;
}
return $rowList;
}
UPDATE:
Error reporting is enabled. I've started using a file that's only 130KB at 1,500 lines and it does the same thing...
When I add debug code as in the following example nothing echoes at all unless I put an exit after the echo "test<br/>";
public function svToArray ($delimiter, $string) {
$x = 0;
$rowList = array();
$splitContent = preg_split("#\n+#", trim($string));
echo "test<br/>";
foreach ($splitContent as $key => $value) {
$newData = preg_split("#".$delimiter."#", $value);
if ($x == 0) {
$headerValues = array_values($newData);
} else {
$tempRow = array();
foreach ($newData as $rowColumnKey => $rowColumnValue) {
$tempRow[$headerValues[$rowColumnKey]] = $rowColumnValue;
}
$rowList[] = $tempRow;
}
$x++;
}
echo "test";
$this->tru->debug($rowList);
exit;
return $rowList;
}
UPDATE
If I comment out $tempRow[] = $rowColumnValue; then it echoes everything fine....
Probably it just timeouts. Does it always stop after X seconds?
Try setting the max execution time higher: set_time_limit(900) at the top of your pages.
You can check the max execution time in your phpinfo():
1. Create a new php page with
2. Search for max_execution_time
Have you looked at the files? Is there a line with too many delimiters? Also, what are all the "#" about?
My best guess is that you're hitting a line where $headerValues[$rowColumnKey] is not defined.
What about $rowColumnKey and $rowColumnValue ?
They are not defined in the function.
Make sure that you have error reporting set, put this on top of your php file:
ini_set('display_errors', true);
error_reporting(E_ALL);
Also you can extend the script's execution time:
ini_set('max_execution_time', 50000);
About the only time I've a php script die, with no output and no errors is when it runs out of memory. It doesn't look like your script would use much memory, but I would check to make sure that the memory limit for php is high enough.
Are you sure that you are iterating through the returned array instead of simply trying to print it? (The issue may be outside of the function rather than within it.)
Also...
`exit;
return $rowList;`
Try removing the 'exit;' line and see if that changes anything.
Also, $splitContent is not defined as an array before being used, but preg_split is going to return an array. (This should not impact your results, but it is safe to do so.)
Why are you using $key => $value pairs when you cannot be sure of what will be within the string? If we could see an small example of the content of $string, we might be able to adjust this function to work better.
The # should be replaced with /, but that may simply be a formatting issue.
$newData should be defined as an array before being used just to be safe even though that is not causing your issue.
If you can, increase maximum execution time in php.ini.. also increase the maximum memory amount for each instance.. checking error logs of your webserver could also help.
It appears as though there was too much output to the output buffer, causing the page to show nothing at all.

Categories