PHP'de tip bildirimi, bir parametrenin, dönüş değerinin veya sınıf özelliğinin hangi tipte olması gerektiğini yazmaktır: function topla(int $a, int $b): int. Çağrı anında değer bu tipe uymazsa PHP TypeError fırlatır. Varsayılan (coercive) modda PHP uygun skaler değerleri beklenen tipe çevirmeyi dener; örneğin '5' metni int parametreye 5 olarak girer. Dosyanın en başına declare(strict_types=1); yazarsanız bu çeviri kapanır ve yalnızca tam olarak doğru tipteki değer kabul edilir; tek istisna int değerin float beklenen yere girebilmesidir.
Bu yazıda skaler tipleri, nullable (?string), union (int|string) ve intersection (A&B) tiplerini, yalnızca dönüşte kullanılan void ve never tiplerini, her şeyi kabul eden mixed tipini ve strict_types davranışını çalıştırılmış örneklerle anlatıyoruz. Örneklerin tamamı PHP 8.5.12 ile denendi. Fonksiyon sözdizimi için PHP fonksiyon tanımlama, serinin tamamı için PHP öğrenme rehberi sayfasına bakabilirsiniz.
Tip bildirimi nereye yazılır ve hangi tipler var?

Kılavuza göre tip bildirimleri fonksiyon parametrelerine ve dönüş değerlerine, PHP 7.4'ten beri sınıf özelliklerine, PHP 8.3'ten beri de sınıf sabitlerine eklenebilir. resource dışındaki her tip kullanıcı tanımlı bildirimde yazılabilir. Dönüş tipi parametre listesinden sonra iki nokta üst üste ile gelir. Sınıf adları ve arayüz adları da tip olarak kullanılır; değer o sınıfın veya onu genişleten bir alt sınıfın örneği olmalıdır.
| Tip | Ne kabul eder | Eklendiği sürüm |
|---|---|---|
| int, float, string, bool | Skaler değerler | Değişiklik tablosunda ayrıca yer almaz |
| ?T | T veya null (T|null ile aynı) | PHP 7.1 |
| void | Yalnızca dönüş: değer döndürmez | PHP 7.1 |
| iterable | array veya Traversable | PHP 7.1 |
| object | Herhangi bir nesne | PHP 7.2 |
| A|B | Union: türlerden herhangi biri | PHP 8.0 |
| mixed | Her değer | PHP 8.0 |
| static | Yalnızca dönüş: çağrılan sınıf | PHP 8.0 |
| A&B | Intersection: tüm arayüzleri sağlayan nesne | PHP 8.1 |
| never | Yalnızca dönüş: fonksiyon hiç dönmez | PHP 8.1 |
| (A&B)|null | DNF tipleri | PHP 8.2 |
| true; tek başına false ve null | Tekil tipler | PHP 8.2 |
Tablodaki sürüm bilgileri, skaler satır dışında kılavuzun tip bildirimleri sayfasındaki değişiklik tablosundan alındı. Dikkat edilmesi gereken bir ayrıntı: boolean, integer, double gibi takma adlar tip olarak desteklenmez. PHP bunları sınıf adı sanır ve çağrı başarısız olur:
<?php
function aktif(boolean $durum) {}
aktif(true);Warning: "boolean" will be interpreted as a class name. Did you mean "bool"? Write "\boolean" to suppress this warning in /yol/ornek.php on line 2
Fatal error: Uncaught TypeError: aktif(): Argument #1 ($durum) must be of type boolean, true given, called in /yol/ornek.php on line 3 and defined in /yol/ornek.php:2Coercive mod: PHP varsayılan olarak çevirir
strict_types açık değilse PHP, skaler tip bildirimlerinde değeri beklenen tipe çevirmeyi dener. Kılavuzun tip dönüşümü sayfası kuralları şöyle özetler: bool bildiriminde değer bool olarak yorumlanır; int ve float bildiriminde dönüşüm yalnızca iyi tanımlıysa yapılır, örneğin metin sayısal bir metinse; string bildiriminde değer metne çevrilir. Dönüş tipinde de aynı kurallar geçerlidir.
<?php
function topla(int $a, int $b)
{
return $a + $b;
}
var_dump(topla(2, 3)); // çıktı: int(5)
var_dump(topla('2', '3')); // çıktı: int(5)
var_dump(topla(2.0, 3)); // çıktı: int(5)
var_dump(topla(1.5, 2.5));
/* çıktı:
Deprecated: Implicit conversion from float 1.5 to int loses precision in /yol/ornek.php on line 2
Deprecated: Implicit conversion from float 2.5 to int loses precision in /yol/ornek.php on line 2
int(3)
*/Kesirli kısmı olan bir float değer int parametreye girerken kesirli kısım atılır; PHP 8.5.12 bu kayıp için çıktıda görüldüğü gibi Deprecated uyarısı verir. Sayısal olmayan bir metin ise çevrilmez. '5 elma' gibi başı sayı olan bir metin bile int parametreye girmez ve TypeError üretir: topla(): Argument #1 ($a) must be of type int, string given. Dönüş tipinde de çeviri yapılır: : string bildiren bir fonksiyon 99.5 döndürürse sonuç string(4) "99.5" olur.
declare(strict_types=1): sıkı mod
Sıkı mod dosya bazında açılır ve dosyanın ilk deyimi olmalıdır. Açıkken skaler bildirimlere yalnızca tam o tipteki değer kabul edilir; uymayan değer TypeError fırlatır. Kılavuzun belirttiği tek istisna, int değerin float bildirimine girebilmesidir.
<?php
declare(strict_types=1);
function topla(int $a, int $b): int
{
return $a + $b;
}
function yuzde(float $oran): float
{
return $oran * 100;
}
var_dump(yuzde(1)); // çıktı: float(100)
var_dump(topla(2, 3)); // çıktı: int(5)
var_dump(topla('2', '3'));
/* Fatal error: Uncaught TypeError: topla(): Argument #1 ($a) must be of type int, string given, called in /yol/ornek.php on line 14 and defined in /yol/ornek.php:4 */Sıkı mod dönüş değerlerini de kapsar. Aşağıdaki fonksiyon ilk çağrıda tam sayı ortalama ürettiği için çalışıyor, ikinci çağrıda ise 1.5 döndürmeye çalıştığı için hata veriyor:
<?php
declare(strict_types=1);
function ortalama(array $d): int
{
return array_sum($d) / count($d);
}
var_dump(ortalama([2, 4])); // çıktı: int(3)
var_dump(ortalama([1, 2]));
/* Fatal error: Uncaught TypeError: ortalama(): Return value must be of type int, float returned in /yol/ornek.php:6 */İlk çağrı ilginçtir: 6 / 2 PHP'de int(3) sonucunu verdiği için tip uyuyor. Bölme işlemi tam bölünmediğinde float üretir; sıkı modda bu fark hemen yüzeye çıkar. Bu, coercive modun sessizce yapacağı bir dönüşümü görünür hale getirmenin iyi bir örneğidir.
strict_types hakkında en çok karıştırılan nokta, hangi dosyanın ayarının geçerli olduğudur. Kılavuz bunu açıkça yazar: Sıkı mod, fonksiyonun tanımlandığı dosyaya değil, çağrının yapıldığı dosyaya göre uygulanır. Sıkı modlu bir dosyada tanımlanan fonksiyonu sıkı mod açık olmayan bir dosyadan çağırırsanız değer yine çevrilir. Ayrıca sıkı mod yalnızca skaler tip bildirimleri için tanımlıdır ve PHP'nin kendi fonksiyonlarının içinden yapılan çağrıları etkilemez.
<?php
declare(strict_types=1);
var_dump(strlen(12345));
// Fatal error: Uncaught TypeError: strlen(): Argument #1 ($string) must be of type string, int given in /yol/ornek.php:3Yukarıdaki örnek, sıkı modun sizin dosyanızdan PHP'nin kendi fonksiyonlarına yaptığınız çağrılarda da geçerli olduğunu gösteriyor: Coercive modda 5 dönecek çağrı burada hata veriyor. declare satırını dosyanın başına değil de bir çıktıdan sonra yazarsanız derleme şu mesajla durur: strict_types declaration must be the very first statement in the script.
Nullable tipler ve PHP 8.4 örtük nullable uyarısı

