Advice on combining two XML feeds together - own3d/twitch.tv - php

I am working on a small project to display live streams for Dota 2, League of Legends and StarCraft 2 and was using a 3rd party hosted api that had both feeds from Twitch.tv and own3d - I couldn't of been happier, until they shut down their servers!
I tried merging them together with Yahoo pipes but didn't have much luck!
These are the two feeds I am working with:
Twitch.tv/justin.tv - http://api.justin.tv/api/stream/list.xml?category=gaming&limit=15
Own3d - http://api.own3d.tv/live?limit=15
Here is my attempt at combining the two feeds, by just listing them on top of each other. Its a temporary solution but they are not sorted by live viewers (which is something I would like to do) -
The current script I have:
<table class="table">
<thead>
<tr>
<th colspan="4" class="streamheader">Current live Sstreams</th>
</tr>
</thead>
<tbody>
<?php
$xmlFileData2 = file_get_contents("http://api.own3d.tv/live?limit=15");
$xmlData2 = new SimpleXMLElement($xmlFileData2);
foreach($xmlData2->channel->item as $item)
if ($item->misc['game'] == 'Dota 2' OR $item->misc['game'] == 'League of Legends' OR $item->misc['game'] == 'StarCraft II') {
{
$titlelimit = $item->title;
$title = substr($titlelimit,0,20);
echo "<tr><td>";
if ($item->misc['game'] == 'League of Legends')
echo"<img src='http://localhost/ae/wp-content/themes/ae/img/lol.jpg' /></td><td>";
elseif ($item->misc['game'] == 'StarCraft II')
echo"<img src='http://localhost/ae/wp-content/themes/ae/img/sc2.jpg' /></td><td>";
elseif ($item->misc['game'] == 'Dota 2')
echo"<img src='http://localhost/ae/wp-content/themes/ae/img/dota2.jpg' /></td><td>";
else
echo "none";
echo "<a href='";
$link = $item->link;
$findthis ="/www.own3d.tv/live/";
$replacement ="ae/stream/";
echo str_replace ($findthis, $replacement, $link);
echo "'>";
echo $title;
echo "</a></td><td>";
$author = $item->author;
$find ="/rss#own3d.tv/";
$replace ="";
echo preg_replace ($find, $replace, $author);
echo "<td>";
echo $item->misc['viewers'];
echo "</td> </tr>";
}
}
else
{
echo "";
}
$xmlFileData1 = file_get_contents("http://api.justin.tv/api/stream/list.xml?category=gaming&limit=15");
$xmlData1 = new SimpleXMLElement($xmlFileData1);
foreach($xmlData1->stream as $itemtwitch) {
$game = $itemtwitch->meta_game;
$sc2 = "StarCraft II: Wings of Liberty";
if ($itemtwitch->meta_game == 'Dota 2' OR $itemtwitch->meta_game == 'League of Legends' OR $itemtwitch->meta_game == 'StarCraft II: Wings of Liberty') {
{
echo "<tr><td>";
$titlelimittwitch = $itemtwitch->title;
$titlelimittwitch = substr($titlelimittwitch,0,20);
if ($itemtwitch->meta_game == 'League of Legends')
echo"<img src='http://localhost/ae/wp-content/themes/ae/img/lol.jpg' /></td><td>";
elseif ($itemtwitch->meta_game == 'StarCraft II: Wings of Liberty')
echo"<img src='http://localhost/ae/wp-content/themes/ae/img/sc2.jpg' /></td><td>";
elseif ($itemtwitch->meta_game == 'Dota 2')
echo"<img src='http://localhost/ae/wp-content/themes/ae/img/dota2.jpg' /></td><td>";
else
echo "none";
$data = $itemtwitch->name;
$find ="/live_user_/";
$replace ="";
echo "<a href='";
echo "http://localhost/ae/stream/";
echo preg_replace ($find, $replace, $data);
echo "''>";
echo "$titlelimittwitch";
//print(" - " . $itemtwitch->meta_game . "");
echo "</a></td><td>";
echo preg_replace ($find, $replace, $data);
print("</td><td>" . $itemtwitch->channel_count . "</td></tr>");
}
}
else {
echo "";
}
}
?>
<tr>
<th colspan="4" class="streamheader centered">View all streams</th>
</tr>
</tbody>
</table>
Any guidance or being pointed in the right direction would be fantastic.
Cheers!

Dan, you will need to add both sets of information(own3d/twitch) to the same array, then sort it. Say you add them to an array named $streamArray you would use the following code to then sort them by viewers.
foreach ($streamArray as $key => $row) {
$viewers[$key] = $row['viewers'];
}
array_multisort($viewers, SORT_DESC, SORT_NUMERIC, $streamArray);
I have developed a similar setup at http://halfw.com/streams.php
If you have any questions just let me know!

