Посетитель
Покинул форум
Сообщений всего: 425
Дата рег-ции: Февр. 2015
Помог: 14 раз(а)
|
при добавлении события можно выбрать периодичность с которой оно будет повторяться(то есть, каждый любой/любые дни недели), выбрать его месторасположение среди других событий, и когда оно начинается и заканчивается.
имеется две таблицы:
1. id, name, period(здесь указывается как будет повторяться событие: каждый день - every_day, в определенные дни недели - week_days), sort(если 0, то это week_days), start, end
2. event_id, Monday,Tuesday,Wednesday, Thursday, Friday, Saturday, Sunday в этой таблице хранится сортировка по дням недели, если 0, то в этом событии, этот день не повторяется( не участвует в сортировке),
сортировка храниться в таком виде - sort(из первой таблицы).сортировка по дням недели( пример 1.001,2.001,2.002)
и так
После ввода даты начала и конца, и периодичности, происходит запрос в базу данных для выбора сортировки:
если периодичность указана как every_day, то запрос выбирает все события, которые соответствуют диапазону дат(начало - конец)
CODE ( SQL):
скопировать код в буфер обмена
SELECT `sort`,`name` FROM `event` WHERE `period`="every_day" AND ((`start`<=? AND `end`>=?) OR (`end`>=? AND `start`<=?)) OR (`start`>=? AND `end`<=?)) ORDER BY sort $array = array('ssssss',$day_end, $day_end, $day_start, $day_start, $day_start, $day_end);
и вывожу списком для определения месторасположения добавляемого события($sort), после этого идет добавление события в базу:
с начало происходит корректировка сортировки:
CODE ( SQL):
скопировать код в буфер обмена
UPDATE `event` SET `sort` = `sort` + 1 //добавляем 1 ко всем событиям WHERE `period`="every_day" AND `user_id`=? AND ((`start`<=? AND `end`>=?) OR (`end`>=? AND `start`<=?) OR (`start`>=? AND `end`<=?)) AND `sort`>= ?; //которые больше или равны выбранного месторасположения $array = array('ssssssi',$day_end,$day_end,$day_start,$day_start,$day_start,$day_end,$sort)
потом добавляется само событие
CODE ( SQL):
скопировать код в буфер обмена
INSERT INTO event (name,sort,period,start,end) VALUES (?,?,?,?,?) $array = array('sisss', $name,$sort,$period,$data_start,$data_end);
если периодичность указана week_days, то пользователь может выбрать любые дни недели для повтора, и что бы пользователь мог выбрать месторасположения нового события, запрос должен выбирать события, которые:
1. соответствуют диапазону дат(начало - конец)
2. повторяются каждый день или по тем же дням, что и добавляемое событие
3. если между начальной и конечной датой(добавляемого события) разница меньше 7ми дней, то исключить те дни недели, которые не совпадают с выбранным диапазоном дат
PHP:
скопировать код в буфер обмена
// $days дни в которые должно повторяться событие (например array(0,1,0,1,1,0,0)) то есть массив состоит из 7 элементов, 0 - это Monday, 1- это Tuesday и т.д. foreach ($days as $key => $value) { if($value==1){ $day = $this->eng_week_days[$key]; // здесь день переводим в английское название $query = 'SELECT e.id, e.name, IF(e.sort,e.sort,d.'.$day.') AS new_sort, e.start, e.end FROM event e ' // IF(e.sort,e.sort,d.'.$day.') если событие повторяется every_day, то sort берется из e.sort, если weeks_days то сорт берется из d.название дня недели . 'LEFT OUTER JOIN event_days_of_week d ON d.event_id=e.id ' . 'WHERE e.user_id=? AND ((e.start<=? AND e.end>=?) OR (e.end>=? AND e.start<=?) OR (e.start>=? AND e.end<=?)) ' // выбирается совпадающий диапазон дат с такой логикой e.start<=day_start<=e.end или e.start<=day_end<=e.end или e.start<=day_start<=day_end<=e.end . 'AND (d.'.$day.' != 0 OR e.period = "every_day") ' // дни которые не участвуют в сортировке . 'ORDER BY new_sort '; $array = array('issssss',parent ::$user_id, $day_end, $day_end, $day_start, $day_start, $day_start, $day_end); $result[$day] = $this->get_data($query, 'assoc', $array); // запрос к базе $result[$day] = $this->days_match($result[$day], $day_start, $day_end, $day); // исключить те дни недели, которые не совпадают с выбранным диапазоном дат //например есть два диапазона дат 5.01 - 10.01(база) и 10.01 - 15.10(новое) - у них совпал один день, но из базы данных выведутся все дни, которые будут повторяться для этого события то есть , если 10 .01 - это допустим четверг , и только он совпал , но из базы по моему запросу выведутся все дни которые есть у данного события , это с помощью mysql не придумал как сделать , сделал в php } } $_SESSION['new_event']['incorect_week_day'] = $this->incorect_week_day; // дни недели и индексы событий которые не подходят по диапазону дат private function days_match($array_db,$start_post,$end_post,$week_day){ foreach($array_db as $key=>$res_value){ if($start_db>$start_post AND $end_db>$end_post){ //в диапазон входит только $end_post (start_db < end_post < end_db) $days_enter = $end_post - $start_db; if(!$this->day_coincidence($days_enter, $start_db, $week_day, $res_value['id'])){ //проверяем или совпал день с диапазоном совпадения дат, если нет то удаляем событие из массива } continue; } if($start_db<$start_post AND $end_db<$end_post){ //в диапазон входит только $start_post (start_db < start_post < end_db) $days_enter = $end_db - $start_post; if(!$this->day_coincidence($days_enter, $start_post, $week_day, $res_value['id'])){ } continue; } if($start_db>$start_post AND $end_db<$end_post){ //в диапазон входит $start_db и $end_db ($start_post < $start_db $end_db < end_post) $days_enter = $end_db - $start_db; if(!$this->day_coincidence($days_enter, $start_db, $week_day, $res_value['id'])){ } continue; } $array_db[$key]['days_enter'] = 'all'; } return $array_db; } private function day_coincidence($days_enter, $day_start, $week_day, $event_id){ $days_enter = (int)($days_enter/60/60/24 + 1); if($days_enter<=7){ $one_day = 60*60*24; $add_days = 0; for($a=1;$a<=$days_enter;$a++){ $db_day[] = date('l',$day_start+$add_days); $add_days += $one_day; } return TRUE; } $this->incorect_week_day[$week_day][] = $event_id; return NULL; } return TRUE; }
выводим список сортировки, пользователь выбирает месторасположение, отсылает нам запрос
PHP:
скопировать код в буфер обмена
$incorect_week_day = $_SESSION['new_event']['incorect_week_day']; //в этот массиве содержатся индекс события и дни недели, которые не вошли в диапазон для сорта ($incorect_week_day[week_day] = array(event_id)) $query_day_sort_p1 = 'INSERT INTO event_days_of_week (event_id,user_id'; // $query_day_sort_p2 = ' VALUES (?,?'; //создаем запрос mysql для вставки в таблицу сортировки по дням недели foreach($_POST['sort_after_event'] as $eng_day_week => $sort){ if(!in_array($eng_day_week, $this->eng_week_days)){ // $this->set_error('add_entry_incorect_period'); // return NULL; //проверяем валидность присланных данных, } $sort+= 0.001; //вставляем наше событие после пришедшего с формы сорта, добавляя к нему 0.001 $to_query_update_sort = ''; //переменная для добавления в запрос обновления сортировки по дням недели(event_days_of_week) if(is_array($incorect_week_day[$eng_day_week])){ //что бы не обновлялась сортировка событий, которые не входят в диапазон дат foreach($incorect_week_day[$eng_day_week] as $event_id){ $to_query_update_sort .= ' AND event_id != '.$event_id; } } $query_day_sort_p1 .= ','.$eng_day_week; $query_day_sort_p2 .= ','.$sort; $this->create_sort($sort,$eng_day_week,$to_query_update_sort); } $query_day_sort = $query_day_sort_p1.')'.$query_day_sort_p2.')'; $this->insert_new_event(0,$query_day_sort); return TRUE; function create_sort($sort,$day=NULL,$to_querty_sort='',$operation='+'){ // $operation служит для того что бы, если не вышла вставка события, можно было откатить сортировку назад ($operation = '-') // сортировка по дням недели осуществляется по дробным числам в диапазоне 0.001 - 1 // запрос обновляет все записи сортировки(+0.001), где совпадает диапазон дат, где есть сортировка(сортировка есть, если в таблице столбик с днем недели не равен 0), // где сортировка больше или равно $sort и меньше округленной в большую сторону $sort // $query = 'UPDATE `event_days_of_week` SET `'.$day.'` = `'.$day.'` '.$operation.' 0.001 ' . 'WHERE event_id IN (SELECT id FROM event WHERE user_id = ? AND (`start`<=? AND `end`>=?) OR (`end`>=? AND `start`<=?) OR (`start`>=? AND `end`<=?)) ' . 'AND `'.$day.'`!=0 AND `'.$day.'`>=? AND `'.$day.'`< ? '.$to_querty_sort; $sort_max = ceil($sort); // округлил в большую сторону, для того, что бы обновить сортировку только в диапазоне 1, а не все! $array = array('issssssdi', parent ::$user_id, $day_end,$day_end,$day_start,$day_start,$day_start,$day_end,$sort,$sort_max); $result = $this->insert_db($query,$array); return TRUE; } function insert_new_event($sort = 1, $days_query=NULL){ $name = $_SESSION['new_event']['name']; $text = $_SESSION['new_event']['text']; $time = $_SESSION['new_event']['time']; $importance = $_SESSION['new_event']['importance']; $period = $_SESSION['new_event']['period']; $query = 'INSERT INTO event (user_id,name,text,time,sort,importance,period,start,end) ' . 'VALUES (?,?,?,?,?,?,?,?,?)'; $array = array('issiissss', parent ::$user_id,$name,$text,$time,$sort,$importance,$period,$this->data_start,$this->data_end); $result = $this->insert_db($query, $array); if(!$result){ $this->create_sort($sort,NULL,'-'); // откат сортировки }else{ foreach($_POST['sort_after_event'] as $day=>$sort_val){ // $sort_val+= 0.001; // $this->create_sort($sort_val,$day,'-'); // } // откат сортировки } $this->set_error('add_entry_mysql_error'); return NULL; } if($this->sort_type == 'days'){ $days_array = array('ii',$this->insert_last_id, parent ::$user_id); $days_result = $this->insert_db($days_query, $days_array); if(!$days_result){ foreach($_POST['sort_after_event'] as $day=>$sort_val){ // $sort_val+= 0.001; // $this->create_sort($sort_val,$day,'-'); // } // откат сортировки $query = 'DELETE FROM event WHERE id='.$this->insert_last_id; // удаляем добавленное событие return NULL; } } unset($_SESSION['new_event']); $_SESSION['new_event_add'] = 'TRUE'; header('location:'.DOMEN .$_SERVER['REQUEST_URI']); }
как лучше организовать логику таблиц, и запросов к ней в данной ситуации??
|