! is_null () не работает должным образом

dispatch_address_postcode

не является обязательным, и он все равно будет работать, даже если он пуст:

if (!is_null($_POST['personal_info_first_name']) && 
    !is_null($_POST['personal_info_surname']) && 
    !is_null($_POST['personal_info_email']) && 
    !is_null($_POST['personal_info_telephone']) && 
    !is_null($_POST['dispatch_address_country']) && 
    !is_null($_POST['dispatch_address_first_name']) &&
    !is_null($_POST['dispatch_address_surname']) && 
    !is_null($_POST['dispatch_address_address']) && 
    !is_null($_POST['dispatch_address_town']) && 
    !is_null($_POST['dispatch_address_postcode']) && 
    !is_null($_POST['dispatch_address_county']) && 
    (   ($_POST['payment_method'] == "Pay by credit card.") ||
        (
            ($_POST['payment_method'] == "Pay by new credit card.") && 
            !is_null($_POST['card_number']) && 
            !is_null($_POST['expiration_date']) && 
            !is_null($_POST['security_code'])
        )
    )
)

Что дает?


person JoeCortopassi    schedule 19.07.2010    source источник
comment
Разве вы не можете просто использовать isset()?   -  person Falmarri    schedule 20.07.2010


Ответы (6)


«dispatch_address_postcode не является обязательным, и он все равно будет работать, даже если он пуст…»

Просто посмотрите на это предложение еще раз. Если поле не является обязательным, это нормально, если код запускается, если поле пустое. Если поле не является обязательным, не проверяйте его как обязательное.

Однако настоящая проблема в том, что is_null проверяет только, равна ли переменная null. POST-значения никогда не будут null, если они пустые, они будут '' (пустая строка). Все ваши !is_null тесты всегда будут true, и вы получите предупреждение, если переменная не будет установлена ​​(чего вы не хотите). Более подходящим тестом будет !empty.

Еще более подходящие тесты могли бы включать проверку того, является ли значение допустимым (выглядит ли электронная почта как адрес электронной почты, есть ли в телефоне хотя бы x цифр?). Вы также должны прокручивать поля в цикле, чтобы сделать ваш код более читабельным, бесконечные вложенные и связанные if условия не доставляют удовольствия.

$mandatoryFields = array('foo' => 'email', 'bar' => 'telephone');

foreach ($mandatoryFields as $field => $rule) {
    if (empty($_POST[$field]) || !validateByRule($_POST[$field], $rule)) {
        raiseHell();
    }
}
person deceze♦    schedule 19.07.2010
comment
Тем не менее, неопределенные переменные будут также переданы как null. - person zneak; 20.07.2010
comment
@zneak Хороший улов, это заявление было пересмотрено. - person deceze♦; 20.07.2010
comment
Взять из прошлого комментария, но empty($_POST[$field]) будет правдой, если поле равно "0"; может быть лучше использовать isset() или array_key_exists() и позволить validateByRule() обрабатывать содержимое. - person Ja͢ck; 22.08.2012

Похоже, вы пытаетесь убедиться, что отправлены все переменные сообщения. Вам нужна помощь с этим?

Использование! Empty () не может быть ответом на ваш конкретный вопрос, но определенно поможет с тем, что, похоже, вы пытаетесь сделать.

empty () возвращает TRUE, если ключ $ _POST не установлен, если это пустой массив или даже если это пустая строка, поэтому использование! empty () - хороший способ убедиться, что пользователь заполнил информацию .

person Navarr    schedule 19.07.2010
comment
Нет is_empty(), вы имеете в виду empty()? - person igorw; 20.07.2010

Попробуйте написать свою собственную is_valid функцию и использовать ее, а не is_null.

Например (и это отнюдь не исчерпывающе):

function is_valid(&$array, $key, $required=false) {
    if(!array_key_exists($array))
        return false;
    $value = trim($array[$key]);
    if(empty($value) && $required)
        return false;
    return true;
}

Используйте так:

if(is_valid($_POST, 'personal_info_first_name', true) && ...)

person thetaiko    schedule 19.07.2010
comment
Я бы проголосовал за это, если бы вы исправили ошибку в вызове array_key_exists и, возможно, упростили бы инструкции _2 _ / _ 3_. :) - person deceze♦; 20.07.2010

используйте 1_

person Casey    schedule 19.07.2010
comment
Это довольно избыточно, вы можете пропустить там вызов array_key_exists. - person deceze♦; 20.07.2010

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

НЕ ДЕЛАЙТЕ ЭТО - прочтите комментарии, чтобы узнать, почему это плохо.

