PHP 8.4'e geçtikten sonra ekranınızda ya da günlük dosyanızda "Deprecated:" ile başlayan satırlar gördüyseniz, kodunuz çalışmaya devam ediyor ama gelecekteki bir sürümde kaldırılacak bir davranışı kullanıyor demektir. Bu sürümde en sık karşılaşılan uyarı, varsayılan değeri null olan tipli parametrelerde örtük nullable kullanımıdır: function f(string $s = null) yazımı artık eskimiş sayılıyor ve çözümü tipin başına ? eklemektir.

Bu yazıda kılavuzun PHP 8.4 Deprecated Features sayfasındaki dil çekirdeği maddelerini tek tek ele alıyor, her biri için uyarının gerçek metnini ve düzeltilmiş kodu gösteriyoruz. Ardından standart kütüphanedeki önemli eskimiş fonksiyonlara ve projenizdeki tüm uyarıları toplu bulmanın yollarına geçiyoruz. Örnekler PHP 8.5.12 ile çalıştırıldı; bu sürümde de aynı uyarılar geçerlidir. PHP 8.4'ün yeni özellikleri PHP 8.4 yenilikleri yazısında, serinin geneli PHP öğrenme rehberinde.

Deprecated uyarısı ne anlama gelir?

Deprecated uyarısı ne anlama gelir?

PHP'de hatalar iki ana gruba ayrılır: akışı kesen Throwable hataları ve çoğu zaman akışı kesmeyen "diagnostic" (tanılama) hataları. E_DEPRECATED ikinci gruptandır. Kod çalışır, sonuç değişmez; PHP yalnızca "bu kullanım ileride kaldırılabilir" diye haber verir. Kılavuza göre PHP 8.0'dan beri varsayılan olarak tüm tanılama hataları raporlanır; PHP 8.0 öncesinde E_NOTICE ve E_DEPRECATED varsayılan olarak raporlanmıyordu. Bu yüzden eski projelerde biriken uyarılar sürüm yükseltildiğinde birden görünür hâle gelir.

Uyarıları susturmak yerine düzeltmek gerekir, çünkü bugün Deprecated olan bir davranış ileride Fatal error'a dönüşebilir. Kılavuz da tanılama hatalarının sürümler arasında eklenebileceğini, kaldırılabileceğini, ciddiyetinin değişebileceğini ya da Throwable hatalara yükseltilebileceğini açıkça not eder. Hata seviyelerinin tamamı için PHP error_reporting ve hata seviyeleri yazısına bakın.

Örtük nullable parametre (en yaygın uyarı)

PHP'de bir parametrenin varsayılan değeri null ise, tipi yazılmamış olsa bile o parametre null kabul ediyordu. Yani string $ad = null aslında ?string $ad = null gibi davranıyordu. Bu "sessiz genişletme" PHP 8.4 ile eskimiş sayıldı. Uyarı derleme aşamasında üretilir, yani fonksiyon hiç çağrılmasa bile dosya yüklendiği anda görünür.

php
<?php
function selamla(string $ad = null): string
{
    return 'Merhaba ' . ($ad ?? 'misafir');
}

echo selamla(), PHP_EOL;
/* çıktı:
Deprecated: selamla(): Implicitly marking parameter $ad as nullable is deprecated, the explicit nullable type must be used instead in /yol/ornek.php on line 2
Merhaba misafir
*/

Düzeltme için tipi açıkça nullable yapmanız yeterli. ?string ile string|null aynı anlama gelir; birden fazla tipten oluşan union tiplerde ? kullanılamadığı için int|string|null biçimini seçmelisiniz.

php
<?php
function selamla(?string $ad = null): string
{
    return 'Merhaba ' . ($ad ?? 'misafir');
}

echo selamla(), PHP_EOL;      // çıktı: Merhaba misafir
echo selamla('Can'), PHP_EOL; // çıktı: Merhaba Can

Kılavuzun özellikle uyardığı ikinci bir durum var: varsayılan değeri null olan parametreden sonra zorunlu bir parametre geliyorsa, yalnızca ? eklemek yetmez. Zorunlu parametreden önce gelen isteğe bağlı parametre de ayrıca eskimiş sayılır, çünkü pratikte zaten zorunludur. Aşağıda üç hâli görüyorsunuz:

