-
Posts
24,604 -
Joined
-
Last visited
-
Days Won
830
Everything posted by Barand
-
I'll try to explain what the function is doing First, in the test data we are trying to achieve this and we are starting with two sets of numbers sign_x - "0,0,100,100,0,50,100,0,100" sign_y - "100,20,20,100,20,0,20,100,100" These numbers need to be put into (x, y) pairs. The first x with first y give (0, 100). The second x with the second y gives (0, 20), the third (100, 20) and so on. By far the easiest way to do this is with indexed arrays so we use explode to put the x and y values into two arrays $xa = Array $ya = Array ( ( [0] => 0 [0] => 100 [1] => 0 [1] => 20 [2] => 100 [2] => 20 [3] => 100 [3] => 100 [4] => 0 [4] => 20 [5] => 50 [5] => 0 [6] => 100 [6] => 20 [7] => 0 [7] => 100 [8] => 100 [8] => 100 ) ) As described inthe above figure, we first want to move to the start point (0, 100) then, after that, we want to draw lines to each successive point. Using SVG (Scalable Vector Graphics) the way to this is to create a path which has a definition of "M 0 100 L 0 20 L 100 20 L 100 100 L 0 20 L 50 0 L 100 20 L 0 100 L 100 100" where M x y means "move to x,y" and L x y means "line to x,y" The function line by line function drawImage($xcoords, $ycoords) { $xa = explode(',', $xcoords); // put x coords string into an array $ya = explode(',', $ycoords); // put x coords string into an array $w = max($xa)+1; // get the max coord values so we know the size $h = max($ya)+1; // define the path $path = "M $xa[0] $ya[0] "; // move to the first x,y position unset($xa[0], $ya[0]); // remove the the first items from the array foreach ($xa as $i => $x) { // loop through arrays $y = $ya[$i]; // pairing the i'th x with the i'th y $path .= "L $x $y "; // define line to x y } // create svg object $w x $h to display image $im = "<svg width='$w' height='$h'> <path d='$path' stroke='#000' stroke-width='1' fill='none'/> </svg>"; return $im; }
-
When that combination is required to be unique anyway you may as well make it the primary key instead of an artificial one.
-
No, but every table should have a unique primary key, but not necessarily auto_incremented (for example the plan_version table above, where the primary key is the (plan_id, version_no) combination)
-
you posted [44, 44, 44, 45, 45, 45, 45, 45, 45, 43, 42, 41, 40, 39, 39, 39, 37, 37, 37, 37, 37, 37, 37, 39, 40, 43, 47, 47, 49, 51, 52, 52, 53, 54, 55, 57, 58, 59, 64, 68, 73, 80, 85, 89, 93, 94, 94, 95, 95, 95, 93, 91, 89, 87, 85, 83, 81, 79, 75, 75, 72, 69, 66, 63, 60, 57, 55, 52, 50, 47, 45, 43, 41, 41, 41, 123, 124, 124, 123, 122, 119, 117, 111, 105, 100, 94, 89, 85, 82, 78, 76, 75, 73, 73, 72, 72, 72, 72, 75, 77, 79, 81, 83, 83, 87, 91, 95, 101, 109, 118, 127, 137, 144, 150, 153, 155, 155, 155, 155, 155, 155, 154, 154, 153, 150, 147, 147, 145, 144, 144, 144, 144, 144, 149, 152, 155, 158, 163, 167, 170, 176, 184, 191, 197, 201, 203, 204, 205, 206, 206, 206, 205, 203, 203, 202, 202, 202, 202, 202, 202, 202, 204, 207, 210, 213, 219, 220, 222, 223, 224, 226, 228, 230, 234, 237, 242, 246, 252, 259, 269, 278, 287, 293, 301, 309, 316, 325, 333, 340, 345, 345, 343, 341, 341, 339, 335, 332, 329, 327, 327, 327, 327, 328, 328, 329, 329, 332, 332, 335, 336, 338, 339, 343, 343, 346, 346] [39, 45, 50, 58, 72, 86, 91, 97, 102, 106, 108, 111, 112, 114, 114, 112, 108, 102, 98, 92, 86, 81, 75, 69, 65, 60, 56, 55, 53, 50, 50, 48, 48, 48, 48, 48, 46, 46, 47, 48, 51, 53, 55, 58, 60, 61, 62, 66, 70, 76, 80, 84, 86, 89, 93, 94, 97, 99, 101, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 72, 72, 71, 69, 68, 65, 64, 62, 61, 61, 61, 61, 61, 61, 62, 64, 64, 66, 68, 71, 76, 81, 86, 92, 94, 96, 100, 102, 102, 104, 104, 104, 104, 104, 101, 98, 94, 91, 86, 84, 80, 78, 76, 74, 73, 72, 71, 70, 69, 71, 75, 76, 82, 86, 92, 95, 98, 102, 105, 108, 108, 110, 111, 111, 111, 110, 106, 102, 98, 94, 91, 88, 84, 82, 79, 77, 74, 71, 70, 68, 68, 66, 66, 65, 64, 63, 62, 62, 59, 58, 57, 57, 56, 56, 56, 56, 58, 58, 60, 61, 63, 64, 66, 68, 68, 68, 68, 68, 65, 63, 59, 55, 51, 50, 47, 47, 48, 50, 51, 52, 55, 57, 58, 60, 59, 58, 57, 56, 55, 55, 54, 53, 52, 51, 50, 50, 48, 47, 47, 46, 46] I just copy/pasted and changed it to $xx = "44, 44, 44, 45, 45, 45, 45, 45, 45, 43, 42, 41, 40, 39, 39, 39, 37, 37, 37, 37, 37, 37, 37, 39, 40, 43, 47, 47, 49, 51, 52, 52, 53, 54, 55, 57, 58, 59, 64, 68, 73, 80, 85, 89, 93, 94, 94, 95, 95, 95, 93, 91, 89, 87, 85, 83, 81, 79, 75, 75, 72, 69, 66, 63, 60, 57, 55, 52, 50, 47, 45, 43, 41, 41, 41, 123, 124, 124, 123, 122, 119, 117, 111, 105, 100, 94, 89, 85, 82, 78, 76, 75, 73, 73, 72, 72, 72, 72, 75, 77, 79, 81, 83, 83, 87, 91, 95, 101, 109, 118, 127, 137, 144, 150, 153, 155, 155, 155, 155, 155, 155, 154, 154, 153, 150, 147, 147, 145, 144, 144, 144, 144, 144, 149, 152, 155, 158, 163, 167, 170, 176, 184, 191, 197, 201, 203, 204, 205, 206, 206, 206, 205, 203, 203, 202, 202, 202, 202, 202, 202, 202, 204, 207, 210, 213, 219, 220, 222, 223, 224, 226, 228, 230, 234, 237, 242, 246, 252, 259, 269, 278, 287, 293, 301, 309, 316, 325, 333, 340, 345, 345, 343, 341, 341, 339, 335, 332, 329, 327, 327, 327, 327, 328, 328, 329, 329, 332, 332, 335, 336, 338, 339, 343, 343, 346, 346"; $yy = "39, 45, 50, 58, 72, 86, 91, 97, 102, 106, 108, 111, 112, 114, 114, 112, 108, 102, 98, 92, 86, 81, 75, 69, 65, 60, 56, 55, 53, 50, 50, 48, 48, 48, 48, 48, 46, 46, 47, 48, 51, 53, 55, 58, 60, 61, 62, 66, 70, 76, 80, 84, 86, 89, 93, 94, 97, 99, 101, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 72, 72, 71, 69, 68, 65, 64, 62, 61, 61, 61, 61, 61, 61, 62, 64, 64, 66, 68, 71, 76, 81, 86, 92, 94, 96, 100, 102, 102, 104, 104, 104, 104, 104, 101, 98, 94, 91, 86, 84, 80, 78, 76, 74, 73, 72, 71, 70, 69, 71, 75, 76, 82, 86, 92, 95, 98, 102, 105, 108, 108, 110, 111, 111, 111, 110, 106, 102, 98, 94, 91, 88, 84, 82, 79, 77, 74, 71, 70, 68, 68, 66, 66, 65, 64, 63, 62, 62, 59, 58, 57, 57, 56, 56, 56, 56, 58, 58, 60, 61, 63, 64, 66, 68, 68, 68, 68, 68, 65, 63, 59, 55, 51, 50, 47, 47, 48, 50, 51, 52, 55, 57, 58, 60, 59, 58, 57, 56, 55, 55, 54, 53, 52, 51, 50, 50, 48, 47, 47, 46, 46"; to give me two string variables (as you get from the db table), then echo drawImage($xx, $yy); to get the signature displayed. Why are you changing the function like that?
-
Your soul would be in mortal peril. As with so many things
-
The same way that the function does in the first two lines function drawImage($xcoords, $ycoords) { $xa = explode(',', $xcoords); // create array from $xcoord string $ya = explode(',', $ycoords); // create array from $ycoord string $w = max($xa)+10; $h = max($ya)+10; $path = "M $xa[0] $ya[0] "; unset($xa[0], $ya[0]); foreach ($xa as $i => $x) { $y = $ya[$i]; $path .= "L $x $y "; } $im = "<svg width='$w' height='$h' > <path d='$path' stroke='#000' fill='none'/> </svg>"; return $im; } example $x = "1, 2, 3, 4, 5"; // comma separated string $arr = explode (', ', $x); // explode into array elements splitting on ", " echo '<pre>', print_r($arr, 1), '</pre>'; // view the array /* result : Array ( [0] => 1 [1] => 2 [2] => 3 [3] => 4 [4] => 5 ) */
-
That's what ids are for (row identification) "Some point" is version 8. https://dev.mysql.com/doc/refman/8.0/en/create-table-check-constraints.html Yes, I agree.
-
Probably best to leave it as it is then; it works (if it ain't bust, don't fix it)
-
I prefer to use ids as foreign keys and not data attribute values (such as dates, names etc) So does NOT NULL You would validate end > start on processing the input. The method I proposed for entering new versions would ensure contiguous logical date sequences. The valid_from / valid_until dates give you a history. (see my data and query examples) That is up to you. If you assign a member to a particular plan/version then you get that problem. Alternatively assign them to a plan and the use the "current" version. Prices for each plan would also have valid_from / valid_to dates. For new members, get the current price. (SELECT price FROM plan_price WHERE CURDATE() BETWEEN valid_from and valid_to) For renewals (grandfathering) get the price that applied on the date_joined (SELECT price FROM plan_price WHERE date_joined BETWEEN valid_from and valid_to)
-
They would still be a strings of comma-separated values. Changing to column type TEXT just increases the maximum storage capacity of each column to 65500 (which should be sufficient to hold the longest signature with several thousand points.) Normalising the data would allow you store the data as a series of (x,y) points which, to me, seems more logical as that is how the data is used. At the moment you have a huge block of x coordnates and another of y coordinates. Storing it this way way would be done as part of your transfer from the phone app. Question: Does the app put the data directly into the mysql db in your current format or is there some sort if interface process between the two?
-
You only need to query once $res = $conn->query("SELECT userid, fname, lname, sign_x, sign_y FROM winuser_demo"); $conn->query("SELECT userid, fname, lname, sign_x, sign_y FROM winuser_demo"); // <--- REMOVE THIS LINE
-
I get NOTE: the 2 values you posted are arrays. The function expects strings of comma-separated values. If you prefer to pass arrays like those the query can be modified. You should also consider normalizing the data ... +-------------+ | user | +-------------+ | id |--------+ +-------------+ | firstname | | | signature | | lastname | | +-------------+ +-------------+ +--------<| user_id | | seq | | x | | y | +-------------+
-
Change the column type of the sign_x and sign_y columns to TEXT instead of varchar(N). That should give sufficient capacity.
-
Go Ahead. If it is a different problem then you should start a new topic.
-
I had just received the notification from PP. Thank you.
-
There are links to PP in all my posts if you insist.
-
should be $res = $conn->query("SELECT userid, fname, lname, sign_x, sign_y FROM winuser_demo");
-
When you use mysqli, call mysqli_report() before you connect. You will then be notified automatically of any errors encountered in your mysqli code. Your connection is "$conn" so you need to use that and not "$db" in the query call. mysqli_report(MYSQLI_REPORT_ERROR|MYSQLI_REPORT_STRICT); $conn = mysqli_connect('localhost', '???', '???', 'pmapp'); $conn->query("SELECT ....
-
You are definitely on the right track. TABLE: plan +-----------+-------------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +-----------+-------------+------+-----+---------+-------+ | plan_id | int(11) | NO | PRI | | | | plan_name | varchar(45) | YES | | | | +-----------+-------------+------+-----+---------+-------+ TABLE: plan_version +-------------+---------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +-------------+---------+------+-----+---------+-------+ | plan_id | int(11) | NO | PRI | | | | version_no | int(11) | NO | PRI | | | | valid_from | date | YES | | | | | valid_until | date | YES | | | | +-------------+---------+------+-----+---------+-------+ TABLE: entitlement +------------+---------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +------------+---------+------+-----+---------+-------+ | plan_id | int(11) | NO | PRI | | | | version_no | int(11) | NO | PRI | | | | feature_id | int(11) | NO | PRI | | | +------------+---------+------+-----+---------+-------+ TABLE: feature +------------+--------------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +------------+--------------+------+-----+---------+-------+ | feature_id | int(11) | NO | PRI | | | | title | varchar(45) | YES | | | | | page | varchar(100) | YES | | | | +------------+--------------+------+-----+---------+-------+ Suppose the data is... TABLE: plan TABLE: entitlement +---------+-----------+ +---------+------------+------------+ | plan_id | plan_name | | plan_id | version_no | feature_id | +---------+-----------+ +---------+------------+------------+ | 1 | Silver | | 1 | 1 | 1 | | 2 | Gold | | 1 | 1 | 2 | | 3 | Platinum | | 1 | 1 | 3 | +---------+-----------+ | 1 | 2 | 1 | | 1 | 2 | 2 | TABLE: plan_version | 1 | 2 | 3 | +---------+------------+------------+-------------+ | 1 | 2 | 4 | | plan_id | version_no | valid_from | valid_until | | 2 | 1 | 1 | +---------+------------+------------+-------------+ | 2 | 1 | 2 | | 1 | 1 | 2019-06-01 | 2019-12-31 | | 2 | 1 | 3 | | 1 | 2 | 2020-01-01 | 9999-12-31 | | 2 | 1 | 4 | | 2 | 1 | 2019-06-01 | 2019-10-31 | | 2 | 1 | 5 | | 2 | 2 | 2019-11-01 | 2020-02-29 | | 2 | 1 | 6 | | 2 | 3 | 2020-03-01 | 9999-12-31 | | 2 | 2 | 1 | | 3 | 1 | 2019-12-01 | 9999-12-31 | | 2 | 2 | 2 | +---------+------------+------------+-------------+ | 2 | 2 | 3 | | 2 | 2 | 4 | TABLE: feature | 2 | 2 | 5 | +------------+-------+------------+ | 2 | 2 | 6 | | feature_id | title | page | | 2 | 2 | 7 | +------------+-------+------------+ | 2 | 3 | 1 | | 1 | AAA | Page1.php | | 2 | 3 | 2 | | 2 | BBB | Page2.php | | 2 | 3 | 3 | | 3 | CCC | Page3.php | | 2 | 3 | 4 | | 4 | DDD | Page4.php | | 2 | 3 | 5 | | 5 | EEE | Page5.php | | 2 | 3 | 6 | | 6 | FFF | Page6.php | | 2 | 3 | 7 | | 7 | GGG | Page7.php | | 2 | 3 | 8 | | 8 | HHH | Page8.php | | 3 | 1 | 1 | | 9 | JJJ | Page9.php | | 3 | 1 | 2 | | 10 | KKK | Page10.php | | 3 | 1 | 3 | +------------+-------+------------+ | 3 | 1 | 4 | | 3 | 1 | 5 | | 3 | 1 | 6 | | 3 | 1 | 7 | | 3 | 1 | 8 | | 3 | 1 | 9 | | 3 | 1 | 10 | +---------+------------+------------+ to summarize... SELECT p.plan_name , v.version_no , DATE_FORMAT(v.valid_from, '%m/%d/%Y') as `From` , DATE_FORMAT(v.valid_until, '%m/%d/%Y') as `Until` , GROUP_CONCAT(f.title ORDER BY title SEPARATOR ', ') as features FROM plan p JOIN plan_version v USING (plan_id) JOIN entitlement e USING (plan_id, version_no) JOIN feature f USING (feature_id) GROUP BY plan_id, version_no; +-----------+------------+------------+------------+--------------------------------------------------+ | plan_name | version_no | From | Until | features | +-----------+------------+------------+------------+--------------------------------------------------+ | Silver | 1 | 06/01/2019 | 12/31/2019 | AAA, BBB, CCC | | Silver | 2 | 01/01/2020 | 12/31/9999 | AAA, BBB, CCC, DDD | | Gold | 1 | 06/01/2019 | 10/31/2019 | AAA, BBB, CCC, DDD, EEE, FFF | | Gold | 2 | 11/01/2019 | 02/29/2020 | AAA, BBB, CCC, DDD, EEE, FFF, GGG | | Gold | 3 | 03/01/2020 | 12/31/9999 | AAA, BBB, CCC, DDD, EEE, FFF, GGG, HHH | | Platinum | 1 | 12/01/2019 | 12/31/9999 | AAA, BBB, CCC, DDD, EEE, FFF, GGG, HHH, JJJ, KKK | +-----------+------------+------------+------------+--------------------------------------------------+ to get the ones in effect on a particular date, add a where clause to the above query ... WHERE CURDATE() BETWEEN v.valid_from AND v.valid_until ... +-----------+------------+------------+------------+--------------------------------------------------+ | plan_name | version_no | From | Until | features | +-----------+------------+------------+------------+--------------------------------------------------+ | Silver | 2 | 01/01/2020 | 12/31/9999 | AAA, BBB, CCC, DDD | | Gold | 2 | 11/01/2019 | 02/29/2020 | AAA, BBB, CCC, DDD, EEE, FFF, GGG | | Platinum | 1 | 12/01/2019 | 12/31/9999 | AAA, BBB, CCC, DDD, EEE, FFF, GGG, HHH, JJJ, KKK | +-----------+------------+------------+------------+--------------------------------------------------+ ** ** ** Now to address your question about preventing date overlaps. Suppose that on March 1st you are adding a new feature 'LLL/page11.php' for Platinum plans and you want to introduce a new version. Add new feature LLL Select Platinum v1 record for editing On the edit form, change date_from to "2020-03-01" and add LLL to feature list. However, when you update the version table, leave the "from" date as it is and change the "until" date to the date before the new one (2020-02-29), save insert a new record for Platinum / v2 / 2020-03-01 / 9999-12-31 insert entitlement records for new version
-
The first parts of the code, which use ->exec(), can be thrown away once you have your data table. (I just used those to create the db table and test data) You will need to set up your own connection to SQLite and use that. Meanwhile here is a DB-less version that generates sign_x and sign_y data for random squiggles. <?php $tdata = ''; for ($i=1; $i<=10; $i++) { $tdata .= randomSignature($i) ; } function randomSignature($i) { $n1 = mt_rand(1, 15); $n2 = mt_rand(1, 15); $x = $y = []; for ($a = 1; $a < 360; $a++) { $x[] = $a; $y[] = round(35 + sin(deg2rad($n1 * $a)) * 15 - cos(deg2rad($n2 * $a)) * 15); } $sx = join(',',$x); $sy = join(',',$y); return "<tr><td>$i</td><td>$n1</td><td>$n2</td><td>" . drawImage($sx, $sy) . "</td>\n"; } function drawImage($xcoords, $ycoords) { $xa = explode(',', $xcoords); $ya = explode(',', $ycoords); $w = max($xa)+1; $h = max($ya)+1; $scaled_h = 50; $scaled_w = $scaled_h * $w / $h; $path = "M $xa[0] $ya[0] "; unset($xa[0], $ya[0]); foreach ($xa as $i => $x) { $y = $ya[$i]; $path .= "L $x $y "; } $im = "<svg width='$scaled_w' height='$scaled_h' viewBox='0 0 $w $h'> <path d='$path' stroke='#000' stroke-width='1' fill='none'/> </svg>"; return $im; } ?> <!DOCTYPE html> <html> <head> <style type="text/css"> table { border-collapse: collapse; width: 60%; } th { background-color: black; color: white; padding: 8px; text-align: left; } td { padding: 4px 8px;; } </style> </head> <body> <table border="1" style="width: 60%;"> <tr><th>ID</th> <th>N1</th> <th>N2</th> <th>Image</th> <tr> <?=$tdata?> </table> </body> </html>
-
What is the error message?
-
Use curly braces $currency_symbol = '£'; \\\ Thats £ print "Price: {$currency_symbol}5";
-
Needs a "country" table (country_id/country_name) and store the id of the country (not the name) in your table.
-
OK, I'm going to stick my neck out and assume I know what you are talking about. I am guessing that the columns sign_x and sign_y contain coordinates and that you want to put them into (x,y) pairs and join the dots. If I'm right, here's an example. If I'm wrong, well, it was fun but you need to explain a little more.. $db->exec("CREATE TABLE IF NOT EXISTS `winuser_demo` ( `userid` int(11) NOT NULL AUTO_INCREMENT, `fname` varchar(20) DEFAULT NULL, `lname` varchar(20) DEFAULT NULL, `sign_x` varchar(500) DEFAULT NULL, `sign_y` varchar(500) DEFAULT NULL, PRIMARY KEY (`userid`) ) "); $db->exec("INSERT IGNORE INTO winuser_demo (userid,fname,lname,sign_x,sign_y) VALUES (1, 'Tom', 'Di Canari', '0,0,100,100,0,50,100,0', '100,20,20,100,20,0,20,100'); "); $tdata = ''; $res = $db->query("SELECT userid , fname , lname , sign_x , sign_y FROM winuser_demo "); foreach ($res as $r) { $tdata .= "<tr><td>{$r['userid']}</td> <td>{$r['fname']}</td> <td>{$r['lname']}</td> <td>" . drawImage($r['sign_x'], $r['sign_y']) . "</td>\n"; } function drawImage($xcoords, $ycoords) { $xa = explode(',', $xcoords); $ya = explode(',', $ycoords); $w = max($xa)+10; $h = max($ya)+10; $path = "M $xa[0] $ya[0] "; unset($xa[0], $ya[0]); foreach ($xa as $i => $x) { $y = $ya[$i]; $path .= "L $x $y "; } $im = "<svg width='$w' height='$h' > <path d='$path' stroke='#000' fill='none'/> </svg>"; return $im; } ?> <!DOCTYPE html> <html> <head> <style type="text/css"> table { border-collapse: collapse; width: 60%; } th { background-color: black; color: white; padding: 8px; text-align: left; } td { padding: 4px 8px;; } </style> </head> <body> <table border="1" style="width: 60%;"> <tr><th>ID</th> <th>First name</th> <th>Last name</th> <th>Image</th> <tr> <?=$tdata?> </table> </body> </html>
-
In fact this guy had the same problem a couple of days ago