Consecutive dateranges in PHP - php

This is a follow-up question for my earlier question here:
Some help "syncing" two loops in PHP
I want to take a list of dates and show them as ranges if their date is the same or max 1 day apart.
This is the output of my database:
+-----+------------+
| uid | date |
+-----+------------+
| 39 | 2014-09-17 |
| 46 | 2014-09-18 |
| 40 | 2014-09-19 |
| 48 | 2014-09-19 |
| 45 | 2014-09-20 |
| 47 | 2014-12-05 |
+-----+------------+
This is the HTML I want to generate:
Contract from 17/09/2014 to 20/09/2014
UIDS: 39-46-40-48-45
Contract from 05/12/2014
UIDS: 47
This is my sourcecode
<?php
$output = '';
$list = array();
$lastitem = $lastdate = null;
$query = 'SELECT * FROM project_dates';
$sth = $dbh->prepare($query);
$sth->execute();
if($sth->rowCount() > 0) {
$i = 0;
while($row = $sth->fetch()) {
// CURRENT DATE
$date = new DateTime($row['date']);
// STORAGE
$item = array(
'date' => array(),
'var' => $row['uid'], // A '-' delimited variable of all the uids in the range (40-41-...)
'uids' => array() // An array of all the uids in the range
);
// IF THE DATE DIFF IS LESS THAN OR EQUAL TO ONE DAY
if ($item['date'] === $lastitem['date'] && $date->diff($lastdate)->days <= 1) {
// Problem here: looking for last date in set!
$list[$i-1]['date']['end'] = $date;
//Add current uid to the '-' delimited variable of uids of this range
$list[$i-1]['uid'] = $list[$i-1]['uid'].'-'.$item['uid'];
// Add current uid to the array of uids of this range
array_push($list[$i-1]['uids'],$item['uid']);
} else {
// Next range
$list[$i] = $item;
$list[$i]['date']['start'] = $date;
$lastitem = $item;
$lastdate = $date;
array_push($list[$i]['uids'],$item['uid']);
$i++;
}
}
}
if(count($list)){
// Show text with first date and last date of the range
$output .= 'Contract from '.$item['date']['start']->format('d/m/Y');
$output .= isset($item['date']['end']) ? ' to ' . $item['date']['end']->format('d/m/Y') : '';
$output .= '<br />Uids: '.$item['var'];
}
foreach ($list AS $item) {
// Loop over the dates in this range
$output .= $item['date'].'<br />';
}
if(count($list)) {
// Line under this range
$output .= '<hr />';
}
echo $output;
?>
For some reason, my code returns 4 ranges instead of 2. I've been trying to figure out for hours why. Can someone help me? This is the faulty HTML:
Contract from 17/09/2014 to 18/09/2014
UIDS: 39-46
Contract from 19/09/2014
UIDS: 40
Contract from 19/09/2014 tot 20/09/2014
UIDS: 48-45
Contract van 05/12/2014
UIDS: 47
Can anyone be of assistance?

Related

PHP Table Column name

I have an script for getting a table from a DB which is written in PHP.
I am trying to add name for each column to be in the first row:
A part of the Code is:
$rows = [];
foreach (range(1, 4) as $row) {
$rows[$row] = "";
}
$rows["Name"] = $order->user->aFirstName;
$rows["Last Name"] = $alumn->aLastName;
$rows["Age"] = $alumn->aAge;
$rows["Gender"] = $alumn->aGender;
$string = "";
foreach ($rows as $r) {
$string .= $r . "\t";
}
what I want to get is
1 | Name | Last Name | Age | Gender
2 | John | Des | 45 | Male.
What I get now is the data in 1st row.
1 | John | Des | 45 | Male.
Any suggestion? Thanks
You can create a new first element in $rows using https://www.php.net/manual/de/function.array-unshift.php
$labels = ["Name" => "NameLabel", "Last Name" => "Last NameLabel" ...];
array_unshift($rows, $labels);
So the first element of the $rows array are the labels. Now when the table is generated is will display the labels at the top.
You are loading the arrays incorrectly.
I assume you dont want to get the column names from the meta data available to you, and are happy to add the column names manually, if not let me know
$rows = [];
// add labels
$rows[] = ["Name", "Last Name", "Age", "Gender"];
#$rows[] = [$order->user->aFirstName, $alumn->aLastName, $alumn->aAge, $alumn->aGender];
// I dont have your data, so this is to simulate the above line
$rows[] = ['John', 'Des', 45, 'Male'];
$string = '';
foreach ($rows as $i => $row) {
$n = $i+1;
$string .= "$n\t";
foreach ($row as $col){
$string .= $col . "\t";
}
$string .= '<br>'. PHP_EOL;
}
print_r($string);
RESULTS, as you can see a Tab is not really enough to correctly format the table
1 Name Last Name Age Gender <br>
2 John Des 45 Male <br>

