简体   繁体   English

具有多个字段的Doctrine2唯一验证

[英]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实体的代码如下:

Input Filter 输入过滤器

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,
                        ),
                    ),
                ),
            )
        );
    }
} 

Controller Action 控制器动作

public function create($data)
{

    $user    = $this->zfcUserAuthentication()->getIdentity();
    $booking = $this->getTimeBookingService()->validateBooking($data, $user);

    $booking->setUser($user);
    //some other stuff
    //persist
}

Service 服务

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;
}

Question

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方法以使用dateuser字段搜索存储库?

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: 向模型添加一些更改,您可以一起设置dateuser_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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM