我有一个实体Booking
,它与User
有多对一的关系。
每个Booking
实体都有一个date
字段,对用户来说应该是唯一的。
例如,条目可能如下所示:
+----------+---------+
| date | user_id |
+----------+---------+
| 12-04-88 | 1 |
| 13-04-88 | 1 |
| 12-04-88 | 2 |
+----------+---------+
但不是这样的:
+----------+---------+
| date | user_id |
+----------+---------+
| 12-04-88 | 1 |
| 12-04-88 | 1 |
+----------+---------+
使用ZF2 REST控制器添加Booking
实体的代码如下:
class BookingFilter extends InputFilter
{
//TODO: Get from module config
protected $config = array(
'date-format' => 'd-m-Y',
'start-min' => '07:00',
'start-max' => '10:00',
'end-min' => '16:00',
'end-max' => '19:00',
'step' => '900', //15 x 60 - 15 Min's
);
public function init()
{
$this->add(
array(
'name' => 'date',
'required' => true,
'validators' => array(
array(
'name' => 'Date',
'options' => array(
'format' => 'd-m-Y',
),
),
),
)
);
$this->add(
array(
'name' => 'startTime',
'required' => true,
'filters' => array(
array('name' => 'StringTrim')
),
'validators' => array(
array(
'name' => 'Date',
'options' => array(
'format' => 'H:i',
),
),
array(
'name' => 'GreaterThan',
'options' => array(
'min' => $this->config['start-min'],
'inclusive' => true,
),
),
array(
'name' => 'LessThan',
'options' => array(
'max' => $this->config['start-max'],
'inclusive' => true,
),
),
array(
'name' => 'DateStep',
'options' => array(
'format' => 'H:i',
'baseValue' => $this->config['start-min'],
'step' => new \DateInterval("PT{$this->config['step']}S"),
),
),
),
)
);
$this->add(
array(
'name' => 'endTime',
'required' => true,
'filters' => array(
array('name' => 'StringTrim')
),
'validators' => array(
array(
'name' => 'Date',
'options' => array(
'format' => 'H:i',
),
),
array(
'name' => 'GreaterThan',
'options' => array(
'min' => $this->config['end-min'],
'inclusive' => true,
),
),
array(
'name' => 'LessThan',
'options' => array(
'max' => $this->config['end-max'],
'inclusive' => true,
),
),
array(
'name' => 'DateStep',
'options' => array(
'format' => 'H:i',
'baseValue' => $this->config['end-min'],
'step' => new \DateInterval("PT{$this->config['step']}S"),
),
),
),
)
);
//notes
$this->add(
array(
'name' => 'notes',
'required' => false,
'filters' => array(
array('name' => 'StripTags'),
array('name' => 'StringTrim')
),
'validators' => array(
array(
'name' => 'StringLength',
'options' => array(
'encoding' => 'UTF-8',
'min' => 1,
'max' => 512,
),
),
),
)
);
}
}
public function create($data)
{
$user = $this->zfcUserAuthentication()->getIdentity();
$booking = $this->getTimeBookingService()->validateBooking($data, $user);
$booking->setUser($user);
//some other stuff
//persist
}
public function validateBooking(array $data, UserInterface $user, Booking $booking = null)
{
$filter = $this->getInputFilter();
$filter->setData($data);
if (!$filter->isValid()) {
$this->messages = $filter->getMessages();
return false;
}
if (!$booking) {
$booking = new Booking;
}
$this->getDoctrineHydrator()->hydrate($filter->getValues(), $booking);
//if this is a new booking - not an update
if (!$booking->getId()) {
$row = $this->bookingRepository->findOneBy(array('date' => $booking->getDate(), 'user' => $user));
if (is_object($row)) {
//user already has booking for this date
$this->messages['date'] = array('This user already has a booking for this date');
return false;
}
}
return $booking;
}
如何使用默认的Doctrine Validator或自定义Doctrine / ZF2验证器?
我不喜欢我的方法,似乎我复制了Validator组件的工作,但是,我上次尝试时无法使用Doctrine Unique Validator,因为那里超过1个字段需要是唯一的。
我正在考虑扩展Doctrine Unique验证器,它依赖于User
,它将注入一个构造,然后扩展validate
方法以使用date
和user
来搜索存储库。 {{1}}字段?
答案 0 :(得分:1)
我正在考虑用一个扩展Doctrine Unique验证器 对用户的依赖将被注入一个构造然后 扩展validate方法以使用两个日期搜索存储库 和用户字段?
向模型添加一些更改,您可以将date
和user_id
主键设置在一起:
/** @Id @Column(type="integer") */
private $id;
/** @Id @Column(type="date") */
private $date;
我不知道你的框架控制器如何持久保存该对象,但你可以这样做:
try
{
$booking = new Booking(1, '12-19-2000');
em->persist($booking);
em->flush();
}
catch( \Doctrine\DBAL\DBALException $e )
{
/* the error 23000 should print the unique constrains mysql error */
if( $e->getPrevious()->getCode() === '23000' )
{
echo "entity already exists";
}
}