Q: How can I combine these two foreach loop - php

I have a simple html dom query which read informations from a football fixtures source, and I loading also a json source.
Here is my full code:
<?php
header('Content-Type: text/html; charset=utf-8');
ini_set("user_agent", "User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.17 (KHTML, like Gecko) Chrome/24.0.1312.60 Safari/537.17");
include_once('simple_html_dom.php');
ini_set('display_errors', true);
error_reporting(E_ALL);
$str = file_get_contents('general.json');
$json = json_decode($str,true);
$filename = "source.html";
$html = file_get_html($filename);
class matches {
var $day;
var $kickofftime;
var $result;
function matches ($day, $kickofftime, $tip){
$this->day=$day;
$this->kickofftime=$kickofftime;
$this->result=$result;
return $this;
}
}
$i=0;
$day=$html->find('h1',0);
$day->plaintext;
$day=str_replace("<h1>TODAY FOOTBALL FIXTURES: ","", $day);
$day=str_replace("</h1>","", $day);
$matchday = str_replace(array('MONDAY ', 'TUESDAY ', 'WEDNESDAY ', 'THURSDAY ', 'FRIDAY ', 'SATURDAY ', 'SUNDAY '), '', $day);
$matchday=str_replace(" ","-", $matchday);
$matchday=date('Y-m-d', strtotime($matchday));
foreach($html->find('table.fixtures') as $matches)
{
foreach ($matches->find('tr[class=a1],tr[class=a2]') as $matchesTR) {
$kickofftime=$matchesTR->find('td[class=a11],td[class=a21]',0)->plaintext;
$kodate = date('Y-m-d H:i:s', strtotime("$matchday $kickofftime +1 hour"));
$result=$matchesTR->find('td');
echo $kodate;
echo $result[6]->plaintext.'<br>' ;
$i++;
}
}
//Here is the 2nd foreach with the data of JSON source:
foreach($json as $key => $value) {
$value = json_decode($value, true);
echo $value["country"] . ", " . $value["competition"] . " " . $value["club"] . "<br>";
}
// clean up memory
$html->clear();
unset($html);
?>
The current results from the simple html dom html source:
2014-12-23 20:00:00 2-1
2014-12-23 11:00:00 3-1
2014-12-26 08:00:00 1-1
The result from the JSON source:
America Copa America Boca Juniors
Europe Bundesliga Hannover
Asia JLeague Nagoya
I would like to combine these two results in one foreach and I would like to get this result:
2014-12-23 20:00:00 2-1 America Copa America Boca Juniors
2014-12-23 11:00:00 3-1 Europe Bundesliga Hannover
2014-12-26 08:00:00 1-1 Asia JLeague Nagoya
I hope that there is some expert who can help for me because I tried a lot of variation but without result. I got some advice (with code) from experts, but there was everytime errors. With my code there is no error, but I need other solution because I would like to put all variables to one foreach. Many thanks, I hope that somebody could help me with code, because I am not on high level at php. Thanks again!
I would like to put the two foreach into one foreach, but I don't want to create a new array because I not need.

Assuming you will always have the same amount of items in each and that they match 1 to 1, 2 to 2, you can do this:
$htmlDates = array();
$jsonLeag = array();
foreach($html->find('table.fixtures') as $matches) {
foreach($matches->find('tr[class=a1],tr[class=a2]') as $matchesTR) {
$kickofftime=$matchesTR->find('td[class=a11],td[class=a21]',0)->plaintext;
$kodate = date('Y-m-d H:i:s', strtotime("$matchday $kickofftime +1 hour"));
$result=$matchesTR->find('td');
//echo $kodate;
//echo $result[6]->plaintext.'<br>' ;
$htmlDates[] = $kodates;
}
}
//Here is the 2nd foreach with the data of JSON source:
foreach($json as $key => $value) {
$value = json_decode($value, true);
//echo $value["country"] . ", " . $value["competition"] . " " . $value["club"] . "<br>";
$jsonLeag[] = $value["country"] . ", " . $value["competition"] . " " . $value["club"];
}
if(count($htmlDates) < count($jsonLeag)){
for($i=0;$i<count($htmlData);$i++){
echo $htmlData[$i] . " " . $jsonLeag[$i] . "<br />\r\n";
}
} else {
for($i=0;$i<count($jsonLeag);$i++){
echo $htmlData[$i] . " " . $jsonLeag[$i] . "<br />\r\n";
}
}
Since you have the nested list first and nothing ties the two data sets together, there is no simple way to run one loop and get the data from both. It's easier to push the data you want into an array for each set, and then walk both arrays with one counter. The caveat here is that if one has an extra element, you will get missing results or errors.

