Я пытаюсь организовать вывод данных DATA следующим образом: сегодня, вчера и все, что было до вчерашнего дня, с соответствующим полным DateTime минус часовое время, конечно. Для лучшего понимания взгляните на снимок экрана ниже:
Я написал этот код:
try{ $db = new PDO("mysql:host=" .$hostname. ";dbname=" .$database. "", "" .$user. "", "" .$pass. ""); $db->setAttribute(PDO::ATTR_PERSISTENT, true); $db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); $notifications = $db->prepare("SELECT * FROM reports ORDER BY timestamp DESC"); $notifications->execute(); $result = (object)$notifications->fetchAll(PDO::FETCH_OBJ); echo "<pre>"; print_r($result); echo "</pre>"; } catch(PDOException $e) { echo $e->getMessage(); }
Я пытаюсь выяснить способ разделить вещи, например, «Сегодня», «Вчера», «День до вчерашнего дня» и т. Д. До тех пор, пока считается нормальным, например, целый месяц.
* Как бы я правильно структурировал это с помощью подготовленного заявления PDO? *
[Today] => stdClass Object ( [id] => 1 [timestamp] => 2015-04-09 13:20:05 [seen] => 0 ) [Yesterday] => stdClass Object ( [id] => 2 [timestamp] => 2015-04-08 15:30:50 [seen] => 0 )
Ясно: я хочу напечатать все с отметкой времени СЕГОДНЯ. Далее, все с меткой времени YESTERDAYS. И так далее.
SQL:
// Today AND DATE(from_unixtime(comment_date)) = CURRENT_DATE // Yesterday AND DATE(from_unixtime(comment_date)) = DATE_SUB(CURRENT_DATE,INTERVAL 1 DAY) // This week AND YEARWEEK(from_unixtime(comment_date), 1) = YEARWEEK(CURRENT_DATE, 1) // This month AND YEAR(from_unixtime(comment_date)) = YEAR(CURRENT_DATE) AND MONTH(from_unixtime(comment_date)) = MONTH(CURRENT_DATE)
Вот пример того, как я буду справляться с этим. Я бы не изменил ваш запрос – все в порядке. Предполагая, что вы хотите показать все в базе данных, отсортированную с последней по самую раннюю. Пусть PHP обрабатывает тяжелый подъем. Я намеренно разбил некоторые вещи на несколько строк, вместо того, чтобы вставлять функции, чтобы их было легче читать. Конденсируйте, как вы считаете нужным.
Я не утверждаю, что это лучший способ сделать это. Только то, что я использую.
//MOCK UP SOME DISPLAY DATA - YOU WOULD USE YOUR QUERY RESULT INSTEAD $rows = array(); $rows[] = date('Ymd H:i:s'); $rows[] = date('Ymd H:i:s'); $rows[] = date('Ymd H:i:s'); $rows[] = date('Ymd H:i:s', mktime(0, 0, 0, date('n'), date('j') - 1, date('Y'))); $rows[] = date('Ymd H:i:s', mktime(0, 0, 0, 12, 24, 2014)); $rows[] = date('Ymd H:i:s', mktime(0, 0, 0, 12, 25, 2014)); $rows[] = date('Ymd H:i:s', mktime(0, 0, 0, 12, 26, 2014)); $rows[] = date('Ymd H:i:s', mktime(0, 0, 0, 3, 2, 2001)); //CREATE AN ARRAY OF THE REPLACEMENTS YOU WANT $aArray = array(); $aArray[date('Ym-d')] = 'Today'; $aArray[date('Ym-d', mktime(0, 0, 0, date('n'), date('j') - 1, date('Y')))] = 'Yesterday'; $aArray[date('Ym-d', mktime(0, 0, 0, date('n'), date('j') - 2, date('Y')))] = 'Day before Yesterday'; $aArray['2014-12-25'] = 'Christmas 2014'; //INITIALIZE SOME VARIABLES $cLastHeader = ''; $cCurrHeader = ''; //THIS WOULD BE YOUR QUERY RESULTS LOOP foreach ($rows AS $nNull => $cDate) { $cLookup = substr($cDate, 0, 10); //TRIM OUT THE TIME FROM CURRENT RECORD //IS DATE IN ARRAY? IF NOT, FORMAT if (isset($aArray[$cLookup])) { $cCurrHeader = $aArray[$cLookup]; } else { $cCurrHeader = $cLookup; //WOULD SHOW 'YYYY-MM-DD' $cCurrHeader = date('F Y', strtotime($cLookup)); //WOULD SHOW 'MONTH YYYY' } //HAS HEADER CHANGED? IF SO PRINT if ($cCurrHeader != $cLastHeader) { $cLastHeader = $cCurrHeader; print($cCurrHeader . "\n"); } //PRINT RECORD print("\t" . $cDate . "\n"); }
Результатом этого является:
Today 2015-05-28 18:40:35 2015-05-28 18:40:35 2015-05-28 18:40:35 Yesterday 2015-05-27 00:00:00 December 2014 2014-12-24 00:00:00 Christmas 2014 2014-12-25 00:00:00 December 2014 2014-12-26 00:00:00 March 2001 2001-03-02 00:00:00
SELECT IF( DATEDIFF( NOW( ) , `timestamp` ) =0, "Today", if( DATEDIFF( NOW( ) , `timestamp` ) =1, "Yesterday", DATE_FORMAT( `timestamp`, '%M %d' ) ) ) AS day, id,timestamp,seen FROM reports ORDER BY timestamp DESC
Попытка решить вашу проблему с помощью запроса, проверьте, полезен ли он для вас.
Согласно данному снимку экрана, после сегодняшнего и вчера этого запроса вы получите месяц и дату.
Есть несколько способов приблизиться к этому. Во-первых, вы можете создавать отдельные вызовы и объединять данные на стороне php.
Во-вторых, вы можете использовать подзапрос, но я не рекомендую подзапросы, поскольку они являются довольно сложными и могут поднять много ресурсов.
В-третьих, вы можете использовать союзы. Вы создаете 3 отдельных запроса для выбора на основе разных сценариев, а затем используйте union. Таким образом, вы получите все результаты в один звонок.
SELECT *, 'today' as day FROM table WHERE DATE(from_unixtime(comment_date)) = CURRENT_DATE UNION SELECT *, 'yesterday' as day FROM table WHERE MONTH(from_unix_MONTH(CURRENT_DATE)) = MONTH(CURRENT_DATE)
Таким образом, в принципе, союзы представляют собой разные команды выбора, объединенные в один запрос. Вы можете объединить столько операторов выбора, сколько хотите. ОДНАКО, обратите внимание, что вы хотите, чтобы все операторы select вернули SAME COLUMNS или это приведет к ошибке. Вы также можете прочитать о UNION ALL. Существуют некоторые незначительные различия между UNION и UNION ALL, но не очень.
Вы также должны изменить свой запрос MySQL, чтобы получить разницу дат.
SELECT *,DATEDIFF(NOW(),`timestamp`) as `dateDifference` FROM `reports` ORDER BY `dateDifference`
пример приведен здесь http://sqlfiddle.com/#!9/ecad0/6
Затем запустите оператор if или случай переключения на dateDifference, чтобы упорядочить ваши результаты так, как вы хотите. Пример подходящего оператора switch-case приведен ниже
switch (true) { case ($dateDifference===0): echo "Today's reports!"; break; case ($dateDifference===1): echo "Yesterday's reports!"; break; case ($dateDifference>1): echo "Even older reports!"; break; case ($dateDifference<0): echo "An unexpected error occurred. Please contact your system administrator!"; }
Как получить все строки и проверить дату в PHP, затем сгруппировать результаты, которые существуют в тот же временной фрейм в отдельном массиве, как показано ниже:
$notifications = $db->prepare("SELECT * FROM reports ORDER BY timestamp DESC"); $notifications->execute(); $rows = $notifications->fetchAll(PDO::FETCH_ASSOC); foreach($rows as $row ){ if ( date('Ymd') == date('Ymd', strtotime($row['timestamp'])) ){ $today_rows[] = $row; } else if (date('Ymd', strtotime('yesterday')) == date('Ymd', strtotime($row['timestamp'])) ){ $yesterday_rows[] = $row; } else if () ... etc }
Теперь вы можете использовать $ today_row, $terday_rows … и т. Д. В своем представлении и отображать их по своему усмотрению.