how to add number into table array php saprfc [duplicate]

This question already has answers here:
Zero-pad digits in string
(5 answers)
Closed 4 years ago.
my table sap rfc
how can I add number in front of ID? if ID contain 3 digits it will add 000 in front of ID, if ID contain 4 digits it will add 00 in front of ID, if ID contain 5 digits it will add 0 in front of ID. For an example
ID | FEE | NAME | PERIOD
000711 | 204000 | YUDI MANDALA | 201807
000790 | 84000 | AGUS WAHYUDI | 201807
001171 | 151500 | SARJANA | 201807
my code:
if ($FI_HPs!=0)
{
$array = [];
for ($i=1;$i<=$FI_HPs;$i++)
{
$FI_HP = saprfc_table_read ($fce,"FI_HP",$i);
$id = $FI_HP['ID'];
if(isset($array[$id]))
{
$array[$id]['FEE'] += $FI_HP['FEE'];
}
else
{
$array[$id] = $FI_HP;
}
}
foreach($array as $item)
{
echo '<tr>
<td>'.$item['ID'].'</td>
<td>'.($item['FEE']*100).'</td>
<td>'.$item['NAME'].'</td>
<td>'.$item['PERIOD'].'</td>
</tr>';
}
}
you could use str_pad
foreach($array as $item)
{
echo '<tr>
<td>'.str_pad($item['ID'], 6, "0", STR_PAD_LEFT) .'</td>
<td>'.($item['FEE']*100).'</td>
<td>'.$item['NAME'].'</td>
<td>'.$item['PERIOD'].'</td>
</tr>';
}
$base = 100000 ;
'. substr($base+$item['ID'],1) .'

display all the elements of an array in a single table cell using for loop

In my database, the table table_log where I get the data from has 3 columns but I only need: (1) id (2) start (3) end. there are multiple logs with the same id and different start and end values. I'm trying to get the start values so I've placed said values in an array storage. Now, what I'm trying to do is place all values in the arrow in a single cell in the table but only the first value [0] appears not unless I make another column. How can I resolve this?
Query:
$logs = mysql_query("SELECT start FROM table_log WHERE id = '". $resultID."'");
$storage = Array();
while ($res = mysql_fetch_array($logs, MYSQL_ASSOC)) {
$storage[] = $res['start'];
}
Loop:
for($i = 0; $i < count($res); ++$i) {
if(count($res) > $i) {
$start_log = " $storage[$i] <br>";
}
}
$data .= "<td>". $start_log ."</td>";
Database:
id | start | end
01 | 10:00 | 11:00
01 | 12:00 | 01:00
01 | 03:00 | 03:30
Needed Output:
id | start | end
01 | 10:00 | 11:00
| 12:00 | 01:00
| 03:00 | 03:30
First of all - use same variable names ($storage & $storeArray & $res)
Secondly - mysql is removed in php7, instead try to make mysqli or PDO;
Do you want outputting only start times or all data???
$logs = mysql_query("SELECT start FROM table_log WHERE id = $resultID");
$storage = Array(); // from PHP5.6 use fetch_all
while ($res = mysql_fetch_assoc($logs)) {
$storage[] = $res['start'];
}
$output = "<div><b>$resultID:</b>". implode (' | ', $storage) ."</div>";
<?php
$logs = mysql_query("SELECT start FROM table_log WHERE id =$resultID");
while ($res = mysql_fetch_array($logs)) {
?>
<table>
<tr>
<th>id</th>
<th>start</th>
<th>end</th>
</tr>
<tr>
<td><?php echo $res['id'];</td>
<td><?php echo $res['start'];</td>
<td><?php echo $res['end'];</td>
</tr>
</table>
<?php
}
?>
got it! this one worked for me :)
$start_log = "";
$j = 1;
while ($res = mysql_fetch_array($logs, MYSQL_ASSOC)) {
$storage[] = $res['start'];
$j++;
}
for($i = 0; $i<=$ctr; $i++) {
$start_log .= " $storage[$i] <br>";
}

