2016-08-11 2 views
1

Je suis stack essayer de regrouper mes entités par datetime. Chaque entité a les colonnes suivantes: id, device, start, stop, ipaddress.(Symfony 3.1) des entités du Groupe Doctrine PHP par datetime

Je veux être en mesure d'obtenir des entités au sein d'une gamme de date et de les regrouper par date (jour) suivant avec combien d'heures chaque jour a.

C'est ce que j'ai jusqu'à présent

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(); 
} 

Ceci est le code de ma classe référentiel.

et le code de mon contrôleur ressemble à ceci:

$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 
    ]); 

i Jusqu'à présent, a pu calculer le temps total passé pour un jour donné (un seul jour). Maintenant, je voudrais obtenir toutes les entités, les regrouper par la même date (jour) et retourner les données avec intervalle.

exemple de tableau DB ressemble à ceci [id, device_id, démarrer, arrêter, 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 

Donc dans ce cas ma sortie serait quelque chose comme:

[ 
    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"] 
] 

l'intervalle dépend démarrer et arrêter les deux sont type de DateTime

J'ai essayé d'utiliser doctrine-extensions: oro/doctrine-extensions mais maintenant je reçois une erreur d'exception:

[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' 

Ma méthode référentiel ressemble à ceci:

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(); 

} 

ma table 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 j'utilise Symfony 3, pourrait-il être le problème?

Répondre

0

Sur la base de votre tableau ci-dessus (si je me trompe pas) Je voudrais essayer d'obtenir les données directement avec MYSQL puis me frayer un chemin à la doctrine.

Si vous avez le tableau ci-dessous:

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`) 
); 

Et peuplé ci-dessous les données de test (je l'ai créé deux dispositifs, le second était bien actif pour exactement 3 heures à la date d'aujourd'hui):

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) 

Après requête MYSQL alors je crois que la sortie les données que vous souhaitez:

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 ; 

Et le résultat ressemblerait à ceci:

+------------+----------+--------+-----------+ 
| 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) 

Notez que l'heure du deuxième périphérique est correcte. Maintenant, la question restante est de savoir comment faire cela dans Doctrine.Pour autant que je sais que la fonction TIMEDIFF ne fait pas partie de la doctrine mais si je propose 2 approches différentes:

  1. Écrivez votre propre fonction dans http://www.doctrine-project.org/2010/03/29/doctrine2-custom-dql-udfs.html#date-diff (Il est par exemple de DATEDIFF dans ce lien il est donc facilement réglable), ou
  2. Utilisez https://packagist.org/packages/oro/doctrine-extensions

Votre fonction finale de référentiel dans doctrine/Symfony2 avec/oro doctrine extensions installées ressemblerait à quelque chose comme ceci:

$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(); 

J'ai écrit cette fonction sans la tester du tout et du haut de ma tête. Vous trouverez probablement que cela échoue. Cela donnerait la différence de temps en secondes car le TIMESTAMPDIFF nécessite des unités à spécifier. Installer oro/doctrine-extensions avec

composer require oro/doctrine-extensions 
+0

Tomislav vous remercie de votre réponse, je vais essayer, vous permettra de savoir comment il a –

+0

Salut Je l'ai essayé mais ne fonctionne toujours pas, maintenant je suis obtenir une erreur d'attente: [2/2] QueryException: [Erreur de syntaxe] ligne 0, col 50: Erreur: L'unité attendue n'est pas valide pour la fonction TIMESTAMPDIFF. Les unités prises en charge sont les suivantes: "MICROSECOND, SECOND, MINUTE, HEURE, JOUR, SEMAINE, MOIS, QUARTIER, ANNÉE", "stop" –

+0

Copiez votre code ici. –