php
<?php
// 1) Eski yazım: örtük nullable uyarısı
function kaydet(int $id, string $not = null, bool $acil) {}
// Deprecated: kaydet(): Implicitly marking parameter $not as nullable is deprecated, the explicit nullable type must be used instead in /yol/ornek.php on line 3
php
<?php
// 2) Yarım düzeltme: bu kez başka bir uyarı
function kaydet(int $id, ?string $not = null, bool $acil) {}
// Deprecated: kaydet(): Optional parameter $not declared before required parameter $acil is implicitly treated as a required parameter in /yol/ornek.php on line 3
php
<?php
// 3) Doğru düzeltme: varsayılan değeri kaldırın, tipi nullable bırakın
function kaydet(int $id, ?string $not, bool $acil) {}
echo 'uyarı yok', PHP_EOL; // çıktı: uyarı yok

Üçüncü hâlde çağıran kod artık $not için açıkça bir değer (gerekirse null) vermek zorundadır; bu, kodun gerçek davranışını dürüstçe ifade eder. Parametre ve tip bildirimlerinin ayrıntıları için PHP tip bildirimleri ve strict_types ile PHP fonksiyon tanımlama ve parametreler yazılarına bakın.

Sıfırın negatif kuvveti

Bir sayının negatif kuvveti, o sayının pozitif kuvvetinin tersidir: 10 ** -2, 1 / 10 ** 2 ile aynıdır. Buna göre 0 ** -1 aslında 1 / 0 demektir, yani sıfıra bölmedir. Kılavuz bu yüzden hem ** operatöründe hem de pow() fonksiyonunda tabanın 0, üssün negatif olduğu kullanımı eskimiş saymıştır. IEEE 754 davranışını (sonsuz sonucu) bilerek istiyorsanız yeni fpow() fonksiyonunu kullanın.

php
<?php
var_dump(0 ** -1);
var_dump(fpow(0, -1)); // çıktı: float(INF)
var_dump(2 ** -1);     // çıktı: float(0.5)
/* çıktı:
Deprecated: Power of base 0 and negative exponent is deprecated in /yol/ornek.php on line 2
float(INF)
float(INF)
float(0.5)
*/

Pratikte bu uyarı genellikle bir değişkenin beklenmedik biçimde sıfır olduğuna işaret eder. Hesaplamadan önce tabanı kontrol etmek çoğu zaman fpow()'a geçmekten daha doğru çözümdür. Sıfıra bölmenin / ve % operatörlerinde nasıl davrandığı TypeError ve DivisionByZeroError yazısında.

Sınıf adı olarak alt çizgi "_"

Sınıfa yalnızca _ adını vermek PHP 8.4 ile eskimiş sayıldı. Kılavuz, adı alt çizgiyle başlayan sınıfların (_Yardimci gibi) bu kuraldan etkilenmediğini özellikle belirtir.

php
<?php
class _ {}
class _Yardimci {}
echo 'tamam', PHP_EOL;
/* çıktı:
Deprecated: Using "_" as a class name is deprecated since 8.4 in /yol/ornek.php on line 2
tamam
*/

trigger_error() ile E_USER_ERROR

Eskiden kendi ölümcül hatanızı üretmek için trigger_error('...', E_USER_ERROR) çağırılırdı. Bu kullanım PHP 8.4'te eskimiş sayıldı. Kılavuz yerine istisna fırlatmayı ya da duruma göre exit() çağırmayı önerir. İstisna kullanmak, çağıran kodun hatayı try/catch ile yakalayıp toparlanabilmesini sağladığı için genellikle daha iyi bir seçimdir.

php
<?php
trigger_error('Ayar dosyası bulunamadı', E_USER_ERROR);
echo 'buraya gelinmez', PHP_EOL;
/* çıktı:
Deprecated: Passing E_USER_ERROR to trigger_error() is deprecated since 8.4, throw an exception or call exit with a string message instead in /yol/ornek.php on line 2

Fatal error: Ayar dosyası bulunamadı in /yol/ornek.php on line 2
Stack trace:
#0 /yol/ornek.php(2): trigger_error('Ayar dosyas\xC4\xB1 b...', 256)
#1 {main}
*/

Düzeltilmiş hâli tek satırdır: throw new RuntimeException('Ayar dosyası bulunamadı');. Kendi istisna sınıflarınızı yazmak ve yakalamak için PHP try catch ve exception yazısına bakın. E_USER_WARNING, E_USER_NOTICE ve E_USER_DEPRECATED ile trigger_error() kullanımı eskimiş değildir.

E_STRICT sabiti

E_STRICT hata seviyesi motor tarafından artık hiç kullanılmadığı için PHP 8.4'te kaldırıldı ve sabitin kendisi eskimiş sayıldı. Eski kodlarda sık görülen error_reporting(E_ALL & ~E_STRICT) satırı bu yüzden uyarı üretir:

php
<?php
error_reporting(E_ALL & ~E_STRICT);
echo 'tamam', PHP_EOL;
/* çıktı:
Deprecated: Constant E_STRICT is deprecated since 8.4, the error level was removed in /yol/ornek.php on line 2
tamam
*/

Çözüm, ifadeden E_STRICT parçasını tamamen çıkarmaktır: error_reporting(E_ALL). Bu seviye artık hiçbir hata üretmediği için çıkarmak davranışı değiştirmez.

Standart kütüphanede eskimiş sayılanlar

Standart kütüphanede eskimiş sayılanlar: function f(T $x = null), 0 ** -1, pow(0, -1), class _ {}, trigger_error(..., E_USER_ERROR)

Dil çekirdeği dışında, günlük kodda sık kullanılan bazı fonksiyon imzaları da eskimiş sayıldı. En çok etkileyeni CSV fonksiyonlarıdır: fputcsv(), fgetcsv() ve str_getcsv() çağrılarında escape parametresinin varsayılan değerine güvenmek artık uyarı veriyor. Parametreyi sırasıyla ya da isimli argümanla açıkça vermeniz gerekiyor. Kaçış karakteri mekanizmasını kullanmak istemiyorsanız boş metin verebilirsiniz.

php
<?php
print_r(str_getcsv('elma,"armut, taze",muz'));
print_r(str_getcsv('elma,"armut, taze",muz', escape: ''));
/* çıktı:
Deprecated: str_getcsv(): the $escape parameter must be provided as its default value will change in /yol/ornek.php on line 2
Array
(
    [0] => elma
    [1] => armut, taze
    [2] => muz
)
Array
(
    [0] => elma
    [1] => armut, taze
    [2] => muz
)
*/

İsimli argümanın (escape: '') avantajı, ayırıcı ve tırnak karakteri için varsayılanları yeniden yazmak zorunda kalmamanızdır. Dosyadan CSV okuma örnekleri için PHP dosya okuma ve yazma yazısına bakabilirsiniz. Diğer önemli maddeler:

php
<?php
$x = lcg_value();
$r = new Random\Randomizer();
$y = $r->getFloat(0, 1);
var_dump($y >= 0 && $y < 1); // çıktı: bool(true)
/* çıktının ilk satırı:
Deprecated: Function lcg_value() is deprecated since 8.4, use \Random\Randomizer::getFloat() instead in /yol/ornek.php on line 2
*/
php
<?php
$p = new DatePeriod('R2/2026-11-01T00:00:00Z/P1W');
$p2 = DatePeriod::createFromISO8601String('R2/2026-11-01T00:00:00Z/P1W');
foreach ($p2 as $t) {
    echo $t->format('Y-m-d'), PHP_EOL;
}
/* çıktı:
Deprecated: Calling DatePeriod::__construct(string $isostr, int $options = 0) is deprecated, use DatePeriod::createFromISO8601String() instead in /yol/ornek.php on line 2
2026-11-01
2026-11-08
2026-11-15
*/

Reflection API'de de benzer bir imza temizliği var: ReflectionMethod kurucusunu tek bir "Sinif::metot" metniyle çağırmak eskimiş sayıldı. Aynı iş için adı açık olan statik createFromMethodName() fabrika metodu geldi; iki argümanlı kurucu kullanımı (new ReflectionMethod('DateTime', 'format')) ise etkilenmedi.

php
<?php
$m = new ReflectionMethod('DateTime::format');
$m2 = ReflectionMethod::createFromMethodName('DateTime::format');
echo $m2->getName(), PHP_EOL;
/* çıktı:
Deprecated: Calling ReflectionMethod::__construct() with 1 argument is deprecated, use ReflectionMethod::createFromMethodName() instead in /yol/ornek.php on line 2
format
*/

Aşağıdaki tablo, dil çekirdeği ve standart kütüphanedeki başlıca maddeleri düzeltmeleriyle bir arada gösteriyor. Oturum (session) ayarları, LDAP, PGSQL ve SOAP gibi eklentilere özgü maddeler için kılavuzdaki listenin tamamına bakın.

Eskimiş kullanımYerine
function f(T $x = null)function f(?T $x = null) veya T|null
0 ** -1, pow(0, -1)Tabanı kontrol edin ya da fpow()
class _ {}Anlamlı bir sınıf adı
trigger_error(..., E_USER_ERROR)throw new ...Exception veya exit()
E_STRICTİfadeden çıkarın
str_getcsv / fgetcsv / fputcsv escape varsayılanıescape parametresini açıkça verin
lcg_value()Random\Randomizer::getFloat()
new DatePeriod(ISO metni)DatePeriod::createFromISO8601String()
new ReflectionMethod('Sinif::metot')ReflectionMethod::createFromMethodName()
mysqli_ping(), mysqli_kill(), mysqli_refresh()SQL KILL veya FLUSH komutları
stream_context_set_option() iki argümanlastream_context_set_options()
xml_set_object()Doğrudan metodu gösteren callable

