I am not getting any output from the bottom half as I was expecting. I can grab the top table's data, but I am also trying to grab the bottom table data and place encode them into json. The columns I need to grab are
1. Week Date Home Away At Notes
<?php
libxml_use_internal_errors(true);
$doc = new DOMDocument();
$doc->loadHTML(file_get_contents('https://www.leagueleader.net/sharedreport.php?operatorid=98&code=bc155b01-7492-412d-aa75-3c1e357248f1'));
$doc->strictErrorChecking = false;
$pre = [];
$keys = ['team', 'div', 'team-site-name', 'site-address', 'site-phone'];
$keys2 = ['week', 'date', 'home', 'away', 'at', 'notes'];
foreach ($doc->getElementsByTagName('table') as $k => $table) {
if (strpos($table->getAttribute('class'), 'report') === false) {
continue;
}
foreach ($table->getElementsByTagName('tr') as $i => $tr) {
if ($tr->parentNode->nodeName === 'thead') continue; // skip headers
$row_values = [];
foreach ($tr->childNodes as $td) {
$text = trim($td->nodeValue);
if ($text === '') continue;
$row_values[] = $text;
}
if($k == 1 ){
$row_values = array_combine($keys, $row_values);
}else if($k == 2 ){
unset($row_values[1]);
$row_values = array_combine($keys2, $row_values);
}
$pre[$row_values['name']][] = $row_values;
}
}
$combined = [];
foreach($pre as $week => $row){
$combined[$name] = [
"week"=> $week,
"team"=> $row[0]['team'],
"div"=> $row[0]['div'],
"team-site-name" => $row[0]['team-site-name'],
"site-address" => $row[0]['site-address'],
"site-phone" => $row[0]['site-phone'],
//"week" => $row[1]['week'],
"date" => $row[1]['date'],
"home" => $row[1]['home'],
"away" => $row[1]['away'],
"at" => $row[1]['at'],
"notes" => $row[1]['notes']
];
}
echo '<pre>'.json_encode($combined, JSON_PRETTY_PRINT).'</pre>';
?>
Here is the output
{
"": {
"week": "",
"team": "1",
"div": "A",
"team-site-name": "Team 01Freer Bar",
"site-address": "\u00a07355 Michigan Ave Detroit, MI 48210",
"site-phone": "\u00a03138993699",
"date": null,
"home": null,
"away": null,
"at": null,
"notes": null
}
}
To get the data from the second table with the matches, I've changed the processing to use XPath. This extracts the <tr> tags from the body of the second table with class='report' (using //table[#class='report'][2]/tbody/tr).
So this will return all of the rows in the body of the table. Then extract all of the <td> elements and pick out the details in the row. If there is a week/date present it just overwrites the current data, if there are match details it creates a row on the output...
$xpath = new DOMXPath($doc);
$reportRow = $xpath->query("//table[#class='report'][2]/tbody/tr");
$matches = [];
$week = '';
$date = '';
foreach ($reportRow as $row) {
$cells = $row->getElementsByTagName("td");
// Set week and date if present in the current row
$week = trim($cells[0]->textContent)?:$week;
$date = trim($cells[1]->textContent)?:$date;
// Extract the other details
$teamHome = trim($cells[2]->textContent);
$teamAway = trim($cells[3]->textContent);
$at = trim($cells[4]->textContent);
$notes = trim($cells[5]->textContent);
// If there are some match details, the store them
if ( !empty($teamHome) ) {
$matches[] = ["week" => $week, "date" => $date,
"teamHome" =>$teamHome, "teamAway" =>$teamAway,
"at" => $at, "notes" => $notes
];
}
}
print_r($matches);
This gives...
Array
(
[0] => Array
(
[week] => 1
[date] => 09/10/2019
[teamHome] => Team 01
[teamAway] => BYE
[at] => BYE
[notes] =>
)
Related
I have two json strings in my database that contain data I'm trying to compare against one another to show in an activity log to see what a user has changed about an entry: old_properties and properties.
This is my current controller:
$properties = json_decode($log->properties, true);
$old_properties = json_decode($log->old_properties, true);
$changes = array_diff($properties, $old_properties);
This is my blade:
#foreach ($changes as $key => $value)
{{$key}}: {{$value}}<br>
#endforeach
So for example, if my data is:
old_properties: 'name' => 'Matthew', 'state' => 'Oregon'
properties: 'name' => 'Samuel', 'state' => 'Oregon'
all that I see from my $changes is: name: Samuel
What I am trying to display is: name: Matthew -> Samuel, or some other way to show what the old property was, and what it was changed to in the same line.
It looks like you could do something like:
#foreach ($changes as $key => $value)
{{$key}}: {{$old_properties[$key]}} -> {{$value}}<br>
#endforeach
Do Set calculation can solve this problem:
function printKeptAndUpdated ($setMapKeptAndUpdated, $setA, $setB) {
$changes = [];
foreach ($setMapKeptAndUpdated as $key => $value) {
$changes[] = $key . ": " . $setA[$key] . " -> " . $setB[$key];
}
echo("<pre>");
print_r($changes);
echo("</pre>");
}
$old_properties = [
"ape" => "black",
"cat" => "white",
"dog" => "black",
"fox" => "red",
];
$properties = [
"bear" => "brown",
"cat" => "white",
"dog" => "yellow",
"eagle" => "grey",
"fox" => "white",
"giraffe" => "yellow",
];
// Define 2 Set of array, setA is old set data, setB is new set data.
// Both setA and setB should only be one dimensional array
// which elements are always key => value pair only.
$setA = $old_properties;
$setB = $properties;
$setMap = [];
// Set map will do Set calculation in the future,
// and imply those 4 possibility: deleted, added, kept (updated or untouched),
// but only 3 of them are shown: deleted, added, kept.
// 4 possiblility after Set calculation.
$setMapDeleted = [];
$setMapAdded = [];
$setMapKeptAndUpdated = [];
$setMapKeptAndUntouched = [];
// Put $setA in $setMap first.
foreach($setA as $key => $value) {
$setMap[$key] = "a";
}
// Then put $setB in $setMap too.
foreach($setB as $key => $value) {
if (array_key_exists($key, $setMap)) {
$setMap[$key] = "ab";
} else {
$setMap[$key] = "b";
}
}
// So now the $setMap structure looks like this
// (just example, not as same as current data):
//$setMap = [
// "ape" => "b",
// "bear" => "ab",
// "cat" => "a",
// "dog" => "a",
// "eagle" => "b",
//];
// Where "a" = setA - setB, "b" = setB - setA, "ab" = setA ∩ setB (intersection)
// Now finish the Set calculation and also separate Set "kept" to set "updated" and Set "untouched".
foreach($setMap as $key => $value) {
if ($value === "a") {
$setMapDeleted[$key] = $setA[$key];
} elseif ($value === "b") {
$setMapAdded[$key] = $setB[$key];
} elseif ($value === "ab") {
if ($setB[$key] === $setA[$key]) {
$setMapKeptAndUntouched[$key] = $setB[$key];
} else {
$setMapKeptAndUpdated[$key] = $setB[$key];
}
}
}
printKeptAndUpdated($setMapKeptAndUpdated, $setA, $setB);
// Print the result you want.
I have to be able to detect all changes in a "guild" (like an activity feed), with new and old data. The data is presented in this fashion, as an array:
{"GUILDMASTER":["foo"],"OFFICER":["bar","baz"],"MEMBER":["foobar","foobaz"]}
I need to detect if, for example, "bar" moves from his current rank down one (to "MEMBER"), it will output an array something like this:
[{"user":"bar","was_found_in":"OFFICER","now_found_in":"MEMBER"}]
What I currently have, below, only detects if a member has joined of left, is there any way to extend this to fulfill what I want it to?
function compareThem($a, $b) {
$flat_new = call_user_func_array('array_merge', $a);
$flat_old = call_user_func_array('array_merge', $b);
$rm = array();
if($flat_new != $flat_old) {
$new_old = array_diff($flat_new, $flat_old);
$old_new = array_diff($flat_old, $flat_new);
$diff = array_merge($new_old, $old_new);
foreach ($diff as $key => $value) {
if(in_array($value, $flat_new) && !in_array($value, $flat_old)) {
$rm[] = array("new"=>true, "left"=>false, "user"=>$value);
} else if(in_array($value, $flat_old) && !in_array($value, $flat_new)) {
$rm[] = array("new"=>false, "left"=>true, "user"=>$value);
}
}
}
return $rm;
}
$new = array("GUILDMASTER" => array("foo"), "OFFICER" => array("bar", "baz"), "MEMBER" => array("foobar", "foobaz"));
$old = array("GUILDMASTER" => array("foo"), "OFFICER" => array("bar", "baz"), "MEMBER" => array("foobar"));
compareThem($new,$old) // will output [{"new":true,"left":false,"user":"foobaz"}]
You can do this. It detects additions, deletions, and modifications:
// your array before the change
$before = ["GUILDMASTER" => ["foo"], "OFFICER" => ["bar","baz"], "MEMBER" => ["foobar","foobaz"]];
// your array after the change (foo was moved from GUILDMASTER to OFFICER)
$after = ["GUILDMASTER" => [], "OFFICER" => ["bar","baz", "foo"], "MEMBER" => ["foobar","foobaz"]];
// create lookup table to check the position a person previously held
$positions_before = [];
foreach($before as $position => $people) {
foreach($people as $person) {
$positions_before[$person] = $position;
}
}
// scan new positions...
$changes = [];
foreach($after as $position => $people) {
foreach($people as $person) {
// track when a new person is added (they wont be in the table)
if(!isset($positions_before[$person])) {
$changes[] = ["user" => $person, "was_found_in" => "DIDNT_EXIST", "now_found_in" => $position];
// track when a change is detected (different value than table)
}elseif($positions_before[$person] != $position) {
$changes[] = ["user" => $person, "was_found_in" => $positions_before[$person], "now_found_in" => $position];
}
// remove this person from the table after parsing them
unset($positions_before[$person]);
}
}
// anyone left in the lookup table is in $before and $after
// so track that they were removed/fired
foreach($positions_before as $person => $position) {
$changes[] = ["user" => $person, "was_found_in" => $position, "now_found_in" => "REMOVED"];
}
print_r($changes);
outputs [user] => foo [was_found_in] => GUILDMASTER [now_found_in] => OFFICER
I am trying to create a schedule of who uses a specific item on which day.
I have 2 arrays.
one with dates &
another with names and how many days they can use the item.
i have managed to create dates array using this.
function dateArray($from, $to, $value = NULL) {
$begin = new DateTime($from);
$end = new DateTime($to);
$interval = DateInterval::createFromDateString('1 day');
$days = new DatePeriod($begin, $interval, $end);
$baseArray = array();
foreach ($days as $day) {
$dateKey = $day->format("d-m-Y");
$baseArray[$dateKey] = $value;
}
return $baseArray;
}
$dates_array = dateArray('01-01-2014', '30-09-2014',true);
print_r($dates_array );
which gives me dates as
Array
(
[01-01-2014] => 1
[02-01-2014] => 1
[03-01-2014] => 1
[04-01-2014] => 1
[05-01-2014] => 1
[06-01-2014] => 1
[07-01-2014] => 1
[08-01-2014] => 1
[09-01-2014] => 1
and so on.
)
i have another array of names having name as key and days as value , they can use the item like this.
$names_array = array("name1" => "4", "name2" => "3", "name3" => "1");
Now i would like to assign names to dates depending on how many days the person can use the item.
like this.
I need my final output array to be like this
Array
(
[01-01-2014] => name1
[02-01-2014] => name1
[03-01-2014] => name1
[04-01-2014] => name1
[05-01-2014] => name2
[06-01-2014] => name2
[07-01-2014] => name2
[08-01-2014] => name3
[09-01-2014] => name1
and so on. notice name1 comes again
)
so i am trying to get output like above but i am failing at the while loop inside the foreach.
so far i have tried this.
function dateArray($from, $to, $value = NULL) {
$begin = new DateTime($from);
$end = new DateTime($to);
$interval = DateInterval::createFromDateString('1 day');
$days = new DatePeriod($begin, $interval, $end);
$baseArray = array();
foreach ($days as $day) {
$dateKey = $day->format("d-m-Y");
$baseArray[$dateKey] = $value;
}
return $baseArray;
}
$dates_array = dateArray('01-01-2014', '30-09-2014',true);
$names_array = array("name1" => "4", "name2" => "3", "name3" => "1");
print_r($dates_array );
$new_dates = array();
foreach($dates_array as $dates => $key){
//echo $dates;
foreach ($names_array as $name => $days){
while($days <= 1){
$new_dates[$dates] = $name ;
$days = $days - 1;
}
}
}
print_r($new_dates);
But my final array is empty.
so how can i solve this ?
You can use a MultipleIterator whereby the second array (names) loops around when needed:
$names_array = array();
// unwind the array values
foreach (array("name1" => "4", "name2" => "3", "name3" => "1") as $value => $freq) {
for ($i = 0; $i < $freq; ++$i) {
$names_array[] = $value;
}
}
// attach both arrays
$m = new MultipleIterator;
$m->attachIterator(new ArrayIterator(array_keys($dates_array)));
$m->attachIterator(new InfiniteIterator(new ArrayIterator($names_array)));
// build final array
$result = array();
foreach ($m as $value) {
$result[$value[0]] = $value[1];
}
It should probably go like this...
while($days <= 1){
$new_dates[$dates] = $name ;
$names_array[$name] = $days - 1;
}
Hi You can try this one
$dates_array = array_keys(dateArray('01-01-2014', '30-09-2014',true));
$names_array = array("name1" => "4", "name2" => "3", "name3" => "1");
$new_dates = array();
$daysindex = 0;
while($daysindex < count($dates_array)){
foreach ($names_array as $name => $day){
for($x = 0; $x<$day; $x++){
if(isset($dates_array[$daysindex])){
$new_dates[$dates_array[$daysindex]] = $name ;
$daysindex++;
}
}
}
}
print_r($new_dates);
$dates = dateArray('01-01-2014', '30-09-2014',true);
$names = array('name1' => 4,'name2' => 3,'name3' => 1);
$count = current($names);
$name = key($names);
foreach($dates as &$value) {
$value = $name;
//if we've displayed a name $count times, move to the next name
if(--$count == 0) {
//if we're at the end of $names, wrap around
if(false === next($names)) {
reset($names);
}
$count = current($names);
$name = key($names);
}
}
print_r($dates);
I have this code, which is parcially working... I'm trying to do this:
Array
(
[servicio_id 1] => Array
(
[peticion_id 1] => Array
(...)
[peticion_id 2] => Array
(...)
[peticion_id 3] => Array
(...)
)
[servicio_id 2] => Array
(
[peticion_id 1] => Array
(...)
[peticion_id 2] => Array
(...)
[peticion_id 3] => Array
(...)
)
)
So each [servicio_id] has it's [peticion_id] with its own values... the problem is that my code actually set the same values inside every [peticion_id] array, increasing it's size as long as the loop is running... Any advice on how to clear and start again the [peticion_id] array once the [servicio_id] is finished?
Thank you in advice
while($row = sqlsrv_fetch_array($sqlQuery)) {
if($row['peticion_id'] == 0) {
$ok[] = round($row['valor'], 3);
if($row['media_ok'] == null) {
$medias_ok = array("0", "0", "0", "0");
} else {
$medias_ok = Umbrales::getValues($row['media_ok'], $row['media']);
}
$max_ok[] = $medias_ok[1];
$min_ok[] = $medias_ok[0];
}
if($row['peticion_id'] == 1) {
$ko[] = round($row['valor'], 3);
if($row['media_ok'] == null) {
$medias_ko = array("0", "0", "0", "0");
} else {
$medias_ko = Umbrales::getValues($row['media_ok'], $row['media']);
}
$max_ko[] = $medias_ko[2];
}
if($row['peticion_id'] == 2) {
$rt[] = round($row['valor'], 3);
if($row['media_ok'] == null) {
$medias_rt = array("0", "0", "0", "0");
} else {
$medias_rt = Umbrales::getValues($row['media_ok'], $row['media']);
}
$max_rt[] = $medias_rt[3];
}
$datos[$servicios[$row['servicio_id']]] = array(
"OK" => $ok,
"KO" => $ko,
"RT" => $rt,
"UMBRAL_MIN_OK" => $min_ok,
"UMBRAL_MAX_OK" => $max_ok,
"UMBRAL_MAX_KO" => $max_ko,
"UMBRAL_MAX_RT" => $max_rt
);
}
You need to clear the array on each loop.
After you while it should read:
while($row = sqlsrv_fetch_array($sqlQuery)) {
$ok = array();
$ko = array();
$rt = array();
$min_ok = array();
$max_ok = array();
$max_ko = array();
$max_rt = array();
if($row['peticion_id'] == 0) {
Right now i got an array which has some sort of information and i need to create a table from it. e.g.
Student{
[Address]{
[StreetAddress] =>"Some Street"
[StreetName] => "Some Name"
}
[Marks1] => 100
[Marks2] => 50
}
Now I want to create database table like which contain the fields name as :
Student_Address_StreetAddress
Student_Address_StreetName
Student_Marks1
Student_Marks2
It should be recursive so from any depth of array it can create the string in my format.
You can use the RecursiveArrayIterator and the RecursiveIteratorIterator (to iterate over the array recursively) from the Standard PHP Library (SPL) to make this job relatively painless.
$iterator = new RecursiveIteratorIterator(new RecursiveArrayIterator($arr));
$keys = array();
foreach ($iterator as $key => $value) {
// Build long key name based on parent keys
for ($i = $iterator->getDepth() - 1; $i >= 0; $i--) {
$key = $iterator->getSubIterator($i)->key() . '_' . $key;
}
$keys[] = $key;
}
var_export($keys);
The above example outputs something like:
array (
0 => 'Student_Address_StreetAddress',
1 => 'Student_Address_StreetName',
2 => 'Student_Marks1',
3 => 'Student_Marks2',
)
(Working on it, here is the array to save the trouble):
$arr = array
(
'Student' => array
(
'Address' => array
(
'StreetAddress' => 'Some Street',
'StreetName' => 'Some Name',
),
'Marks1' => '100',
'Marks2' => '50',
),
);
Here it is, using a modified version of #polygenelubricants code:
function dfs($array, $parent = null)
{
static $result = array();
if (is_array($array) * count($array) > 0)
{
foreach ($array as $key => $value)
{
dfs($value, $parent . '_' . $key);
}
}
else
{
$result[] = ltrim($parent, '_');
}
return $result;
}
echo '<pre>';
print_r(dfs($arr));
echo '</pre>';
Outputs:
Array
(
[0] => Student_Address_StreetAddress
[1] => Student_Address_StreetName
[2] => Student_Marks1
[3] => Student_Marks2
)
Something like this maybe?
$schema = array(
'Student' => array(
'Address' => array(
'StreetAddresss' => "Some Street",
'StreetName' => "Some Name",
),
'Marks1' => 100,
'Marks2' => 50,
),
);
$result = array();
function walk($value, $key, $memo = "") {
global $result;
if(is_array($value)) {
$memo .= $key . '_';
array_walk($value, 'walk', $memo);
} else {
$result[] = $memo . $key;
}
}
array_walk($schema, 'walk');
var_dump($result);
I know globals are bad, but can't think of anything better now.
Something like this works:
<?php
$arr = array (
'Student' => array (
'Address' => array (
'StreetAddress' => 'Some Street',
'StreetName' => 'Some Name',
),
'Marks1' => array(),
'Marks2' => '50',
),
);
$result = array();
function dfs($data, $prefix = "") {
global $result;
if (is_array($data) && !empty($data)) {
foreach ($data as $key => $value) {
dfs($value, "{$prefix}_{$key}");
}
} else {
$result[substr($prefix, 1)] = $data;
}
}
dfs($arr);
var_dump($result);
?>
This prints:
array(4) {
["Student_Address_StreetAddress"] => string(11) "Some Street"
["Student_Address_StreetName"] => string(9) "Some Name"
["Student_Marks1"] => array(0) {}
["Student_Marks2"] => string(2) "50"
}
function getValues($dataArray,$strKey="")
{
global $arrFinalValues;
if(is_array($dataArray))
{
$currentKey = $strKey;
foreach($dataArray as $key => $val)
{
if(is_array($val) && !empty($val))
{
getValues($val,$currentKey.$key."_");
}
else if(!empty($val))
{
if(!empty($strKey))
$strTmpKey = $strKey.$key;
else
$strTmpKey = $key;
$arrFinalValues[$strTmpKey]=$val;
}
}
}
}