PHP 8.3.4 Released!

Tür bildirimleri

Tür bildirimleri işlev bağımsız değişkenlerine, dönüş değerlerine ve PHP 7.4.0 ve sonrasında sınıf özelliklerine eklenebilir. Çağrı sırasında değerin belirtilen türde olmasını gerektirir, aksi takdirde TypeError oluşur.

resource türü dışında PHP'nin desteklediği her tür, kullanıcı bildirimi olarak kullanılabilir. Bu sayfa, farklı türlerin kullanılabilirliğine ilişkin bir değişiklik günlüğü ve bunların tür bildirimlerinde kullanımına ilişkin belgeleri içerir.

Bilginize:

Bir sınıf, bir arayüz yöntemini gerçeklediğinde veya bir üst sınıf tarafından zaten tanımlanmış bir yöntemi yeniden gerçeklediğinde, gerçeklediği tanımla uyumlu olması gerekir. Bir yöntem, özgüllük kurallarına uyuyorsa uyumludur.

Sürüm Bilgisi

Sürüm: Açıklama
8.3.0 Sınıf, arayüz, nitelik ve sayılama sabit türleri için destek eklendi.
8.2.0 DNF türleri desteklenmeye başlandı.
8.2.0 true kendisi tür olanlardan biri olarak eklendi.
8.2.0 null ve false tek başlarına kullanılabilir oldu.
8.1.0 Kesişim türleri desteklenmeye başlandı.
8.1.0 void dönüş türünde bir işlevden dönen değere başvuru artık önerilmiyor.
8.1.0 never dönüş türü desteklenmeye başlandı.
8.0.0 mixed türü desteklenmeye başlandı.
8.0.0 static dönüş türü desteklenmeye başlandı.
8.0.0 Birleşik türler desteklenmeye başlandı.
7.4.0 Sınıf özellik türü bildirim desteği eklendi.
7.2.0 object türü desteklenmeye başlandı.
7.1.0 iterable türü desteklenmeye başlandı.
7.1.0 void türü desteklenmeye başlandı.
7.1.0 Null olabilen türler desteklenmeye başlandı.

Temel türlerle ilgili kullanım bilgileri

Temel türler, bu bölümde açıklanan bazı küçük yetersizlikler dışında basit şekilde davranır.

Sayıl türler

Uyarı

Sayıl türler (bool, int, float, string) için takma adlar desteklenmemekte, bunlar bir sınıf veya arayüz adı olarak ele alınmaktadır. Örneğin, tür bildirimi olarak boolean, değerin bool türünden ziyade boolean isimli sınıfın veya arayüzün bir örneği olmasını gerektirir:

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

Yukarıdaki örneğin PHP 8 çıktısı:

Warning: "boolean" will be interpreted as a class name. Did you mean "bool"? Write "\boolean" to suppress this warning in /in/9YrUX on line 2
Fatal error: Uncaught TypeError: test(): Argument #1 ($param) must be of type boolean, bool given, called in - on line 3 and defined in -:2
Stack trace:
#0 -(3): test(true)
#1 {main}
  thrown in - on line 2

void

Bilginize:

void dönüş türünde bir işlevden dönen değere başvuru çelişki sebebiyle PHP 8.1.0 ve sonrasında önerilmemektedir. Evvelce böyle bir çağrı şöyle bir E_NOTICE çıktılıyordu: Only variable references should be returned by reference (Yalnızca değişkene atıflar atıf olarak döndürülebilir).

<?php
function &test(): void {}
?>

Çağrılabilir türler

Bu türler sınıf özelliği türü olarak kullanılamaz.

Bilginize: İşlev bildirimi olarak belirtilemez.

Atıf olarak aktarılan bağımsız değişkenlerde tür bildirimi

Atıf olarak aktarılan bir bağımsız değişkende tür bildirimi yapılmışsa değişkenin türü işlev dönerken değil, yalnızca çağrının başında işlev girdisi olarak sınanır. Yani işlev atıf yapılan değişkenin türünü değiştirebilir.

Örnek 1 - Atıf olarak aktarılan tür bildirimli bağımsız değişkenler