You can use a library like Streamtastic (disclaimer: I wrote it) to get latest and top viewed streams for both Own3d and Twitch.tv
https://github.com/sergiotapia/Streamtastic
Usage is very simple:
Own3d Examples:
StreamFinder own3dStreamtastic = new StreamFinder(new Own3dStreamRepository());
// Let's find the most viewed streamers in general.
var topStreamers = own3dStreamtastic.FindTopViewedStreams();
foreach (var stream in topStreamers)
{
Console.WriteLine(String.Format("{0} - Viewers: {1}", stream.Title, stream.ViewerCount));
}
// You can find the top viewed streamers for any game Own3d supports.
// For example, League of Legends.
var topStreamersForLeagueOfLegends = own3dStreamtastic.FindTopViewedStreamsByGame("League+of+Legends");
foreach (var stream in topStreamersForLeagueOfLegends)
{
Console.WriteLine(String.Format("{0} - Viewers: {1}", stream.Title, stream.ViewerCount));
}
// Or how about League of Legends.
var topStreamersForLol = own3dStreamtastic.FindTopViewedStreamsByGame("League+of+Legends");
foreach (var stream in topStreamersForLol)
{
Console.WriteLine(String.Format("{0} - Viewers: {1}", stream.Title, stream.ViewerCount));
}
Since you're using PHP, just run this application and save results to the database. Then have your PHP program just fetch results from the database.

Related

separate data from a api