Мой ответ будет совершенно другим, но я совершенно другой парень ...

Я ПРОСТО обнаружил, что это сработает. Вместо всего этого, просто назначьте переменные программно! Думаю, мне нужно провести рефакторинг ... ну, знаешь, весь мой код ...

if (!is_array($_POST)){exit "$_POST isn't an array";}
foreach ($_POST as $param => $value){
    ${$param} = secure($value);
}

//now you have a set of variables that are named exactly as the posted param
//for example, $_POST['personal_info_first_name'] == $personal_info_first_name

if ($payment_method == "Pay by credit card."){
    //do stuff that you were gonna do anyways
} else if ($payment_method == "Pay by new credit card.") {
    if ($card_number && $expiration_date && $security_code){
        //do stuff that you were gonna do anyways
    } else {
        exit("info missing for credit card transaction");
    }
} else {
    exit("unknown payment method")
}

function secure($input){
    //sanitize user input
}

Если вы используете этот код, то не имеет значения, что имеет значение null, а что нет в foreach, потому что ничего, что равно null, просто не будет сделано. Затем вы можете использовать более красивый код (и, возможно, более быстрый код), чтобы проверить все, что требуется.

person TCCV    schedule 19.07.2010
comment
Первая строка мало что делает ... $ _POST всегда является массивом, даже в интерфейсе командной строки PHP, если вы не сделали с ним что-то безумное ранее в программе. Но как вообще это улучшение? Вместо проверки ключа массива, который не установлен, вы в конечном итоге будете проверять переменные, которые не установлены? - person JAL; 20.07.2010
comment
Вы получите много предупреждений о несуществующих переменных с таким кодом, вам все равно нужно будет использовать isset. Вы также засоряете свое пространство имен множеством переменных, и вам придется более тщательно их инициализировать, вы, по сути, воссоздаете старую register_globals проблему. Никаких улучшений. - person deceze♦; 20.07.2010
comment
да ладно ... я думаю, мое изобилие было немного преждевременным. Спасибо, что указали на недостатки. Я не понимал, что это проблема, просто кажется, что это так легко использовать для такого рода вещей. Думаю, именно поэтому ваши представители исчисляются тысячами, а мои - сотнями: op Однако, чтобы внести ясность. Похоже, проблема с несуществующими переменными возникла после цикла foreach? Было бы нормально создавать переменные, как в случае с циклом foreach, если бы я не делал никаких предположений в коде после этого? - person TCCV; 20.07.2010
comment
Действительно, проблема в if ($payment_method ...) частях. Если payment_method не был частью массива $_POST, переменная существовать не будет. Это та же проблема, независимо от того, создаете ли вы переменные с помощью своего foreach или просто оставляете их в массиве $_POST. Оставить переменные в массиве $_POST намного чище, поскольку они занимают только одну переменную. Если вы начнете использовать переменную $foo для внутренних целей, но ваш массив $_POST также содержит ключ 'foo', вы столкнетесь с небольшим конфликтом имен, возможно, с последствиями для безопасности. Вот почему register_globals устарел. - person deceze♦; 20.07.2010
comment
Правильно ... кто-то может на самом деле затереть ваши собственные переменные, отправив неожиданные поля во вводе POST, что будет угрозой безопасности и здравомыслию, в точности как register_globals. - person JAL; 20.07.2010
comment
Спасибо за вклад, ребята, я очень ценю это. Такая информация во время обучения бесценна. - person TCCV; 21.07.2010

person    schedule
comment
Как что-то может быть не нулевым и не установлено одновременно? Кроме того, вы хотите проверить isset прежде всего. - person deceze♦; 20.07.2010
comment
@deceze: isset() - это языковая конструкция, и она не будет автоматически создавать переменную, если вы передадите ту, которая не существует. is_null() - это полноценная функция, и она БУДЕТ автоматически создавать переменную (и устанавливать для нее значение null), если она еще не существует. Таким образом, is_null() не может использоваться для проверки отсутствия чего-либо, так как он будет создан автоматически просто путем тестирования. - person Marc B; 21.07.2010
comment
@Marc Разница в том, что isset не создает переменную, но также не выдает предупреждение при попытке доступа к той, которая не определена. Поэтому тестирование is_null first бессмысленно, так как оно выдаст предупреждение и сделает последующий isset вызов бессмысленным. Кроме того, если переменная не существует или равна null, все выражение завершится ошибкой на !is_null. Если переменная существует и не равна null, она завершится ошибкой на !isset. - person deceze♦; 21.07.2010