Uygulamalı örnek: eski bir fonksiyonu temizlemek

Gerçek projelerde uyarılar genellikle tek tek değil, aynı dosyada birkaç tane birden çıkar. Aşağıdaki fonksiyon PHP 7 döneminde yazılmış tipik bir kod: hata raporlama satırında E_STRICT var, indirim oranı örtük nullable, geçersiz fiyatta da E_USER_ERROR ile ölümcül hata üretiliyor.

php
<?php
error_reporting(E_ALL & ~E_STRICT);

function indirim(float $fiyat, int $oran = null): float
{
    if ($fiyat <= 0) {
        trigger_error('Geçersiz fiyat', E_USER_ERROR);
    }
    return $fiyat - $fiyat * ($oran ?? 0) / 100;
}

echo indirim(200, 10), PHP_EOL;
/* çıktı:
Deprecated: indirim(): Implicitly marking parameter $oran as nullable is deprecated, the explicit nullable type must be used instead in /yol/ornek.php on line 4

Deprecated: Constant E_STRICT is deprecated since 8.4, the error level was removed in /yol/ornek.php on line 2
180
*/

Çıktıdan iki ders çıkıyor. Birincisi, satır 4'teki uyarı satır 2'dekinden önce geldi: örtük nullable uyarısı dosya derlenirken, E_STRICT uyarısı ise satır çalışırken üretilir. İkincisi, E_USER_ERROR uyarısı hiç görünmedi, çünkü fiyat pozitif olduğu için o satır çalışmadı. Yani çalışma anı uyarıları yalnızca ilgili kod yolu çalıştırıldığında ortaya çıkar; test senaryolarınızın hata dallarını da kapsaması bu yüzden önemlidir. Temizlenmiş hâli şöyle:

php
<?php
error_reporting(E_ALL);

function indirim(float $fiyat, ?int $oran = null): float
{
    if ($fiyat <= 0) {
        throw new InvalidArgumentException('Geçersiz fiyat');
    }
    return $fiyat - $fiyat * ($oran ?? 0) / 100;
}

echo indirim(200, 10), PHP_EOL; // çıktı: 180
try {
    indirim(0);
} catch (InvalidArgumentException $e) {
    echo 'Hata: ', $e->getMessage(), PHP_EOL; // çıktı: Hata: Geçersiz fiyat
}

Yeni sürüm hiçbir uyarı üretmiyor ve geçersiz fiyat durumu artık çağıran tarafından yakalanabiliyor. Eski sürümde aynı durum betiği tamamen durduruyordu.

Projedeki tüm deprecated uyarılarını bulmak

Büyük bir projede uyarıları tek tek görmek yerine hepsini toplamak isteyebilirsiniz. Kılavuzun önerdiği yöntem, geliştirme ortamında hata raporlamayı E_ALL düzeyinde tutmak ve kendi tanılama işleyicinizi set_error_handler() ile kaydetmektir. Aşağıdaki işleyici yalnızca E_DEPRECATED ve E_USER_DEPRECATED seviyelerini yakalar, diğer seviyeler için false döndürerek PHP'nin standart işleyicisine bırakır.

php
<?php
set_error_handler(function (int $seviye, string $mesaj, string $dosya, int $satir): bool {
    if ($seviye === E_DEPRECATED || $seviye === E_USER_DEPRECATED) {
        echo "[eskimiş] $mesaj (satır $satir)", PHP_EOL;
        return true;
    }
    return false;
});

$a = str_getcsv('a,b');
$b = 0 ** -2;
echo 'devam ediyor', PHP_EOL;
/* çıktı:
[eskimiş] str_getcsv(): the $escape parameter must be provided as its default value will change (satır 10)
[eskimiş] Power of base 0 and negative exponent is deprecated (satır 11)
devam ediyor
*/

Gerçek bir projede echo yerine mesajları bir günlük dosyasına yazarsınız. Bir sınır var: örtük nullable uyarısı gibi derleme anında üretilen uyarılar, işleyici kaydedilmeden önce yüklenen dosyalarda yakalanamaz. Bu nedenle işleyiciyi uygulamanın en başında, diğer dosyaları require etmeden önce kaydedin. Derleme uyarılarını kodu çalıştırmadan bulmanın en hızlı yolu yukarıda anlattığımız php -l denetimidir; komut satırı kullanımının ayrıntıları için PHP CLI yazısına bakın.

