nuri60 Composite index oluşturarak benzersizlik sağlayabilirsiniz ama burada kullanılan sütunların hepsinin dolu olması gerekiyor, null değer olursa olmaz. Mesela title ve deleted_at olsun, her ikisi de nullable olmak üzere;
$table->unique(['title', 'deleted_at']);
yaptığınızda title ya da deleted_at null ise index çalışmayacaktır. Eğer bunu veri tabanı düzeyinde yapmak isterseniz generated column oluşturabilirsiniz. Generated column dediğimiz belli ifadeler (expression) kullanarak otomatik değer alan sütunları ifade eder. (Bir de virtual column var, bunun yer kaplamayanı, anlık oluşturulan versiyonu ama ona anlık oluştuğu için index atamazsınız)
$storedAs = <<<SQL
CASE
WHEN title IS NOT NULL AND deleted_at IS NULL THEN title
ELSE NULL
END
SQL;
$table->string('title_generated')
->nullable()
->storedAs($storedAs);
$table->unique('title_generated');
$storedAs kısmında title_generated şeklinde bir alan oluşturdum. Eğer title alanı varsa ve deleted_at null ise title_generated değeri title ile aynı olacak, diğer durumlarda ise değeri null olacak. Böylece sadece title varsa unique index çalışacak, eğer bir şekilde hem title hem de deleted_at null olursa ya da deleted_at alanı dolu olursa unique index çalışmayacak. Böylece silinmiş bir alandaki title değerini tekrar kullanabileceksiniz ama aynı title değerine sahip iki sütun var, birinde deleted_at dolu ise ve siz o kaydı geri getirmek için deleted_at sütununu null yaparsanız duplicate entry hatası alacaksınız. Yani ne yaptığınızı sadece yazılımsal değil iş mantığı olarak da bir düşünün. Bu durumda ya o kaydı geri getiremeyeceksiniz ya da geri getirmeden önce title değerini değiştirmeniz gerekecek.