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
는 무언가를 의미 하려는 써드 파티 라이브러리 일 것입니다. 그러나 null
PHP에서 감지하기가 너무 어렵 기 때문에 아직 이것을 수행하는 라이브러리를 찾지 못했습니다.
답변
그것에 대한 함수를 작성하십시오. 다음과 같은 것 :
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()
기능을 사용해도 괜찮습니다. 사실, 난 사용하여 선호 이 특정 기능을 하는 대신에 의존 해킹 미래에 자신의 행동을 변경할 수 있습니다 기능 과 같은 (회피에 strikedthrough 감수성 ).empty
과isset
그러나 나는 이것에 편리한 간단한 함수 와 배열 인덱스를 다루는 다른 상황 을 사용합니다 .
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이 아닌 경우 첫 번째 피연산자를 리턴합니다. 그렇지 않으면 두 번째 피연산자를 반환합니다.