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

これまでのところ、特定の日(1日のみ)の合計消費時間を計算できました。今、私は alle エンティティを取得し、それらを同じ日付 (日) でグループ化し、間隔のあるデータを返したいと考えています。

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

間隔は start と stop に依存し、どちらも DateTime 型です

doctrine-extensions: 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

ところで、私は 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`)
);

そして、以下のテストデータが取り込まれます (2 つのデバイスを作成しましたが、2 つ目のデバイスは、今日の日付で正確に 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)

2 番目のデバイスの時刻が正しいことに注意してください。さて、残っている問題は、Doctrine でそれを行う方法です。私が知る限り、TIMEDIFF関数はまだDoctrineの一部ではないので、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を使用

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 に答える