Save keys of json arrays and use the next in each loop.
$json_keys = array_keys($json);
$i_key = 0;
foreach($html->find('table.fixtures') as $matches)
{
foreach ($matches->find('tr[class=a1],tr[class=a2]') as $matchesTR) {
$kickofftime=$matchesTR->find('td[class=a11],td[class=a21]',0)->plaintext;
$kodate = date('Y-m-d H:i:s', strtotime("$matchday $kickofftime +1 hour"));
$result=$matchesTR->find('td');
echo $kodate;
echo $result[6]->plaintext.
$value = json_decode($json[$json_keys[$i_key++]], true);
echo $value["country"] . ", " . $value["competition"] . " " . $value["club"] . "<br>";
$i++;
}
}
// clean up memory
$html->clear();
unset($html);
There are many other variants - use array_shift(), next()... I've written the first come in mind

Related

Nested foreach when reading XML (in PHP)

I need to create a CRON job that are weekly going to read a XML file. The XML file contains information about all the shows at a range of cinemas.
What I want to do is to read the XML file, extract the information I need about each show, and then upload each show to a database. But I run into trouble when I start nesting the for-loops.
I want each tuple to contain the following information:
Tile | FilmWebNr | Rating | Version | Center | Screen | Date | Time |
The URL for the XML is http://217.144.251.113/static/Shows_FilmWeb.php
Here is a pastebin where I try to list all the dates for each screen per Title.
Here is the result. As you can see, the dates is only displayed when there are more than 1 screen per Title. I dont get why the attributes array isn't always available.
I struggle with getting the last three (screen, date and time).
$map_url = "http://217.144.251.113/static/Shows_FilmWeb.php";
$response_xml_data = file_get_contents($map_url);
$data = simplexml_load_string($response_xml_data);
$array = (array) simplexml_load_string($response_xml_data);
$json = json_encode($array);
$configData = json_decode($json, true);
$movies = $configData['Performances']['Title'];
foreach ($movies as $title) {
echo "Title: " . $title['#attributes']['Name'] . '<br/>';
echo "FilmWebNr: " . $title['FilmWebNum'] . '<br/>';
echo "Rating: " . $title['TitleRating'] . '<br/>';
echo "Version: " . $title['TitleVersion'] . '<br/>';
echo "Center: " . $title['Center']['#attributes']['Name'] . '<br/>';
foreach ($title['Center']['Screen'] as $screen) {
//here I run into trouble
}
}
Let say I try to add the following in the inner loop:
$screen['#attributes']['Name'];
I get an error saying "Undefined index: #attributes".
So sometimes the attributes seems to be in an array, but sometimes not. Even though It is always a part of the XML.
Rather than going from XML-JSON-Arrays, it may be better to learn how to work with SimpleXML and you will find it's quite easy.
The main thing is to get used to how the various elements are layered and use foreach loops to iterate over the blocks...
$map_url = "http://217.144.251.113/static/Shows_FilmWeb.php";
$response_xml_data = file_get_contents($map_url);
$data = simplexml_load_string($response_xml_data);
$movies = $data->Performances->Title;
foreach ($movies as $title) {
echo "Title: " . $title['Name'] . '<br/>';
echo "FilmWebNr: " . $title->FilmWebNum . '<br/>';
echo "Rating: " . $title->TitleRating . '<br/>';
echo "Version: " . $title->TitleVersion . '<br/>';
echo "Center: " . $title->Center['Name'] . '<br/>';
foreach ($title->Center->Screen as $screen) {
echo "screen:".$screen['Name']. '<br/>';
foreach ( $screen->Date as $date ) {
echo "Date:".$date['Name']. '<br/>';
foreach ( $date->ShowID as $showID ) {
echo "Time:".$showID->Time. '<br/>';
}
}
}
}