we are trying to make a website for our class, here you can see important news, the class schedule, homework schedule and a contact page for tips and bugs...
So, we want to have the schedule always up to date and a class mate made a api to get the schedule-data from our school site. but now we have an issue... he don't want to help us anymore!!! -,-
here is the question?
The schedule is echo in a table but it stand next to eachother, because the api only separate the days including the lesson. but we want the lesson seperate from the day! and echo the table below each other..
Is there anyone who want to help me / Us out???
Link for a live previeuw how its now!
<?php
$apis = array('verandermij');
if (!isset($_GET['afdeling'])) //school sector
{
echo "FOUTCODE 1"; //Wrongcode
exit;
}
if (!isset($_GET['klas'])) // class
{
echo "FOUTCODE 2"; //Wrongcode
exit;
}
if (!isset($_GET['api']))
{
echo "FOUTCODE 3"; //Wrongcode
exit;
}
$apigeldig = false;
foreach ($apis as $api)
{
if ($api == $_GET['api'])
{
$apigeldig = true;
}
}
if ($apigeldig == false)
{
echo "FOUTCODE 4"; //Wrongcode
exit;
}
$afdeling = $_GET['afdeling'];
$klas = $_GET['klas'];
// get the class data
$url = "https://rooster.rocfriesepoort.nl/emmeloord.aspx?group=" . $afdeling . "&specs=" . $klas . "&a=1";
$content = file_get_contents($url);
// little bit cleaning
$content = explode("<div class=header>Rooster</div>", $content);
$content = $content[1];
// Splits dagen
$raw_dagen = explode("<td valign=top style='background-color: #e5e5e5'>", $content); //Raw_Days
$clean_dagen = array(); // Clean_Days
$dagen = array( //Days
$raw_dagen[1],
$raw_dagen[2],
$raw_dagen[3],
$raw_dagen[4],
$raw_dagen[5]
);
// Beginnen met sorteren
$opgeschoond = array(); //Cleand
$stoploop = false;
foreach ($dagen as $dag) //Days as Day
{
$tmp = explode("</div>", $dag);
$i = 0;
foreach ($tmp as $item)
{
if ($stoploop == true) { $i++; continue; }
if ($tmp[$i] == null) { $i++; continue; }
$tmp[$i] = str_replace("<div class='dagHeader'>", "", $tmp[$i]);
$tmp[$i] = str_replace("<div class=tablecell3>", "VRIJ", $tmp[$i]);
$tmp[$i] = str_replace("<div class=tablecell1>", "", $tmp[$i]);
$tmp[$i] = str_replace("<div class=tablecell2>", "", $tmp[$i]);
$tmp[$i] = str_replace('<br style="clear:both"></br><br><br><div id=footer style="width:95%;">© ROC Friese Poort 2015 - ', "", $tmp[$i]);
$tmp[$i] = str_replace("<a href='javascript:void(0)'". ' onclick="Disclaimer' . "('500','500','YES')" . '" title=' . "'Disclaimer'>", "", $tmp[$i]);
if ($tmp[$i] == "</td>")
{
$tmp[$i] = "DAG EINDE";
}
if ($tmp[$i] == "</td></table>")
{
$tmp[$i] = "DAG EINDE";
unset($tmp[$i + 1]);
unset($tmp[$i + 2]);
unset($tmp[$i + 3]);
unset($tmp[$i + 4]);
unset($tmp[$i + 5]);
unset($tmp[$i + 6]);
$stoploop = true;
}
$i++;
}
array_push($opgeschoond, $tmp);
}
print(json_encode($opgeschoond));
?>
this we use the echo the data!!!!!
<table>
<tr>
<?php
foreach ($maandag as $lesuur)
{
print("<td>");
print($lesuur);
print("</td>");
}
?>
</tr>
<tr>
<?php
foreach ($dinsdag as $lesuur)
{
print("<td id='oneven'>");
print($lesuur);
print("</td>");
}
?>
</tr>
<tr>
<?php
foreach ($woensdag as $lesuur)
{
print("<td>");
print($lesuur);
print("</td>");
}
?>
</tr>
<tr>
<?php
foreach ($donderdag as $lesuur)
{
print("<td id='oneven'>");
print($lesuur);
print("</td>");
}
?>
</tr>
<tr>
<?php
foreach ($vrijdag as $lesuur)
{
print("<td>");
print($lesuur);
print("</td>");
}
?>
</tr>
</table>
link for the raw data: enter link description here
[["Maandag 09-11-2015","MTM
Nederlands
C2.02
","MTM
Nederlands
A2.08
","VRIJ","KAS
Wiskunde
B2.02
","KSR
SLB
A2.07
","DAG EINDE"],["Dinsdag 10-11-2015","VRIJ","CRL
Database techn.
A2.07
","CRL
Database techn.
A2.07
","CRL
CMS
A2.07
","VRIJ","CRL
CMS
A2.07
","CRL
Webservers
A2.07
","CRL
Webservers
A2.07
","DAG EINDE"],["Woensdag 11-11-2015","VRIJ","VRIJ","KSR
Java Script
A2.07
","KSR
Java Script
A2.07
","VRIJ","VRIJ","VSS
Routeplanner
B2.04
","VSS
LevO
B2.04
","VSS
LLB
B2.04
","DAG EINDE"],["Donderdag 12-11-2015","VRIJ","KRJ
Project
A2.07
","KRJ
Project
A2.07
","KRJ
Project
A2.07
","VRIJ","KSR
Scrum
A2.07
","GFO
Rekenen
B2.01
","KSR
Scrum
A2.07
","DAG EINDE"],["Vrijdag 13-11-2015","ZAA
Engels
B2.03
","ZAA
Engels
B2.06a
","KRJ
Project
A2.07
","KRJ
Project
A2.07
","VRIJ","KSR
SLB
A2.07
","GFO
Rekenen
B2.06
","DAG EINDE"]]
thanks for helping me, a beginner (a)
The data returned from the 'api' is a two dimensional array, with the second dimension variable width, but the first entry is the day. data[0][0] = "Maandag 09-11-2015";.
If I understand correctly, what you want is something like this:
$apidata = file_get_contents($apiurl);
$data = json_decode($apidata, true);
$maandag = array_slice($data[0],1)
$dinsdag = array_slice($data[1],1)
$woensdag = array_slice($data[2],1)
$donderdag = array_slice($data[3],1)
$vrijdag = array_slice($data[4],1)
Then your echo from above will work, the day names removed from the arrays (though also the dates).
Once in this form, building a table for the days is relatively simple (though I'm sure others will have a cleaner way to do it):
<?php
$longest = 0;
for($i=0;$i<5;$i++) {
if($data[$i].count()>$longest) $longest=$data[$i].count();
}
$longest--; // we removed one entry already
?>
<table>
<tr><th>Maandag</th><th>Dinsdag</th><th>Woensdag</th><th>Donderdag</th><th>Vrijdag</th></tr>
<?php
for($i=0;$i<$longest;$i++) {
print "<tr><td>{$maandag[$i]}</td><td>{$dinsdag[$i]}</td><td>{$woensdag[$i]}</td><td>{$donderdag[$i]}</td><td>{$vrijdag[$i]}</td></tr>\n";
}
?>
</table>
That should have you set. There may be runtime errors attempting to access the array entries of the shorter days before the longest day is finished, but you can fix that with another loop adding empty strings.

Change background color of a cell when next value is different from the preceding one

I've been around for years on Stack but this is my first time posting. I'm working on a website (php + mysql) and the following problem is driving me absolutely nuts.
I have a table with 2 columns: Size and Amount. The table is generated by a basic php script simply outputting values stored in the database as rows in the table. Super basic, no fancy stuff there:
SELECT Size, Amount FROM database WHERE product = 'product123' ORDER BY Size ASC
The php echo outputs an html table displaying Size and the corresponding available packs (Amount).
Echo '<td>'.$record['size'].'</td><td>'.$record['amount'].'</td>'
Some Sizes are available in different Amounts, so therefore a particular Size can appear multiple times. Example:
Size | Amount
1 | 10
1 | 50
2 | 10
2+ | 10
3 | 40
3+ | 25
3+ | 40
4+ | 25
What I'm looking to achieve is that rows containing the same Size have the same background color. So it should alternate, grouped by Size, and this is irregular unfortunately. Example:
Size | Amount
1 | 10 < yellow
1 | 50 < yellow
2 | 10 < transparent
2+ | 10 < yellow
3 | 40 < transparent
3+ | 25 < yellow
3+ | 40 < yellow
4+ | 25 < transparent
So if the next Size is different from the preceding one, the row background color should change. This way a single Size is alternately highlighted as a group. Note that Size 2 and 2+ (same for 3 and 3+) are considered to be different sizes, hence the background color should change.
I can't figure out how to achieve this with php. The difficulty is that I can't use an evaluation based on odd/even since there sometimes is a "+" involved, making not all Sizes numeric values. Changing the naming scheme to get rid of that "+" is not an option unfortunately.
I was thinking of somehow having php check, while generating the table row by row, if the next outputted Size is identical to the preceding one. If yes: no change in bg-color. If no: change bg-color. However I can't figure out what the best way is to code something like this. Any pointers in the right direction are much appreciated.
Just a MCVE:
// your data
$records[] = array('size' => "1");
$records[] = array('size' => "1");
$records[] = array('size' => "2");
$records[] = array('size' => "2+");
$records[] = array('size' => "3");
$records[] = array('size' => "3+");
$records[] = array('size' => "3+");
$records[] = array('size' => "4");
$lastSize = $records[0]['size'];
$color = "yellow";
foreach ($records as $record) {
if ($lastSize != $record['size']) {
$lastSize = $record['size'];
if ($color == "yellow") $color = "transparent";
else $color = "yellow";
}
$lastSize == $record['size'];
echo $record['size'].' - '.$color.'<br>';
}
// OUTPUT:
// 1 - yellow
// 1 - yellow
// 2 - transparent
// 2+ - yellow
// 3 - transparent
// 3+ - yellow
// 3+ - yellow
// 4 - transparent
Ok, we'll start at the end. You probably want to put your color on the <tr>. The cleanest way to do it would be using css classes.
if ($newSize) {
echo '<tr class="tranparentRow">';
} else {
echo '<tr class="yellowRow">';
}
We'll figure out how to get the right value into $newSize in a moment. Next, we need the css for classes above, so make sure this is in your styles somewhere:
.transparentRow {
background-color: transparent;
}
.yellowRow {
background-color: yellow;
}
Ok, lets rip the + off the size:
$plainSize = trim($record['size'], '+')
Ok, we use that for comparison, using an ever changing $oldSize valiable. Here is a full, functional, block:
$oldSize = 0;
foreach($whatever as $record) {
$plainSize = trim($record['size'], '+')
if ($plainSize == $oldSize) {
$newSize = false;
} else {
$newSize = true;
}
$oldSize = $plainSize;
if ($newSize) {
echo '<tr class="tranparentRow">';
} else {
echo '<tr class="yellowRow">';
}
echo '<td>'.$record['size'].'</td><td>'.$record['amount'].'</td>';
echo '</td>';
}
Some cleanup can lead to this:
$oldSize = 0;
foreach($whatever as $record) {
$plainSize = trim($record['size'], '+')
if ($plainSize == $oldSize) {
echo '<tr class="tranparentRow">';
} else {
echo '<tr class="yellowRow">';
}
$oldSize = $plainSize;
echo '<td>'.$record['size'].'</td><td>'.$record['amount'].'</td>';
echo '</td>';
}
I hope that helped not just with this problem, but with an example of how you can approach many other problems. Start at the end, work your way back.
As my comment suggested, use a double foreach() + implode() (and yet another solution):
<?php
$array[] = array("size"=>1,"amount"=>50);
$array[] = array("size"=>2,"amount"=>10);
$array[] = array("size"=>"2+","amount"=>10);
$array[] = array("size"=>3,"amount"=>40);
$array[] = array("size"=>"3+","amount"=>25);
$array[] = array("size"=>"3+","amount"=>40);
$array[] = array("size"=>"3+","amount"=>25);
$array[] = array("size"=>'4+',"amount"=>30);
// Sort by size
foreach($array as $row) {
$new[$row['size']][] = $row['amount'];
}
?>
<table>
<?php
$i = 0;
// Loop through the sorted groups
foreach($new as $size => $amts) {
// Determine odd or even
$color = ($i % 2 == 0)? "yellow":"transparent";
?> <tr>
<td class="<?php echo $color; ?>"><?php echo $size; ?></td>
<td class="<?php echo $color; ?>"><?php echo implode("</td>".PHP_EOL."</tr>".PHP_EOL."<tr>".PHP_EOL.'<td class="'.$color.'">'.$size.'</td><td class="'.$color.'">',$amts); ?></td>
</tr>
<?php $i++;
}
?>
</table>
You can do this using php sessions like this
session_start();
$_SESSION["pre_val"]='not set';
$_SESSION["pre_class"]='transparent';
//in your loop for showing table
//your loop starts
if($_SESSION["pre_val"]==$record['size']){
$suitable_class=$_SESSION["pre_class"];
}
else{
if($_SESSION["pre_class"]=='yellow'){$suitable_class='transparent';}
else{$suitable_class='yellow';}
}
//setting current values to session
$_SESSION["pre_class"] = $suitable_class;
$_SESSION["pre_val"] = $record['size'];
Echo '<tr class="$suitable_class"><td>'.$record['size'].'</td><td>'.$record['amount'].'</td></tr>';
//your loop ends
in your css
.yellow{background-color:yellow;}
.transparent{ background-color: rgba(255, 0, 0, 0.5);}
hope this solve your problem
Some for loop fun while printing out the table
$rows = array(
array("size"=>"1" ,"amount"=>"10"),
array("size"=>"1" ,"amount"=>"50"),
array("size"=>"2" ,"amount"=>"10"),
array("size"=>"2+","amount"=>"10"),
array("size"=>"3" ,"amount"=>"40"),
array("size"=>"3+","amount"=>"25"),
array("size"=>"3+","amount"=>"40"),
array("size"=>"4+","amount"=>"25")
);
echo "
<table>
<thead>
<tr><th>Size</th><th>Amount</th></tr>
</thead>
<tbody>";
$bgColors = ['transparent','yellow'];
$bgColor = 0;
echo "
<tr>
<td class='" . $bgColors[$bgColor] . "'>" . $rows[0]["size"] . "</td><td>" . $rows[0]["amount"] . "</td>
</tr>";
for($i = 1, $max = count($rows), $lastSize = $rows[0]; $i < $max; $lastSize = $rows[$i], $i++) {
if($rows[$i]["size"] !== $lastSize["size"])
$bgColor = ($bgColor + 1) % 2;
echo "
<tr>
<td style='background-color:" . $bgColors[$bgColor] . "'>" . $rows[$i]["size"] . "</td><td>" . $rows[$i]["amount"] . "</td>
</tr>";
}
echo "
</tbody>
</table>";
And an unasked for JS solution (assuming you've printed out the table as usual)
var rows = document.querySelectorAll('#sizeTable tbody td[name=size]');
var bgColors = ['transparent','yellow'];
var bgColor = 0;
for(var i = 1, lastSize = rows[0], max = rows.length; i < max; lastSize = rows[i],i++) {
if(rows[i].innerHTML !== lastSize.innerHTML) {
bgColor = (bgColor + 1) % 2;
}
rows[i].style['background-color'] = bgColors[bgColor];
}
you can keep the current size on a variable and if it changes you can change the color.
<html>
<head><title> Sample - Menukz </title></head>
<body>
<?php
/* Sample data array with size and amount */
$product['product123'] = array
(
array("size"=>"1", "amount"=>10),
array("size"=>"1", "amount"=>50),
array("size"=>"2", "amount"=>10),
array("size"=>"2+", "amount"=>10),
array("size"=>"3", "amount"=>40),
array("size"=>"3+", "amount"=>25),
array("size"=>"3+", "amount"=>40),
array("size"=>"4+", "amount"=>25)
);
$pre_size=0;
$pre_init=1;
echo "<table>";
foreach($product['product123'] as $row)
{
echo "<tr>";
/* Initialize */
if(strcmp($pre_size, $row['size']) !== 0 && $pre_init ===1)
{
$pre_size = $row['size'];
$pre_init = 0;
}
/* Change track */
if (strcmp($pre_size, $row['size']) !== 0 && $pre_init ===0)
{
echo "<td>Changed ... </td><td>". $row['size'] . "</td><td>" . $row['amount'] . "</td>";
$pre_size = $row['size'];
}
else
{
echo "<td>Not Changed ... </td><td>". $row['size'] . "</td><td>" . $row['amount'] . "</td>";
}
echo "</tr>";
}
?>
</body>
</html>
Thanks all for the proposed solutions. Berriel's MCVE works like a charm! However Stack doesn't let me +1 the answer yet.
I have one additional question:
I also have a second table in which the output of the first column can be any article code consisting of 10 chars limited to [a-z][0-9]. Since there is no predefined scheme such as in the Size table, I can't hardcode/predict any output like in most of the proposed solutions. However I still want to color the rows it in the same way described in my opening post.
I am not familiar with Stored Procedures or PDO in mysql. Is there any way to work around arrays with predefined content and still achieve the color grouping of rows with the same article code?
You can accomplish this using a nested repeat region.
First select your product by group WHERE product = 'product123' GROUP BY size
<?php
require ('conn.php');
try {
$prod = 'product123';
$sql = "SELECT * FROM sizes WHERE product=:prod GROUP BY size";
$query = $conn->prepare($sql);
$query->bindValue(':prod', $prod, PDO::PARAM_INT);
$query->execute();
$row = $query->fetch(PDO::FETCH_ASSOC);
$totalRows = $query->rowCount();
} catch (PDOException $e) {
die('failed!');
}
?>
Then get all the products in each group ordered by amount inside a nested repeat region.
Each "grouped row" will alternate colors.
<table width="200" border="0" cellspacing="0" cellpadding="5">
<tr>
<td>Size</td>
<td>Amount</td>
</tr>
<?php
$i = 0;
do {
$i = $i + 1;
if ($i % 2 == 0){
echo '<tr bgcolor=#E4E4E4><td colspan="2">';
} else {
echo '<tr bgcolor=#EEEEEE><td colspan="2">';
}
try {
$group = $row['size'];
$sql = "SELECT * FROM sizes WHERE size=:group ORDER BY amount ASC";
$nested = $conn->prepare($sql);
$nested->bindValue(':group', $group, PDO::PARAM_INT);
$nested->execute();
$row_nested = $nested->fetch(PDO::FETCH_ASSOC);
$totalRows_nested = $nested->rowCount();
} catch (PDOException $e) {
die('nested failed');
}
echo '<table border="0" cellpadding="0" cellspacing="0" width="200">';
do {
echo '<tr><td width="100">'.$row_nested['size'].'</td><td width="100">'.$row_nested['amount'].'</td></tr>';
} while ($row_nested = $nested->fetch(PDO::FETCH_ASSOC));
echo '</table>';
echo '</td></tr>';
} while ($row = $query->fetch(PDO::FETCH_ASSOC));
?>
</table>

Foreach loops in PHP and Joomla

I'm currently managing the display of MySQL content in HTML with foreach loop like this :
<?php
echo "<table class=\"tableau\">
<tr bgcolor=\"#a72333\" class=\"first\">
<th>Repere</th>
<th>Niveau</th>
<th>Enseigne</th>
<th>Activités</th>
</tr>
<tbody>";
$db= JFactory::getDBO();
$query = 'SELECT baseData, sid, fid FROM XXXX_sobipro_field_data';
$db->setQuery($query);
$results = $db->loadObjectList();
foreach ($results as &$value) {
if ($value->sid == 55) {
if ($value->fid == 20) {
$repere = $value->baseData;
}
if ($value->fid == 16) {
$level = $value->baseData;
}
if ($value->fid == 22) {
$title = $value->baseData;
}
if ($value->fid == 17) {
$activity = $value->baseData;
}
if ($value->fid == 21) {
$display = $value->baseData;
}
}
[...]
// It ends at if ($value->fid == 83)
}
So I name my variable like this $title_NUM, $activity_NUM, ..., where _NUM is a number starting at "nothing", it ends at 24 for now, but it could be more if I have more data in my table.
After I get the data I display the html like this :
if ($display == 1) {
echo "<tr bgcolor=\"#eaeaeb\">
<td valign=\"top\">".$repere."</td>
<td align=\"top\">".$level."</td>
<td valign=\"top\"><a data-lightbox=\"width:600;type:iframe;\" href=\"LINK\">".$title."</a></td>
<td align=\"top\">".$activity."</td>
</tr>";
}
And the same happens here I'm displaying each linke of the html "by hand" , O don't have any loop to do the job.
Is there a way to do the job with only loops ?
what i understand so far is that you have
$title1 , $title2 , $title3 , ...
you want to do loop for it
see this example
<?php
for($i=0;$i<=8;$i++)//note it start from 0 to 8
${'test'.$i}=5*$i;
$test9=5*9;
echo "let's test <br/>";
echo $test0.'<br/>';
for($i=1;$i<=9;$i++)//note it start from 1 to 9
echo ${'test'.$i}.'<br/>';
?>

How to speedup by code?

is there a way to speed up my code? It takes about 15 seconds to load ... I don't really see a way to reduce my code... I just thought about inserting the values into database, so the user does not have to load new info every time.. but the thing is that my cron only allows 1 load per hour ... by loading new info on every load it gives me fresh information..
$q1=mysql_query("SELECT * FROM isara");
while($r1=mysql_fetch_array($q1)){
$named=$r1['name'];
$idd=$r1['id'];
$descd=$r1['desc'];
$online=check_online($named);
$char = new Character($r1['name'],$r1['id'],$r1['desc']);
if($online == "online"){
$char->rank = $i++;
}
else{
$char->rank = 0;
}
$arr[] = $char;
}
?>
<br />
<h2 style="color:green">Online enemies</h2>
<?php
foreach ($arr as $char) {
if($char->rank>=1){
echo "<a style=\"color:green\" href=\"http://www.tibia.com/community/?subtopic=characters&name=$char->name\">";
echo $char->name." ";
echo "</a>";
echo level($char->name)."<b> ";
echo vocation($char->name)."</b> (<i>";
echo $char->desc." </i>)<br />";
}
}
?>
<br />
<h2 style="color:red">Offline enemies</h2>
<?php
foreach ($arr as $char) {
if($char->rank==0){
echo "<a style=\"color:red\" href=\"http://www.tibia.com/community/?subtopic=characters&name=$char->name\">";
echo $char->name." ";
echo "</a>";
echo level($char->name)."<b> ";
echo vocation($char->name)."</b> (<i>";
echo $char->desc." </i>)<br />";
}
}
?>
As I wrote in the comment, fetch the page once instead of once for every name in the database.
Pseudo code for my comment:
users = <get users from database>
webpage = <get webpage contents>
for (user in users)
<check if user exists in webpage>
As mentioned in the comments you're calling a webpage for each entry in your database, assuming that's about 2 seconds per call it's going to slow you down a lot.
Why don't you call the page once and pass the contents of it into the check_online() function as a parameter so your code would look something like this which will speed it up by quite a few magnitudes:
$content=file_get_contents("http://www.tibia.com/community/?subtopic=worlds&worl‌​d=Isara",0);
$q1=mysql_query("SELECT * FROM isara");
while($r1=mysql_fetch_array($q1)){
$named=$r1['name'];
$idd=$r1['id'];
$descd=$r1['desc'];
$online=check_online($named,$content);
$char = new Character($r1['name'],$r1['id'],$r1['desc']);
if($online == "online"){
$char->rank = $i++;
}
else{
$char->rank = 0;
}
$arr[] = $char;
}
?>
<br />
<h2 style="color:green">Online enemies</h2>
<?php
foreach ($arr as $char) {
if($char->rank>=1){
echo "<a style=\"color:green\" href=\"http://www.tibia.com/community/?subtopic=characters&name=$char->name\">";
echo $char->name." ";
echo "</a>";
echo level($char->name)."<b> ";
echo vocation($char->name)."</b> (<i>";
echo $char->desc." </i>)<br />";
}
}
?>
<br />
<h2 style="color:red">Offline enemies</h2>
<?php
foreach ($arr as $char) {
if($char->rank==0){
echo "<a style=\"color:red\" href=\"http://www.tibia.com/community/?subtopic=characters&name=$char->name\">";
echo $char->name." ";
echo "</a>";
echo level($char->name)."<b> ";
echo vocation($char->name)."</b> (<i>";
echo $char->desc." </i>)<br />";
}
}
?>
and your check_online() function would look something like this:
function check_online($name,$content){
$count=substr_count($name, " ");
if($count > 0){ $ex=explode(" ",$name); $namez=$ex[1]; $nameused=$namez; }
else{ $nameused=$name; }
if(preg_match("/$nameused/",$content)){ $status="online"; }
else{ $status="offline"; }
return $status;
}
You can also do the following to make it faster
Stop using select * which is very bad on innodb
Put better indexes on your database to make the recordset return faster
Install PHP 5.4 as it's faster especially as you're creating a new object in each iteration
Use a byte code accelerator/cache such as xdebug
you should avoid using distinct (*) keyword in your SQL Query
for more information read this http://blog.sqlauthority.com/category/sql-coding-standards/page/2/

PHP Function givine IE problems

I have a small PHP function that is called from one of my pages.
function ratingDetails($uid, $align, $width) {
$queryFull = "SELECT * FROM rating WHERE uid = $uid";
$resultFull = mysql_query($queryFull);
//START DISPLAY TABLE IF RESULTS
if(mysql_num_rows($resultFull) > 0) {
echo "<table class=\"ratingTable\" align=\"center\" border=\"1\" cellspacing=\"0\" cellpadding=\"3\" width=\"550\">\n";
echo "<tr bgcolor=\"#6699cc\"><th>STARS</th><th>DATE RATED</th><th>COMMENT</th><th>RATED BY</th></tr>\n";
while($rowFull = mysql_fetch_array($resultFull)) {
$rating = $rowFull['rating'];
$comment = $rowFull['comment'];
$datePosted = date("M j, Y", $rowFull['date']);
$rid = $rowFull['raterID'];
$rater = getUsername($rid);
//SHOW STARS
if($rating == 0) { $stars = "notYet.jpg"; }
if($rating == 1) { $stars = "starOne.jpg"; }
if($rating == 1.5) { $stars = "starOneHalf.jpg"; }
if($rating == 2) { $stars = "starTwo.jpg"; }
if($rating == 2.5) { $stars = "starTwoHalf.jpg"; }
if($rating == 3) { $stars = "starThree.jpg"; }
if($rating == 3.5) { $stars = "starThreeHalf.jpg"; }
if($rating == 4) { $stars = "starFour.jpg"; }
if($rating == 4.5) { $stars = "starFourHalf.jpg"; }
if($rating == 5) { $stars = "starFive.jpg"; }
//DISPLAY IT ALL
echo "<tr><td width=\"10\"><img src=\"/images/rating/$stars\" width=\"105\" height=\"20\" /></td>";
echo "<td width=\"75\" align=\"center\">$datePosted</td><td>$comment</td><td width=\"85\">$rater</td></tr>\n";
}//END WHILE
echo "</table>\n";
} //END IF
else {
echo "<table class=\"ratingTable\" align=\"center\" border=\"1\" cellspacing=\"0\" cellpadding=\"8\" width=\"550\">\n";
echo "<tr><td align=\"center\"><span class=\"blue\">NO REVIEWS OR RATINGS FOR THIS DISTRIBUTOR</span></td></tr></table>\n";
} //END IF ELSE
}
But when it runs in IE (7 or 8), it throws this error:
A script on this page is causing Internet Explorer to run slowly. Bla bla bla...
I call this function from two pages and both cause the same error. If I remove the call from the page, the page loads fine.
There is no javascript involved with the pages in question...
Help, help, help... I don't have much hair left...
Rick
What's happening is that it's taking a long time to execute your script. IE is waiting for output from the server but it's taking a long time.
You may want to try either a call to flush() every row (or maybe every 25 rows using the modulus operator) or using ob_implicit_flush() to turn on implicit flushing. That way you have data continually coming back to the browser (I assume you have a huge amount of data). You probably will also need to call set_timeout(0) to disable the 30 second time limit on your script.
The first thing I would do is get rid of all those IF statements for the stars, either using an array for them or a switch statement, either of which would reduce the processing required for your script. An array would be my approach. Your code would look something like the following:
function ratingDetails($uid, $align, $width) {
$queryFull = "SELECT * FROM rating WHERE uid = $uid";
$resultFull = mysql_query($queryFull);
// Declare the array for the stars.
$astars = array(
0=> "notYet.jpg",
1=> "starOne.jpg",
1.5=> "starOneHalf.jpg",
2=> "starTwo.jpg",
2.5=> "starTwoHalf.jpg",
3=> "starThree.jpg",
3.5=> "starThreeHalf.jpg",
4=> "starFour.jpg",
4.5=> "starFourHalf.jpg",
5=> "starFive.jpg"
);
//START DISPLAY TABLE IF RESULTS
if(mysql_num_rows($resultFull) > 0) {
echo "<table class=\"ratingTable\" align=\"center\" border=\"1\" cellspacing=\"0\" cellpadding=\"3\" width=\"550\">\n";
echo "<tr bgcolor=\"#6699cc\"><th>STARS</th><th>DATE RATED</th><th>COMMENT</th><th>RATED BY</th></tr>\n";
while($rowFull = mysql_fetch_array($resultFull)) {
$rating = $rowFull['rating'];
$comment = $rowFull['comment'];
$datePosted = date("M j, Y", $rowFull['date']);
$rid = $rowFull['raterID'];
$rater = getUsername($rid);
$stars = $astars[$rating];
//DISPLAY IT ALL
echo "<tr><td width=\"10\"><img src=\"/images/rating/$stars\" width=\"105\" height=\"20\" /></td>";
echo "<td width=\"75\" align=\"center\">$datePosted</td><td>$comment</td><td width=\"85\">$rater</td></tr>\n";
}//END WHILE
echo "</table>\n";
} //END IF
else {
echo "<table class=\"ratingTable\" align=\"center\" border=\"1\" cellspacing=\"0\" cellpadding=\"8\" width=\"550\">\n";
echo "<tr><td align=\"center\"><span class=\"blue\">NO REVIEWS OR RATINGS FOR THIS DISTRIBUTOR</span></td></tr></table>\n";
} //END IF ELSE
The decimals may cause a problem in the array; if so, you can enclose the keys in quotes; e.g., "1.5"=>"starOneHalf.jpg"
The other thing you could do is create a variable for the HTML output instead of echoing the output every line, and then just echo the output at the end.
I found my problem...
The table within my function was assigned a css class. This particular css class contained a behavior, which called PIE.htc. Apparently, this caused some sort of IE melt down whenever it was called. I removed PIE (bummer, no more rounded corners or shadows in IE) and my problem is solved!!!
Thanks to everyone who provided assistance along the way!!!

Categories