Bir tipin önüne soru işareti koymak (?string) o tipi null da kabul eder hale getirir; kılavuza göre ?T ile T|null birebir aynıdır. Nullable parametre, argümanın isteğe bağlı olduğu anlamına gelmez: Varsayılan değer vermediyseniz argümanı yine yazmak zorundasınız, aksi halde ArgumentCountError alırsınız.
<?php
function selam(?string $ad): string
{
return 'Merhaba ' . ($ad ?? 'misafir');
}
echo selam('Zeynep'), PHP_EOL; // çıktı: Merhaba Zeynep
echo selam(null), PHP_EOL; // çıktı: Merhaba misafir
function bul(array $liste, string $aranan): ?int
{
$i = array_search($aranan, $liste, true);
return $i === false ? null : $i;
}
var_dump(bul(['a', 'b'], 'b')); // çıktı: int(1)
var_dump(bul(['a', 'b'], 'z')); // çıktı: NULLEski PHP kodlarında nullable parametre şöyle yazılırdı: function ara(string $q = null). Varsayılanın null olması tipi örtük olarak nullable yapıyordu. Kılavuz bu kullanımın PHP 8.4'te deprecated edildiğini belirtir; PHP 8.5.12 şu uyarıyı verir:
<?php
function ara(string $q = null)
{
var_dump($q);
}
ara();
/* çıktı:
Deprecated: ara(): Implicitly marking parameter $q as nullable is deprecated, the explicit nullable type must be used instead in /yol/ornek.php on line 2
NULL
*/
// Düzeltilmiş hali:
// function ara(?string $q = null)Düzeltme mekaniktir: Tip $p = null gördüğünüz her yerde ?Tip $p = null veya Tip|null $p = null yazın. Diğer 8.4 deprecated değişiklikleri için PHP 8.4 deprecated uyarıları yazısına bakabilirsiniz.
Union ve intersection tipler
Union tip, birden fazla tipten herhangi birini kabul eder ve tipler | ile ayrılır: int|string. Coercive modda değerin tam tipi birleşimde yoksa PHP sırasıyla int, float, string ve bool tiplerini dener ve ilk uygun olana çevirir. Kılavuzun belirttiği istisna: Değer bir metinse ve birleşimde hem int hem float varsa, seçim sayısal metin kurallarına göre yapılır; "42" için int, "42.0" için float seçilir.
<?php
function kimlik(int|string $id): string
{
return get_debug_type($id) . ':' . $id;
}
echo kimlik(42), PHP_EOL; // çıktı: int:42
echo kimlik('A-17'), PHP_EOL; // çıktı: string:A-17
echo kimlik(4.0), PHP_EOL; // çıktı: int:4
function sayi(int|float $x)
{
var_dump($x);
}
sayi('42'); // çıktı: int(42)
sayi('42.0'); // çıktı: float(42)
sayi('1e3'); // çıktı: float(1000)Kılavuz, derleme anında fark edilebilen gereksiz tekrarların hata olduğunu da belirtir: int|INT (Duplicate type int is redundant), bool|false veya object ile birlikte bir sınıf adı yazmak reddedilir. true|false birleşimi de yazılamaz; bunun yerine bool kullanılır.
Intersection tip ise değerin aynı anda birden fazla sınıf tipini sağlamasını ister ve & ile yazılır. Yalnızca sınıf ve arayüz adlarıyla kullanılabilir; int gibi skalerler veya self, parent, static kullanılamaz. Aşağıdaki fonksiyon hem sayılabilen (Countable) hem gezilebilen (Traversable) bir nesne istiyor. ArrayIterator ikisini de uygular; düz bir dizi ise nesne olmadığı için reddedilir:
<?php
function ozet(Countable&Traversable $c): string
{
$parcalar = [];
foreach ($c as $k => $v) {
$parcalar[] = "$k=$v";
}
return count($c) . ' öğe: ' . implode(', ', $parcalar);
}
echo ozet(new ArrayIterator(['a' => 1, 'b' => 2])), PHP_EOL; // çıktı: 2 öğe: a=1, b=2
echo ozet(['a' => 1]);
/* Fatal error: Uncaught TypeError: ozet(): Argument #1 ($c) must be of type Countable&Traversable, array given, ... */PHP 8.2'den itibaren intersection ve union tipleri parantezle birleştirilebilir (DNF tipleri): (A&B)|null. Arayüzlerin nasıl tanımlandığı kalıtım, abstract ve interface yazısında anlatılıyor.
void, never ve mixed
void yalnızca dönüş tipi olarak kullanılır ve fonksiyonun bir değer döndürmediğini belirtir. Böyle bir fonksiyonda erken çıkmak için yalın return; yazılır. İfadeli bir return, buna return null; da dahil, derleme hatasıdır. Fonksiyonun çağrısı yine de bir değer üretir ve bu değer her zaman null olur.
<?php
function kaydet(string $mesaj): void
{
if ($mesaj === '') {
return;
}
echo "Kaydedildi: $mesaj", PHP_EOL;
}
var_dump(kaydet('test'));
/* çıktı:
Kaydedildi: test
NULL
*/
// return null; yazılsaydı:
// Fatal error: A void function must not return a value (did you mean "return;" instead of "return null;"?)never, PHP 8.1 ile gelen ve yine yalnızca dönüşte kullanılan bir tiptir. Fonksiyonun hiç normal biçimde geri dönmediğini, yani exit() çağırdığını, bir istisna fırlattığını ya da sonsuz döngüye girdiğini söyler. Kılavuza göre böyle bir fonksiyonda return yazmak derleme hatasıdır; akış fonksiyonun sonuna ulaşırsa TypeError fırlatılır.
<?php
function hata(string $mesaj): never
{
throw new RuntimeException($mesaj);
}
function yasYaz(int $yas): string
{
if ($yas < 0) {
hata('Yaş negatif olamaz');
}
return "$yas yaşında";
}
echo yasYaz(30), PHP_EOL; // çıktı: 30 yaşında
try {
yasYaz(-1);
} catch (RuntimeException $e) {
echo 'Yakalandı: ', $e->getMessage(), PHP_EOL; // çıktı: Yakalandı: Yaş negatif olamaz
}
// Gövdesi sona ulaşan bir never fonksiyonu ise şunu verir:
// Fatal error: Uncaught TypeError: bitir(): never-returning function must not implicitly returnmixed ise her değeri kabul eden en geniş tiptir; kılavuz onu object|resource|array|string|float|int|bool|null birleşimine denk sayar. mixed yazmak tip bildirmemekle aynı sonucu verir, ama niyetinizi açıkça belgeler: "Burada gerçekten her tip olabilir." mixed ve never başka tiplerle birleşime konamaz. İstisna fırlatma ve yakalama ayrıntıları için try catch ve exception yazısına bakabilirsiniz.
Tipler ne zaman kontrol edilir? Özellik tipleri
Kılavuzun tip sistemi sayfası, PHP'nin isme dayalı (nominal) bir tip sistemi kullandığını, alt tip ilişkisinin derleme anında, değerlerin tipe uygunluğunun ise çalışma anında kontrol edildiğini belirtir. Pratikte bu şu anlama gelir: int|INT gibi bir yazım hatası dosya çalışmadan önce yakalanır, ama bir fonksiyona yanlış tipte değer verdiğinizi PHP ancak o çağrı gerçekleştiğinde fark eder. Hiç çalışmayan bir kod yolundaki tip hatası sessiz kalır; bu yüzden testler ve statik analiz araçları tip bildirimlerini tamamlar.
Tipli sınıf özellikleri de aynı kurallarla çalışır: Coercive modda sayısal bir metin int özelliğe çevrilerek yazılır, çevrilemeyen bir değer ise atama anında TypeError üretir. Bu kontrol, nesne oluşturulduktan çok sonra yapılan atamalarda bile geçerlidir; özelliğe her yazışta tip denetlenir.
<?php
class Urun
{
public int $stok = 0;
public ?string $aciklama = null;
}
$u = new Urun;
$u->stok = '15';
var_dump($u->stok); // çıktı: int(15)
$u->stok = 'bilinmiyor';
// Fatal error: Uncaught TypeError: Cannot assign string to property Urun::$stok of type int in /yol/ornek.php:10Bir alt sınıf, üst sınıftaki ya da uyguladığı arayüzdeki bir metodu yeniden tanımladığında imzanın uyumlu olması gerekir. Kılavuz bunu varyans kurallarına bağlar ve never tipinin, her tipin alt tipi olduğu için miras alınan herhangi bir dönüş tipinin yerine geçebileceğini not eder.
Referansla parametrelerde tip kontrolü
Kılavuzun az bilinen bir notu: Referansla geçen ve tipi bildirilmiş bir parametrenin tipi yalnızca fonksiyona girişte kontrol edilir, fonksiyon dönerken kontrol edilmez. Yani fonksiyon, referansla aldığı değişkenin tipini değiştirebilir:
<?php
function bozar(array &$p)
{
$p = 'artık metin';
}
$v = [];
bozar($v);
var_dump($v); // çıktı: string(12) "artık metin"Çıktıdaki 12, metnin bayt uzunluğudur; ı harfi UTF-8'de iki bayt tutar. Bu davranış nedeniyle referansla parametre kullanan fonksiyonlarda tip bildirimine tam güvenmemek gerekir. Referansların genel davranışı için PHP referanslar yazısına bakın.
Küçük uygulama: tipli bir ödeme fonksiyonu
Sınıf ve arayüz tipleri, bir fonksiyonun yalnızca belirli bir sözleşmeyi uygulayan nesnelerle çalışmasını garanti eder. Aşağıda tahsilEt() yalnızca Odeme arayüzünü uygulayan nesneleri kabul ediyor. Arayüzü uygulamayan bir sınıf verildiğinde hata, yanlış nesnenin metodu çağrılmadan önce, fonksiyonun girişinde yakalanıyor:
<?php
interface Odeme
{
public function ode(float $tutar): string;
}
class KrediKarti implements Odeme
{
public function ode(float $tutar): string
{
return "Kartla $tutar TL ödendi";
}
}
class Havale {}
function tahsilEt(Odeme $yontem, float $tutar): string
{
return $yontem->ode($tutar);
}
echo tahsilEt(new KrediKarti, 150), PHP_EOL; // çıktı: Kartla 150 TL ödendi
echo tahsilEt(new Havale, 150), PHP_EOL;
/* Fatal error: Uncaught TypeError: tahsilEt(): Argument #1 ($yontem) must be of type Odeme, Havale given, called in /yol/ornek.php on line 20 and defined in /yol/ornek.php:15 */Hata mesajının yapısı her zaman aynıdır: fonksiyon adı, kaçıncı argüman olduğu ve parametre adı, beklenen tip ve gelen tip. Bu mesajları okuyup çözmek için TypeError ve ArgumentCountError hataları yazısını inceleyebilirsiniz.
Sık yapılan hatalar

