PHP 7 öncesinde “dize, verilen dize örneği olmalı” nasıl çözümlenir?


217

İşte benim kod:

function phpwtf(string $s) {
    echo "$s\n";
}
phpwtf("Type hinting is da bomb");

Bu hatayla sonuçlanan:

Catchable ölümcül hatası: phpwtf () öğesine iletilen argüman 1 dize örneği olmalı, dize verildi

PHP'nin aynı nefeste istenen türü tanıdığını ve reddettiğini görmek biraz Orwellian'dan daha fazla. Beş ışık var, kahretsin.

PHP dizeleri için tür ipucu eşdeğeri nedir? Burada neler olup bittiğini tam olarak açıklayan cevaba bonus değerlendirmesi.


5
Çünkü yanlış yapıyorsunuz. Kodunuzun çalışmaya başlaması gerekmez. PHP belgelerinde hokkabazlık türünü okuyun. PHP dinamik ve zayıf yazılmıştır. Dizeye bir argüman atmak için (string) öğesini kullanabilirsiniz (yalnızca işlev gövdesinde olsa da), ancak yalnızca kod snippet'inizde yaptığınız gibi nesneleri ve dizileri işaretleyebilirsiniz.
Richard Knop

7
Sorun şu ki, küçük bir hata yaptınız. Orada dört ışıkları!
CJ Dennis

@ Gordon, 5.6'da test ettim. Hala şans yok.
Pacerier

@Pacerier En son gelişmeler için lütfen wiki.php.net/rfc adresini takip edin .
Gordon

