-
Posts
24,420 -
Joined
-
Last visited
-
Days Won
805
Posts posted by Barand
-
-
Use glob() function which returns an array of the files.
E.G.
$folder = 'C:/Users/... /chartSamples/' ; foreach (glob("{$folder}*.png") as $fn) { echo basename($fn) . '<br>'; }
giving
column.png doughnut.png line.png radar.png rosechart.png stacked.png
-
1
-
-
The $freqs array contains the counts for P1, P2 , P3 for each digit...
$freqs = Array ( [0] => Array # digit "0" ( [0] => 4 # P1 [1] => 7 # P2 [2] => 1 # P3 ) [1] => Array ( [0] => 3 [1] => 2 [2] => 6 ) [2] => Array ( [0] => 4 [1] => 4 [2] => 6 )
which, coincidentally, is the same structure as the output table. You now loop through the array and for each digit (row) loop through its array (positions columns) and build the table.
// // create frequncy table and calc digit totals // $totals = array_fill_keys(range(0,9), []); $tdata = ''; foreach ($freqs as $n => $occs) { $tdata .= "<tr><td><b>$n</b></td>"; foreach ($occs as $o) { $tdata .= "<td>$o</td>"; } $total = array_sum($occs); $totals[$n] = [$n,$total]; $tdata .= "<td>=</td><td><b>$total</b></td></tr>\n"; }
My complete solution...
<?php // // Get the input string of comma-separated numbers // explode into an array and trim off any spaces // $input_str = "572, 545, 884, 123, 802, 337, 879, 307, 759, 227, 211, 002, 968, 532, 459, 895, 681, 967, 580, 399, 664, 077, 307, 227, 461, 594, 645, 859, 484, 827, 618, 675, 302, 246, 007, 842, 471, 006, 161, 171"; $input_arr = array_map('trim', explode(',', $input_str)); // // now split each number into a 3-element array // and store in $input // foreach ($input_arr as $n) { $input[] = str_split($n, 1); } // // create output table to display the input numbers // in rows of 10 numbers // $inputdata = ''; $chunks = array_chunk($input_arr, 10); foreach ($chunks as $nums) { $inputdata .= "<tr>"; foreach ($nums as $num) { $inputdata .= "<td>$num</td>"; } $inputdata .= "</tr>\n"; } // // get the counts in each position // $freqs = array_fill_keys(range(0,9), [0,0,0]); for ($pos=0; $pos<3; $pos++) { $digits = array_column($input, $pos); $occurs = array_count_values($digits); foreach ($occurs as $n => $tot) { $freqs[$n][$pos] += $tot; } } // // create frequncy table and calc digit totals // $totals = array_fill_keys(range(0,9), []); $tdata = ''; foreach ($freqs as $n => $occs) { $tdata .= "<tr><td><b>$n</b></td>"; foreach ($occs as $o) { $tdata .= "<td>$o</td>"; } $total = array_sum($occs); $totals[$n] = [$n,$total]; $tdata .= "<td>=</td><td><b>$total</b></td><td>" . bar($total, 30) . "</td></tr>\n"; } // // put digits in frequncy order (highest to lowest) // uasort ($totals, function($a, $b) { $x = $b[1] <=> $a[1]; if ($x == 0) return $a[0] <=> $b[0]; return $x; }); $freqorder = '<b>' . join('</b> – <b>', array_keys($totals)) . "</b>" ; /** * draw bar representing number of occurences * * @param int $val * @param int $max */ function bar($val, $max) { $wid = 200; $ht = 15; $svg = "<svg width='$wid' height='$ht'> <rect x='0' y='0' width='$wid' height='$ht' stroke='#CCC' fill='none'/> "; $pix = $wid/$max; $w = $val * $pix; $svg .= "<rect x='0' y='0' width='$w' height='$ht' fill='#396' stroke='#CCC' />\n"; $svg .= "</svg>\n"; return $svg; } ?> <!DOCTYPE html> <html> <head> <meta http-equiv="content-language" content="en"> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> <meta name="generator" content="PhpED 18.0 (Build 18044, 64bit)"> <title>Number frequencies</title> <meta name="creation-date" content="09/29/2019"> <style type="text/css"> table { border-collapse: collapse; font-family: verdana, sans-serif; font-size: 10pt; } th { background-color: #396; color: #FFF; padding: 8px; font-variant: small-caps;} td { text-align: center; padding: 4px 8px; } #league, #inputs { padding: 16px; background-color: #FCF8E8; font-size: 12pt; border: 1px solid gray; display: inline-block; } </style> </head> <body> <h3>Input</h3> <div id="inputs"> <table> <?=$inputdata?> </table> </div> <h3>Digit Frequencies</h3> <table border="1"> <tr><th>Digit</th><th>P1</th><th>P2</th><th>P3</th><th> </th><th>Digit<br>Totals</th></tr> <?=$tdata?> </table> <br> <h3>Digit Frequency League</h3> <div id="league"> <?=$freqorder?> </div> </body> </html>
-
1
-
-
Like this...
// // Get the input string of comma-separated numbers // explode into an array and trim off any spaces // $input_str = "572, 545, 884, 123, 802, 337, 879, 307, 759, 227, 211, 002, 968, 532, 459, 895, 681, 967, 580, 399, 664, 077, 307, 227, 461, 594, 645, 859, 484, 827, 618, 675, 302, 246, 007, 842, 471, 006, 161, 171"; $input_arr = array_map('trim', explode(',', $input_str)); // // now split each number into a 3-element array // and store in $input // foreach ($input_arr as $n) { $input[] = str_split($n, 1); }
Now you have a processable array. You now need an array ($freqs) which contains, for each digit 0-9, an array the counts of that digits in P1, P2 and P3...
// // get the counts in each position // $freqs = array_fill_keys(range(0,9), [0,0,0]); for ($pos=0; $pos<3; $pos++) { $digits = array_column($input, $pos); $occurs = array_count_values($digits); foreach ($occurs as $n => $tot) { $freqs[$n][$pos] += $tot; } }
You now have all the data that you want to output in your table in the $freqs array.
From that input data you should be able to end up with something like this...
-
1 hour ago, haymanpl said:
Runs because i tested it
Then how about posting the code that "works" because that code above contains syntax errors and undefined function calls.
22 hours ago, haymanpl said:There's no errors but the additional code is not printing.
There is no code there to print anything (except throw error messages of course)
-
You really need to turn on the error reporting. That code won't even run, let alone produce incorrect results.
-
Regarding your current code
It is going to throw warning notices when the dgits do not appear in the array eg
Notice: Undefined offset: 0 Notice: Undefined offset: 4 Notice: Undefined offset: 6 Notice: Undefined offset: 7 Notice: Undefined offset: 8
It is repetetive. The advantage of arrays is they can be used in loops, so your code can be replaced by
$arr = array('9','2','3','2','1','5'); $result = array_count_values($arr); echo "DIGIT FREQUENCY RESULTS ..<br><br>"; for ($d=0; $d<10; $d++) { echo "{$d}s : " . ($result[$d] ?? 0) . '<br>'; }
-
I'd store the input as arrays of 3 digits instead of 3-digit numbers.
$input = []; for ($i=0; $i<5; $i++) { $input[] = str_split(sprintf('%03d',mt_rand(1,999)), 1); }
Giving...
$input Array ( [0] => Array ( [0] => 8 [1] => 5 [2] => 2 ) [1] => Array ( [0] => 3 [1] => 6 [2] => 3 ) [2] => Array ( [0] => 4 [1] => 1 [2] => 1 ) [3] => Array ( [0] => 1 [1] => 5 [2] => 6 ) [4] => Array ( [0] => 7 [1] => 8 [2] => 2 ) )
Then, if you want, you can get the individual positions for counting by using array_column()
$p1 = array_column($input, 0); $p2 = array_column($input, 1); $p3 = array_column($input, 2);
E.G...
$p1 Array ( [0] => 8 [1] => 3 [2] => 4 [3] => 1 [4] => 7 )
-
The onclick will still work after a refresh.
Are you saying that you want disabled buttons to remain disabled after a refresh?
-
55 minutes ago, Barand said:
Because I preferred to pass the parameters in an array when executing instead.
Binding is useful when you want to process records in a loop. Bind the variables first then, in the loop, update the values and execute. EG
$data = [ [ 1, 'Curly'], [ 2, 'Larry'], [ 3, 'Mo'] ]; $stmt = $db->prepare("INSERT INTO testuser (id, username) VALUES (:id, :user)"); $stmt->bindParam(':id', $id, PDO::PARAM_INT); $stmt->bindParam(':user', $username, PDO::PARAM_STR); foreach ($data as $user) { list($id, $username) = $user; $stmt->execute(); }
EDIT:
But, with PDO, there is the alternative that I used before EG
$data = [ [ 1, 'Curly'], [ 2, 'Larry'], [ 3, 'Mo'] ]; $stmt = $db->prepare("INSERT INTO testuser (id, username) VALUES (?, ?)"); foreach ($data as $user) { $stmt->execute($user); }
where the values are passed as an array when executing.
-
1
-
-
1 minute ago, mahenda said:
but why no bindParam()
Because I preferred to pass the parameters in an array when executing instead.
-
It's like American Football but without all the armour.
-
The number value of the string "1,000" is 1. (ie anything befor the first non-numeric character.)
Do all your maths on unformatted numbers and only format imediately prior to output.
$value = 1000; $multiplier = 1.02; for ($i = 1; $i <= 10; $i++) { $value *= $multiplier; echo number_format($value, 2) . '<br>'; }
-
Just curious - anyone across the pond watching the England v USA match that's currently being played in Japan?
-
Sample query I forgot to add to my last post...
SELECT r.rid , r.role_name , p.page_id , p.page , CASE WHEN ra.page IS NULL THEN '' ELSE 'Y' END as checked FROM role r CROSS JOIN pages p LEFT JOIN role_access ra ON r.rid = ra.role AND p.page_id = ra.page ORDER BY r.rid, p.page_id; +-----+-----------+---------+--------------+---------+ | rid | role_name | page_id | page | checked | +-----+-----------+---------+--------------+---------+ | 1 | Admin | 1 | Registration | Y | | 1 | Admin | 2 | List | Y | | 1 | Admin | 3 | Edit | Y | | 1 | Admin | 4 | Export | Y | | 1 | Admin | 5 | MRD | Y | | 2 | Others | 1 | Registration | | | 2 | Others | 2 | List | Y | | 2 | Others | 3 | Edit | | | 2 | Others | 4 | Export | Y | | 2 | Others | 5 | MRD | Y | +-----+-----------+---------+--------------+---------+
-
The answer is "normalize".
Don't store comma-separated lists (especially when the list items are ids). The role_access table should be
CREATE TABLE `role_access` ( `id` int(10) NOT NULL PRIMARY KEY, `page` int NOT NULL, `role` int(7) NOT NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1; INSERT INTO `role_access` (`id`, `page`, `role`) VALUES (1,1,1), (2,2,1), (3,3,1), (4,4,1), (5,5,1), (6,2,2), (7,4,2), (8,5,2);
Now you can join to the page table to get the page name
-
1
-
-
-
Another option is to display, for each frame, all the referenced banners. For example if you have banner_frames table thus
+----+-----------+----------+ | id | banner_id | frame_id | +----+-----------+----------+ | 1 | 1 | 1 | | 2 | 2 | 1 | | 3 | 2 | 3 | | 4 | 3 | 3 | | 5 | 1 | 4 | | 6 | 2 | 4 | | 7 | 3 | 4 | +----+-----------+----------+
then the output would look like
CODE:
<?php include 'db_inc.php'; $db = pdoConnect('chibi'); // // Get the banner data // $res = $db->query("SELECT id , title FROM banners ORDER BY id "); $banner_data = $res->fetchAll(); $banner_count = count($banner_data); $banner_heads = '<th>' . join('</th><th>', array_column($banner_data,'title')) . '</th>'; $banner_template = array_fill_keys(array_column($banner_data, 'id'), ''); // // Get frame-banner data // store in array // $res = $db->query("SELECT f.id as fid , f.title , b.id as bid , CASE WHEN bf.banner_id IS NULL THEN '' ELSE 'Y' END as checked FROM frames f CROSS JOIN banners b LEFT JOIN banner_frame bf ON f.id = bf.frame_id AND b.id = bf.banner_id ORDER BY f.id, b.id "); $data = []; foreach ($res as $r) { if (!isset($data[$r['fid']])) { $data[$r['fid']] = [ 'title' => $r['title'], 'banners' => $banner_template ]; } $data[$r['fid']]['banners'][$r['bid']] = $r['checked']; } ?> <!DOCTYPE html > <html> <head> <meta http-equiv="content-language" content="en"> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <link rel="stylesheet" href="https://www.w3schools.com/w3css/4/w3.css"> <title>Banner Frames</title> </head> <body> <header class="w3-container w3-blue"> <h1>Banner Frames</h1> </header> <div class="w3-container w3-margin w3-padding"> <table class="w3-table w3-bordered"> <tr class="w3-brown"> <th rowspan="2">Frame ID</th> <th rowspan="2">Title</th> <th colspan="<?=$banner_count?>">Banners</th> </tr> <tr class="w3-brown"> <?=$banner_heads?> </tr> <?php // output the data array as table rows foreach ($data as $fid => $fdata) { echo "<tr><td>$fid</td><td>{$fdata['title']}</td>"; foreach ($fdata['banners'] as $bid => $chkd) { $checked = $chkd=='Y' ? 'checked' : ''; echo "<td><input type=\"checkbox\" name=\"banner[$fid][]\" value=\"$bid\" $checked></td>"; } echo "</tr>\n"; } ?> </table> </div> </body> </html>
-
In that case you need to specify the banner you are looking for in the LEFT JOIN's ON clause
EG (looking for banner #2)
SELECT DISTINCT f.id as frameId , f.title as frameTitle , bf.banner_id FROM frames f LEFT JOIN banner_frame bf ON bf.frame_id = f.id AND bf.banner_id = 2 ORDER BY f.id;
+---------+------------+-----------+ | frameId | frameTitle | banner_id | +---------+------------+-----------+ | 1 | Frame 1 | 2 | | 2 | Frame 2 | NULL | | 3 | Frame 3 | NULL | | 4 | Frame 4 | NULL | | 5 | Frame 5 | 2 | +---------+------------+-----------+
-
1
-
-
4 hours ago, Chibi said:
The purpose of the query is to list all the frames from the frames table and then only put a check next to those that
is linked to the banner table through the pivot table.I used
COUNT(DISTINCT bf.banner_id) as banner_table
so that it would be non-zero if the frame were linked to any banners. You are trying to match that that count value against a $banner_id (???).
Does that mean you want to show as checked those frames that are link to s specific banner and not just any banner? If so the query will be different.
-
Something like this?
mysql> SELECT f.id as frameId -> , f.title as frameTitle -> , COUNT(DISTINCT bf.banner_id) as banner_tot -> FROM frames f -> LEFT JOIN banner_frame bf ON bf.frame_id = f.id -> GROUP BY f.id; +---------+------------+------------+ | frameId | frameTitle | banner_tot | +---------+------------+------------+ | 1 | Frame 1 | 2 | | 2 | Frame 2 | 0 | | 3 | Frame 3 | 0 | | 4 | Frame 4 | 0 | | 5 | Frame 5 | 1 | +---------+------------+------------+
-
With the provided data your query gives
mysql> SELECT frames.id as frameId, frames.title as frameTitle, banners.id as banner_id -> FROM frames -> LEFT JOIN banner_frame ON banner_frame.frame_id = frames.id -> LEFT JOIN banners ON banners.id = banner_frame.banner_id -> ORDER BY frames.id; +---------+------------+-----------+ | frameId | frameTitle | banner_id | +---------+------------+-----------+ | 1 | Frame 1 | 1 | | 1 | Frame 1 | NULL | | 2 | Frame 2 | NULL | | 3 | Frame 3 | NULL | | 4 | Frame 4 | NULL | | 5 | Frame 5 | NULL | +---------+------------+-----------+
Beacause you have "... FROM frames LEFT JOIN ..." you get every frames record even if there is no matching data in the other tables.
You get 2 rows for Frame 1 because there are 2 matching records for frame 1 in "banner_frame" table
57 minutes ago, Chibi said:id | banner_id | frame_id
1 | 1 | 1
2 | 2 | 1
2 | 2 | 5So the question is "What is the purpose of the query?"
-
This was my rearrangement of your code
<?php const KM2MILES = 0.62; $Distances = array( "Berlin" => array( "Berlin" => 0, "Moscow" =>1607.99, "Paris" => 876.96, "Prague" => 280.34, "Rome" => 1181.67 ), "Moscow" => array( "Berlin" => 1607.99, "Moscow" => 0, "Paris" => 2484.92, "Prague" => 1664.04, "Rome" => 2374.26 ), "Paris" => array( "Berlin" => 876.96, "Moscow" => 641.31, "Paris" => 0, "Prague" => 885.38, "Rome" => 1105.76 ), "Prague" => array( "Berlin" => 280.34, "Moscow" => 1664.04, "Paris" => 885.38, "Prague" => 0, "Rome" => 922 ), "Rome" => array( "Berlin" => 1181.67, "Moscow" => 2374.26, "Paris" => 1105.76, "Prague" => 922, "Rome" => 0 ) ); /** * convert Km to miles * * @param float $km distance in Kilometers * @return string miles */ function toMiles($km) { return number_format($km * KM2MILES, 2); } /** * create list of city options * * @param array $Distances distances array * @param string $current currently selected city * @return string list of options */ function cityOptions($Distances, $current) { $opts = "<option value=''> - Select city -</option>"; foreach (array_keys($Distances) as $city) { $sel = $city == $current ? 'selected' : ''; $opts .= "<option $sel> $city</option>"; } return $opts; } // // Initialise output variables // $StartIndex = ""; $EndIndex = ""; $kms = 0;; // // Was form data posted? // if ($_SERVER['REQUEST_METHOD']=='POST') { $StartIndex = $_POST['Start'] ?? ''; $EndIndex = $_POST['End'] ?? ''; $kms = $Distances[$StartIndex][$EndIndex] ?? 0;; } ?> <!DOCTYPE html > <html> <head> <meta http-equiv="content-language" content="en"> <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" /> <title>European Travel</title> </head> <body> <form action="" method="post"> <p>Starting City: <select name="Start"> <?=cityOptions($Distances, $StartIndex)?> </select></p> <p>Ending City: <select name="End"> <?=cityOptions($Distances, $EndIndex)?> </select></p> <p><input type="submit" name="btnSubmit" value="Calculate Distance" /></p> </form> <br><br> Distance <br><?=$kms?> Km <br><?=toMiles($kms)?> Miles </body> </html>
-
Just about all of your code is misplaced.
- The PHP code should be first. (except for output which should be in the html/body section
- Your <form> should be in the html/body section.
- Your <options>..</options>s should be between the <select>..</select> tags
plus your course material appears to be many years out of date.
-
1
-
P.S.
If you want to show the nurse allotment even when there are no patients on the allocated ward...
... then you will need LEFT JOINS thus
$stmt = $db->prepare("SELECT sdate , DATE_FORMAT(sdate, 'Week %v %W %d/%m/%Y') as fdate , wa.shift , w.ward_name , a.bed , a.patient_id , p.patient_name FROM ward_allotment wa INNER JOIN ward w ON wa.ward = w.wid LEFT JOIN admission a ON wa.ward = a.ward AND wa.sdate BETWEEN a.from_date AND a.discharge_date LEFT JOIN patient p ON a.patient_id = p.patient_id WHERE wa.nurse = ? AND sdate BETWEEN CURDATE() - interval 30 day AND CURDATE() + INTERVAL 6 DAY ORDER BY sdate, shift, ward_name, a.bed, a.patient_id ");
Sub/Child Class Override
in PHP Coding Help
Posted
I've cleaned it up, provided the missing function definition and added something that prints, but it's only a guess at what you really want.