[php] isset () 및 empty ()를 피하는 방법

E_NOTICE 오류 수준에서 실행할 때 많은 “xyz is undefined”및 “undefined offset”메시지를 던지는 이전 응용 프로그램이 여러 개 있습니다. 왜냐하면 변수의 존재는 isset()and consorts를 사용하여 명시 적으로 확인하지 않기 때문 입니다.

누락 된 변수 또는 오프셋에 대한 알림이 생명의 은인이 될 수 있고, 약간의 성능 향상을 얻을 수 있으며, 전체적으로 더 깔끔한 방식이므로 E_NOTICE와 호환되도록 작업하는 것을 고려하고 있습니다.

그러나 수백 개의 isset() empty()array_key_exists()s가 내 코드에 미치는 영향이 마음에 들지 않습니다 . 가치 나 의미의 측면에서 아무것도 얻지 못하고 부풀어지고 가독성이 떨어집니다.

변수 검사를 초과하지 않고 E_NOTICE와 호환되는 코드를 어떻게 구성 할 수 있습니까?



답변

관심있는 분들을 위해이 주제를 작은 기사로 확장했습니다. 아래 정보는 좀 더 구조화 된 형식으로 제공됩니다. The Definitive Guide To PHP isset And empty


IMHO 앱을 “E_NOTICE 호환”으로 만드는 것뿐만 아니라 모든 것을 재구성하는 것에 대해 생각해야합니다. 데 수백 코드에 포인트를 정기적으로 다소 심하게 구조화 된 프로그램과 같은 존재하지 않는 변수 소리를 사용하려고있다. 존재하지 않는 변수에 접근하려는 시도는 절대 일어나서는 안되며, 다른 언어는 컴파일 타임에이 상황을 방해합니다. PHP가 그렇게 할 수 있다는 사실이 그렇게해야한다는 의미는 아닙니다.

이러한 경고는 당신을 성가 시게하는 것이 아니라 당신 을 돕기 위한 것입니다. “존재하지 않는 작업을 시도하고 있습니다!” 라는 경고가 표시되는 경우 , 귀하의 반응은 “죄송합니다. 죄송합니다. 최대한 빨리 수정하겠습니다.” “정의되지 않고 잘 작동하는 변수”심각한 오류를 유발할 수있는 정직하게 잘못된 코드 의 차이점을 어떻게 구분할 있습니까? 이것은 또한 항상 오류보고 를 11로 설정하여 개발 하고 단 하나가 아닐 때까지 코드를 계속 연결 하는 이유이기도합니다.NOTICE . 오류보고 기능을 끄는 것은 정보 유출을 방지하고 버그가있는 코드가있는 경우에도 더 나은 사용자 경험을 제공하기 위해 프로덕션 환경에만 해당됩니다.


자세히 설명하려면 :

항상 필요 isset하거나 empty코드의 어딘가에서 발생을 줄이는 유일한 방법은 변수를 올바르게 초기화하는 것입니다. 상황에 따라 다른 방법이 있습니다.

함수 인수 :

function foo ($bar, $baz = null) { ... }

여부를 확인 할 필요가 없습니다 $bar또는 $baz경우에 그 값들을 평가하는 것입니다에 대해 당신은 단지 그들을 설정하기 때문에 함수 내에서 설정이 모든 당신이 걱정할 필요 true하거나 false(또는 어떤 다른).

어디서나 일반 변수 :

$foo = null;
$bar = $baz = 'default value';

변수를 사용할 코드 블록의 맨 위에서 변수를 초기화하십시오. 이것은 문제를 해결하고 !isset, 변수가 항상 알려진 기본값을 가지도록 보장하고, 독자에게 다음 코드가 어떤 작업을 수행 할 것인지에 대한 아이디어를 제공하여 일종의 자체 문서화 역할도합니다.

어레이 :

$defaults = array('foo' => false, 'bar' => true, 'baz' => 'default value');
$values = array_merge($defaults, $incoming_array);

위와 마찬가지로 기본값으로 배열을 초기화하고 실제 값으로 덮어 씁니다.

나머지 경우 컨트롤러에 의해 설정되거나 설정되지 않은 값을 출력하는 템플릿을 가정 해 보겠습니다. 다음 사항 만 확인하면됩니다.

<table>
    <?php if (!empty($foo) && is_array($foo)) : ?>
        <?php foreach ($foo as $bar) : ?>
            <tr>...</tr>
        <?php endforeach; ?>
    <?php else : ?>
        <tr><td>No Foo!</td></tr>
    <?php endif; ?>
</table>

을 정기적으로 사용 array_key_exists하고 있다면 어떤 용도로 사용하는지 평가해야합니다. 차이를 만드는 유일한 경우는 다음과 같습니다.

$array = array('key' => null);
isset($array['key']); // false
array_key_exists('key', $array); // true

위에서 언급했듯이 변수를 올바르게 초기화하는 경우 키가 존재하는지 여부를 알기 때문에 확인할 필요가 없습니다. 외부 소스에서 배열을 얻는 경우, 값이 가장 가능성이되지 않습니다 null'', 0, '0', false또는 같은, 즉 가치 당신과 함께 평가할 수 있습니다 isset또는 empty귀하의 의도에 따라. 정기적으로 배열 키를 설정 한 경우 null와 평균 아무것도를 원하지만 false, 즉, 위의 예에서의 서로 다른 결과를 경우 isset와는 array_key_exists왜 프로그램 로직에 변화를, 당신은 자신을 요청해야합니다. 변수의 존재만으로는 중요하지 않으며 그 값만이 중요해야합니다. 키가 true/ false플래그이면true또는 false,하지 null. 이것에 대한 유일한 예외 null는 무언가를 의미 하려는 써드 파티 라이브러리 일 것입니다. 그러나 nullPHP에서 감지하기가 너무 어렵 기 때문에 아직 이것을 수행하는 라이브러리를 찾지 못했습니다.


