2017-02-10 72 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

相关问题