PHP crosstab formatting from array

Hi I have a PHP array like this
$table=array();
$subject_names=array();
$subject_names[118]="English";
$subject_names[108]="Software Engeneering";
$table['Josh'][118]['int'] =55;
$table['Josh'][118]['ext'] = 10;
$table['Josh'][108]['int'] =45;
$table['Josh'][108]['ext'] = 12;
$table['Matt'][118]['int'] =45;
$table['Matt'][118]['ext'] = 12;
$table['Matt'][108]['int'] =50;
$table['Matt'][108]['ext'] = 15;
Here 118 and 108 are subject_id I am trying to format it like this
student | English | Software Engeneering |
| int. mark | ext. mark | int. mark | ext. mark |
___________________________________________________________
Josh | 55 | 10 | 45 | 12
Matt | 45 | 12 | 50 | 15
I tried
echo "Student Name\t";
foreach($subject_names as $sub_name)
{
echo "$sub_name\t";
}
echo "<br>";
foreach($table as $sname => $subjects){
echo "$sname\t";
foreach($subjects as $subject_name => $types)
{
foreach($types as $marks)
{
echo "$marks\t";
}
}
echo "<br>";
}
It working fine but if I change the position of array item of table like
$table['Josh'][118]['int'] =55;
$table['Josh'][108]['int'] =45;
$table['Josh'][118]['ext'] = 10;
$table['Josh'][108]['ext'] = 12;
It won't give a correct result. Is there anyway to assure that the result are always correct.
Thank you for your any help and suggestions
Here's a solution I wrote for your request, picking the scores using the $subject_names as control rather than the students' scoresheet (I hope you get what I mean after going through the codes)...
$table=array();
$subject_names=array();
// notice that I switched subject order, just to show that subjects control the marks displayed thereby ensuring consistent score mapping
$subject_names[108]="Software Engeneering";
$subject_names[118]="English";
// and I'm using the rearranged scores (the sample use-case you specified in the question that distorts your output)
$table['Josh'][118]['int'] =55;
$table['Josh'][108]['int'] =45;
$table['Josh'][118]['ext'] = 10;
$table['Josh'][108]['ext'] = 12;
$table['Matt'][118]['int'] =45;
$table['Matt'][118]['ext'] = 12;
$table['Matt'][108]['int'] =50;
$table['Matt'][108]['ext'] = 15;
echo "Student Name\t";
foreach($subject_names as $sub_name)
{
echo "$sub_name\t";
}
echo "\n";
// proposed solution:
foreach($table as $sname => $subjects){
echo "$sname\t";
foreach ($subject_names as $subject_id => $name) {
foreach ($subjects[$subject_id] as $mark) {
echo "$mark\t";
}
}
echo "\n";
}
Here's the output of the script above...
Student Name Software Engeneering English
Josh 45 12 55 10
Matt 50 15 45 12
Running the same data through the script provided in the question, here's the output (distorted)...
Student Name Software Engeneering English
Josh 55 10 45 12
Matt 45 12 50 15
P.S: 'Engeneering' should be 'Engineering'
I hope I've been helpful.
Cheers!

Grouping similar records with php

