Basically on my website there are checkboxes for each day of the week. If a user checks them, those are the days to be saved (in a field) in their user account.
How would I go about saving these dates? For example, if someone checks Saturday and Wednesday, another saves Monday and Tuesday, what's a good pattern to keep this info?
Someone suggested saving it as a bit string like 0001001 the 1's representing the days of the week check marked, out of the 7 bits representing each day. Any ideas?
The table would look like this:
user_id | days
10 | 0010010 (Wednesday and Saturday, week starts on Monday)
The only issue with is how would I output this info from php?
(I'm trying to do this in the most optimal way both on the mysql and php side)
The suggestion to use a bit field type in MySQL with a length of seven sounds fair to keep storage requirements low (BIT(7)).
The only issue with is how would I output this info from php?
The first step would be to define a mapping of each bit to a weekday-name:
$days = array(
'Monday',
'Tuesday',
...
'Sunday'
);
Then you first need to select the binary value from the database, e.g. as a decimal (integer) value:
SELECT days+0 FROM table;
In PHP you can convert this to a fixed-width binary number string using decbin and substr:
$binary = substr('000000'.decbin($integer), -7);
or probably more convenient sprintf:
$binary = sprintf('%07b', $integer);
As each of those characters is either 0 or 1 you can iterate over them and create an array for all set days:
$array = array();
foreach (range(0, 7) as $day)
{
if (! $set = (int) $binary[$day])
continue;
$array[] = $days[$day];
}
The resulting $array contains now all weekday names that the user checked. You can then output them:
$output = '(none)';
if (1 === $count = count($array)
{
$output = $array[0]; # one day
}
elseif ($count)
{
$last = array_pop($array); # last day
$output = implode(', ', $array) . ' and ' . $last;
}
That was the output of the database value. Hope this is helpful.
You can store the days in a serialized array, and that way, get it back easily when you want it.
$days = array('wednesday','saturday');
$store = serialize($days);
and then store $store for that user_id
I think it would be easier to store like this:
user_id | sun | mon | tues | wed |...
01 | 1 | 0 | 0 | 1 |
And leave the day columns as tinyint(1)'s. That way, in PHP, you could just go like this:
if($row['sun'] == 1)
Do sunday stuff
I would suggest a table like this:
id user_id day
1 1 1
2 1 4
3 2 1
4 3 7
Related
I need to generate an invoice number from an integer of a table with an auto incrementing ID of the database where the user purchases saved.
Example of the table invoice database:
The invoice number format floor do one of two ways.
Example 1: of the number of invoices without prefix:
0000001 |
0000002 |
0000003 |
0000004 |
0000005
Example 2: the number of invoices with prefixes:
F-0000001 |
F-0000002 |
F-0000003 |
F-0000004 |
F-0000005
Question:
1) ¿What is the best way to do this, you can do directly from MySQL or PHP?
2) ¿What is the most appropriate format Example 1 or Example 2?
I appreciate your support as always!
Thanks to Gordon Linoff, I could get a way to solve this.
I will share an example, perhaps someone may be interested.
SQL - Invoice without prefix: SELECT id, LPAD(id,7,'0') FROM invoice WHERE id = 1;
Result: 0000001
SQL - Invoice with prefix: SELECT id, CONCAT( 'F-', LPAD(id,7,'0') ) FROM invoice;
Result: F-0000001
You can write a good helper function in PHP to use it wherever you want in your application to return an invoice number. The following helper function can simplify your process.
function invoice_num ($input, $pad_len = 7, $prefix = null) {
if ($pad_len <= strlen($input))
trigger_error('<strong>$pad_len</strong> cannot be less than or equal to the length of <strong>$input</strong> to generate invoice number', E_USER_ERROR);
if (is_string($prefix))
return sprintf("%s%s", $prefix, str_pad($input, $pad_len, "0", STR_PAD_LEFT));
return str_pad($input, $pad_len, "0", STR_PAD_LEFT);
}
// Returns input with 7 zeros padded on the left
echo invoice_num(1); // Output: 0000001
// Returns input with 10 zeros padded
echo invoice_num(1, 10); // Output: 0000000001
// Returns input with prefixed F- along with 7 zeros padded
echo invoice_num(1, 7, "F-"); // Output: F-0000001
// Returns input with prefixed F- along with 10 zeros padded
echo invoice_num(1, 10, "F-"); // Output: F-0000000001
Once you are done writing the helper function, you don't need to use LPAD or CONCAT MySQL functions every time in your query to return ID with padding zeros or zeros with prefix. If you have global access to the helper function in the entire application, you only need to invoke it wherever you want to generate an invoice number.
1 - 0000001 | 0000002 | 0000003 | 0000004 | 0000005
$dbValue = 1;
echo $dbValue = str_pad($dbValue, 7, "0", STR_PAD_LEFT); // it will give 0000001;
2 - F-0000001 | F-0000002 | F-0000003 | F-0000004 | F-0000005
$dbValue = 1;
echo $dbValue = "F-".str_pad($dbValue, 7, "0", STR_PAD_LEFT); // it will produce F-0000001;
Fetch last ID from database and store it in a PHP variable.
For example, if last record is 100, then increment it by 1.
$last = 100; // This is fetched from database
$last++;
$invoice_number = sprintf('%07d', $last);
Finally, the answer for second question is,
$number = "F-". $number;
Ans 1):
You can do this with PHP(directly by concat or use str-pad ) as well as with MySQL( LPAD ) also
But as per my view you should do this by PHP, so that you can change it according to your requirements e.g. extend zeroes as per number of id's in DB.So that not to change SQL queries and make it heavy.
Ans 2):
You can use both formats but if you want to be more specific about particular user or any thing else, then use second format.
I think second format can give you more information about data
Im looking for someone to point me in the right direction to coding some statistical comparisons. Currently I query my database, and will get data back as follows:
main data set :
3,4,7,10,5,8,1,3,7
sets to compare with could be like this, and can have multiple sets.
4,5,6,9,10,2,3,4,6
Now i need to work out the difference between these two sets of data - for example, difference between 3-4 is 1. I then need to choose the biggest difference, the most agreed upon, and the lowest scoring.
How would you tackle coding this?
I would recommend to use the function array_walk(), passing the first array as the first parameter and the second array as the third, optional parameter. It would look like this:
<?php
$array_1 = array(3,4,7,10,5,8,1,3,7);
$array_2 = array(4,5,6,9,10,2,3,4,6);
// making a copy, because the callback function
// works on the actual value
$array_1_copy = $array_1;
echo '<pre>';
array_walk($array_1_copy, 'difference', $array_2);
echo "\nThe maximum difference is: ". max($array_1_copy);
echo "\nThe minimum difference is: ". min($array_1_copy);
echo '</pre>';
// the callback function, takes the 1st param as reference
function difference(&$value_1, $index_1, $array_2) {
$difference = abs($value_1 - $array_2[$index_1]);
echo "Difference between $value_1 and {$array_2[$index_1]} is $difference\n";
$value_1 = $difference;
}
?>
And the output for this code is:
Difference between 3 and 4 is 1
Difference between 4 and 5 is 1
Difference between 7 and 6 is 1
Difference between 10 and 9 is 1
Difference between 5 and 10 is 5
Difference between 8 and 2 is 6
Difference between 1 and 3 is 2
Difference between 3 and 4 is 1
Difference between 7 and 6 is 1
The maximum difference is: 6
The minimum difference is: 1
$max_diff = 0;
for ($i = 0; $i < (min(count($array1), count($array2));$i++){
if (($array1[$i]-$array2[$i]) > $max_diff ) $max_diff = $array1[$i]-$array2[$i];
}
echo $max_diff;
Something like that...Didn't actually tested it, but that's the idea.
I need to generate a ten digits product code (for bar code generation) for a fashion store, which is a combination of:
collectionYear (this or next year), two digits, e.g. 14 or 15
collectionSeason (spring to winter) one digit, e.g. 1 for spring
productId (from 1 to 99.999 with zeros filled), e.g. 12 -> 00012
productVariant (from 1 to 99 with zero filled), e.g. 2 -> 02
The result should be something like this: 1510001202
Using php I would do this like this:
$year = str_pad($year, 2 ,'0', STR_PAD_LEFT); // for future safety, e.g. 2102 :-)
$prodId = str_pad($prodId, 5 ,'0', STR_PAD_LEFT);
$prodVar = str_pad($prodVar, 2 ,'0', STR_PAD_LEFT);
$finalCode = $year.$season.$prodId.$prodVar;
Is there a mysql syntax equiv for this like
SELECT CONCAT(collectionYear,collectionSeason,productIdproductVariant) AS prodCode
with the zero fill functions included ??
Thanks for your engagement.
I have a primary key field (news_id) in the news table
it start from 1, 2, 3, 4 and so on..
However, I like to change to 01, 02, 03, 04,e tc ... is that possible?
If not, how can that be done in PHP?
Manipulating the keys directly is a bad idea in 99% of cases.
The best way to go is probably to change the format when outputting the keys like shown in this question:
$key = 4;
echo sprintf('%02d', $key); // outputs 04
If it's for output, just add a 0 if the primary key is less than 10:
if($result['id'] < 10){
echo '0' . $result['id'];
}
Okay... Another way of doing this is... (though overly logical and mathematical...)
$id = 5;
$noOfZeros = 2; // i.e. you are converting 2 to 002.
$divider = pow(10,$noOfZeros); // Now you are creating a divider (/100 in this case)
$id = $id / $divider; // dividing the id by 100. i.e. 5 gets converted to 0.05
$zeroedId = str_replace(".","",$id); // finally replace the "." with nothing... so 0.05 becomes 005 :).
Hey guys - The problem stems from a poorly designed database used to store real estate information. I set up a template for my client to select a weekend and to display the open houses for that weekend. Open house times (ohtime1, ohtime2, ohtime3) are stored as tinytext, with no way of knowing AM or PM. "12:00 - 2:00" and "01:00 - 03:00" are common entries that we humans discern as noon-2pm and 1pm-3pm, however when I query the database and ORDER BY ohtime1, it obviously puts 01:00 before 12:00. I am having difficulty sorting using SQL and using the different php sort methods. The initial listings array with all the open house information is set up like something as follows:
$listings[0][displayaddress] = empire state building
$listings[0][baths] = too many to count
$listings[0][ohtime1] = 12:00 - 02:00
$listings[1][displayaddress] = madison square garden
$listings[1][baths] = 2
$listings[1][ohtime1] = 01:00 - 03:00
etc...
I iterate through $listings with foreach($listings as $listing) to process for the smarty templates we use, as well as to separate into the different days, and then again for manhattan and brooklyn listings. This results in 4 new arrays. My theory was if I convert all the times before 09:00am to 24 hour time, then sort them, then assign to the different day/borough it would work. Here is the converting code:
$p = explode("-",$listing[ohtime1]); //01:00 - 03:00
$time1 = trim($p[0]); //01:00
$time2 = trim($p[1]); //03:00
$hour1 = substr($time1,0,2); //01
$hour2 = substr($time2,0,2); //03
$min1 = explode(":",$time1);
$min2 = explode(":",$time2);
$min1 = $min1[1]; //00
$min2 = $min2[1]; //00
//convert all times to 24 hour
if($hour1 < 9) $hour1 = $hour1+12; //13
if($hour2 < 9) $hour2 = $hour2+12; //15
$listing[ohtime1] = $hour1.":".$min1." - ".$hour2.":".$min2; //13:00 - 15:00
$listing[hour1] = $hour1;
$listing[hour2] = $hour2;
Converting wasn't difficult, but am at a loss as to how to sort them. I am not versed in advanced SQL theory as to implement the conversion to 24hrs I did in php into mysql. I was also thinking I could implement a sorting feature when I create the new arrays but I am again at a loss. Here is the code for separating into the new arrays:
foreach($openhouse_date_fields as $oh){ //3 possible open house dates
if(substr($listing[$oh], 0,10) == $date) { //if any of the listings's open houses match the first search date
if($listing[sect] == "Brooklyn") {
$listingsb[$listing[displayaddress]] = $listing;
}
else
$listingsm[$listing[displayaddress]] = $listing;
}
elseif(substr($listing[$oh], 0,10) == $date2) { //if any of the listings's open houses match the second search date
if($listing[sect] == "Brooklyn")
$listingsb2[$listing[displayaddress]] = $listing;
else
$listingsm2[$listing[displayaddress]] = $listing;
}
}
I hope that is enough information. Thanks for taking the time to read and for any feedback!
Here's an example of converting one of the TINYTEXT columns to a pair of columns of type TIME:
SELECT
MAKETIME(start_hour + IF(start_hour<9, 12, 0), start_minute, 0) AS start_time,
MAKETIME(finish_hour + IF(start_hour<9, 12, 0), finish_minute, 0) AS finish_time
FROM (
SELECT
SUBSTRING_INDEX(SUBSTRING_INDEX(ohtime1, ' - ', 1), ':', 1) AS start_hour,
SUBSTRING_INDEX(SUBSTRING_INDEX(ohtime1, ' - ', 1), ':', -1) AS start_minute,
SUBSTRING_INDEX(SUBSTRING_INDEX(ohtime1, ' - ', -1), ':', 1) AS finish_hour,
SUBSTRING_INDEX(SUBSTRING_INDEX(ohtime1, ' - ', -1), ':', -1) AS finish_minute
FROM MyOpenHouseTable) t
ORDER BY start_time;