2016-08-11 10 views
1

Я стек, пытающийся сгруппировать мои объекты по дате. каждый объект имеет следующие столбцы: id, device, start, stop, ipaddress.(Symfony 3.1) Объекты группы PHP Doctrine by datetime

Я хочу иметь возможность получать объекты в пределах диапазона дат и группировать их по дате (дню), следующим за количеством часов в каждый день.

Это то, что я до сих пор

public function findAllGroupedByDate($from = null, $to = null) 
{ 
    $from = isset($from) && !is_null($from) ? $from : date('Y-m-d', time()); 
    $to = isset($to) && !is_null($to) ? $to : date('Y-m-d', time()); 

    $from = new \DateTime("-3 days"); 
    $to = new \DateTime("1 days"); 

    $from = date("Y-m-d", $from->getTimestamp()); 
    $to = date("Y-m-d", $to->getTimestamp()); 

    $q = $this->getEntityManager()->createQueryBuilder() 
     ->select("timelog") 
     ->from("AppBundle:Timelog", "timelog") 
     ->where("timelog.start BETWEEN :from AND :to") 
     ->setParameter("from", $from) 
     ->setParameter("to", $to) 
     ->orderBy("timelog.stop") 
     ->getQuery(); 
    return $q->getResult(); 
} 

public function findFromToday() 
{ 
    $q = $this->createQueryBuilder('t') 
      ->select('t.id', 't.start', 't.stop', 't.stop') 
      ->where("t.start >= :today") 
      ->setParameter("today", date('Y-m-d', time())) 
      ->groupBy("t.id", "t.stop") 
      ->orderBy("t.start", "asc") 
      ->getQuery(); 

    return $q->getResult(); 
} 

Это код для моего репозитория класса.

и код от моего контроллера выглядит следующим образом:

$timelogsRepo = $this->getDoctrine()->getRepository('AppBundle:Timelog'); 

// Grab logs from today 
$timelogsCollection = $timelogsRepo->findFromToday(); 
$tmpLogs = $timelogsRepo->findAllGroupedByDate(); 

// THIS SECTION IS FOR CALCULATING HOURS & MINUTES 
    $minutes = 0; 
    $hours = 0; 
    foreach($timelogsCollection as $log) 
    { 
     $time1 = $log['start']; 
     $time2 = $log['stop']; 
     $interval = date_diff($time1, $time2); 

     $hours += $interval->h; 
     $minutes += $interval->i; 

    } 


    $minutes = $minutes >59 ? $minutes/60 : $minutes; 


    return $this->render(':Timelog:index.html.twig', [ 
     'timelogs' => $logsOut, 
     'hours' => $hours, 
     'minutes' => $minutes 
    ]); 

До сих пор я был в состоянии вычислить общее время, затраченное на данный день (только один день). Теперь я хотел бы получить все сущности, группировать их по той же дате (день) и возвращать данные с интервалом.

Пример DB таблица выглядит следующим образом [идентификатор, device_id, старт, стоп, IPAddress]

1 1 2016-08-09 09:00:06 2016-08-09 12:00:06 127.0.0.1 
2 1 2016-08-08 07:00:00 2016-08-08 13:00:00 127.0.0.1 
3 1 2016-08-08 13:10:00 2016-08-08 15:05:00 127.0.0.1 

Так что в этом случае мой результат будет что-то вроде:

[ 
    0 => ["date" => "2016-08-09", "hours" => 9.00, "ipaddress" =>  "127.0.0.1"], 
    1 => ["date" => "2016-08-09", "hours" => 1.45, "ipaddress" => "127.0.0.1"] 
] 

интервал зависит от start и stop оба типа типа DateTime

Я пробовал использовать доктрины-расширения: oro/doctrine-extensions, но теперь я получаю ошибку исключения:

[2/2] QueryException: [Syntax Error] line 0, col 50: Error: Expected Unit is not valid for TIMESTAMPDIFF function. Supported units are: "MICROSECOND, SECOND, MINUTE, HOUR, DAY, WEEK, MONTH, QUARTER, YEAR", got 'stop' 

Мой метод хранилища выглядит следующим образом:

public function findByToday() 
{ 
    $fields = array(
     'DATE(stop) as stop', 
     'TIME(SUM(TIMESTAMPDIFF(stop, start))) AS tdiff', 
     'device_id', 
     'ipaddress' 
    ); 

    $q = $this->createQueryBuilder('t') 
     ->select($fields) 
     ->where('DATE(stop) = :today') 
     ->setParameter('today', date('Y-m-d', time())) 
     ->groupBy('device_id') 
     ->getQuery(); 

    return $q->getResult(); 

} 

мой DB стол:

id device_id start stop ipaddress 
5 1 2016-08-09 09:00:06 2016-08-09 12:00:06 127.0.0.1 
6 1 2016-08-08 07:00:00 2016-08-08 13:00:00 127.0.0.1 
7 1 2016-08-08 13:10:00 2016-08-08 15:05:00 127.0.0.1 