how to get only some href attribute

I have this PHP code which I'm trying to extract some information but I stopped to href step:
$site = "http://www.sports-reference.com/olympics/countries";
$site_html = file_get_html($site);
$country_dirty = $site_html->getElementById('div_countries');
foreach($country_dirty->find('img') as $link){
$country = $link->alt;
$link_country = "$site/$country";
$link_country_html = file_get_html($link_country);
$link_season = $link_country_html->getElementById('div_medals');
foreach($link_season->find('a') as $season){
echo $link_year_season = $season->href . "\n";
//echo $link_season = strstr ($link_year_season,'summer') . "\n";
}
}
The variable $link_year_season gets me the following output:
/olympics/countries/AFG/summer/2012/
/olympics/athletes/ba/nesar-ahmad-bahawi-1.html
/olympics/athletes/ni/rohullah-nikpai-1.html
/olympics/countries/AFG/summer/2008/
/olympics/athletes/ba/nesar-ahmad-bahawi-1.html
/olympics/athletes/ni/rohullah-nikpai-1.html
/olympics/countries/AFG/summer/2004/
/olympics/countries/AFG/summer/1996/
/olympics/countries/AFG/summer/1988/
/olympics/countries/AFG/summer/1980/
/olympics/countries/AFG/summer/1972/
.....
I'd like to know if it is possible to get only this output:
/olympics/countries/AFG/summer/2012/
/olympics/countries/AFG/summer/2008/
/olympics/countries/AFG/summer/2004/
/olympics/countries/AFG/summer/1996/
/olympics/countries/AFG/summer/1988/
/olympics/countries/AFG/summer/1980/
/olympics/countries/AFG/summer/1972/
You should be able to use this regex to check that the link starts with /olympics/countries/AFG/summer/ then a number and a /.
foreach($link_season->find('a') as $season){
if(preg_match('~^/olympics/countries/AFG/summer/\d+/~', $season->href)) {
echo $link_year_season = $season->href . "\n";
//echo $link_season = strstr ($link_year_season,'summer') . "\n";
}
}
Demo: https://regex101.com/r/bZ1vP3/1
You could also pull the current year by capturing the number after summer (presuming that is a year, first regex just checks for number this one is stricter)..
foreach($link_season->find('a') as $season){
if(preg_match('~^/olympics/countries/AFG/summer/(\d{4})/~', $season->href, $year)) {
echo $link_year_season = $season->href . "\n";
//echo $link_season = strstr ($link_year_season,'summer') . "\n";
echo 'The year is ' . $year[1] . "\n";
}
}
If the season also can vary you could do (?:summer|winter) which would allow for summer or winter to be the fourth directory.

Q: How can I combine these two foreach?