<?php
function array_baz(array &$param)
{
$param = 1;
}
$var = [];
array_baz($var);
var_dump($var);
array_baz($var);
?>

Yukarıdaki örnek şuna benzer bir çıktı üretir:

int(1)
Fatal error: Uncaught TypeError: array_baz(): Argument #1 ($param) must be of type array, int given, called in - on line 9 and defined in -:2
Stack trace:
#0 -(9): array_baz(1)
#1 {main}
  thrown in - on line 2

Birleşik türlerle ilgili kullanım bilgileri

Birleşik tür bildirimleri ile ilgili birkaç kısıtlama vardır ve basit hataları önlemek için derleme sırasında gereksiz fazlalık denetimi yapılır.

Dikkat

PHP 8.2.0 öncesinde ve DNF türler desteklenmeye başlandığında kesişim türlerini bileşik türlerle birleştirmek mümkün değildi.

Bileşik türler

Uyarı

false ve true türlerini aynı bileşik tür altında bildirmek mümkün değildir.

Dikkat

PHP 8.2.0 öncesinde, false ve null tek başlarına kullanılamadığından yalnızca bu türlerden ibaret bir bileşik türe izin verilmezdi. İzin verilmeyen tür bildirimleri: false, false|null ve ?false.

Null olabilen türde sözdizimsel nane

Temel tür bildirimlerinden yalnızca biri, türün önüne bir soru imi (?) konularak null olabilir olarak imlenebilir. Bu bakımdan ?T ve T|null aynıdır.

Bilginize: Bu sözdizimi PHP 7.1.0 ve sonrasında desteklenmekte olup genelleştirilmiş bileşik tür desteğinden önce desteklenmekteydi.

Bilginize:

null öntanımlı değer yapılarak null olabilir bağımsız değişkenler elde etmek de mümkündür. Bir alt sınıfta öntanımlı değer değiştirilirse, tür bildirimine null türün eklenmesini gerektireceğinden ve dolayısıyla tür uyumluluğunu bozacağından bu önerilmez.

Örnek 2 - Bağımsız değişkenlerin null olabilmesinin eski yolu

<?php
class C {}
function
f(C $c = null) {
var_dump($c);
}
f(new C);
f(null);
?>

Yukarıdaki örneğin çıktısı:

object(C)#1 (0) {
}
NULL

Yinelenen ve gereksiz türler

Birleşik tür bildirimlerindeki basit hataları yakalamak için, sınıf yüklemeden algılanabilen gereksiz türler, derleme zamanı hatasına neden olur. Bunlar:

  • Adla çözümlenen her tür bir bildirimde yalnızca bir kez var olabilir. int|string|INT ve Countable&Traversable&COUNTABLE gibi türler hataya neden olur.
  • mixed kullanımı hataya yol açar.
  • Birleşik türler için:
  • Kesişim türleri için:
    • Sınıf türünde olmayan türlerin kullanımı hataya yol açar.
    • self, parent veya static kullanımı hataya yol açar.
  • DNF türleri için:
    • Genel bir türün yanına kısıtlayıcı bir türü eklemek gereksizdir.
    • İki eşdeğer kesişim türü kullanımı.

Bilginize: Bu, türün "en az" olasılığını garanti etmez çünkü bunu yapmak, kullanılan tüm sınıf türlerinin yüklenmesini gerektirir.

Örneğin, A ve B sınıf takma adlarıysa, A or B'ye indirgenebilse bile A|B uygun bir bileşik tür olarak kalır. Benzer şekilde, B extends A {} ise, yalnızca A'ya indirgenebilse bile A|B uygun bir bileşik türdür.

<?php
function foo(): int|INT {} // izin verilmez
function foo(): bool|false {} // izin verilmez
function foo(): int&Traversable {} // izin verilmez
function foo(): self&Traversable {} // izin verilmez
use A as B;
function
foo(): A|B {} // izin verilmez ("use" ad çözünürlüğünün parçasıdır)
function foo(): A&B {} // izin verilmez ("use" ad çözünürlüğünün parçasıdır)
class_alias('X', 'Y');
function
foo(): X|Y {} // izin verilir (gereksizlik yalnızca çalışma anında saptanabilir)
function foo(): X&Y {} // izin verilir (gereksizlik yalnızca çalışma anında saptanabilir)
?>