Kendi kodunuzu eskimiş işaretlemek: #[\Deprecated]

PHP 8.4 aynı mekanizmayı kütüphane yazarlarına da açtı. Bir fonksiyonu, metodu ya da sınıf sabitini #[\Deprecated] özniteliğiyle işaretlediğinizde onu çağıran kod E_USER_DEPRECATED seviyesinde, PHP'nin kendi uyarılarıyla aynı biçimde bir mesaj alır. Yukarıdaki işleyici bu uyarıları da yakalar. Ayrıntılı örnek PHP 8.4 yenilikleri ve PHP attributes yazılarında.

Sık yapılan hatalar

Sık yapılan hatalar: Sadece ? ekleyip parametre sırasını kontrol etmemek, Union tipte ? kullanmaya çalışmak, E_STRICT'i yalnızca bir dosyadan kaldırıp yapılandırma veya...
  • Sadece ? ekleyip parametre sırasını kontrol etmemek: isteğe bağlı parametreden sonra zorunlu parametre varsa ikinci bir uyarı alırsınız.
  • Union tipte ? kullanmaya çalışmak: ?int|string geçersizdir, int|string|null yazın.
  • E_STRICT'i yalnızca bir dosyadan kaldırıp yapılandırma veya başlangıç dosyalarındaki kopyalarını unutmak.
  • CSV düzeltmesinde escape değerini rastgele seçmek: mevcut dosyalarınız ters eğik çizgiyle kaçış kullanıyorsa escape: '\\' vererek eski davranışı açıkça koruyun, kullanmıyorsa '' verin.
  • Uyarıları yalnızca CLI'da test edip web ortamındaki hata günlüğüne bakmamak.

Sık Sorulan Sorular

Deprecated uyarısı sitemi bozar mı?

Hayır, uyarı tek başına çalışmayı durdurmaz. Ancak hata gösterimi açıksa mesaj sayfa çıktısına karışır ve örneğin HTTP başlıkları gönderilmeden önce çıktı oluştuğu için başka sorunlara yol açabilir. Üretimde hata gösterimini kapatıp günlüğe yazdırmak, kodu ise en kısa sürede düzeltmek gerekir.

Örtük nullable kullanımı hangi sürümde tamamen kaldırılacak?

Kılavuzun PHP 8.4 eskimiş özellikler sayfası bir kaldırılma sürümü belirtmez. Yalnızca davranışın eskimiş sayıldığını ve açık nullable tip kullanılması gerektiğini söyler. Tarih beklemeden düzeltmek en güvenli yoldur.

WordPress eklentilerimde bu uyarıları görüyorum, ne yapmalıyım?

Uyarılar eklentinin kodundan geliyorsa düzeltme eklenti geliştiricisine düşer; güncel sürüme geçmek çoğu zaman yeterlidir. WordPress tarafında PHP sürüm yükseltme adımları için WordPress PHP sürümü yükseltme yazısına bakabilirsiniz.

Uyarıları yalnızca kendi kodum için nasıl görebilirim?

set_error_handler() ile kaydettiğiniz işleyici, uyarının üretildiği dosyanın yolunu üçüncü parametre olarak alır. Bu yolu kontrol ederek örneğin üçüncü taraf kütüphanelerin bulunduğu klasörden gelen mesajları ayrı bir günlüğe yazabilir, kendi kodunuzdan gelenleri ise öncelikli listeye alabilirsiniz. Böylece düzeltme işini sahibi olduğunuz koddan başlatırsınız; dış kütüphaneler için de güncel sürümlerini kontrol edersiniz.

Deprecated, Warning ve Fatal error arasındaki fark nedir?

Deprecated davranışın ileride kaldırılacağını söyler, sonuç bugün doğrudur. Warning bir şeylerin şu anda yanlış gittiğini gösterir (örneğin tanımsız değişken okumak) ama betik devam eder. Fatal error ise betiği durdurur. Tanımsız değişken uyarıları için undefined variable ve array key, ölümcül hatalar için fatal error çözümleri yazılarına bakın.

PHP 8.5 yeni eskimiş özellikler getirdi mi?

Evet. (integer) gibi kanonik olmayan tür dönüşüm adları, sayısal olmayan metni ++ ile artırma ve dizi anahtarı olarak null kullanma bunlardan bazıları. Liste PHP 8.5 yenilikleri yazısında.

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 8.4 yenilikleri · Tip bildirimleri · Hata seviyeleri · Undefined variable uyarısı · WordPress PHP sürümü yükseltme