Слабая типизация в PHP: зачем вообще использовать isset? - PullRequest
17 голосов
/ 05 января 2009

Кажется, что мой код работает, чтобы проверить на ноль, если я делаю

if ($tx) 

или

if (isset($tx))

зачем мне делать второй, когда писать труднее?

Ответы [ 9 ]

20 голосов
/ 05 января 2009
if ($tx)

Этот код оценивается как ложный для любого из следующих условий:

unset($tx); // not set, will also produce E_WARNING
$tx = null;
$tx = 0;
$tx = '0';
$tx = false;
$tx = array();

Приведенный ниже код будет иметь значение false только при следующих условиях:

if (isset($tx))

// False under following conditions:
unset($tx); // not set, no warning produced
$tx = null;

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

9 голосов
/ 06 января 2009

isset () не имеет ничего общего с TYPE или VALUE - только с EXISTENCE.

if ($ condition) ... оценит VALUE of VARIABLE как логическое значение.

if (isset ($ condition)) ... оценит СУЩЕСТВОВАНИЕ ПЕРЕМЕННОГО ЗНАЧЕНИЯ как логическое значение.

isset () может быть ложным по двум причинам.

Во-первых, потому что переменная не установлена ​​и поэтому не имеет значения.

Во-вторых, потому что переменная имеет значение NULL, что означает «неизвестное значение» и не может считаться установленным, потому что оно включает в себя «нет значения» и потому, что многие люди используют $ v = null для обозначения того же, что и unset ($ v).

(Помните, если вы специально хотите проверять на ноль, используйте is_null ().)

isset () обычно используется для проверки внешней переменной, которая может существовать или не существовать.

Например, если у вас есть страница с именем page.php, которая имеет это:

ini_set('display_errors', 1);
error_reporting(E_ALL);

if ( $_GET["val"] ) {
    // Do Something
} else {
    // Do Nothing
}

это будет работать нормально для любого из этих URL:

http://www.example.com/page.php?val=true // Something will be done.
http://www.example.com/page.php?val=monkey // Something will be done.

http://www.example.com/page.php?val=false  // Nothing will be done.
http://www.example.com/page.php?val=0// Nothing will be done.

Однако вы получите сообщение об ошибке для этого URL:

http://www.example.com/page.php

, поскольку в URL нет аргумента 'val', поэтому в массиве $ _GET нет индекса 'val'.

Правильный способ сделать это так:

if ( isset($_GET["val"]) ) {
    if ( $_GET["val"] ) {
        // Do Something
    } else {
        // Do Nothing
    }
} else {
    // $_GET["value"] variable doesn't exist.  It is neither true, nor false, nor null (unknown value), but would cause an error if evaluated as boolean.
}

Хотя для этого есть ярлыки.

Вы можете проверить комбинацию существования и определенных логических условий с помощью empty (),

if ( !empty($_GET["val"]) ) {
    // Do someting if the val is both set and not empty
    // See http://php.net/empty for details on what is considered empty
    // Note that null is considered empty.
}

или

if ( isset($_GET["val"]) and $_GET["val"] ) {
    // Do something if $_GET is set and evaluates to true.
    // See php.net logical operators page for precedence details,
    // but the second conditional will never be checked (and therefor
    // cause no error) if the isset returns false.
}
6 голосов
/ 06 января 2009

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

"isset () вернет FALSE, если тестирует переменную, для которой установлено значение NULL" ( php.net / isset ).

Это означает, что в некоторых случаях, таких как проверка параметра GET или POST, достаточно использовать isset (), чтобы определить, установлена ​​ли переменная (потому что она будет либо строкой, либо выиграла не будет установлен). Однако в тех случаях, когда NULL является возможным значением для переменной, что довольно часто встречается, когда вы попадаете в объекты и в более сложные приложения, isset () оставляет вас сильным и сухим.

Например (протестировано с PHP 5.2.6 с Suhosin-Patch 0.9.6.2 (cli) (построено: 17 августа 2008 г. 09:05:31)):

<?php
$a = '';
$b = NULL;
var_dump(isset($a));
var_dump(isset($b));
var_dump(isset($c));

выходы:

bool(true)
bool(false)
bool(false)

Спасибо, PHP!

4 голосов
/ 05 января 2009

Проще говоря, эти сравнения не совпадают. Первый приведёт переменную к логическому значению, которое не выполнит проверку пустых массивов, нечисловых строк и других проверок, в которых переменная определенно установлена. Вторая проверка (isset ()) проверяет, существует ли переменная вообще.

Я бы никогда не выполнил первую проверку (логическое приведение) без проверки типа переменной.

Не говоря уже о том, что первая проверка выдает E_NOTICE, и я всегда работаю с максимальным уровнем сообщения об ошибках.

4 голосов
/ 05 января 2009

Первый работает только в зависимости от того, как настроен ваш сервер. На многих производственных серверах он сломается.

Используйте isset() и веселитесь.

Или попробуйте свой код в верхней части исходного кода PHP со следующим текстом:

ini_set('display_errors', 1);
error_reporting(E_ALL);
3 голосов
/ 05 января 2009

Потому что первый может также проверять на истинность / ложь, чего вы можете или не хотите.

2 голосов
/ 05 января 2009

Поскольку первый выводит предупреждение, а также возвращает true, если $ tx === false, что не совпадает с не определенным

1 голос
/ 06 января 2009

Эти два совершенно разные, как указано в каждом ответе. Если вы не используете isset, многие вещи будут иметь значение false, особенно массивы, значения false, числовые значения 0 (и другие) и т. Д. Верно, что.

Мне кажется странным, что все так быстро защищают правильное программирование на PHP. Если я хочу заниматься правильным программированием, у меня есть тонны статически типизированных, строго типизированных языков. Мне кажется, что одним из преимуществ PHP является то, что мне не нужно много думать о типах. Конечно, есть случаи, когда

if ($tx)

оценивается как ложное, когда на самом деле оно имеет значение, но если вы хотите проверить , является ли он объектом транзакции или нет , оно либо работает, либо нет. Оказывается, с помощью Doctrine этот код

if (isset($tx))

всегда оценивается как true после получения первого объекта запроса. Я вместо этого должен сказать

if ($tx instanceof PurchaseRecord)

Так что я хочу сказать, что в PHP вы знаете, для чего вы тестируете! Например, если это параметр из запроса GET, он будет либо пустым, либо пустым, либо будет иметь значение. Вы должны разобраться с этими тремя случаями. Или два случая, или любое другое число случаев в вашем конкретном коде. Если у вас есть, если он работает на вашем сервере разработки и работает на вашем рабочем сервере, может быть, вы можете сказать, что он работает и продолжает свою жизнь?

(В Java или C # он должен компилироваться и затем запускаться без выброса исключений. Большинство исключений NullPointer в Java на самом деле генерируются без проблем: API-интерфейсы Java не могут проверять все нули в коде, потому что это невозможно, а также потому что это не проблема. Если он компилируется и работает тогда, когда он должен, вы знаете, что с вашим кодом все в порядке. Затем вы можете позаботиться о создании более правильных исключений.)

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

0 голосов
/ 05 января 2009

Также важно отметить, что строка в PHP может быть установлена, но пустая. Поэтому isset возвращает true, даже если в строке ничего нет, чтобы предотвратить это, я использую функцию, подобную этой, чтобы заменить isset:

<?php
    function exists($var) {
        if (isset($var) && $var != "") {
            return true;
        } else {
            return false;
        }
    }
?>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...