2017-02-10 70 views
0

設計重複日期的最佳方式是什麼?我有Service實體與Availability實體有一對多的關係。所以我希望我的服務能夠在有例外情況的重複日期上使用。例如:具有多個時間間隔的重複日期的Symfony3實體設計

  • 每週一09:00至12:00,從今天起至3月3日,除2月20日
  • 每週二08:00至10:00和12:30至14:30至4月1日
  • 每週四全天永遠除了17日和3月24日

的,這是我已經:

class Availability 
{ 
/** 
* @var int 
* 
* @ORM\Column(name="id", type="integer") 
* @ORM\Id 
* @ORM\GeneratedValue(strategy="AUTO") 
*/ 
private $id; 

/** 
* @ORM\Column(name="start_time", type="time") 
*/ 
private $startTime; 

/** 
* @ORM\Column(name="end_time", type="time") 
*/ 
private $endTime; 

/** 
* @var int 
* 
* @ORM\Column(name="day_of_week", type="integer") 
*/ 
private $dayOfWeek; 

/** 
* @var array 
* 
* @ORM\Column(name="date_list", type="array") 
*/ 
private $dateList; 

/** 
* @ORM\ManyToOne(targetEntity="Service", inversedBy="availabilityList") 
*/ 
private $service; 
} 

我問題是存儲這些數據的最佳方式是什麼?我應該如何改變我的實體?每個領域應該有什麼類型?

我需要能夠按日期搜索服務,如週日上午提供的查找服務,所以我希望我的Availability實體能夠滿足此搜索。

+0

我嚴重推薦使用一些像圖書館的優秀https://github.com/simshaun/recurr,而不是試圖重新發明輪子。 – LBA

+0

@LBA我想過了,但我無法弄清楚如何設置多個時間間隔,比如'從每個星期一的08:00到10:00和12:30到14:30' – blahblah

+0

看我的示例中提供的答案 - 可以實現它。 – LBA

回答

2

我們爲此使用了庫Recurr

我們的實體類看起來基本上像下面這樣(它被剝離並且沒有以這種方式測試,但它對我們的情況完美起作用)。我們只將它用於重複日期而不是時間,但使用我們的示例繼續這個問題應該不是問題。

檢查一下 - 因爲我非常肯定這是一個嘗試自己構建它的更多努力。

<?php 

use Doctrine\ORM\Mapping as ORM; 
use Recurr\Recurrence; 
use Recurr\Rule; 
use Recurr\Transformer\ArrayTransformer; 
use Recurr\Transformer\ArrayTransformerConfig; 

class Availability 
{ 

private static $frequencyList = array(0 => 'DAILY', 1 => 'WEEKLY', 2 => 'MONTHLY', 3 => 'YEARLY'); 
private static $weekDays = array(0 => 'SU', 1 => 'MO', 2 => 'TU', 3 => 'WE', 4 => 'TH', 5 => 'FR', 6 => 'SA'); 

/** 
* @var ProductService 
* @ORM\ManyToOne(targetEntity="YourBundle\Service", inversedBy="availabilities") 
*/ 
private $service; 

/** 
* @var \DateTime - indicates 'first date' of recurring timeframe 
* @ORM\Column(type="date", nullable=true) 
*/ 
private $dateStart; 

/** 
* @var \DateTime - indicates 'until date' of rRule 
* @ORM\Column(type="date", nullable=true) 
*/ 
private $dateUntil; 

/** 
* @var int - indicates 'how often' rRule applies 
* @ORM\Column(type="integer", nullable=true) 
*/ 
private $count; 

/** 
* @var int - indicates 'how often' per frequency, ex. 1 means every month, 2 every other month 
* @ORM\Column(type="integer", nullable=true, name="freq_interval") 
*/ 
private $interval; 

/** 
* @var int - indicates 'frequency', uses self::$frequencyList 
* @ORM\Column(type="integer", nullable=true) 
*/ 
private $freq; 

/** 
* @var array - indicates 'every day', uses self::$weekDays 
* @ORM\Column(type="simple_array", nullable=true) 
*/ 
private $byDay; 

/** 
* @var array - integer indicates 'day of month', e.g. 1 is first day of month, -1 is last day 
* @ORM\Column(type="simple_array", nullable=true) 
*/ 
private $byMonthDay; 

/** 
* @var array - integer indicates 'day of year', e.g. 1 is first day of year, -1 is last day of year 
* @ORM\Column(type="simple_array", nullable=true) 
*/ 
private $byYearDay; 

/** 
* @var array - indicates 'every month' January is 0, December = 12 
* @ORM\Column(type="simple_array", nullable=true) 
*/ 
private $byMonth; 

// ...getter and setter for all attributes HERE... 

/** 
* @return null|\DateTime[] 
*/ 
public function getRecurrenceCollection() 
{ 

    if ($this->getDateEffective() !== null) { 
     return null; 
    } 

    if ($this->getFreq() === null) { 
     return null; 
    } 

    $result = array(); 

    if ($this->getFreq() !== null) { 
     $rulePart[] = 'FREQ=' . self::$frequencyList[$this->getFreq()]; 
    } 

    if ($this->getCount() !== null) { 
     $rulePart[] = 'COUNT=' . $this->getCount(); 
    } 

    if ($this->getDateUntil() !== null) { 
     $rulePart[] = 'UNTIL=' . TimeUtil::canonicalDateFormat($this->getDateUntil()); 
    } 

    if ($this->getInterval() === null) { 
     $rulePart[] = 'INTERVAL=1'; 
    } else { 
     $rulePart[] = 'INTERVAL=' . $this->getInterval(); 
    } 
    if (count($this->getByDay()) > 0) { 
     $byWeekDayArray = array(); 
     foreach ($this->getByDay() as $byDay) { 
      $byWeekDayArray[] = self::$weekDays[$byDay]; 
     } 

     $rulePart[] = 'BYDAY=' . implode(',', $byWeekDayArray); 
    } 
    if (count($this->getByMonth()) > 0) { 
     $rulePart[] = 'BYMONTH=' . implode(',', $this->getByMonth()); 
    } 
    if (count($this->getByMonthDay()) > 0) { 
     $rulePart[] = 'BYMONTHDAY=' . implode(',', $this->getByMonthDay()); 
    } 
    if (count($this->getByYearDay()) > 0) { 
     $rulePart[] = 'BYYEARDAY=' . implode(',', $this->getByYearDay()); 
    } 

    $ruleString = implode(';', $rulePart); 

    $rule = new Rule($ruleString, $this->getDateStart(), null, 'UTC'); 

    $transformer = new ArrayTransformer(); 

    // enable fix for MONTHLY 
    if ($this->getFreq() === 2) { 
     $transformerConfig = new ArrayTransformerConfig(); 
     $transformerConfig->enableLastDayOfMonthFix(); 
     $transformer->setConfig($transformerConfig); 
    } 

    $elements = $transformer->transform($rule); 

    /** @var Recurrence $element */ 
    foreach ($elements as $element) { 
     $result[] = $element->getEnd(); 
    } 

    return $result; 
} 

}

+0

感謝這個例子。但我仍然無法理解如何在一天中設置例外日期和多個時間間隔。 – blahblah

+0

多個時間間隔在這裏只是多個條目,並將作爲您的「可用性列表」中的多個條目返回 - 您是否檢查了庫的例外情況? – LBA

+0

如何使用例外日期等約束在[doc](https://github.com/simshaun/recurr#transformation-constraints)中提及, – LBA

相關問題