I am currently editing a (very messy!) custom AJAX filter component in order for a user to be able to search for times of events by time of day (Morning, Afternoon, Evening). The system currently searches records by hour of day (12, 08, etc) and uses the hour submitted in the filtering to perform a LIKE search on the database to return results.
I have grouped hours into time-of-day arrays as follows in the model for the filtering:
if($time == 'morning') {
$times = array('07', '08', '09', '10', '11');
}
if($time == 'afternoon') {
$times = array('12', '13', '14', '15', '16');
}
if($time == 'evening') {
$times = array('17', '18', '19', '20', '21');
}
The current query being used is as follows:
if ($time>0){
$query->where('a.startTime LIKE "%'.$time.'%"');
}
I need to change the query for it to be able to seach the database to check whether the value in the database 'time' field is in my $times array and also perform a like as it's only the first two characters of the string I need to be matching. This is because values in the database could be varying (15.30, 15.45, etc) but only need to match the hour (15).
I have tried looping through the items in my array creating a 'like' and 'or' query but with no success. Does anybody have any ideas?
Many Thanks
$per=array('morning'=>array(7, 8, 9, 10, 11),
'afternoon'=>array(12, 13, 14, 15, 16),
'evening'=>array(17, 18, 19, 20, 21));
$query->where('HOUR(a.startTime) IN ('.implode(',',$per[$need].')');
or
$per=array('morning'=>array('min'=>7, 'max'=>11),
'afternoon'=>array('min'=>12,'max'=> 16),
'evening'=>array('min'=>17,'max'=> 21));
$query->where('HOUR(a.startTime) >= '.$per[$need]['min'].' and HOUR(a.startTime)<='.$per[$need]['max']);
Maybe something like this
$time=15.30;//for example
if ($time>0){
$time=preg_replace('~\.(.*?$)~','',$time);//time is now 15
$morning = array('07', '08', '09', '10', '11');
$afternoon = array('12', '13', '14', '15', '16');
$evening = array('17', '18', '19', '20', '21');
if(in_array($time,$morning)){
echo 'morning';
}else if(in_array($time,$afternoon)){
echo 'afternoon';
}else if(in_array($time,$evening)){
echo 'evening';
}
$query->where('a.startTime LIKE "%'.$time.'%"');
}
Related
I have a rating system on my Wordpress that came with the theme. The maximum rating possible is 10, so I wanted to edit this and make a 100 possible rating.
So I edited this part:
public static function max_rating( $listing_id = null ) {
$default = 100;
So now it understands that the max possible rating is 100.
But under the rating array, there were these lines:
$rating_options = array(
'1' => 1,
'2' => 2,
'3' => 3,
'4' => 4,
'5' => 5,
'6' => 6,
'7' => 7,
'8' => 8,
'9' => 9,
'10' => 10,
Which understand that the maximum possible rating is 10. Now I want to make a maximum rating of 100, but adding '11' => 11, '12' => 12, '13' => 13 etc takes a lot of time and it consumes a lot of space in my file. Is there a possiblity to shorten this or do I really have to enter every rating up to 100?
The accepted answer points you in the right direction.
Additional I would advice using array_combine like so:
$range = range(1,100);
$rating_options = array_combine($range, $range);
// array(1=>1, 2=>2, ...)
This way, your keys will be the same as the values.
you can use PHP's range function:
$ratings = range(0, 100);
reference: https://secure.php.net/manual/en/function.range.php
I currently am working with a database that has a month column and a year column.. Both are of type text. Month is stored as 'January' and year is stored as you would expect, '2016'..
Any recommendations for concatenating these and converting them to a date type?
You can use a query like this. you only must change the strings to your fieldnames:
sample
select STR_TO_DATE(concat('2016',' ','April','1'), '%Y %M %D');
result
2016-04-01
$months = [
'january' => 1,
'february' => 2,
'march' => 3,
'april' => 4,
'may' => 5,
'june' => 6,
'july' => 7,
'august' => 8,
'september' => 9,
'october' =>10,
'november' =>11,
'december' =>12
];
$year = 2016;
$month_text = 'january';
$day = 1;
if($months[strtolower($month_text)]<10){
$month = '0'.$months[strtolower($month_text)];
}else{
$month = $months[strtolower($month_text)];
}
if($day<10){
$day = '0'.$day;
}else{
$day = $day;
}
echo $year.'-'.$month.'-'.$day;
create a new feld in db with type date and insert it into the db. maybe wrap this in a function and put it in a while loop..?
This works for me:
select convert(date,(concat('January',' ','2016')))
Using php, I am looking to find a set of unique combinations of a specified length while making sure that no two identical values are present in more than one combination. For example, if I want to find all unique combinations of 3 values (fallback to combinations of 2 values if 3 are not possible) with this array:
$array = array(
array('1', '2'),
array('3', '4'),
array('5', '6'),
);
One possible set of combinations is 123, 456, 14, 15, 16, 24, 25, 26, 34, 35, 36
Note that each number is always combined once and only once with a different number. No duplicate number pairs show up in any combination. Just for clarity's sake, even though 123 and 135 would be unique combinations, only one of these would be returned since the pair 13 occurs in both. The main criteria is that all numbers are eventually grouped with each other number, but only once.
In the final product, the number of arrays and number of values will be notably larger as in:
$array = array(
array('1', '2', '3', '4', '5', '6', '7', '8'),
array('9', '10', '11', '12', '13', '14', '15', '16'),
array('17', '18', '19', '20', '21', '22', '23', '24'),
array('25', '26', '27', '28', '29', '30', '31')
);
Any help/code to accomplish this would be most appreciated.
UPDATE:
I've taken the brute force approach. First off, I'm using the pear package Math_Combinatorics to create the combinations, starting with a specified maximum size grouping and working my way down to pairs. This way I can get all possible combinations when iterating through to strip out any duplicate clusters within the groups. This code works but is extremely memory intensive. Generating all combinations for an array of 32 values in groups of 6 uses an excess of 1.5G of memory. Is there a better algorithm or approach that will let me use bigger arrays without running out of memory? Here the current state of the code:
require_once 'Combinatorics.php';
$combinatorics = new Math_Combinatorics;
$array = range(1,20,1);
$maxgroup = (6);
$combinations = $combinatorics->combinations($array, $maxgroup);
for($c=$maxgroup-1;$c>1;$c--)
{
$comb = $combinatorics->combinations($array, $c);
$combinations = array_merge($combinations, $comb);
$comb = null;
}
for($j=0;$j<sizeof($combinations);$j++)
{
for($i=sizeof($combinations)-1;$i>=$j+1;$i--)
{
$diff = array_intersect($combinations[$j], $combinations[$i]);
if(count($diff)>1)
{
unset($combinations[$i]);
}
}
$combinations = array_values($combinations);
}
print_r($combinations);
Since the structure is just obscuring the numbers which are available, you should first unfold the nested arrays. I'll be kind and do that for you:
$numbers = []
foreach ($arrar as $subarr) {
foreach ($subarr as $num) {
$numbers[] = $num;
}
}
I'm assuming there aren't any duplicate numbers in the input.
Next, you want to perform your algorithm for finding the unique combinations. With array this small, even a recursive solution will work. You don't have to try all the combinatorially-many combinations.
So I am trying to build out some nice stats displays for my app. I can do this because I keep hit stats in a table. It simply tracks the hits plus some other nice data and the time it occurs. I can query the db to show me how many hits occurred on a particular day or on each day for the past x days as in the code below. However the code below only returns dates for which there is data. I would like to show the last 30 days of hits regardless of whether a day has a hit or not. Thoughts?
SELECT DATE(time) AS theday, COUNT( * ) AS thecount
FROM stats
WHERE time <= curdate( )
AND time >= DATE_SUB( curdate(), INTERVAL 30 DAY )
GROUP BY theday ORDER BY time DESC
Produces
theday thecount
2011-11-22 5
2011-11-21 9
2011-11-18 10
2011-11-16 1
2011-11-11 2
2011-11-10 15
2011-11-09 2
2011-10-26 1
2011-10-24 6
As you can see it skips dates with no results. I understand why this is, as there are no rows with those dates in the db. I am wondering how I would produce a query that works almost like the above but has all the dates for said interval. IE: the last 30 days.
You have 3 options:
try to iterate the dates in the application logic (php)
generate a (temporary) table filled with the dates you need and left join with it
use mysql stored procedure solution like in this answer
Example for app logic implementation:
<?php
date_default_timezone_set('Europe/Paris');
$startdate = strtotime('2011-11-01 00:00:01');
$days = 60;
$found_data = array( // this is generated by 1 mysql query
array('date_field' => '2011-11-02', 'count' => 5),
array('date_field' => '2011-11-03', 'count' => 1),
array('date_field' => '2011-11-04', 'count' => 6),
array('date_field' => '2011-11-08', 'count' => 9),
array('date_field' => '2011-11-09', 'count' => 3),
array('date_field' => '2011-11-10', 'count' => 5),
array('date_field' => '2011-11-12', 'count' => 1),
array('date_field' => '2011-11-15', 'count' => 1),
array('date_field' => '2011-11-18', 'count' => 4),
array('date_field' => '2011-11-21', 'count' => 9),
array('date_field' => '2011-11-23', 'count' => 1),
array('date_field' => '2011-11-28', 'count' => 8),
array('date_field' => '2011-11-30', 'count' => 6),
);
foreach ($found_data as $counts) { // we convert the results to a usable form, you can do this in the query, too
$count_info[$counts['date_field']] = $counts['count'];
}
for ($i = 0; $i <= $days; $i++) {
$date = date('Y-m-d', $startdate+$i*60*60*24);
printf("%s\t%s\n", $date, array_key_exists($date, $count_info) ? $count_info[$date] : 0);
}
?>
echo date("m", strtotime("january"));
Returns 01 as expected
echo date("m", strtotime("february"));
But this returns 03
Anyone else encountered this problem?
PHP Version 5.1.6
Today is the 29th. There is no 29th in February this year and because you're not specifying a day in February, it's using "today". The strtotime function uses relative dates so the 29th of February is basically the 1st March this year.
To solve your problem:
echo date("m", strtotime("February 1"));
As strtotime() only handles English date formats, you should maybe try using this function that I just made for you. With this you can handle month names in other languages too.
Don't know if this is essential to your application, but now you have it.
function getMonth($month, $leadingZero = true) {
$month = strtolower(trim($month)); // Normalize
$months = array('january' => '1',
'february' => '2',
'march' => '3',
'april' => '4',
'may' => '5',
'june' => '6',
'july' => '7',
'august' => '8',
'september' => '9',
'october' => '10',
'november' => '11',
'december' => '12',
'dezember' => '12', // German abrevation
'marts' => '3', // Danish abrevation for March
);
if(isset($months[$month])) {
return $leadingZero ? substr('0' . $months[$month], -2) : $months[$month];
} else {
return false;
}
}