PHP'de katı türler ne işe yarar?


149

PHP 7'de aşağıdaki yeni satırı gördüm, ancak kimse bunun ne anlama geldiğini gerçekten açıklamıyor. Google'da araştırdım ve konuştukları tek şey, bunu etkinleştirip etkinleştirmeyeceğinizdir veya anket türü bir şeyden hoşlanmayacağınızdır.

declare(strict_types = 1);

Bu ne işe yarıyor? Kodumu nasıl etkiler? Yapmalı mıyım?

Bazı açıklamalar güzel olurdu.



5
de bu bir göz sökünüz php.net/manual/en/... strict_types için yönerge
scaisEdge

Yanıtlar:


154

Gönderen Treehouse blogda :

PHP 7 ile artık Skalar türleri ekledik. Özellikle: int, float, string ve bool.

Skaler tip ipuçları ekleyerek ve katı gereksinimleri etkinleştirerek, daha doğru ve kendi kendini belgeleyen PHP programlarının yazılabileceği umulmaktadır. Ayrıca size kodunuz üzerinde daha fazla kontrol sağlar ve kodun okunmasını kolaylaştırabilir.

Varsayılan olarak, skaler tür bildirimleri katı değildir, bu da orijinal türü tür bildiriminde belirtilen türle eşleşecek şekilde değiştirmeye çalışacakları anlamına gelir. Başka bir deyişle, sayı ile başlayan bir dizeyi kayan nokta gerektiren bir işleve geçirirseniz, sayıyı baştan alır ve diğer her şeyi kaldırır. Bir int gerektiren bir işleve bir float geçirmek, int (1) olacaktır.

Varsayılan olarak PHP, mümkünse yanlış türdeki değerleri beklenen skaler türe çevirecektir. Örneğin, bir dizgeyi bekleyen bir parametre için bir tamsayı verilen bir işlev, dize türünde bir değişken alır.

Kesin türler devre dışı bırakıldı ( eval ):

<?php

  function AddIntAndFloat(int $a, float $b) : int
  {
      return $a + $b;
  }

  echo AddIntAndFloat(1.4, '2');
  /*
  * without strict typing, PHP will change float(1.4) to int(1)
  * and string('2') to float(2.0) and returns int(3)
  */

Dosya bazında katı modu etkinleştirmek mümkündür. Katı modda, yalnızca tür bildiriminin tam türünün bir değişkeni kabul edilir veya bir TypeError atılır. Bu kuralın tek istisnası, kayan nokta bekleyen bir işleve bir tamsayı verilebilmesidir. Dahili işlevlerden gelen işlev çağrıları, katı_türler bildiriminden etkilenmez.

Katı modu etkinleştirmek için, declare deyimi katı_tür bildirimi ile birlikte kullanılır:

Etkin katı türler ( eval ):

<?php declare(strict_types=1);

  function AddIntAndFloat(int $a, float $b): int
  {
      return (string) $a + $b;
  }

  echo AddIntAndFloat(1.4,'2');
  // Fatal error: Uncaught TypeError: Argument 1 passed to AddIntAndFloat() must be of the type int, float given
  echo AddIntAndFloat(1,'2');
  // Fatal error: Uncaught TypeError: Argument 2 passed to AddIntAndFloat() must be of the type float, string given

  // Integers can be passed as float-points :
  echo AddIntAndFloat(1,1);
  // Fatal error: Uncaught TypeError: Return value of AddIntAndFloat() must be of the type integer, string returned

Çalışma örneği:

<?php

declare(strict_types=1);

function AddFloats(float $a, float $b) : float
{
    return $a+$b;
}

$float = AddFloats(1.5,2.0); // Returns 3.5

function AddFloatsReturnInt(float $a, float $b) : int
{
    return (int) $a+$b;
}

$int = AddFloatsReturnInt($float,1.5); // Returns 5

function Say(string $message): void // As in PHP 7.2
{
    echo $message;
}

Say('Hello, World!'); // Prints "Hello, World!"

function ArrayToStdClass(array $array): stdClass
{
    return (object) $array;
}

$object = ArrayToStdClass(['name' => 'azjezz','age' => 100]); // returns an stdClass

function StdClassToArray(stdClass $object): array
{
    return (array) $object;
}

$array = StdClassToArray($object); // Returns array

function ArrayToObject(array $array): object // As of PHP 7.2
{
    return new ArrayObject($array);
}

function ObjectToArray(ArrayObject $object): array
{
    return $object->getArrayCopy();
}

var_dump( ObjectToArray( ArrayToObject( [1 => 'a' ] ) ) ); // array(1 => 'a');

3
Kesin türler etkin örneğinizde belirtilen ilk önemli hata yanlıştır. Dokümantasyonda belirtildiği gibi: "Bu kuralın tek istisnası, kayan nokta bekleyen bir işleve bir tamsayı verilebilmesidir." İşlev çağrısı int üzerinde başarısız olmaz. Yine de ipte olurdu.
Paul

63

strict_types tür zorlamasını etkiler.

Yazım ipuçlarını kullanmadan kullanmak strict_typesince hatalara yol açabilir.

Katı türlerden önce, int $x" int için zorlanabilir$x bir değere sahip olması gerekir " anlamına gelir . Bir'e zorlanabilecek herhangi bir değer , aşağıdakiler dahil tür ipucunu geçer:int

  • int uygun ( 242),
  • bir şamandıra ( 10.17),
  • bir bool ( true),
  • nullveya
  • önde gelen basamaklı bir dize ( "13 Ghosts").

Ayarlayarak strict_types=1, motora int $x"$ x yalnızca int uygun olmalıdır, tür zorlamasına izin verilmez" anlamına gelir. Herhangi bir dönüşüm ve potansiyel kayıp olmadan, tam olarak ve yalnızca verileni aldığınız konusunda büyük bir güvenceye sahipsiniz.

Misal:

<?php
function get_quantity(): int {
    return '100 apples';
}
echo get_quantity() . PHP_EOL;

Potansiyel olarak kafa karıştırıcı bir sonuç verir:

Notice: A non well formed numeric value encountered in /Users/bishop/tmp/pmkr-994/junk.php on line 4
100

Çoğu geliştirici, sanırım, int"yalnızca int" anlamına gelen bir ipucu bekler . Ama değil, "int gibi bir şey" anlamına geliyor. Katı_türlerin etkinleştirilmesi, olası beklenen ve istenen davranışı verir:

<?php declare(strict_types=1);

function get_quantity(): int {
    return '100 apples';
}
echo get_quantity() . PHP_EOL;

Verim:

Fatal error: Uncaught TypeError: Return value of get_quantity() must be of the type int, string returned in example.php:4

Yazım ipuçlarını kullanırsanız, burada iki ders olduğunu düşünüyorum:

  • strict_types=1Her zaman kullanın .
  • strict_typesPragmayı eklemeyi unutmanız durumunda, bildirimleri istisnalara dönüştürün .

1
Bu, neredeyse bir yıl önce olduğu gibi zaten iyi bir şekilde cevaplandı;)
emix

6
Nitekim, diğer yanıta @emix'i yükselttim. Ancak, "yapmalı mıyım" sorusuna değinilmediğini hissettim. Ayrıca daha derli toplu ve şok edici bir örneğin insanları kullanmaya teşvik edeceğini hissettim strict_types.
bishop

1
Sanırım bu soru kısaca "Yapmalı mıyım?" OP'nin sorusunun bir parçası. Biraz aradan sonra PHP'ye dönmek ve bu çok yardımcı oldu.
Darragh Enright
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.