I have a simple html dom query which read informations from a football fixtures source, and I loading also a json source.
Here is my full code:
<?php
header('Content-Type: text/html; charset=utf-8');
ini_set("user_agent", "User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.17 (KHTML, like Gecko) Chrome/24.0.1312.60 Safari/537.17");
include_once('simple_html_dom.php');
ini_set('display_errors', true);
error_reporting(E_ALL);
$str = file_get_contents('general.json');
$json = json_decode($str,true);
$filename = "source.html";
$html = file_get_html($filename);
class matches {
var $day;
var $kickofftime;
var $title;
function matches ($day, $kickofftime, $tip){
$this->day=$day;
$this->kickofftime=$kickofftime;
$this->title=$title;
return $this;
}
}
$i=0;
$day=$html->find('h1',0);
$day->plaintext;
$day=str_replace("<h1>TODAY FOOTBALL FIXTURES: ","", $day);
$day=str_replace("</h1>","", $day);
$matchday = str_replace(array('MONDAY ', 'TUESDAY ', 'WEDNESDAY ', 'THURSDAY ', 'FRIDAY ', 'SATURDAY ', 'SUNDAY '), '', $day);
$matchday=str_replace(" ","-", $matchday);
$matchday=date('Y-m-d', strtotime($matchday));
foreach($html->find('table.fixtures') as $matches)
{
foreach ($matches->find('tr[class=a1],tr[class=a2]') as $matchesTR) {
$kickofftime=$matchesTR->find('td[class=a11],td[class=a21]',0)->plaintext;
$kodate = date('Y-m-d H:i:s', strtotime("$matchday $kickofftime +1 hour"));
$result=$matchesTR->find('td');
echo $kodate;
echo $result[6]->plaintext.'<br>' ;
$i++;
}
}
//Here is the 2nd foreach with the data of JSON source:
foreach($json as $key => $value) {
$value = json_decode($value, true);
echo $value["country"] . ", " . $value["competition"] . " " . $value["club"] . "<br>";
}
// clean up memory
$html->clear();
unset($html);
?>
The current results from the simple html dom html source:
2014-12-23 20:00:00 2-1
2014-12-23 11:00:00 3-1
2014-12-26 08:00:00 1-1
The result from the JSON source:
America Copa America Boca Juniors
Europe Bundesliga Hannover
Asia JLeague Nagoya
I would like to combine these two results in one foreach and I would like to get this result:
2014-12-23 20:00:00 2-1 America Copa America Boca Juniors
2014-12-23 11:00:00 3-1 Europe Bundesliga Hannover
2014-12-26 08:00:00 1-1 Asia JLeague Nagoya
I hope that there is some expert who can help for me because I tried a lot of variation but without result. Many thanks!
$j=0;
$jsonDecodedArray=$json;
foreach($html->find('table.fixtures') as $matches)
{
foreach ($matches->find('tr[class=a1],tr[class=a2]') as $matchesTR) {
$kickofftime=$matchesTR->find('td[class=a11],td[class=a21]',0)->plaintext;
$kodate = date('Y-m-d H:i:s', strtotime("$matchday $kickofftime +1 hour"));
$result=$matchesTR->find('td');
echo $kodate;
echo $result[6]->plaintext." ";
echo $jsonDecodedArray[$j]["country"] . ", " . $jsonDecodedArray[$j]["competition"] . " " . $jsonDecodedArray[$j]["club"] . "<br>"; ;
$i++;
$j++;
}
}

Combining two foreach without errors

I have a simple html dom query which read information from a football fixtures source, and I am loading also a json source.
Here is my full code:
<?php
header('Content-Type: text/html; charset=utf-8');
ini_set("user_agent", "User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.17 (KHTML, like Gecko) Chrome/24.0.1312.60 Safari/537.17");
include_once('simple_html_dom.php');
ini_set('display_errors', true);
error_reporting(E_ALL);
$str = file_get_contents('general.json');
$json = json_decode($str,true);
$filename = "source.html";
$html = file_get_html($filename);
class matches {
var $day;
var $kickofftime;
var $result;
function matches ($day, $kickofftime, $result){
$this->day=$day;
$this->kickofftime=$kickofftime;
$this->result=$result;
return $this;
}
}
$i=0;
$day=$html->find('h1',0);
$day->plaintext;
$day=str_replace("<h1>TODAY FOOTBALL FIXTURES: ","", $day);
$day=str_replace("</h1>","", $day);
$matchday = str_replace(array('MONDAY ', 'TUESDAY ', 'WEDNESDAY ', 'THURSDAY ', 'FRIDAY ', 'SATURDAY ', 'SUNDAY '), '', $day);
$matchday=str_replace(" ","-", $matchday);
$matchday=date('Y-m-d', strtotime($matchday));
foreach($html->find('table.fixtures') as $matches)
{
foreach ($matches->find('tr[class=a1],tr[class=a2]') as $matchesTR) {
$kickofftime=$matchesTR->find('td[class=a11],td[class=a21]',0)->plaintext;
$kodate = date('Y-m-d H:i:s', strtotime("$matchday $kickofftime +1 hour"));
$result=$matchesTR->find('td');
echo $kodate;
echo $result[6]->plaintext.'<br>' ;
$i++;
}
}
//Here is the 2nd foreach with the data of JSON source:
foreach($json as $key => $value) {
$value = json_decode($value, true);
echo $value["country"] . ", " . $value["competition"] . " " . $value["club"] . "<br>";
}
// clean up memory
$html->clear();
unset($html);
?>
The current results from the simple html dom html source:
2014-12-23 20:00:00 2-1
2014-12-23 11:00:00 3-1
2014-12-26 08:00:00 1-1
The result from the JSON source:
America Copa America Boca Juniors
Europe Bundesliga Hannover
Asia JLeague Nagoya
I would like to combine these two results in one foreach and I would like to get this result:
2014-12-23 20:00:00 2-1 America Copa America Boca Juniors
2014-12-23 11:00:00 3-1 Europe Bundesliga Hannover
2014-12-26 08:00:00 1-1 Asia JLeague Nagoya
I hope one can help me because I tried a lot of variation but without result. Many thanks!
You can use array_map function of PHP.
Lets say your values are in arrays $a, $b:
$mapFunc = function($n, $m) {
return "$n $m";
};
$c = array_map($mapFunc, $a, $b);

