Çeşitli tartışmalar ve cevapları bir bakışını vermek için çalışılıyor:
There is no single answer to the question which can replace all the ways isset
kullanılabilir. null
mantıksal davranış da Some use cases are addressed by other functions, while others do not stand up to scrutiny, or have dubious value beyond code golf. Far from being "broken" or "inconsistent", other use cases demonstrate why isset
'nin reaksiyonu.
Real use cases (with solutions)
1. Array keys
Diziler unset
ve onlar sanki isset
onları tedavi ile, değişkenlerin koleksiyonları gibi tedavi edilebilir. Onlar iterated beri Ancak, vb, sayılır, bir eksik değer olan değeri olarak aynı değildir null
.
Bu durumda sorunun cevabı, use array_key_exists()
instead of isset()
strong> olduğunu.
Bu bir işlev argüman olarak kontrol etmek için bir dizi alır beri dizinin kendisi yoksa, PHP hala "uyarıları" çıkaracağız. Bazı durumlarda, bu geçerli olarak her boyut ilk başlatıldı olması gerektiğini iddia edilebilir, bu nedenle bildirim işini yapıyor. Diğer durumlarda, bu da dizinin her bir boyuta kontrol "özyinelemeli" array_key_exists
fonksiyonu, bu önlemek, ancak temel olarak @array_key_exists
ile aynı olacaktır. Ayrıca, null
değerlerinin işlenmesi için biraz teğet.
2. Object properties
"Nesne Tabanlı Programlama" geleneksel teoride, kapsülleme ve polimorfizm nesneler önemli özellikleri şunlardır; PHP'nin gibi sınıf tabanlı OOP uygulanmasında, kapsüllü özellikleri, sınıf tanımının parçası olarak bildirilir ve erişim seviyeleri (public
, protected
verilen veya {[(2)] vardır }).
Bir dizi anahtarları, ve bazı insanlar sınıf az nesneleri (kullanmak gibi Ancak, PHP, dinamik bir nesneye özellikler eklemenizi sağlar teknik, hiçbir yöntem vardır ki, stdClass
yerleşik örnekleri veya çağrışımlı dizilere benzer bir şekilde özel işlevleri). Bu fonksiyon, belirli bir özelliği kendisine verilen nesnesine eklenmiş olup olmadığını bilmek isteyebilirsiniz durumlara yol açar.
Dizi tuşları ile olduğu gibi, a solution for checking object properties is included in the language, called, reasonably enough, property_exists
.
Non-justifiable use cases, with discussion
3. register_globals
, and other pollution of the global namespace
register_globals
özellik adları HTTP isteğinin yönleri ile tespit edilmiştir (GET ve POST parametreleri ve çerezler) genel kapsam değişkenleri eklendi. Bu PHP 4.2, released Aug 2000 beri varsayılan olarak devre dışıdır ve PHP 5.4, released Mar 2012 tamamen kaldırılmıştır neden olan, arabası ve güvensiz kod yol açabilir. Ancak, bazı sistemler hala bu özellik etkin veya taklit ile çalışan mümkündür. Bu global
anahtar kelime veya $GLOBALS
dizisi kullanarak başka yollarla küresel ad "kirletme" da mümkündür.
Öncelikle, register_globals
kendisi beklenmedik GET beri, POST ve çerez değerleri her zaman ({hala dönen {[2) (]} ile dizeleri olacak, bir null
değişkeni üretmek olası değildir oturumda [(3)]} den isset
), ve değişkenler tamamen programcının kontrolü altında olmalıdır.
Bu önceki bazı başlatma fazla yazar İkincisi, değer ile bir değişkenin kirlilik null
sadece bir konudur. "Over-yazma" kod başka bir yerde, iki devlet arasındaki ayrım ise bu olasılık against yapmak bir argüman olan kendi üzerinde bu kadar null
, sadece sorunlu olacaktır ile başlatılmamış bir değişken böyle bir ayrım.
4. get_defined_vars
and compact
Böyle get_defined_vars
and compact
, allow you to treat variable names as though they were keys in an array. For global variables, the super-global array $GLOBALS
a> gibi PHP birkaç nadiren kullanılan fonksiyonlar, benzer erişim sağlar ve daha yaygındır. Bir değişken, ilgili kapsamda tanımlı değilse erişim Bu yöntemler farklı davranacaktır.
Bu mekanizmalardan birini kullanarak bir dizi olarak değişkenler bir dizi tedavi etmek için karar verdik, herhangi normal bir dizide gibi üzerinde aynı işlemleri yapabilir. Sonuç olarak, 1'e bakın.
Sadece bu fonksiyonlar (örneğin "get_defined_vars
tarafından döndürülen dizideki bir anahtar 'foo' olacak?") Davranmaya hakkında ne kadar tahmin var İşlevsellik sadece fonksiyonunu çalıştırabilirsiniz beri, gereksiz ve hiçbir kötü etkisi ile öğrenmek.
4a. Variable variables ($$foo
)
Bir ilişkisel diziye değişkenler bir dizi çevirmek fonksiyonları oldukça aynı olmasa da, kullanan çoğu durumda "variable variables" ve kullanmak için değiştirilmesi gerektiğini olabilir ("bu diğer değişkene bağlı adında bir değişkene atamak") ilişkisel dizi yerine.
Bir değişken adı, temelde, programcı tarafından bir değere verilen etiket; run-anda belirlenmesi eğer, gerçekten bir etiket ama bazı anahtar-değer deposunda bir anahtar değil. Daha pratik bir dizi kullanarak değil, vb, yineleme, saymak yeteneğini kaybediyor; o da $$foo
tarafından yazılmış fazla olabilir bu yana, bir değişken "dışarıda" anahtar-değer mağaza olması imkansız hale gelebilir.
Bir kez bir ilişkisel dizi kullanmak için değiştirildi, kod çözüm 1 mükellef olacaktır. Dolaylı nesne özellik erişimi (örneğin, $foo->$property_name
) solüsyonu 2 ile ele alınabilir.
5. isset
is so much easier to type than array_key_exists
Ben bu konuyla çok emin değilim, ama evet, PHP'nin fonksiyon isimleri bazen oldukça soluksuz uzun ve tutarsız olabilir. Görünüşe göre, PHP tarih öncesi sürümleri bir diyez gibi bir işlev adım uzunluğu kullanılır, bu yüzden Rasmus kasten htmlspecialchars
gibi işlev isimleri oluşur bu yüzden karakter alışılmadık bir dizi olurdu ...
Yine de, en azından biz ha, Java yazmıyorsunuz? ;)
6. Uninitialized variables have a type
manual page on variable basics Bu ifadeyi içerir:
Başlatılmamış değişkenler kullanıldıkları bağlama göre kendi türünde bir varsayılan değere sahip
Ben bu deyimi içine çok fazla okuma olup olmadığını "başlatılmamış ama bilinen tip" ya da Zend Motoru bazı kavram var olup olmadığından emin değilim.
Ne açıktır İlklendirilmemiş değişkenler için o sayfada anlatılan davranışları değer bir değişkenin davranışı ile aynıdır, çünkü onların davranışları için hiçbir pratik fark yarattığıdır null
. Bir örnek almak için, hem $a
ve $b
bu kodda tamsayı olarak sona erecek 42
:
unset($a);
$a += 42;
$b = null;
$b += 42;
(Ilk daha iyi kod yazmak için bir girişim, bir bildirilmemiş değişken hakkında bir haber çıkaracağız, ama kod aslında nasıl çalıştığını herhangi bir fark yapmaz.)
99. Detecting if a function has run
(Keeping this one last, as it's much longer than the others. Maybe I'll edit it down later...)
Aşağıdaki kodu göz önünde bulundurun:
$test_value = 'hello';
foreach ( $list_of_things as $thing ) {
if ( some_test($thing, $test_value) ) {
$result = some_function($thing);
}
}
if ( isset($result) ) {
echo 'The test passed at least once!';
}
some_function
null
, echo
bile ulaşmış olmayacak bir olasılık var dönebiliyor some_test
döndürdü {[(4) }]. Programcının niyeti $result
ayarlanmış asla algılamak oldu, ama PHP onları bunu yapmaya izin vermez.
Ancak, bir dış döngü eklerseniz netleşecektir bu yaklaşım ile diğer sorunlar vardır:
foreach ( $list_of_tests as $test_value ) {
// something's missing here...
foreach ( $list_of_things as $thing ) {
if ( some_test($thing, $test_value) ) {
$result = some_function($thing);
}
}
if ( isset($result) ) {
echo 'The test passed at least once!';
}
}
$result
açıkça hiçbir zaman başlatıldı çünkü ilk testi geçerken, imkansız sonraki testleri geçti olup olmadığını söylemek için yapım, bir değer alacaktır. This is actually an extremely common bug when variables aren't initialised properly.
Bunu düzeltmek için, ben bir şey eksik yorumladı ettik hattı üzerinde bir şeyler yapmak gerekiyor. En bariz çözüm $result
some_function
return asla bir "uç değeri" ayarlamak için; Bu ise null
, daha sonra kodun geri kalanı iyi çalışacaktır. some_function
(muhtemelen kendi başına kötü bir işaret) son derece öngörülemeyen bir dönüş türü vardır çünkü bir terminal değer için doğal aday yoksa, o zaman ek bir mantıksal değerdir, örneğin $found
, bunun yerine kullanılabilir.
Thought experiment one: the very_null
constant
, Burada bir terminal değer olarak kullanım için - gibi null
- PHP teorik özel bir sabit sağlayabilir muhtemelen, bir fonksiyonun bu dönmek için yasadışı olurdu, ya da null
zorlanamadığında olacağını ve aynı muhtemelen bir işlev argüman olarak geçen için geçerli olacak. Yani en kısa sürede yeniden faktör kod karar gibi bu çok özel durum biraz daha basit yapmak, ama olur - örneğin, ayrı bir işlevi iç döngü koymak - faydasız olacak. Sürekli fonksiyonlar arasındaki geçmiş olabilir, o some_function
iade etmem garanti olamazdı, bu yüzden artık evrensel bir uç değer olarak yararlı olacaktır.
Bu durumda uninitialised değişkenleri tespit etmek için argüman bu özel sabiti için argüman aşağı kaynar: unset($result)
ile yorum değiştirin ve farklı $result = null
o davranırsanız, size tanıtan bir için "değer" $result
etrafında geçti olamaz, ve sadece belirli yerleşik işlevleri ile tespit edilebilir.
Thought experiment two: assignment counter
Ne son if
"şey $result
için bir atama yaptı?" Sorduğu düşünme başka yolu Aksine özel bir değer olarak dikkate alınarak daha $result
, belki "metadata" about değişkeni, Perl "değişken kusur" gibi bir bit olarak düşünebiliriz. Yani ziyade isset
Eğer has_been_assigned_to
diyoruz, ve oldukça unset
, reset_assignment_state
daha olabilir.
Ama eğer öyleyse, neden bir mantıksal durdurmak? Ne bilmek istiyorsanız how many times testi geçti; sadece bir tamsayı için meta genişletmek ve var get_assignment_count
ve reset_assignment_count
... olabilir
Açıkçası, böyle bir özellik ekleme karmaşıklık ve dil performansında bir trade-off olurdu, bu yüzden dikkatli beklenen faydasına karşı tartılması gerekir. A very_null
sabit olduğu gibi, sadece çok dar durumlarda yararlı olacaktır ve yeniden faktoring benzer şekilde dirençli olacaktır.
PHP zamanı motoru oldukça normal bir kodu kullanarak, açıkça bunu yapmak için bırakmak yerine, bu tür şeyleri takip etmek istediğiniz önceden farz niçin umarım-açık bir soru.