[英]Doctrine2 Unique Validation with multiple fields
I have an entity Booking
which has a many-to-one relationship to a User
. 我有一个实体Booking
,它与User
多对一的关系。 Each Booking
entity has a date
field which should be unique to the user. 每个Booking
实体都有一个date
字段,该字段对于用户应该是唯一的。
For example entries could look like this: 例如,条目可能如下所示:
+----------+---------+
| date | user_id |
+----------+---------+
| 12-04-88 | 1 |
| 13-04-88 | 1 |
| 12-04-88 | 2 |
+----------+---------+
But not like this: 但不是这样的:
+----------+---------+
| date | user_id |
+----------+---------+
| 12-04-88 | 1 |
| 12-04-88 | 1 |
+----------+---------+
The code to add a Booking
entity, is as follows, using the ZF2 REST controller: 使用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;
}
How can I do this with either a default Doctrine Validator or a custom Doctrine/ZF2 validator? 如何使用默认的Doctrine验证程序或自定义的Doctrine / ZF2验证程序执行此操作?
I don't like my approach it seems like I'm replicating work of the Validator component, however, I couldn't get it to work with the Doctrine Unique Validator last time I tried because there is more than 1 one field which need to be unique. 我不喜欢我的方法,好像我正在复制Validator组件的工作,但是,上次我尝试将其与Doctrine Unique Validator结合使用时,因为有多个字段需要独一无二。
I was thinking to extend the Doctrine Unique validator with a dependency on the User
which will be injected an construction and then extending the validate
method to search the repository using both date
and user
fields? 我正在考虑扩展将依赖于将注入构造的User
的Doctrine Unique验证器,然后扩展validate
方法以使用date
和user
字段搜索存储库?
I was thinking to extend the Doctrine Unique validator with a dependency on the User which will be injected an construction and then extending the validate method to search the repository using both date and user fields? 我正在考虑扩展将依赖于将注入构造的User的Doctrine Unique验证器,然后扩展validate方法以使用日期和用户字段搜索存储库?
Adding some changes to the model, you can set date
and user_id
primary key together: 向模型添加一些更改,您可以一起设置date
和user_id
主键:
/** @Id @Column(type="integer") */
private $id;
/** @Id @Column(type="date") */
private $date;
I do not know how your framework controller persist the object, but you could do something like this: 我不知道您的框架控制器如何持久化对象,但是您可以执行以下操作:
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";
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.