Örnekler

Örnek 3 - Temel sınıf türü bildirimi

<?php
class C {}
class
D extends C {}
// C'yi genişletmiyor.
class E {}
function
f(C $c) {
echo
get_class($c)."\n";
}
f(new C);
f(new D);
f(new E);
?>

Yukarıdaki örneğin PHP 8 çıktısı:

C
D
Fatal error: Uncaught TypeError: f(): Argument #1 ($c) must be of type C, E given, called in /in/gLonb on line 14 and defined in /in/gLonb:8
Stack trace:
#0 -(14): f(Object(E))
#1 {main}
  thrown in - on line 8

Örnek 4 - Temel arayüz türü bildirimi

<?php
interface I { public function f(); }
class
C implements I { public function f() {} }
// I'yi gerçeklemiyor.
class E {}
function
f(I $i) {
echo
get_class($i)."\n";
}
f(new C);
f(new E);
?>

Yukarıdaki örneğin PHP 8 çıktısı:

C
Fatal error: Uncaught TypeError: f(): Argument #1 ($i) must be of type I, E given, called in - on line 13 and defined in -:8
Stack trace:
#0 -(13): f(Object(E))
#1 {main}
  thrown in - on line 8

Örnek 5 - Temel dönüş türü bildirimi

<?php
function sum($a, $b): float {
return
$a + $b;
}
// dikkat: float dönecek
var_dump(sum(1, 2));
?>

Yukarıdaki örneğin çıktısı:

float(3)

Örnek 6 - Bir nesne döndürmek

<?php
class C {}
function
getC(): C {
return new
C;
}
var_dump(getC());
?>

Yukarıdaki örneğin çıktısı:

object(C)#1 (0) {
}

Örnek 7 - Null olabilen bağımsız değişken bildirimi

<?php
class C {}
function
f(?C $c) {
var_dump($c);
}
f(new C);
f(null);
?>

Yukarıdaki örneğin çıktısı:

object(C)#1 (0) {
}
NULL

Örnek 8 - Null olabilen dönüş türü bildirimi

<?php
function get_item(): ?string {
if (isset(
$_GET['item'])) {
return
$_GET['item'];
} else {
return
null;
}
}
?>

Katı kodlama

PHP öntanımlı olarak, yanlış türdeki değerleri mümkün olduğunca beklenen sayıl türe zorlar. Örneğin, bir dizge aktarılması gereken bir bağımsız değişkene tamsayı bir değer aktarılırsa, işlev int değil string türünde bir değişken alır.

Katı kipi her dosya için ayrı ayrı etkinleştirmek mümkündür. Katı kipte, yalnızca tür bildirimine tam olarak karşılık gelen değer kabul edilir, aksi takdirde bir TypeError oluşur. Bu kuralın tek istisnası, float tür bildirimine rağmen int türünde değer aktarmaktır.

Uyarı

Dahili işlevler içinden yapılan işlev çağrıları, strict_types bildiriminden etkilenmez.

Katı kipi etkinleştirmek için, strict_types bildirimi declare deyiminde kullanılır:

Bilginize:

Katı kodlama, katı kodlamanın etkinleştirildiği dosya içindeki işlev tanımlarına değil, işlev çağrılarına uygulanır. Katı kodlama etkin olmayan bir dosyadan, katı kodlamanın etkinleştirildiği dosya içinde tanımlanmış bir işleve çağrı yapılırsa, çağrıyı yapanın tercihine (zorlayıcı kodlama) saygı gösterilecek ve değer zorlanacaktır.

Bilginize:

Katı kodlama yalnızca sayıl tür bildirimleri için tanımlanmıştır.

Örnek 9 - Bağımsız değişken değerlerinde katı kodlama

<?php
declare(strict_types=1);
function
sum(int $a, int $b) {
return
$a + $b;
}
var_dump(sum(1, 2));
var_dump(sum(1.5, 2.5));
?>