BTW я использую Symfony 3, это может быть проблема?

ответ

0

Основываясь на вашей таблице выше (если я правильно понял), я попытался бы получить данные непосредственно с помощью MYSQL, а затем проделать свой путь к Доктрине.

Если у вас есть в таблице ниже:

CREATE TABLE `testdevices` (
    `id` INT(11) NOT NULL AUTO_INCREMENT, 
    `device` INT(11) NULL DEFAULT NULL, 
    `dstart` DATETIME NULL DEFAULT NULL, 
    `dend` DATETIME NULL DEFAULT NULL, 
    `ip` TINYTEXT NULL, 
    PRIMARY KEY (`id`) 
); 

И заполняется ниже тестовых данных (я создал два устройства второй было удобно активным для точных 3-х часов на сегодняшнюю дату):

mysql> select * from testdevices; 
+----+--------+---------------------+---------------------+-----------+ 
| id | device | dstart    | dend    | ip  | 
+----+--------+---------------------+---------------------+-----------+ 
| 1 |  1 | 2016-08-09 09:00:06 | 2016-08-09 12:00:06 | 127.0.0.1 | 
| 2 |  1 | 2016-08-08 07:00:00 | 2016-08-08 13:00:00 | 127.0.0.1 | 
| 3 |  1 | 2016-08-08 13:10:00 | 2016-08-11 22:14:46 | 127.0.0.1 | 
| 4 |  2 | 2016-08-11 13:00:00 | 2016-08-11 14:00:00 | 127.0.0.1 | 
| 5 |  2 | 2016-08-11 15:00:00 | 2016-08-11 16:00:00 | 127.0.0.1 | 
| 6 |  2 | 2016-08-11 17:00:00 | 2016-08-11 18:00:00 | 127.0.0.1 | 
+----+--------+---------------------+---------------------+-----------+ 
6 rows in set (0.00 sec) 

После MYSQL запрос будет, то я считаю, вывод данных вы хотите:

SELECT DATE(dend) as dend, TIME(SUM(TIMEDIFF(dend, dstart))) AS tdiff, device, ip 
FROM testdevices WHERE DATE(dend) = '2016-08-11' 
GROUP BY device ; 

И результат будет выглядеть так:

+------------+----------+--------+-----------+ 
| dend  | tdiff | device | ip  | 
+------------+----------+--------+-----------+ 
| 2016-08-11 | 81:04:46 |  1 | 127.0.0.1 | 
| 2016-08-11 | 03:00:00 |  2 | 127.0.0.1 | 
+------------+----------+--------+-----------+ 
2 rows in set (0.01 sec) 

Обратите внимание, что второе время устройства верное. Теперь остается вопрос, как это сделать в Доктрине.Насколько я знаю, функция TIMEDIFF не является частью доктрины еще, так что я хотел бы предложить 2 различные подходы:

  1. Напишите свою собственную функцию, как в http://www.doctrine-project.org/2010/03/29/doctrine2-custom-dql-udfs.html#date-diff (Существует пример DATEDIFF в этой связи так легко регулируемая), или
  2. Использование https://packagist.org/packages/oro/doctrine-extensions

Ваша последняя функция репозитарий в Doctrine/Symfony2 с оро/доктриной-расширений, установленных будет выглядеть примерно так:

$fields = array(
      'DATE(dend) as dend', 
      'SUM(TIMESTAMPDIFF(SECOND, dend, dstart)) AS tdiff', 
      'device', 
      'ip' 
     ); 

public function findFromToday() 
{ 
    $q = $this->createQueryBuilder('t') 
      ->select($fields) 
      ->where('DATE(dend) = :today') 
      ->setParameter('today', date('Y-m-d', time())) 
      ->groupBy('device') 
      ->getQuery(); 

    return $q->getResult(); 

Я написал эту функцию, не протестировав ее вообще и с верхней части головы. Вероятно, вы обнаружите, что он терпит неудачу. Это даст разницу во времени в секундах, так как TIMESTAMPDIFF требует указать единицы измерения. Установка оро/Доктрина-расширения с

composer require oro/doctrine-extensions 
+0

Томислав спасибо за ваш ответ, я собираюсь попробовать его, даст вам знать, как это пошло –

+0

Привет я попробовал это, но до сих пор не работает, теперь я получение ошибки обхода: [2/2] QueryException: [Синтаксическая ошибка] строка 0, col 50: Ошибка: ожидаемое устройство недействительно для функции TIMESTAMPDIFF. Поддерживаемые устройства: «MICROSECOND, SECOND, MINUTE, HOUR, DAY, WEEK, MONTH, QUARTER, YEAR», получили «stop» –

+0

Скопируйте код здесь. –

 Смежные вопросы

  • Нет связанных вопросов^_^