복붙노트

isset () 및 empty ()를 피하는 방법

PHP

isset () 및 empty ()를 피하는 방법

변수의 존재가 isset ()과 consort를 사용하여 명시 적으로 검사되지 않았기 때문에 E_NOTICE 오류 수준에서 실행될 때 "xyz is undefined"및 "undefined offset"메시지를 많이 던지는 여러 오래된 응용 프로그램이 있습니다.

누락 된 변수 나 오프셋에 대한주의 사항이 생명의 은인 일 수 있고 약간의 성능 향상이있을 수 있으며 전반적으로 더 깨끗한 방법이므로 E_NOTICE와 호환되도록 노력하고 있습니다.

그러나, 나는 isset ()과 array_key_exists ()가 내 코드에하는 영향을 좋아하지 않는다. 그것은 부 풀리게되고, 가치 또는 의미면에서 아무것도 얻지 않고 읽기가 어려워집니다.

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

해결법

  1. ==============================

    1.관심있는 사람들을 위해, 나는이 주제를 약간 더 나은 구조화 된 형태로 아래의 정보를 제공하는 작은 기사로 확장했다. PHP의 확실한 안내서 및 비어 있음

    관심있는 사람들을 위해, 나는이 주제를 약간 더 나은 구조화 된 형태로 아래의 정보를 제공하는 작은 기사로 확장했다. PHP의 확실한 안내서 및 비어 있음

    IMHO 당신은 앱을 "E_NOTICE compatible"로 만드는 것뿐만 아니라 모든 것을 재구성하는 것에 대해 생각해야합니다. 존재하지 않는 변수를 정기적으로 사용하려고하는 코드에 수백 가지 포인트가 있으면 오히려 심하게 구조화 된 프로그램처럼 들릴 수 있습니다. 존재하지 않는 변수에 액세스하려는 시도는 절대로 일어나지 않아야합니다. 다른 언어에서는 컴파일 타임에이 작업을 중단해야합니다. PHP가 그렇게 할 수 있다고해서 꼭해야한다는 것은 아닙니다.

    이 경고는 당신을 괴롭히지 않고 당신을 도울 것입니다. "존재하지 않는 무언가로 작업하려고 시도 중입니다!"라는 경고를받는다면 반응은 "죄송합니다. 내 잘못, 최대한 빨리 해결하겠습니다." "잘 정의되지 않은 변수"와 심각한 오류를 유발할 수있는 정직하지 못한 코드의 차이점을 어떻게 알 수 있습니까? 또한 항상 오류보고를 11로 설정하여 개발하고 단일주의 사항이 발행 될 때까지 코드에 계속 표시되도록하는 이유이기도합니다. 오류보고 기능을 해제하면 프로덕션 환경에서만 정보 누출을 방지하고 버그가있는 코드가있는 경우에도 더 나은 사용자 환경을 제공합니다.

    정교하게 :

    코드에서 어딘가에 항상 비어 있거나 빈 공간이 필요합니다. 변수를 제대로 초기화하는 유일한 방법은 변수를 올바르게 초기화하는 것입니다. 상황에 따라 다양한 방법이 있습니다.

    함수 인수 :

    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 플래그 인 경우, null이 아닌 true 또는 false를 사용하십시오. 이것에 대한 유일한 예외는 null을 의미하는 제 3 자 라이브러리이지만, PHP에서 null을 검출하기가 어렵 기 때문에 아직이 라이브러리를 찾지 못했습니다.

  2. ==============================

    2.그것을위한 함수를 작성하십시오. 같은 것 :

    그것을위한 함수를 작성하십시오. 같은 것 :

    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 () 등과 같은 사소한 것들에 대해서도 같은 작업을 수행하십시오.

  3. ==============================

    3.이 문제를 극복하는 최선의 방법 중 하나는 클래스를 통해 GET 및 POST (COOKIE, SESSION 등) 배열의 값에 액세스하는 것입니다.

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

    각 배열에 대한 클래스를 만들고 __get 및 __set 메서드를 선언합니다 (오버로드). __get은 값의 이름이 될 인수 하나를 허용합니다. 이 메소드는 isset () 또는 empty ()를 사용하여 해당 글로벌 배열에서이 값을 확인하고 값이 존재하면 null을 반환하고 그렇지 않으면 null을 반환해야합니다.

    그 후에는 $ POST-> username과 같은 배열 값에 자신있게 액세스 할 수 있으며 필요한 경우 isset () 또는 empty ()를 사용하지 않고 모든 유효성 검사를 수행합니다. username이 대응하는 글로벌 배열 내에 존재하지 않는 경우는 null가 돌려 주어져 경고 또는 통지가 생성되지 않습니다.

  4. ==============================

    4.array_key_exists ()를 사용해도 상관 없습니다. 실제로는 빈 함수와 isset (감수성을 피하기위한 strikedthrough)와 같은 미래의 행동을 바꿀 수있는 해킹 함수에 의존하기보다는이 특정 함수를 사용하는 것을 선호합니다.

    array_key_exists ()를 사용해도 상관 없습니다. 실제로는 빈 함수와 isset (감수성을 피하기위한 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 = 'https://stackoverflow.com/questions/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 = 'https://stackoverflow.com/questions/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')));
    
  5. ==============================

    5.난 당신과 함께 여기 있어요. 그러나 PHP 디자이너들은 그것보다 훨씬 더 나쁜 실수를 저질 렀습니다. 모든 값 독서에 대한 사용자 정의 함수를 정의하는 것만으로는 부족합니다.

    난 당신과 함께 여기 있어요. 그러나 PHP 디자이너들은 그것보다 훨씬 더 나쁜 실수를 저질 렀습니다. 모든 값 독서에 대한 사용자 정의 함수를 정의하는 것만으로는 부족합니다.

  6. ==============================

    6.나는이 기능을 사용한다.

    나는이 기능을 사용한다.

    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")) // really =, not ==
    if($pass=POST("pass"))
    if($login=="Admin" && $pass==...) {
      // login and pass are not empty, login is "Admin" and pass is ...
      $authorized = true;
      ...
    }
    
  7. ==============================

    7.설정되지 않은 경우 false를 반환하는 함수를 만들고, 지정된 경우 비어 있으면 false를 반환합니다. 유효하면 변수를 리턴합니다. 아래 코드와 같이 옵션을 추가 할 수 있습니다.

    설정되지 않은 경우 false를 반환하는 함수를 만들고, 지정된 경우 비어 있으면 false를 반환합니다. 유효하면 변수를 리턴합니다. 아래 코드와 같이 옵션을 추가 할 수 있습니다.

    <?php
    function isset_globals($method, $name, $option = "") {
        if (isset($method[$name])) {    // Check if such a variable
            if ($option === "empty" && empty($method[$name])) { return false; } // Check if empty 
            if ($option === "stringLength" && strlen($method[$name])) { return strlen($method[$name]); }    // Check length of string -- used when checking length of textareas
            return ($method[$name]);
        } else { return false; }
    }
    
    if (!isset_globals("$_post", "input_name", "empty")) {
        echo "invalid";
    } else {
        /* You are safe to access the variable without worrying about errors! */
        echo "you uploaded: " . $_POST["input_name"];
    }
    ?>
    
  8. ==============================

    8.Null 병합 연산자에 오신 것을 환영합니다.

    Null 병합 연산자에 오신 것을 환영합니다.

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

    PHP는 말합니다 :

  9. ==============================

    9.가독성에 대한 정의가 무엇인지 모르겠지만 empty (), isset () 및 try / throw / catch 블록을 올바르게 사용하는 것이 전체 프로세스에서 매우 중요합니다. E_NOTICE가 $ _GET 또는 $ _POST에서 오는 경우, 그 데이터가 통과해야하는 다른 모든 보안 검사와 함께 empty ()를 검사해야합니다. 외부 피드 나 라이브러리에서 오는 경우 try / catch로 래핑해야합니다. 데이터베이스에서 오는 경우 $ db_num_rows () 또는 이에 상응하는 것이 검사되어야합니다. 내부 변수에서 오는 경우 올바르게 초기화해야합니다. 이러한 유형의주의 사항은 종종 실패시 FALSE를 반환하는 함수 반환에 새 변수를 지정하는 것으로부터 발생합니다. 오류가 발생하면 변수를 허용 가능한 기본값으로 할당 할 수있는 테스트에 래핑해야합니다 코드에서 처리 할 수 ​​있거나 코드가 처리 할 수있는 예외를 throw합니다. 이러한 것들은 코드를 더 길게 만들고, 여분의 블록을 추가하고, 추가 테스트를 추가하지만, 나는 그들이 여러분이 가장 가치있게 추가했다고 생각한다는 점에서 동의하지 않습니다.

    가독성에 대한 정의가 무엇인지 모르겠지만 empty (), isset () 및 try / throw / catch 블록을 올바르게 사용하는 것이 전체 프로세스에서 매우 중요합니다. E_NOTICE가 $ _GET 또는 $ _POST에서 오는 경우, 그 데이터가 통과해야하는 다른 모든 보안 검사와 함께 empty ()를 검사해야합니다. 외부 피드 나 라이브러리에서 오는 경우 try / catch로 래핑해야합니다. 데이터베이스에서 오는 경우 $ db_num_rows () 또는 이에 상응하는 것이 검사되어야합니다. 내부 변수에서 오는 경우 올바르게 초기화해야합니다. 이러한 유형의주의 사항은 종종 실패시 FALSE를 반환하는 함수 반환에 새 변수를 지정하는 것으로부터 발생합니다. 오류가 발생하면 변수를 허용 가능한 기본값으로 할당 할 수있는 테스트에 래핑해야합니다 코드에서 처리 할 수 ​​있거나 코드가 처리 할 수있는 예외를 throw합니다. 이러한 것들은 코드를 더 길게 만들고, 여분의 블록을 추가하고, 추가 테스트를 추가하지만, 나는 그들이 여러분이 가장 가치있게 추가했다고 생각한다는 점에서 동의하지 않습니다.

  10. ==============================

    10.소프트웨어는 신의 은혜로 마술처럼 움직이지 않습니다. 당신이 놓친 것을 기대하고 있다면 제대로 처리해야합니다. 이를 무시하면 응용 프로그램에 보안 허점이 생길 수 있습니다. 정의되지 않은 변수에 액세스하는 정적 언어는 단지 불가능합니다. null 인 경우 응용 프로그램을 컴파일하거나 크래시하지 않습니다. 또한 응용 프로그램을 유지할 수 없게 만들고 예기치 않은 일이 발생하면 화를 낼 것입니다. 언어의 엄격함은 필수이고 PHP는 설계 상 많은면에서 잘못되었습니다. 당신이 잘 모르는 경우 나쁜 프로그래머가 될 것입니다.

    소프트웨어는 신의 은혜로 마술처럼 움직이지 않습니다. 당신이 놓친 것을 기대하고 있다면 제대로 처리해야합니다. 이를 무시하면 응용 프로그램에 보안 허점이 생길 수 있습니다. 정의되지 않은 변수에 액세스하는 정적 언어는 단지 불가능합니다. null 인 경우 응용 프로그램을 컴파일하거나 크래시하지 않습니다. 또한 응용 프로그램을 유지할 수 없게 만들고 예기치 않은 일이 발생하면 화를 낼 것입니다. 언어의 엄격함은 필수이고 PHP는 설계 상 많은면에서 잘못되었습니다. 당신이 잘 모르는 경우 나쁜 프로그래머가 될 것입니다.

  11. ==============================

    11.@ 연산자를 사용하는 것은 어떻습니까? 예 :

    @ 연산자를 사용하는 것은 어떻습니까? 예 :

    if(@$foo) { /* do something */ }
    

    $ foo 내부에서 어떤 일이 일어나는지 제어 할 수 없기 때문에 (예를 들어 PHP 오류가 포함 된 함수 호출 인 경우)이 방법을 변수에만 사용하면이 방법은 다음과 동일합니다.

    if(isset($foo) && $foo) { /* ... */ }
    
  12. from https://stackoverflow.com/questions/1960509/how-to-avoid-isset-and-empty by cc-by-sa and MIT license