phantom php echo? - php

im getting this error:
Parse error: syntax error, unexpected T_ECHO in /home/labvc/public_html/AT/site/getimages.php on line 26
from this code:
<?php
echo '<br />';
echo '<div id=gallery>';
function getDirTree($dir,$p=true) {
$d = dir($dir);$x=array();
while (false !== ($r = $d->read())) {
if($r!="."&&$r!=".."&&(($p==false&&is_dir($dir.$r))||$p==true)) {
$x[$r] = (is_dir($dir.$r)?array():(is_file($dir.$r)?true:false));
}
}
foreach ($x as $key => $value) {
if (is_dir($dir.$key."/")) {
$x[$key] = getDirTree($dir.$key."/",$p);
}
}
ksort($x);
return $x;
}
$tree = getDirTree("./res/gallery/painting/");
foreach($tree as $element => $eval) {
if (is_array($eval)) {
foreach($eval as $file => $value) {
if (strstr($file, "png")||strstr($file, "jpg")||strstr($file, "bmp")||strstr($file, "gif")) {
$item = $tree.'/'.$element.$file;
$itemthumb = $tree.'/thumbs/'.$element.$file;
echo '<img src="'.$itemthumb.'" alt="'.$file.'"/>';
}
}
}
}
echo '</div>';
echo '<br />';
echo 'tree: '.$tree.'<br />';
echo 'element: '.$element.'<br />';
echo 'file: '.$file.'<br />';
$abc="res/gallery/painting";
$def="01.png";
echo'<img src="'.$abc.'/thumbs/'.$def.'" alt="'.$def.'"/>';
echo '<br />';
line 26 is not an echo, theres not even an echo close to line 26
foreach($tree as $element => $eval) {
Any ideas?

I know it sounds silly, but are you actually looking at / editing the file you are debugging?
Any number of times it turned out I was in directory A/foo.c, when the code was being run out of directory B/foo.c. I always feel stooooopid after doing this.
Stick a print "foo!" in there to see if you are actually in the file you think you are.

This seems a suspicious line:
$item = $tree.'/'.$element.$file;
$tree should be an array, so if you get the error at runtime (as opposed to compile time) then it would make sense it would complain about this.

Related

Scraping with Simple HTML DOM Parser but it stops suddenly

I'm trying to scrape the following page: http://mangafox.me/manga/
I wanted the script to click on each of those links and scrape the details of each manga and for the most part my code does exactly that. It works, but for some reason the page just stops loading midway (it doesn't even go through the # list).
There is no error message so I don't know what I'm looking for. I would appreciate some advice on what I'm doing wrong.
Code:
<?php
include('simple_html_dom.php');
set_time_limit(0);
//ini_set('max_execution_time', 300);
//Creates an instance of the simple_html_dom class
$html = new simple_html_dom();
//Loads the page from the URL entered
$html->load_file('http://mangafox.me/manga');
//Finds an element and if there is more than 1 instance the variable becomes an array
$manga_urls = $html->find('.manga_list a');
//Function which retrieves information needed to populate the DB from indiviual manga pages.
function getmanga($value, $url){
$pagehtml = new simple_html_dom();
$pagehtml->load_file($url);
if ($value == 'desc') {
$description = $pagehtml->find('p.summary');
foreach($description as $d){
//return $d->plaintext;
return $desc = $d->plaintext;
}
unset($description);
} else if ($value == 'status') {
$status = $pagehtml->find('div[class=data] span');
foreach ($status as $s) {
$status = explode(",", $s->plaintext);
return $status[0];
}
unset($status);
} else if ($value == 'genre') {
$genre = $pagehtml->find('//*[#id="title"]/table/tbody/tr[2]/td[4]');
foreach ($genre as $g) {
return $g->plaintext;
}
unset($genre);
} else if ($value == 'author') {
$author = $pagehtml->find('//*[#id="title"]/table/tbody/tr[2]/td[2]');
foreach ($author as $a) {
return $a->plaintext;
}
unset($author);
} else if ($value == 'release') {
$release = $pagehtml->find('//*[#id="title"]/table/tbody/tr[2]/td[1]');
foreach ($release as $r) {
return $r->plaintext;
}
unset($release);
} else if ($value == 'image') {
$image = $pagehtml->find('.cover img');
foreach ($image as $i) {
return $i->src;
}
unset($image);
}
$pagehtml->clear();
unset($pagehtml);
}
foreach($manga_urls as $url) {
$href = $url->href;
if (strpos($href, 'http') !== false){
echo 'Title: ' . $url->plaintext . '<br />';
echo 'Link: ' . $href . '<br />';
echo 'Description: ' . getmanga('desc', $href) . '<br />';
echo 'Status: ' . getmanga('status',$href) . '<br />';
echo 'Genre: ' . getmanga('genre', $href) . '<br />';
echo 'Author: ' . getmanga('author', $href) . '<br />';
echo 'Release: ' . getmanga('release', $href) . '<br />';
echo 'Image Link: ' . getmanga('image', $href) . '<br />';
echo '<br /><br />';
}
}
$html->clear();
unset($html);
?>
So, it was not a 'just do this' fix, but I did it ;)
Beside the fact is was importing the sub pages way too much, it also had a huge simple_html_dom to iterate through. It has like 13307 items, and simple_html_dom is not made for speed or efficiency. It allocated much space for things you didn't need in this case. That is why I replaced the main simple_html_dom with a regular expression.
I think it still takes ages to load fully, and you are better of using a other language, but this is a working result :-)
https://gist.github.com/dralletje/ee996ffe4c957cdccd01
I have faced the same issue, when the loop with 20k iterations stopped without any error message. So posting the solution so it might help someone.
The issue seems to be of performance as stated before. So I decided to use curl instead of simple html dom. The function bellow returns content of website:
function getContent($url){
$ch = curl_init();
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$result = curl_exec($ch);
curl_close($ch);
if($result){
return $result;
}else{
return "";
}
}
Now to traverse the DOM, I am still using simple html dom, but the code is changed as:
$content = getContent($url);
if($content){
// Create a DOM object
$doc = new simple_html_dom();
// Load HTML from a string
$doc->load($content);
}else{
continue;
}
And at the end of each loop close and unset variable as:
$doc->clear();
unset($doc);

