есть ли лучший способ использовать несколько условий if?

#php

#php

Вопрос:

у меня есть метод класса php, который определяет, имеет ли свойство класса if какое-либо значение. если он содержит какое-либо значение, то он будет проверять и повторять свойство класса $this-> error. вот метод класса, который я использую.

 public function validate() {
    if(!empty($this->name)) {
        if(!preg_match('/^[a-zA-z ]{3,50}$/',$this->name)) {
            $this->error['name'] = 'Name should be valid letters and should be between 3 and 25 characters';
        }
    }
    if(!empty($this->email)) {
        if(!filter_var($this->email,FILTER_VALIDATE_EMAIL)) {
            $this->error['invalidEmail'] = 'Invalid email address';
        }
        if(empty($this->userId) amp;amp; $this->emailCount($this->email)) {
            $this->error['emailExist'] = 'Email already exist';
        }
    }
    if(empty($this->userId) amp;amp; !empty($this->password)) {
        if(strlen($this->password) < 5 || strlen($this->password > 40)) {
            $this->error['password'] = 'Password length should be between 5 and 40 characters';
        }
    }
    if(!empty($this->userId) amp;amp; !empty($this->newPassword)) {
        if(strlen($this->newPassword) < 5 || strlen($this->newPassword > 40)) {
            $this->error['password'] = 'Password length should be between 5 and 40 characters';
        }
    }
    if(!empty($this->pPhone)) {
        if(!preg_match('/^[0-9]{5,10}$/',$this->pPhone)) {
            $this->error['invalidpPhone'] = 'Invalid primary phone number';
        }
    }
    if(!empty($this->sPhone)) {
        if(!preg_match('/^[0-9]{5,10}$/',$this->sPhone)) {
            $this->error['invalidsPhone'] = 'Invalid secondary phone number';
        }
    }
    return (empty($this->error)) ? true : false;    
}
  

я использовал здесь множество условий if, которые, на мой взгляд, не очень хороши, есть ли какой-либо другой способ, которым я мог бы определить вышеупомянутое условие и переписать код более совершенным способом?

Ответ №1:

Вы могли бы использовать переменные variable и выполнять цикл в своем коде. Но это означает, что вам придется придумать какую-то стандартизированную схему проверки для вашего кода

 $validateFields = array('email', 'username', 'userId'); //list of fields to validate
$rules = array(
  'username' => array('type'=> 'regex', 'rule' => '/^[a-zA-z ]{3,50}$/'),
  'email'    => array('type' => 'filter', 'rule' => 'FILTER_VALIDATE_EMAIL')
);

foreach ($validateFields as $field) {
   if (isset($rules[$field])) {
       switch ($rules[$field]['type']) {
           case 'regex' : 
              if(!preg_match($rules[$field]['type']['rule'],$this->$field)) {
                    $this->error[$field] = ucfirst($field) . ' should be valid letters and should be between 3 and 25 characters';
              }
              break;

           case 'filter' :
              if(!filter_var($this->$field, $rules[$field]['type']['rule'])) {
                  $this->error[$field] = 'Invalid email address';
              }
              break

           //more cases
       }
   }
}
return (empty($this->error)) ? true : false; 
  

В этом примере используется только одно правило для каждого поля, но вы должны иметь возможность легко расширить его, чтобы использовать несколько правил для каждого поля.

Изначально вам придется настроить все правила, но проверка не увеличится только потому, что вы добавите другое свойство в свой класс.

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

1. на мой взгляд, это может быть лучшим вариантом, и его также легко прочитать. спасибо, собираюсь с этим поиграть.

2. @IbrahimAzharArmar взгляните на систему проверки CakePHP. Это практически тот же принцип

3. @JonhP, есть ли какая-нибудь конкретная статья, демонстрирующая пример, которая могла бы быть полезной для меня..

4. @IbrahimAzharArmar Вам пришлось бы загрузить CakePHP. Или вы можете просмотреть их исходный код

5. ах, это снова отняло бы много времени (мне нужно уложиться в крайний срок), я действительно хочу понять и реализовать способ, которым cakephp реализует это, в настоящее время я следую той же структуре базы данных, что и рекомендованный cakephp. я собираюсь немного поиграть с приведенным выше кодом и вернусь к вам. :), мне может понадобиться дополнительная помощь … 🙂

Ответ №2:

Я не думаю, что вы можете переписать этот конкретный фрагмент кода существенно лучшим способом.

Но, глядя на общую картину, возможны улучшения. Глядя на переменные класса, это, вероятно, либо класс form, либо экземпляр модели какого-то рода, и вы пытаетесь проверить данные перед их сохранением. Вы могли бы обобщить и абстрагировать логику проверки в отдельном классе. Для вдохновения взгляните на то, как различные фреймворки PHP (например, Symphony, CakePHP) обрабатывают проверку формы и модели.

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

1. Я категорически не согласен. Он может разделить его на функцию для каждой вещи, которую ему нужно проверить. Например, я не понимаю, как вы можете дважды увидеть «$ this-> error[‘password’] = ‘Длина пароля должна составлять от 5 до 40 символов’;» в коде и решить, что его нельзя существенно улучшить. Если он когда-нибудь изменит принцип работы паролей, ему придется дважды скопировать и вставить код только в этом примере.

2. Простое выделение проверки пароля в отдельную функцию — это не то, что я называю существенным улучшением.

Ответ №3:

Сначала вы должны извлечь свои строки ошибок в defines или, что лучше, в константы класса.

 define('ERR_BAD_NAME','Name should be valid letters and should be between 3 and 25 characters');
define('ERR_BAD_EMAIL','Invalid email address');
define('ERR_EMAIL_IN_USE','Email already exist');
define('ERR_BAD_PASSWD','Password length should be between 5 and 40 characters');
define('ERR_BAD_PRIMARY_PHONE','Invalid primary phone number');
define('ERR_BAD_SECONDARY_PHONE','Invalid primary phone number');