3
Görünüşe göre, skaler tip ipucu (OP'nin sezgisel olarak yukarıdaki bir şey olması beklendiği gibi) sonunda kaynağa göre PHP * 7 * için bir RFC altında onaylanmıştır . Onaylanmış RFC, görünüşte tip kontrol dönüş değerleri ve parametreler (argümanlar) için sözdizimsel şeker de sağlar . Çok uzun zaman oldu.
SeldomNeedy

Yanıtlar:


204

PHP 7'den önce tür ipucu yalnızca nesne ve dizilerin türlerini zorlamak için kullanılabilir. Skaler tipler tip-hintable değildir. Bu durumda sınıfın bir nesnesi stringbeklenir, ancak ona bir (skaler) veriyorsunuz string. Hata mesajı komik olabilir, ancak başlamak için çalışması gerekmez. Dinamik yazım sistemi göz önüne alındığında, bu aslında bir çeşit sapkın anlam taşır.

Yalnızca el ile "ipucu yaz" skaler türlerini kullanabilirsiniz:

function foo($string) {
    if (!is_string($string)) {
        trigger_error('No, you fool!');
        return;
    }
    ...
}

1
@deceze, Ters tip ipucu için bir sözdizimi var mı? Örneğin şey ama diziler.
Pacerier

@ Pacer Hayır, yok.
deceze

4
Bu cevap PHP 7
Jose Nobile

24

Gönderen PHP'nin kılavuzu :

Tür İpuçları yalnızca nesne ve dizi (PHP 5.1'den beri) türünde olabilir. İnt ve string ile geleneksel tip ipucu desteklenmez.

Yani sende var. Hata mesajı gerçekten yararlı değil, ben size bunu vermek.

** 2017 Düzenleme **

PHP7 daha fazla işlev veri türü bildirimi getirdi ve yukarıda belirtilen bağlantı İşlev bağımsız değişkenleri: Tür bildirimleri'ne taşındı . Bu sayfadan:

Geçerli tipler

  • Sınıf / arayüz adı : Parametre, verilen sınıf veya arayüz adının bir örneği olmalıdır. (PHP 5.0.0'dan beri)
  • self : Parametre, yöntemin tanımlandığı sınıf ile aynı olmalıdır. Bu yalnızca sınıf ve örnek yöntemlerinde kullanılabilir. (PHP 5.0.0'dan beri)
  • array : Parametre bir dizi olmalıdır. (PHP 5.1.0'dan beri) callable Parametre geçerli bir callable olmalıdır. PHP 5.4.0
  • bool : Parametre bir boolean değeri olmalıdır. (PHP 7.0.0'dan beri)
  • float : Parametre bir kayan nokta sayısı olmalıdır. (PHP 7.0.0'dan beri)
  • int : Parametre bir tamsayı olmalıdır. (PHP 7.0.0'dan beri)
  • string : Parametre bir dize olmalıdır. (PHP 7.0.0'dan beri)
  • iterable : Parametre bir dizi veya Traversable örneği olmalıdır. (PHP 7.1.0'dan beri)

Uyarı

Yukarıdaki skaler tipler için takma adlar desteklenmez. Bunun yerine, sınıf veya arabirim adı olarak ele alınırlar. Örneğin, boolean'ı parametre veya dönüş türü olarak kullanmak, bool türünden ziyade class veya interface boolean örneğinin örneği olan bir argüman veya dönüş değeri gerektirir:

<?php
   function test(boolean $param) {}
   test(true);
 ?>

Yukarıdaki örnek çıktı verecektir:

 Fatal error: Uncaught TypeError: Argument 1 passed to test() must be an instance of boolean, boolean given, called in - on line 1 and defined in -:1

Son uyarı aslında "string türünde argüman olmalı, verilen dize" hatasını anlamak için önemlidir; çoğunlukla yalnızca sınıf / arabirim adlarına bağımsız değişken türü olarak izin verildiğinden, PHP bir sınıf adı "dizesi" bulmaya çalışır, ancak ilkel bir tür olduğu için bulamaz, bu nedenle bu garip hatayla başarısız olur.


8

PHP bir nesneyi belirtmek için bir sınıf sağladığınız "ipucu" sağlar. PHP kılavuzuna göre, "Tür İpuçları yalnızca nesne ve dizi (PHP 5.1'den beri) türünde olabilir. İnt ve string ile geleneksel tür ipuçları desteklenmez." Hata, "string" seçiminiz nedeniyle kafa karıştırıcıdır - "myClass" ifadesini yerine koyun ve hata farklı şekilde okunur: "phpwtf () öğesine iletilen bağımsız değişken 1, verilen dize myClass örneği olmalı"


3

Diğerlerinin söylediği gibi, tür ipucu şu anda yalnızca nesne türleri için çalışır. Ama tetiklediğiniz belirli bir hata yaklaşan dize türü SplString hazırlık olabilir düşünüyorum .

Teoride bir dize gibi davranır, ancak bir nesne olduğu için nesne türü doğrulamasını geçecektir. Ne yazık ki henüz PHP 5.3'te değil, 5.4'te gelebilir, bu yüzden bunu test etmedim.


2

Bu türleri mevcuttur böylece PHP 7.0 itibariyle tür tanımları, skaler türlerine izin ver: self, array, callable, bool, float, int, string. İlk üçü PHP 5'te mevcuttu, ancak son dördü PHP 7'de yeniydi. Sınıf adı olarak yorumlanacak başka bir şey (örneğin integerveya boolean) kullanırsanız.

Daha fazla bilgi için PHP kılavuzuna bakın .


0

Belki güvenli ve güzel değil ama yapmanız gerekiyorsa:

class string
{
    private $Text;
    public function __construct($value)
    {
        $this->Text = $value;
    }

    public function __toString()
    {
        return $this->Text;
    }
}

function Test123(string $s)
{
    echo $s;
}

Test123(new string("Testing"));

5
Hala bir tane oluşturabilirimnew string(array(1,2,3))
Jimmy T.

0

Laravel Controller'dan bir PHP dosyasına bir fonksiyon çağırırken bu hatayı aldım.

Birkaç saat sonra sorunu buldum: statik bir fonksiyon içinde $ bunu kullanıyordum .


Using $this when not in object contextaslında şifreli bir mesajdır.
Ben Fransen

0

(aslen soruya leepowers tarafından gönderildi )

Hata mesajı büyük bir nedenden dolayı kafa karıştırıcı:

İlkel tür adları PHP'de ayrılmaz

Aşağıdakilerin tümü geçerli sınıf bildirimleridir:

class string { }
class int { }
class float { }
class double { }

Benim hatam, hata mesajının sadece dize ilkel türüne atıfta bulunduğunu düşünmektir - 'örnek' kelimesi bana duraklama sağlamalıydı. Daha fazla açıklamak için bir örnek:

class string { }
$n = 1234;
$s1 = (string)$n;
$s2 = new string();
$a = array('no', 'yes');
printf("\$s1 - primitive string? %s - string instance? %s\n",
        $a[is_string($s1)], $a[is_a($s1, 'string')]);
printf("\$s2 - primitive string? %s - string instance? %s\n",
        $a[is_string($s2)], $a[is_a($s2, 'string')]);

Çıktı:

$ s1 - ilkel dize? yes - string örneği? Hayır

$ s2 - ilkel dize? no - string örneği? Evet

PHP'de a'nın gerçekte a stringolması stringdışında bir olması mümkündür string. Örtük tür dönüşümü kullanan herhangi bir dilde olduğu gibi, bağlam her şeydir.


-1

Ben iç blok php üzerinde typecasting düşünüyorum, PHP üzerinde String bildiğim gibi nesne değildir:

<?php
function phpwtf($s) {
    $s = (string) $s;
    echo "$s\n";
}
phpwtf("Type hinting is da bomb");

2
İşleve başka bir değer iletilmesini önlemek için işlevinizin içine is_string () doğrulaması ekleyebilirsiniz.
subosito

1
(string) $s$sdizeye dönüştürülemeyen bir nesne ise (herhangi bir __toString()yöntem uygulanmamışsa) hata atabilir , bu yüzden bu kadar kolay değildir
Yanick Rochon

Evet Yanick haklısın. Ancak tüm girdileri dize olmaya zorlayamıyoruz değil mi? bu yüzden istisna oynamaya geliyor. Doğrulama türlerini birleştirebilir ve geri kalanı için istisna yakalayabiliriz;)
subosito

Sadece değişkenin dökülüp dökülemeyeceğini kontrol etmeden dizeye bazı değişkenler dökmenin, özellikle istisnaları yakalamak maliyetli ve kötü tasarım desenlerine / kodlama alışkanlıklarına yol açtığından kaçınılması gerektiğini söylüyorum.
Yanick Rochon
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.