How to check for circular references in PHP when recursively parsing an associative array?

I created this array with a circular reference:
$arr = array(1 => 'one', 2 => 'two');
$arr[3] = &$arr;
I have a function that recursively prints out the values in an array, but I really couldn't solve the problem of creating a circular reference check. How can you do that?
The current function I have for printing the array is copied below. I haven't included the various attempts I made at doing the circular reference check. They mainly revolved around a strategy of maintaining a $seen array of items that have already been printed for each branch of recursion. This is because I still want to allow the printing of duplicate values, just not printing of a value if it is a parent of the current array being parsed.
The problems I had were figuring out how to add references rather than array copies to this $seen variable. But I'd be happy to use another strategy all together if it worked.
function HTMLStringify($arr)
{
if(is_array($arr)){
$html = '<ul>';
foreach ($arr as $key => $value) {
$html .= '<li>' . $key;
if(is_array($value)){
//Conspicuously missing is a circular reference check,
//causing infinite recursion. After a few failed attempts
//at checking for this (e.g. discovering that array_push doesn't take references)
//I have left it for further study.
//(After all, Javascript's JSON.stringify() doesn't check for circular references)
//TODO: Check for circular references
$html .= HTMLStringify($value, $seen);
}
elseif(is_numeric($value) || is_string($value) || is_null($value))
{
$html .= ' = ' . $value;
}
else
{
$html .= ' [couldn\'t parse ' . gettype($value) . ']';
}
$html .= '</li>';
}
$html .= '</ul>';
return $html;
}
else
{
return null;
}
}
An adapted version of your code, using the strict in_array check from the answer linked by Ryan Vincent, is shown below:
function HTMLStringify($arr, array $seen = array()) {
if (is_array($arr)) {
$seen[] = $arr;
$html = '<ul>';
foreach ($arr as $key => $value) {
$html .= '<li>' . $key;
if (is_array($value)) {
if (in_array($value, $seen, true)) {
// Deal with recursion in your own way here
$html .= ' [RECURSION]';
} else {
$html .= HTMLStringify($value, $seen);
}
} elseif (is_numeric($value) || is_string($value) || is_null($value)) {
$html .= ' = ' . $value;
} else {
$html .= ' [couldn\'t parse ' . gettype($value) . ']';
}
$html .= '</li>';
}
return $html . '</ul>';
} else {
return null;
}
}
$arr = array(1 => 'one', 2 => 'two');
$arr[3] = &$arr;
echo HTMLStringify($arr);
Comparing across a number of PHP versions, it looks like this will work for PHP 5.3.15+ and PHP 5.4.5+.
i'm using this function for debugging. Also upgraded to detect recursive link.
function print_table($mixed, $level=9, $_callstack=array()){
if($level<=0){ echo '**LIMIT**'; return; }
if( array_search(serialize($mixed), $_callstack)!==false){
echo '***recursive detected***';
return ;
}
$_callstack[] = serialize($mixed);
if(is_array($mixed)){
echo '<table cellspacing="0" width="100%" border="1">';
foreach($mixed as $key=>$val){
echo '<tr><td width="20%">'.$key.'</td><td>';
if(is_array($val)){
print_table($val,$level-1, $_callstack);
}elseif(is_null($val)){
echo '<span style="color:blue">null</span>';
}elseif($val===false){
echo '<span style="color:red">false</span>';
}elseif($val===true){
echo '<span style="color:green">true</span>';
}elseif(is_numeric($val) && $val>1000000000){
echo $val,' <span style="color:gray">[',date('d-m-Y H:i:s',$val),']</span>';
}elseif($val===''){
echo '<span style="color:blue">empty string</span>';
}else{
echo $val;
}
echo '</td></tr>';
}
echo '</table>';
}else{
var_dump($mixed);
}
}
As you see, i collect serialaized object, then compare it. Serialization required, because simply comparsion recursive object throw a fatal error:
$arr=array(&$arr);
$arr==$arr; // Fatal error: Nesting level too deep - recursive dependency?
// php 5.2.9
But serialization support recursive objects! So, we should compare serialaized strings, but serialization can take a lot of tima and memory.
If you will find another method - let me know :)

