isset () ve boş () kodu çirkin hale

9 Cevap php

Ben "xyz tanımsız" ve E_NOTICE hata düzeyde çalışırken değişkenlerin varlığı açıkça isset() ve eşlerinden kullanılarak kontrol olmadığı için, mesajları "offset tanımsız" bir sürü atmak birkaç eski uygulamaları var.

Ben eksik değişkenler veya uzaklıklar hakkında bildirimler kurtaranlar olabilir gibi, orada elde edilecek bazı küçük performans iyileştirmeleri olması, ve genel temiz yolu olabilir, onları E_NOTICE uyumlu hale getirmek için çalışma onları aracılığıyla düşünüyor yaşıyorum.

Ancak, isset() empty() ve yüzlerce inflicting array_key_exists() s kodumu ne sevmiyorum. Bu şişirilmiş alır, değer veya anlam açısından hiçbir şey almadan, daha az okunabilir hale gelir.

Aynı şekilde hissediyor orada kimse var mı? Bu konuda ne yapmalıyım?

Ben arıyorum, ve geçici çözümler, sihirli işlevleri ve / veya okunabilirliğe sıkı değişken denetleme etkisini en aza indirmek için en iyi uygulamalar için, umut ediyorum.

9 Cevap

İlgilenenler için, ben biraz daha iyi yapılandırılmış biçimde aşağıdaki bilgileri sağlayan küçük bir makalede, bu konuyu da genişlettik: The Definitive Guide To PHP's isset And empty


Sadece app "E_NOTICE uyumlu" hale, ama her şeyi yeniden olmadığını düşünmek gerekir IMHO. hundreds düzenli olmayan değişkenleri kullanmaya çalışın kodunuzda puan olması oldukça kötü yapılandırılmış bir program gibi geliyor. Olmayan değişkenler hiç gerçekleşmesi asla erişmeye çalışırken, diğer dillerde derleme zamanında bu ürkmek. PHP bunu yapmak için izin verdiği gerçeği gerektiği anlamına gelmez.

Bu uyarılar sizi rahatsız etmek değil, help sizin için vardır. Eğer bir uyarı "You're trying to work with something that doesn't exist!" alırsanız, sizin tepkiniz "Oops, my bad, let me fix that ASAP." başka nasıl "variables that work just fine undefined" ve honestly wrong code that may lead to serious errors arasındaki farkı anlatmak için gidiyoruz olmalıdır? Bu da her zaman, always, hata raporlama turned to 11 ile geliştirmek ve tek bir NOTICE verilir kadar değil kodunuzu uzak takmayı tutmak nedeni de budur. Off raporlama hatası dönüm bilgi sızıntısını önlemek ve hatta arabası kod karşısında daha iyi bir kullanıcı deneyimi sağlamak için, sadece üretim ortamları için olduğunu.


Ayrıntı için:

Her zaman isset ihtiyaç veya empty yere kodu olacak, onların oluşumunu azaltmak için tek yolu düzgün değişkenlerini başlatmak için olduğunu. Duruma bağlı olarak bunu yapmak için farklı yolları vardır:

Fonksiyon argümanları:

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

Onların değerini {değerlendirilirse $bar veya sadece bunları ayarlamak için $baz işlevinin içinde ayarlanır, sen dert etmenize gerek tüm olup olmadığını kontrol etmek gerek [(2)] var } veya false (ya da başka ne olursa olsun).

Her yerde normal değişkenler:

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

Eğer bunları kullanmak için gidiyoruz hangi kod bloğunun üstündeki değişkenlerini başlatmak. Bu, !isset sorunu çözer değişkenler her zaman bilinen bir varsayılan değere sahip olmasını sağlar, okuyucuya aşağıdaki kod üzerinde çalışacak bir fikir verir ve böylece de kendini belgelerin bir tür olarak hizmet vermektedir.

Diziler:

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

Yukarıdaki gibi aynı şey, varsayılan değerlerle dizi başlatılıyor ve gerçek değerleri ile onları üzerine ediyoruz.

Geri kalan durumlarda, diyelim ki ya bir kontrolör tarafından belirlenen olmayabilir değerleri çıktılıyorsanız bir şablon diyelim, sadece kontrol etmek gerekir:

<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>

Kullanarak kendiniz düzenli bulursanız array_key_exists, sizin için kullanıyoruz ne değerlendirmelidir. Bir fark yapar sadece zaman burada:

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

Rağmen yukarıda belirtildiği gibi düzgün değişkenleri başlatırken eğer öyle biliyorum çünkü, sen, anahtar var ya da kontrol etmek gerekmez. Eğer harici bir kaynaktan dizi alıyorsanız, değeri muhtemelen olmayacaktır null ama '', 0, '0' false ya da bunun gibi bir şey, bir değere yani sizin niyet bağlı olarak, isset veya empty ile değerlendirebilir. Düzenli null bir dizi anahtarı ayarlayın ve bir şey ama false, yani demek istiyorum eğer yukarıdaki örnekte isset ve {[farklılaşan sonuçlar (10)]} program mantığı bir fark yaratmak, neden kendinize sormalısınız. Bir değişkenin sadece varlığı önemli olmamalıdır, sadece değer bir sonuç olmalıdır. Anahtar a true / false bayrak ise, o zaman kullanmak true ya da false değil, null. Bunun tek istisnası null şey demek istiyorum 3. parti kütüphaneler olabilir, ama null Bunu yapan herhangi bir kütüphaneyi bulmak için henüz PHP tespit etmek çok zor olduğundan olur.