- strict_types'ın tanım dosyasına göre çalıştığını sanmak: Belirleyici olan çağrının yapıldığı dosyadır.
- declare satırını dosyanın başına koymamak: İlk deyim olmazsa derleme hatası alırsınız.
- Nullable ile isteğe bağlıyı karıştırmak:
?string $adnull kabul eder ama argümanı yine yazmanız gerekir; isteğe bağlı olması için= nullekleyin. - Tip $p = null kalıbını sürdürmek: PHP 8.4'ten beri deprecated;
?Tip $p = nullyazın. - Takma ad kullanmak:
boolean,integersınıf adı sayılır;boolveintyazın. - void fonksiyonda return null yazmak: Derleme hatasıdır; yalın
return;kullanın.
Sık Sorulan Sorular
strict_types kullanmalı mıyım?
Kılavuz bir tavsiye vermez, iki modun nasıl çalıştığını anlatır. Sıkı mod, beklenmedik tip dönüşümlerini çağrı anında hataya çevirir; bu da form verisi gibi metin olarak gelen değerleri açıkça dönüştürmenizi gerektirir. Coercive mod ise sayısal metinleri sessizce kabul eder. Hangi davranışı istediğinize ekibinizle birlikte karar verin ve her dosyada tutarlı olun.
Sınıf özelliklerine tip yazabilir miyim?
Evet, PHP 7.4'ten beri public int $id; biçiminde yazabilirsiniz. Tek istisna callable tipidir; özellik tipi olarak kullanılamaz, onun yerine Closure yazılır. Sınıf ve özellik konusu PHP sınıf ve nesne yazısında, readonly özellikler public, private, protected ve readonly yazısında anlatılıyor.
Kendi tip takma adımı (type alias) tanımlayabilir miyim?
Hayır. Kılavuz, PHP'nin kullanıcı tanımlı tip takma adlarını desteklemediğini belirtir. Dilin kendi içinde yalnızca iki takma ad vardır: mixed ve iterable (Traversable|array).
callable tipiyle fonksiyonun imzasını belirtebilir miyim?
Hayır. Kılavuz, callable tip bildiriminde fonksiyonun imzasının belirtilemediğini yazar. Hangi parametreleri alacağını belgelemek için PHPDoc yorumları kullanılır. Callable türleri için anonim fonksiyon ve callable yazısına bakın.
Marka adları sahiplerine aittir. Bu yazı bağımsız bir teknik rehberdir; adı geçen kuruluşlarla bayilik veya ortaklık ilişkisi bulunduğu anlamına gelmez.
İlgili içerikler: PHP öğrenme rehberi · PHP fonksiyon tanımlama · Eşitlik ve tip dönüşümü · TypeError hataları · PHP veri tipleri