JSON Fatal Error foreach

I´ve got the following:
include('php/get_recipe_byID.php');
$jsonstring1 = $recipe_byidarr;
$recip = json_decode($recipe_byidarr, true);
print_r($recip);
foreach ($recip['Data']['Recipes'] as $key => $newrecipe) {
// echo '<li>
// <a href="/recipe_search.php?id=' . $recipe['ID'] . '">';
echo 'seas';
echo $newrecipe['TITLE'];
echo '<br><br>';
}
When I call it in the browser, it tells me that
Fatal error: Cannot use string offset as an array in /var/www/recipe_search.php on line 43
This is the line of the foreach loop.
$recip is the following:
{"Data":{"Recipes":{"Recipe_9":{"ID":"9","TITLE":"Schnitzel","TEXT":"Alex\u00b4s Hausmannskost","COUNT_PERSONS":"4","DURATION":"40","USER_ID":"1","DATE":"2011-09-16 00:00:00"}}},"Message":null,"Code":200}
Do anybody know where my mistake is?
Just try it:
$taskSeries = $array['Data']['Recipes']['Recipe_'.$_GET['id']];
if(array_key_exists('TITLE', $taskSeries)) {
$taskSeries = array($taskSeries);
}
foreach($taskSeries as $task) {
$title = $task['TITLE'];
// do something with $title and other
}

Title only if foreach exists

I have the following code:
foreach ($model->details as $detail) {
if ($detail->Title) echo $detail->Title;
if ($detail->Info) echo '<br />'.$detail->Info;
}
Now I want to add something like this:
'<h2>Details</h2>'.'<hr />'
to the top of the output but only when the if's in the foreach clause are met. If neither of the if's is met I want nothing to display at all.
Can some help me tweak my code to accomplish this?
Like so?
foreach ($model->details as $detail) {
if ($detail->Title && $detail->Info) {
echo '<h2>Details</h2><hr />';
}
if ($detail->Title) echo $detail->Title;
if ($detail->Info) echo '<br />'.$detail->Info;
}
Addendum: I'd probably rather do something like this, to also avoid the uneccessary <br /> when there's no Title, but only Info
foreach ($model->details as $detail) {
$text = array();
if ($detail->Title) $text[] = $detail->Title;
if ($detail->Info) $text[] = $detail->Info;
if (!empty($text)) {
echo '<h2>Details</h2><hr />';
echo implode('<br />', $text);
}
}
You need to output to a string, or use the output buffering. The following example uses the string approach:
$sOutputHtml = NULL;
foreach ($model->details as $detail) {
if ($detail->Title) $sOutputHtml .= $detail->Title;
if ($detail->Info) $sOutputHtml .= '<br />'.$detail->Info;
}
if ($sOutputHtml !== NULL) {
echo '<h2>Details</h2>'.'<hr />' . $sOutputHtml;
}

PHP - How do I read all attributes of XML items using simpleXML?

I'm making a script, that reads through the passed XML file and displays the source code. I've got it almost done, but the item attributes .. I can't find a way to catch them. Here's the code:
$xml = simplexml_load_file("path/to/file.xml");
showTree($xml->children(), 0);
function showTree($value, $i) {
if($value == '') {
foreach($value as $name2 => $value2) {
echo str_repeat('--', $i)." <$name2> \n";
showTree($value2, ($i+1));
echo str_repeat('--', $i)." </$name2> \n";
}
} else { echo str_repeat('--', $i)." ".trim($value)."\n"; }
} // end: function
As I said, it works fine, but doesn't display the attributes, for example:
<item id=2>Item</item>
returns only the:
<item>Item</item>
Thanks for any responses, Mike.
Unless I missread your code something like this should probably be about right.
$xml = simplexml_load_file("path/to/file.xml");
showTree($xml->children(), 0);
function showTree($value, $i) {
if($value == '') {
foreach($value as $name2 => $value2) {
$attribsStr = '';
foreach($value2->attributes() as $attribName => $attribValue) {
$attribsStr .= $attribName . '="' . $attribValue . '"' . ' ';
}
echo str_repeat('--', $i)." <$name2 $attribsStr> \n";
showTree($value2, ($i+1));
echo str_repeat('--', $i)." </$name2> \n";
}
} else { echo str_repeat('--', $i)." ".trim($value)."\n"; }
} // end: function
Have a look at http://php.net/manual/en/simplexmlelement.attributes.php

Categories