Sadece bunun için bir fonksiyon yazmak. Gibi bir şey:

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;
    }
}

olarak kullanmak hangi

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

get_number(), get_boolean(), get_array() ve benzeri gibi önemsiz şeyler için aynı şeyi.

Ben bu sorunla başa çıkma en iyi yollarından biri bir sınıf aracılığıyla GET ve POST (COOKIE, OTURUM, vb) diziler değerlerini erişerek olduğuna inanıyorum.

O dizilerin her biri için bir sınıf oluşturmak ve __get ve __set yöntemlerini bildirmek (overloading). __get bir değerin adı olacaktır bir argüman kabul eder. Bu yöntem, isset() veya empty() kullanarak ya gelen küresel dizide bu değerini denetlemek ve varsa değer döndürür veya null (veya bazı diğer varsayılan değer) olmalıdır Aksi durumda.

Bundan sonra güvenle bu şekilde dizi değerlerini erişebilirsiniz: $POST->username ve isset() s veya empty() s olmadan gerekli varsa doğrulama yapmak. username gelen küresel dizide yoksa o null iade edilecektir, böylece herhangi bir uyarı veya bildirimler oluşturulur.

Ben, array_key_exists() kullanarak umursamıyorum aslında ben gelecekte onların davranışlarını {[(değişebilir *hack* işlevleri kullanarak this specific function yerine güvenerek tercih 3)]} ve isset (strikedthrough to avoid susceptibilities).


Ben ancak, bu kullanışlı geliyor basit bir fonksiyon, ve diğer bazı durumlarda kullanmak in dealing with array indexes do:

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;
}

Diyelim ki aşağıdaki diziler ettik diyelim:

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

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

Nasıl dizilerin dışında "değerini" alabilirim? Basit:

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');

We already have uni and multi-dimensional arrays covered, what else can we possibly do?


Örneğin aşağıdaki kod parçası atın:

$url = 'http://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';
}

Pretty boring isn't it? Here is another approach using the Value() fonksiyonu:

$url = 'http://stackoverflow.com/questions/1960509';
$domain = Value(parse_url($url), 'host', 'N/A');

Ek bir örnek olarak, take the RealIP() function bir test için:

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

Neat, huh? ;)

Ben bu fonksiyonu kullanmak

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

Örnekler

$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;
  ...
}

Seninle buradayım. Ancak PHP tasarımcılar çok daha kötü hatalar daha yaptı. Herhangi bir değer okuma için özel bir işlevi tanımlamanın kısa, etrafında hiçbir yolu yoktur.

Eğer düzgün ele gerekir eksik bir şey bekliyoruz, yazılım sihirli, tanrının lütfuyla çalışmaz. bunu görmezden eğer muhtemelen uygulamalarda güvenlik açıkları yaratıyor. olmayan bir tanımlı değişken sadece mümkün değildir erişen statik dillerde, sadece derlemek ya da boş ise uygulama çökme olmaz. ayrıca uygulama unmaintainable yapar ve beklenmedik şeyler zaman deli gidecek. dil katılık tasarım, pek çok açıdan yanlış olduğunu, bir zorunluluktur ve php. Eğer farkında değilseniz bu size kötü bir programcı yapacaktır.

Ben okunabilirliği sizin tanımı nedir emin değilim, ama boş doğru kullanımı (), isset () ve / catch blokları atmak / deneyin, tüm süreç için oldukça önemlidir. Lütfen E_NOTICE $ _GET veya $ _POST, geliyor ise o zaman doğru veri geçmek için sahip olması gereken tüm diğer güvenlik kontrolleri ile birlikte () boş karşı kontrol edilmelidir. Dış beslemeleri veya kütüphanelerden geliyor ise, try / catch sarılmış olmalıdır. Bu veritabanından geliyor ise, $ db_num_rows () veya eşdeğer olduğunu kontrol edilmelidir. Iç değişkenler geliyor, bunlar düzgün başlatılmamış olmalıdır. Genellikle, bildirimlerin bu tür bir başarısızlık durumunda FALSE döndüren bir işlevin dönüş için yeni bir değişken atayarak gelen, bu bir başarısızlık durumunda, büyüklüğünün kabul edilebilir bir varsayılan değer atayabilirsiniz ya, bu bir test sarılmış olmalıdır kod işlemek, ya da kod işleyebilir bir istisna atma olabilir. Ben onlar kesinlikle ekstra değer katmak düşünüyorum Bunlar ekstra bloklar eklemek ve ekstra testler eklemek, daha uzun kod yapmak, ama o size katılmıyorum.

What about using the @ operator ? e.g.:

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

Eğer (örneğin bir PHP hatası içeren bir işlev çağrısı ise) ama sadece değişkenler için bu tekniği kullanmak, bu eşdeğerdir "içeride" $ foo ne üzerinde hiçbir kontrole sahip, çünkü bu kötü olduğunu söyleyebiliriz:

if(isset($foo) && $foo) { /* ... */ }