Filament v5, yerleşik bir kayıt sayfası ile birlikte gelir. Ancak bazı eklentiler bunu göz ardı ederek kendi kontrolcülerini oluşturur. İşte nasıl captcha, honeypot, rol ataması ve olay köprülemesi eklediğimiz — tamamen Filament’in belgelenmiş kancaları aracılığıyla, `register()` metodunu değiştirmeden.
<p>Filament, Laravel için en iyi arka uç çerçevelerinden biridir. Yönetim panellerini hızlı bir şekilde oluşturarak, kutudan çıkardığında harika görünür ve derinlemesine genişletilebilir. Ancak, birçok ciddi proje yalnızca arka uç ile sınırlı kalmaz. Bir SaaS, kamuya açık bir bölümü olan bir web uygulaması veya gerçekte kullanıcıların kaydolduğu herhangi bir şey inşa ediyorsanız, sonunda yönetim kabuğunun dışındaki kimlik doğrulamasına ihtiyacınız vardır.</p>
<p>Yaygın bir cevap, Laravel'in resmi başlangıç kitlerinden birine yönelmektir. Modern seriler — React, Vue ve Livewire seçenekleri, kimlik doğrulama iskeletleri ile birlikte geliyor — günümüzde birçok takımın tercih ettiği yoldur. Laravel 10.x döneminde çıkan daha eski kitler olan Breeze ve Jetstream ise hala bakımda ve yaygın olarak kullanılmaktadır. Bu kitler savaş alanında test edilmiştir, mükemmel bir şekilde belgelenmiştir ve birçok proje için harika bir uyum sağlar: kamuya açık kimlik doğrulamasını tamamen ele alırken, Filament'in yönetim tarafına odaklanmasına izin verir. Birçok ekip için bu ayrım tam olarak istediğiniz şeydir ve bu kitler kesinlikle Laravel ekosistemindeki yerlerini hak ediyorlar.</p>
<p>Bununla birlikte, kimlik doğrulamanızı güçlendirmek ve kendi başınıza Filament kullanarak oluşturmak isterseniz, çerçeveden dışarı çıkmanıza gerek yok — Filament v5, genişletmek için ihtiyacınız olan her şeyi içerir. Tamamen bir kimlik doğrulama akışı ile birlikte gelir — \Filament\Auth\Pages\Login, \Filament\Auth\Pages\Register, e-posta doğrulaması, şifre sıfırlama ve çok faktörlü kimlik doğrulama - ve bunlar sadece yönetim paneli araçları değildir. Gerçek, temalandırılabilir, genişletilebilir sayfalardır; bunları kullanıcılarınıza sunabilirsiniz.</p>
<p>Ancak, sorun şu ki: özellikle kayıt sayfası, üretime hazır hale gelmeden önce çalışmaya ihtiyaç duyar. Kutudan çıktığında, captcha yok, honeypot yok, rol ataması yok ve uygulamanızın diğer bölümlerinde zaten bağımlı olan Laravel etkinlik köprülemesi yok. Çoğu eklenti bunu özel bir Laravel kontrolcüsüne, bir Blade formuna ve manuel doğrulamaya başvurarak çözüyor - tamamen Filament'in kimlik doğrulama akışından vazgeçerek.</p>
<p>Biz, tallcms/filament-registration (Link) projesini geliştirirken, diğer yaklaşımı benimsedik. Her üretim özelliği — captcha, honeypot, hız sınırlaması, varsayılan rol ataması, kayıt sonrası yönlendirme - Filament'in belgelenmiş uzantı noktalarına yerleştirildi. `register()` metodunu asla geçersiz kılmadık. Bu kalıplar, çerçeveyi terk etmeden açık bir kayıt sayfasına ihtiyaç duyan herhangi bir Filament v5 projesine uygulanabilir.</p>
<p>Temel Fikir: Tek Geçersiz Kılma Değil, İki Kanca<br/>Filament'in Kayıt sayfası, iki genişletme noktasını açığa çıkarır:</p>
<ul>
<li><code>mutateFormDataBeforeRegister(array $data): array</code> — doğrulamadan sonra ama <code>User::create()</code> yönteminden önce çalışır. Kayıt sürecini engellemesi gereken her şey için uygundur.</li>
<li><code>handleRegistration(array $data): Model</code> — kullanıcı oluşturmayı sarar. Kullanıcı oluşturulduktan sonra koşması gereken her şey için uygundur.</li>
</ul>
<p>Eski bir kontrolcüden geçiş yapıyorsanız, `register()` yöntemini geçersiz kılma cazibesi özellikle yüksektir ve her şeyi tek bir yöntem içinde yeniden inşa etmeyi düşünebilirsiniz. Bunu yapmayın. Filament'in `register()` yöntemi zaten yavaşlatmayı, doğrulamayı, e-posta doğrulamasını, yanıt dağıtımını ve etkinlik ateşlemeyi düzenliyor. Bunu yeniden yazarak hepsi doğru gitmeyecek. Ayrıca buna ihtiyacınız yok.</p>
<div class="highlight js-code-highlight">
<pre class="highlight php"><code><span class="kd">class</span> <span class="nc">Register</span> <span class="kd">extends</span> <span class="nc">\Filament\Auth\Pages\Register</span>{
public function form(Schema $schema): Schema
{
return $schema->components([
$this->getNameFormComponent(),
$this->getEmailFormComponent(),
$this->getPasswordFormComponent(),
$this->getPasswordConfirmationFormComponent(),
HoneypotField::make(),
CaptchaField::make(),
]);
}
<span class="k">protected</span> <span class="k">function</span> <span class="n">mutateFormDataBeforeRegister</span><span class="p">(</span><span class="kt">array</span> <span class="nv">$data</span><span class="p">):</span> <span class="kt">array</span>
<span class="p">{</span>
<span class="nv">$this</span><span class="o">-></span><span class="nf">checkHoneypot</span><span class="p">(</span><span class="nv">$data</span><span class="p">);</span>
<span class="nv">$this</span><span class="o">-></span><span class="nf">throttleCaptcha</span><span class="p">();</span>
<span class="nv">$this</span><span class="o">-></span><span class="nf">verifyCaptcha</span><span class="p">(</span><span class="nv">$data</span><span class="p">);</span>
<span class="k">unset</span><span class="p">(</span><span class="nv">$data</span><span class="p">[</span><span class="nv">$this</span><span class="o">-></span><span class="n">honeypotField</span><span class="p">],</span> <span class="nv">$data</span><span class="p">[</span><span class="nv">$this</span><span class="o">-></span><span class="n">tokenField</span><span class="p">]);</span>
<span class="k">return</span> <span class="nv">$data</span><span class="p">;</span>
<span class="p">}</span>
<span class="k">protected</span> <span class="k">function</span> <span class="n">handleRegistration</span><span class="p">(</span><span class="kt">array</span> <span class="nv">$data</span><span class="p">):</span> <span class="kt">Model</span>
<span class="p">{</span>
<span class="nv">$user</span> <span class="o">=</span> <span class="k">parent</span><span class="o">::</span><span class="nf">handleRegistration</span><span class="p">(</span><span class="nv">$data</span><span class="p">);</span>
<span class="nv">$this</span><span class="o">-></span><span class="nf">maybeMarkEmailVerified</span><span class="p">(</span><span class="nv">$user</span><span class="p">);</span>
<span class="nv">$this</span><span class="o">-></span><span class="nf">maybeAssignDefaultRole</span><span class="p">(</span><span class="nv">$user</span><span class="p">);</span>
<span class="nf">event</span><span class="p">(</span><span class="k">new</span> <span class="nc">\Illuminate\Auth\Events\Registered</span><span class="p">(</span><span class="nv">$user</span><span class="p">));</span>
<span class="k">return</span> <span class="nv">$user</span><span class="p">;</span>
<span class="p">}</span>}
<p>Bu, kalıbın tamamıdır. Aşağıda, bu yöntemlerin içine girmesi gereken her şey.</p>
<p>Katman 1: Honeypot, Gizlilik Değil, Doğrulama Aracılığıyla<br/>Honeypot'ların eski yaklaşımı, alan doldurulduğunda sahte bir başarı sayfası sessizce görüntülemektir; umarım bot yanlış bir pozitif kaydeder. Bu işe yarar, ta ki işe yaramayana kadar — modern botlar, kendi başarı sayfası tespit edicilerini geliştirir.</p>
<p>Filament içinde daha temiz bir yaklaşım: bir <code>ValidationException</code> atmak. Filament, Laravel'in doğrulama istisnalarını otomatik olarak yakalar ve mesajı forma yansıtır. Honeypot'u doldurmayan botlar doğrulamadan geçerken, dolduran botlar honeypot alanına ekli olan genel bir "Bot kontrolü başarısız" mesajını görürler.</p>
<div class="highlight js-code-highlight">
<pre class="highlight php"><code><span class="k">if</span> <span class="p">(</span><span class="o">!</span> <span class="k">empty</span><span class="p">(</span><span class="nv">$data</span><span class="p">[</span><span class="nv">$this</span><span class="o">-></span><span class="n">honeypotField</span><span class="p">]))</span> <span class="p">{</span>
<span class="k">throw</span> <span class="nc">ValidationException</span><span class="o">::</span><span class="nf">withMessages</span><span class="p">([</span>
<span class="nv">$this</span><span class="o">-></span><span class="n">honeypotField</span> <span class="o">=></span> <span class="s1">'Bot check failed. Please try again.'</span><span class="p">,</span>
<span class="p">]);</span>
<span class="p">}</span>