public function validate() {
    if(!empty($this->name)) {
        if(!preg_match('/^[a-zA-z ]{3,50}$/',$this->name)) {
            $this->error['name'] = ERR_BAD_NAME;
        } 
    }
    if(!empty($this->email)) {
        if(!filter_var($this->email,FILTER_VALIDATE_EMAIL)) {
            $this->error['invalidEmail'] = ERR_BAD_EMAIL;
        }
        if(empty($this->userId) amp;amp; $this->emailCount($this->email)) {
            $this->error['emailExist'] = ERR_EMAIL_IN_USE;
        }
    }
    if(empty($this->userId) amp;amp; !empty($this->password)) {
        if(strlen($this->password) < 5 || strlen($this->password > 40)) {
            $this->error['password'] = ERR_BAD_PASSWD;
        }
    }

    if(!empty($this->pPhone)) {
        if(!preg_match('/^[0-9]{5,10}$/',$this->pPhone)) {
            $this->error['invalidpPhone'] = ERR_BAD_PRIMARY_PHONE;
        }
    }
    if(!empty($this->sPhone)) {
        if(!preg_match('/^[0-9]{5,10}$/',$this->sPhone)) {
            $this->error['invalidsPhone'] = ERR_BAD_PRIMARY_PHONE;
        }
    }
    return (empty($this->error)) ? true : false;    
}
  

второй шаг — преобразовать тесты в отдельные частные методы и избавиться от блоков if:

 private function validate_name($name) {
    return = empty($name) || preg_match('/^[a-zA-z ]{3,50}$/',$name);
}

private function validate_phone($phone) {
    return empty($phone) || preg_match('/^[0-9]{5,10}$/',$phone);
}

private function validate_email($email) {
   return empty($email)) || filter_var($email,FILTER_VALIDATE_EMAIL);
}

private function emailInUse($email, $userId) {
   if(!empty($email)) {
        if(empty($this->userId) amp;amp; $this->emailCount($this->email)) {
            $this->error['emailExist'] = ERR_EMAIL_IN_USE;
        }
    }
}

private function validate_userPassword($userId, $password) {
    $passwordLen=strlen($this->password);
    return (empty($this->userId) amp;amp; !empty($this->password)) ||
           (5 <= $passwordLen) amp;amp; (40 >= $passwordLen); 
}

private function lor_error($type, $message) {
    $this->error[$type] = $message;
    return false;
}

public function validate() {
  $isValid = true;
  $isValid amp;= $this->validate_name($this->name) || 
              $this->logError('name',ERR_BAD_NAME);
  $isValid amp;= $this->validate_email($this->email) || 
              $this->logError('invalidEmail',ERR_BAD_EMAIL);
  $isValid amp;= $this->emailInUse($this->userId, $this->email) || 
              $this->logError('emailExist',ERR_EMAIL_IN_USE);
  $isValid amp;= $this->validateUserPassword($this->userId, $this->password) ||
              $this->log('password', ERR_BAD_PASSWD);
  $isValid amp;= $this->validate_phone($this->pPhone) ||
              $this->log('invalidpPhone',ERR_BAD_PRIMARY_PHONE);
  $isValid amp;= $this->validate_phone($this->sPhone) ||
              $this->log('invalidsPhone',ERR_BAD_SECONDARY_PHONE);
  return $isValid;
}
  

На третьем этапе рефакторинга вы должны извлечь метод validate_* в класс validator, чтобы отделить задачи проверки от вашего основного класса. Этот последний этап, очевидно, зависит от вас (как бремя определения надлежащего класса журнала).

Ответ №4:

если вы хотите использовать условие if в файле, вы можете использовать select case с блоком if

случай строки 1, блок if

случай 2, если блок

if поможет вам лучше

Ответ №5:

Я не думаю, что вы можете избежать этих нескольких операторов If, поскольку я вижу, что это то место, где вы проверяете поля.

Другой альтернативой для нескольких операторов if был оператор Swtich,

Я не уверен, что это выполнимо для данной ситуации, поскольку вы передаете String в качестве аргументов, где as Switch не принимает String в качестве аргументов, он принимает только integer в качестве входных данных

Ответ №6:

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

Но да, это очень близко к тому, что вы делаете сейчас, я просто потерял некоторые проверки идентификаторов и другие различные фрагменты кода, которые вам придется повторно реализовать.

Кроме того, я делаю это, исходя из предположения, что это уже есть в классе, и вы обращаетесь к переменным класса $this->name

 <?php 

public function validate() {
    //You can place your simple ID checks around these wherever they're supposed to go, I lost them ;P.
    //This code probably won't compile without errors, but it's to give you a much neater idea.
    //Never ever repeat code !!! Your life becomes so much better :]
    $this->validate_name($this->name);
    $this->validate_email($this->email); // I didn't complete this one.. but this is just all for an idea


    $this->validate_phone_number($this->pPhone,'Primary');
    $this->validate_phone_number($this->sPhone,'Secondary');

    return (empty($this->error)) ? true : false;    
}

function validate_password($password){
    !empty($password)) {
        if(strlen($password) < 5 || strlen($password > 40)) {
            $this->error['password'] = 'Password length should be between 5 and 40 characters';
        }
}

function validate_name($name){
        if(!preg_match('/^[a-zA-z ]{3,50}$/',$name)) {
            $this->error['name'] = 'Name should be valid letters and should be between 3 and 25 characters';
        }
}

function validate_phone_number($number,$type){
    if(!preg_match('/^[0-9]{5,10}$/',number)) {
            $this->error['invalidsPhone'] = "Invalid $type phone number";
        }
}