Yukarıdaki örneğin PHP 8 çıktısı:

int(3)
Fatal error: Uncaught TypeError: sum(): Argument #1 ($a) must be of type int, float given, called in - on line 9 and defined in -:4
Stack trace:
#0 -(9): sum(1.5, 2.5)
#1 {main}
  thrown in - on line 4

Örnek 10 - Bağımsız değişken değerlerinde zorlayıcı kodlama

<?php
function sum(int $a, int $b) {
return
$a + $b;
}
var_dump(sum(1, 2));
// Değerler tamsayıya zorlanır. Çıktıya dikkat!
var_dump(sum(1.5, 2.5));
?>

Yukarıdaki örneğin çıktısı:

int(3)
int(3)

Örnek 11 - Dönüş değerlerinde katı kodlama

<?php
declare(strict_types=1);
function
sum($a, $b): int {
return
$a + $b;
}
var_dump(sum(1, 2));
var_dump(sum(1, 2.5));
?>

Yukarıdaki örneğin çıktısı:

int(3)
Fatal error: Uncaught TypeError: sum(): Return value must be of type int, float returned in -:5
Stack trace:
#0 -(9): sum(1, 2.5)
#1 {main}
  thrown in - on line 5

Örnek 12 - Sınıf özellik türü bildirimi

<?php
class User {
public static
string $foo = 'foo';

public
int $id;
public
string $username;

public function
__construct(int $id, string $username) {
$this->id = $id;
$this->username = $username;
}
}
?>
add a note

User Contributed Notes 2 notes

up
18
toinenkayt (ta at ta) [iwonderr] gmail d
2 years ago
While waiting for native support for typed arrays, here are a couple of alternative ways to ensure strong typing of arrays by abusing variadic functions. The performance of these methods is a mystery to the writer and so the responsibility of benchmarking them falls unto the reader.

PHP 5.6 added the splat operator (...) which is used to unpack arrays to be used as function arguments. PHP 7.0 added scalar type hints. Latter versions of PHP have further improved the type system. With these additions and improvements, it is possible to have a decent support for typed arrays.

<?php
declare (strict_types=1);

function
typeArrayNullInt(?int ...$arg): void {
}

function
doSomething(array $ints): void {
(function (?
int ...$arg) {})(...$ints);
// Alternatively,
(fn (?int ...$arg) => $arg)(...$ints);
// Or to avoid cluttering memory with too many closures
typeArrayNullInt(...$ints);

/* ... */
}

function
doSomethingElse(?int ...$ints): void {
/* ... */
}

$ints = [1,2,3,4,null];
doSomething ($ints);
doSomethingElse (...$ints);
?>

Both methods work with all type declarations. The key idea here is to have the functions throw a runtime error if they encounter a typing violation. The typing method used in doSomethingElse is cleaner of the two but it disallows having any other parameters after the variadic parameter. It also requires the call site to be aware of this typing implementation and unpack the array. The method used in doSomething is messier but it does not require the call site to be aware of the typing method as the unpacking is performed within the function. It is also less ambiguous as the doSomethingElse would also accept n individual parameters where as doSomething only accepts an array. doSomething's method is also easier to strip away if native typed array support is ever added to PHP. Both of these methods only work for input parameters. An array return value type check would need to take place at the call site.

If strict_types is not enabled, it may be desirable to return the coerced scalar values from the type check function (e.g. floats and strings become integers) to ensure proper typing.
up
12
crash
2 years ago
The documentation lacks the information, that it's possible to change the return type of a method defined in an interface when the interface's methods return type is defined as `mixed`.

From the RFC:

"The mixed return type could be narrowed in a subclass as this is covariant and is allowed in LSP." (https://wiki.php.net/rfc/mixed_type_v2)

This means the following code is valid in PHP 8.0:

<?php

interface ITest
{
public function
apfel(): mixed; // valid as of 8.0
}

class
Test implements ITest
{
public function
apfel(): array // more explicit
{
return [];
}
}

var_dump((new Test())->apfel());
?>

You can see the result here: https://3v4l.org/PXDB6
To Top