Sorting a google calendar feed (parsing with DOM)

I'm embedding dates from google calendar into a website, and it's all working, with the exception of sorting. For some reason, it sorts into reverse-chronological order, when I'd really just like it to be normal chronological (first event first).
this is the output:
August 11th: Intern depart
August 6th: Last Day of Summer Camp
July 7th: Ignore this
July 6th: This is another example event
July 5th: example
June 28th: Summer Camp Starts
June 24th: Summer Pool Party
June 21st: Intern arrival date
June 15th: Assistant Director Arrival Date
June 14th: Director's training begins
May 26th: Brainstorm day for directors
I'm really still just learning a lot of this stuff- thanks for the help in advance!
<?php
$confirmed = 'http://schemas.google.com/g/2005#event.confirmed';
$three_months_in_seconds = 60 * 60 * 24 * 28 * 3;
$three_months_ago = date("Y-m-d\Th:i:sP", time() - 172800);
$three_months_from_today = date("Y-m-d\Th:i:sP", time() + $three_months_in_seconds);
$feed = "http://www.google.com/calendar/feeds/qp6o02ka3iaoem2kr8odga6j7s%40group.calendar.google.com/" .
"public/full?orderby=starttime&singleevents=true&" .
"start-min=" . $three_months_ago . "&" .
"start-max=" . $three_months_from_today;
$doc = new DOMDocument();
$doc->load( $feed );
$entries = $doc->getElementsByTagName( "entry" );
foreach ( $entries as $entry ) {
$status = $entry->getElementsByTagName( "eventStatus" );
$eventStatus = $status->item(0)->getAttributeNode("value")->value;
if ($eventStatus == $confirmed) {
$titles = $entry->getElementsByTagName( "title" );
$title = $titles->item(0)->nodeValue;
$times = $entry->getElementsByTagName( "when" );
$startTime = $times->item(0)->getAttributeNode("startTime")->value;
$when = date( "F jS", strtotime( $startTime ) );
$whentime = date( "g:ia", strtotime ( $startTime ) );
$places = $entry->getElementsByTagName( "where" );
$where = $places->item(0)->getAttributeNode("valueString")->value;
$links = $entry->getElementsByTagName( "link" );
$link = $links->item(0)->nodeValue;
print $when;
if ($whentime == "12:00am"){
;
}
else{
echo " at ";
print $whentime;
}
echo ": ";
echo "<b>";
print $title . "\n";
echo "</b>";
echo " ";
if(empty($where)){;}else{
echo "<br />";
print $where . "\n";
}
print $link;
print "<br />";
}
}
?>
Add &sortorder=descending to your feed URL. You can find documentation for this in the FAQ

Categories