I need help writing the logic of the php script which sorts data into a certain format...
Firstly the script needs to loop through each s1 value and ping an endpoint to get the ml values (more like) which are actually referencing other s1 records. this is the easy part! the data is returned like so;
Table 1
s1 | ml
----------
1 | -
2 | 3,4
3 | 2,8,9
4 | -
5 | 2
6 | 1
7 | 10
8 | -
9 | -
10 | -
Condition 1: As you can see the endpoint returns data for the s1 value telling it other s1 records are similar to other ones, but the direction of ml is not always bidirectional. sometimes, like when s1=6 the ml value is 1 however when s1=1 there isn't a ml value.
Condition 2: Again just to explain the ml records, look above and below where s1=5 (above) and where s1=2 + rec=5 (below), this script needs to realise there is already an s1 record for it's value and that it should be added there.
Condition 3: Note how when s1=2,ml=3 this is stored but when s1=3,ml=2 this is ignored because we have the reverse record.
I basically want to match all the data into 1 sorted 'profile' so it ends up in the below format which i will store in another db table of 'sorted' records.
Table 2
s1 | rec
----------
2 | 3
2 | 4
2 | 8
2 | 9
2 | 9
2 | 5
6 | 1
7 | 10
This has been racking my brains for days now, I need something thats efficient because in the end it will deal with millions of records and I'm sure there is an easy solution but i just can't figure how to start it.
I tried the following, but I'm stuck and don't know how to go further;
public function getrelated($id='', $t=''){
if($id != ""){
$get = Easytest::where('s1','=',$id)->get();
if(count($get) > 0){
$ret= array();
foreach($get as $go){
$v = explode(",", $go->s2);
foreach ($v as $e) {
if($e != $t){
$ret[$e] = $this->getrelated($e, $id);
}
}
}
if(count($ret) > 0){
return $ret;
}else{
return "";
}
}else{
return $id;
}
}else{
return "";
}
}
public function easytest(){
ob_start();
$a = array(
array("s1"=>1,"s2"=>implode(",",array()).""),
array("s1"=>2,"s2"=>implode(",",array(3,4)).","),
array("s1"=>3,"s2"=>implode(",",array(2,8,9)).","),
array("s1"=>4,"s2"=>implode(",",array()).""),
array("s1"=>5,"s2"=>implode(",",array(2)).","),
array("s1"=>6,"s2"=>implode(",",array(1)).","),
array("s1"=>7,"s2"=>implode(",",array(10)).","),
array("s1"=>8,"s2"=>implode(",",array()).""),
array("s1"=>9,"s2"=>implode(",",array()).""),
array("s1"=>10,"s2"=>implode(",",array()).""),
array("s1"=>11,"s2"=>implode(",",array(12)).","),
array("s1"=>12,"s2"=>implode(",",array(2)).",")
);
//return Easytest::insert($a);
$records = Easytest::all();
foreach ($records as $record) {
$id = $record->s1;
echo "ROW: ".$id." > ";
$record->s2 = ltrim($record->s2,",");
$ml = explode(",",$record->s2);
if(count($ml) >= 1){
foreach ($ml as $t) {
echo "RESULT: ".$t." -".print_r($this->getrelated($t, $id), true);
echo ",\n";
}
}
echo " <br><br>\n\n";
}
return ob_get_clean();
}
Ok, so I eventually solved this... esentially this is the code below;
improvements welcome :)
You need to call the function like so
related(array('searched'=>array(),'tosearch'=>array(13)));
function:
public function related($input){
$searched = $input['searched'];
$ar = array();
$bits = array();
if(count($input['tosearch']) != 0){
$get = Easytest::orWhere(function($query) use ($input)
{
foreach ($input['tosearch'] as $k=>$v) {
$query->orWhere('s2', 'LIKE', '%,'.$v.',%')->orWhere('s1', '=', $v);
}
})
->orderBy('s1', 'ASC')->get();
foreach ($input['tosearch'] as $k=>$v) {
unset($input['tosearch'][$k]);
$input['searched'][$v] = $v;
}
foreach ($get as $result) {
$thesebits = explode(",", trim($result->s2,","));
foreach ($thesebits as $smallbit) {
if($smallbit != ""){
$bits[] = $smallbit;
}
}
$bits[] = $result->s1;
$bits = array_unique($bits);
foreach ($bits as $k=>$v) {
if(($key = array_search($v, $input['searched'])) == false) {
$input['tosearch'][$v] = $v;
}else{
unset($input['tosearch'][$v]);
}
}
$input['tosearch'] = array_unique($input['tosearch']);
}
return $this->related($input);
}else{
return $input;
}
}

Categories