Как использовать правило `validCount`, чтобы ограничить количество записей текущей модели?

#validation #cakephp #associations #cakephp-3.x

#проверка #cakephp #ассоциации #cakephp-3.x

Вопрос:

Я пытаюсь использовать правило проверки validCount в cakephp 3.x

У меня есть событие с максимальным количеством участников (Событие-> max_pax)

Я хотел бы добавить правило проверки, которое отказывает участнику, если у него число max_pax 1.

Я делаю что-то не так, но я не понимаю, что (мой код следует)

 //This is in Participant Model.php
public function buildRules(RulesChecker $rules)
{
      $rules->add(
            function ($entity, $options) use ($rules) {
                $query = $this->Events->find();
                $max_pax = $query->select('max_pax')
                    ->where(['id'=>$entity->event_id])
                    ->first();                      
                $r =  $rules->validCount('events', $max_pax , '<=', "maximum $max_pax participants");
                debug($r);  
                return $r;
            },
            'maxPax',
            [
                'errorField' => 'event_id',
                'message' => "Choose another event"
            ]
        );
  

Кто-нибудь может помочь?

Ответ №1:

Прежде всего, если вы хотите вложить подобные правила, вам придется их оценить. В вашем примере $r был бы вызываемый объект типа CakeDatasourceRuleInvoker , поэтому вы бы сделали что-то вроде:

 $result = $r($entity, $options);
  

А затем либо дополнительно оцените результат проверки (это логическое значение), либо верните его из вашего пользовательского правила. Также в вашем примере $max_pax будет объект, вам нужно будет фактически получить доступ к полю в нем и передать это validCount() методу.

Однако, validCount() это улучшение, которое будет использоваться для подсчета связанных данных, которые в настоящее время существуют в данном объекте, оно не выполняет никаких поисков в базе данных, т. Е. Оно улучшено для ситуаций, когда вы сохраняете запись, включая связанные записи, и хотите определить ограничения на количество связанных записей, которые могут / должны быть сохранены. Таким образом, вы могли бы, например, использовать его, если вам нужно создать новое событие, включающее участников, чтобы убедиться, что вы не пытаетесь вставить больше участников, чем разрешено.

При создании записей с помощью вашей модели участников вы хотите фактически запросить базу данных, чтобы подсчитать, сколько участников уже связано с выбранным событием. Нет встроенного правила, которое делало бы это, поэтому вы должны сделать это самостоятельно, например, что-то вроде этого:

 $event = $this->Events
    ->find()
    ->select(CakeORMQuery $query) {
        return [
            'Events.max_pax',
            'number_of_participants' => $query->func()->count('Participants.id')
        ];
    })
    ->leftJoinWith('Participants')
    ->where(['Events.id' => $entity->event_id])
    ->first();

return $event->get('number_of_participants') < $event->max_pax;
  

Это запросило бы максимальное количество разрешенных участников и количество участников, которые уже существуют, а затем просто сравнило бы эти значения.

Комментарии:

1. Спасибо. Еще один вопрос. Куда бы вы поместили приведенный выше код? В модели участника, верно? Как я должен вызвать метод, содержащий этот код? Подойдет любая приватная функция? Или я должен следовать определенному соглашению об именовании? Спасибо. Макс

2. @massimoi Этот пример будет использоваться в модели участников, в функции обратного вызова правила, как и в вашем примере. И, конечно, вы также могли бы поместить это в метод модели, соглашения об именовании не применяются, но вам, вероятно, придется немного изменить код, в зависимости от того, помещаете ли вы его в модель участников или событий (обе работают, и вы бы назвали это как $this-> methodName ($ args) или $this->Events->methodName($args) ). Еще лучше было бы обернуть его в пользовательский класс правил, см. book.cakephp.org/3.0/en/orm /… .