1

我正在尝试按日期时间对我的实体进行分组。每个实体都有以下列:id、device、start、stop、ipaddress。

我希望能够在某个日期范围内获取实体,并按日期(天)对它们进行分组,然后是每天有多少小时。

这就是我到目前为止所拥有的

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 表如下所示[id, device_id, start, stop, 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"]
]

间隔取决于开始和停止都是 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();

}

我的数据库表:

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

顺便说一句,我正在使用 Symfony 3,这可能是问题吗?

4

1 回答 1

0

根据您上面的表格(如果我做对了),我会尝试直接使用 MYSQL 获取数据,然后按照我的方式使用 Doctrine。

如果你有下表:

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)

请注意,第二个设备时间是正确的。现在,剩下的问题是如何在 Doctrine 中做到这一点。据我所知,该TIMEDIFF功能还不是 Doctrine 的一部分,所以我会提出两种不同的方法:

  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

安装了 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需要指定单位。安装 oro/doctrine-extensions

composer require oro/doctrine-extensions
于 2016-08-11T21:07:11.667 回答