답변

그것에 대한 함수를 작성하십시오. 다음과 같은 것 :

function get_string($array, $index, $default = null) {
    if (isset($array[$index]) && strlen($value = trim($array[$index])) > 0) {
        return get_magic_quotes_gpc() ? stripslashes($value) : $value;
    } else {
        return $default;
    }
}

당신이 사용할 수있는

$username = get_string($_POST, 'username');

같은 사소한 것들에 대해 동일한 작업을 수행 get_number(), get_boolean(), get_array()과에 이렇게.


답변

이 문제를 해결하는 가장 좋은 방법 중 하나는 클래스를 통해 GET 및 POST (COOKIE, SESSION 등) 배열의 값에 액세스하는 것입니다.

각 배열 및 선언 __get__set메서드에 대한 클래스를 만듭니다 ( overloading ). __get값의 이름이 될 하나의 인수를 허용합니다. 이 메서드는 다음을 사용하여 해당 전역 배열에서이 값을 확인해야합니다.isset() 하거나 empty()및 존재하는 경우, 또는 값을 반환 null달리 (또는 다른 디폴트 값).

그런 다음 다음과 같이 자신있게 배열 값에 액세스 할 수 있습니다. $POST->username 필요한 경우 isset()s 또는 empty()s를 사용하지 않고 유효성 검사를 수행 할 수 있습니다. 경우 username해당 전역 배열에 존재하지 않는 다음 null에는 경고 또는주의 사항이 발생되지 않도록, 반환됩니다.


답변

array_key_exists()기능을 사용해도 괜찮습니다. 사실, 난 사용하여 선호 이 특정 기능을 하는 대신에 의존 해킹 미래에 자신의 행동을 변경할 수 있습니다 기능 과 같은 emptyisset (회피에 strikedthrough 감수성 ).


그러나 나는 이것에 편리한 간단한 함수 와 배열 인덱스를 다루는 다른 상황 을 사용합니다 .

function Value($array, $key, $default = false)
{
    if (is_array($array) === true)
    {
        settype($key, 'array');

        foreach ($key as $value)
        {
            if (array_key_exists($value, $array) === false)
            {
                return $default;
            }

            $array = $array[$value];
        }

        return $array;
    }

    return $default;
}

다음과 같은 배열이 있다고 가정 해 보겠습니다.

$arr1 = array
(
    'xyz' => 'value'
);

$arr2 = array
(
    'x' => array
    (
        'y' => array
        (
            'z' => 'value',
        ),
    ),
);

배열에서 “값”을 어떻게 얻습니까? 단순한:

Value($arr1, 'xyz', 'returns this if the index does not exist');
Value($arr2, array('x', 'y', 'z'), 'returns this if the index does not exist');

우리는 이미 단일 및 다차원 배열을 다루고 있습니다. 다른 무엇을 할 수 있습니까?


예를 들어 다음 코드를 사용하십시오.

$url = '/programming/1960509';
$domain = parse_url($url);

if (is_array($domain) === true)
{
    if (array_key_exists('host', $domain) === true)
    {
        $domain = $domain['host'];
    }

    else
    {
        $domain = 'N/A';
    }
}
else
{
    $domain = 'N/A';
}

꽤 지루하지 않나요? 다음은 Value()함수를 사용하는 또 다른 접근 방식입니다 .

$url = '/programming/1960509';
$domain = Value(parse_url($url), 'host', 'N/A');

추가 예를 들어, 테이크 RealIP()기능 테스트를 들어 :

$ip = Value($_SERVER, 'HTTP_CLIENT_IP', Value($_SERVER, 'HTTP_X_FORWARDED_FOR', Value($_SERVER, 'REMOTE_ADDR')));

깔끔 하죠? 😉


답변

난 당신과 함께 여기 있어요. 그러나 PHP 디자이너는 그보다 훨씬 더 나쁜 실수를 저질렀습니다. 값 읽기에 대한 사용자 지정 함수를 정의하는 데 부족하면 그 주위에 방법이 없습니다.


답변

이 기능을 사용합니다

function load(&$var) { return isset($var) ? $var : null; }
function POST($var) { return isset($_POST[$var]) ? $_POST[$var] : null; }

$y = load($x); // null, no notice

// this attitude is both readable and comfortable
if($login=POST("login") and $pass=POST("pass")) { // really =, not ==
  // executes only if both login and pass were in POST
  // stored in $login and $pass variables
  $authorized = $login=="root" && md5($pass)=="f65b2a087755c68586568531ad8288b4";
}


답변

null 병합 연산자 (PHP> = 7.0.1)에 오신 것을 환영합니다 .

$field = $_GET['field'] ?? null;

PHP 말한다 :

isset ()과 함께 삼항을 사용해야하는 일반적인 경우를 위해 null 병합 연산자 (??)가 구문 설탕으로 추가되었습니다. 존재하고 NULL이 아닌 경우 첫 번째 피연산자를 리턴합니다. 그렇지 않으면 두 번째 피연산자를 반환합니다.