Bu yazıda, Laravel 12 uygulamasını özel bir PHP framework’e düşürme sürecini detaylandıracağım. Migrasyon sürecinde yeni paketlerin oluşturulması, TDD (Test Driven Development) pipeline’ının nasıl çalıştığı ve dikkat edilmesi gereken noktalar üzerinde duracağız.
<h2>
<a name="the-setup" href="#the-setup"></a>
Kurulum
</h2>
<p>GoFormX, form yönetimi için bir platformdur. Web ön yüzü Laravel 12 + Inertia v2 + Vue 3 ile çalışıyordu. Go API arka ucu formları ve gönderimleri yönetmektedir. Waaseyaa, yeni bir PHP framework olarak hazır durumda — GoFormX'u Laravel'den Waaseyaa'ya geçirme zamanı geldi.</p>
<p>Migrasyon spesifikasyonu zaten yazılmıştı. Üç yeni framework paketi oluşturulması gerekiyordu (<code>waaseyaa/inertia</code>, <code>waaseyaa/auth</code>, <code>waaseyaa/billing</code>), ayrıca tüm uygulama iskeletine ihtiyaç vardı. Plan, bunu birkaç oturumda yürütmekti.</p>
<p>Ancak, bu tek bir oturumda gerçekleştirildi.</p>
<h2>
<a name="what-got-built" href="#what-got-built"></a>
Neler Yapıldı?
</h2>
<p>Tek bir Claude Code oturumunda (~8 saat), aşağıdaki çıktılar elde edildi:</p>
<p><strong>3 Waaseyaa paketi (hepsi Packagist'e yayımlandı):</strong></p>
<ul>
<li>
<code>waaseyaa/inertia</code> — Sunucu tarafında Inertia v3 protokol adaptörü. Gömülü JSON sayfa nesneleri ile ilk HTML sayfa yüklemelerini yönetir, XHR JSON yanıtlarını işler, sürüm kontrolü (409) ve yönlendirme durum kodu dönüşümünü sağlar. 30 test.
</li>
<li>
<code>waaseyaa/auth</code> — Başsız kimlik doğrulama. Oturum yönetimi ile giriş/çıkış, HMAC imzalı şifre sıfırlama token'ları, imzalı e-posta doğrulama URL'leri, TOTP iki adımlı doğrulama (RFC 6238, dış kütüphane yok), token-bucket hız sınırlaması. 46 test.
</li>
<li>
<code>waaseyaa/billing</code> — Stripe faturalandırma. Aboneliklerden ve yönetici geçersiz kılmalarından plan katmanı belirleme, ödeme seansı oluşturma, müşteri portalı, webhook olayı işleme, kurucu üye slot yönetimi. 35 test.
</li>
</ul>
<p><strong>1 tam uygulama (<code>goformx-web</code>):</strong></p>
<ul>
<li>7 PHP kontrolcüsü (Auth, Public, Dashboard, Form, Billing, Settings, GoFormsClient)</li>
<li>37 PHP birim testi</li>
<li>28 Vue 3 sayfa bileşeni (Laravel uygulaması ile tam parite)</li>
<li>24 shadcn-vue UI bileşen dizini</li>
<li>9 SSR Twig şablonu ana tasarım ile</li>
<li>5 MariaDB migrasyon dosyası</li>
<li>6 hizmetle Docker Compose (PHP/nginx, Vite, Go API, MariaDB, PostgreSQL, Mailpit)</li>
<li>GitHub Actions CI/CD pipeline'ı</li>
<li>Ansible dağıtım konfigürasyonu</li>
</ul>
<p><strong>Toplam: 148 test her şey üzerinde.</strong></p>
<h2>
<a name="the-tdd-pipeline-that-made-it-work" href="#the-tdd-pipeline-that-made-it-work"></a>
TDD Pipeline'ı
</h2>
<p>Her paket aynı desenle takip edildi ve tekrar kullanılabilir bir beceri olan <code>laravel-to-waaseyaa</code> içerisine alındı:</p>
<ol>
<li>
<strong>İskelet</strong> — <code>composer.json</code>, minimal <code>ServiceProvider</code>, üst düzey monorepo'ya bağlanma
</li>
<li>
<strong>TDD çekirdek bileşenler</strong> — Test yaz, başarısız olduğunu gör, implement et, geçerli olduğunu gör. Her sınıf bu işlemden geçer.
</li>
<li>
<strong>Bağla</strong> — Servis sağlayıcı tekil nesneleri, middleware, rotaları kaydeder
</li>
<li>
<strong>Doğrula</strong> — Tam test paketi + CS Fixer
</li>
<li>
<strong>Dağıt</strong> — Monorepo bölünmüş iş akışına ekle, GitHub bölünmüş deposu oluştur, etiketle, Packagist'e gönder
</li>
</ol>
<p>Ana fikir: Claude Code bu pipeline'ı güvenilir bir şekilde uygulayabilir çünkü her adımın somut ve doğrulanabilir bir sonucu vardır. Testler sadece doğruluk için değil — her adımın başarılı olup olmadığını bildiren geri bildirim döngüsü olarak çalışır.</p>
<h2>
<a name="the-hard-parts" href="#the-hard-parts"></a>
Zor Kısımlar
</h2>
<h3>
<a name="waaseyaas-kernel-vs-goformxs-needs" href="#waaseyaas-kernel-vs-goformxs-needs"></a>
Waaseyaa'nın Kernel’i vs GoFormX'in İhtiyaçları
</h3>
<p>Waaseyaa kernel’i, varlık depolama katmanı için SQLite ile açılır. GoFormX'in kullanıcıları ise MariaDB'de (Laravel'den taşınmış) yer alır. Çözüm: auth işlemleri için PDO üzerinden doğrudan MariaDB sorgulayan bir <code>UserRepository</code> oluşturmak. Estetik değil, ama pratik — varlık sistemi framework varlıklarını, MariaDB uygulama verilerini yönetir.</p>
<h3>
<a name="inertia-v3s-page-data-format" href="#inertia-v3s-page-data-format"></a>
Inertia v3’ün Sayfa Veri Formatı
</h3>
<p>Bu, öğretici bir hata ayıklama seansıydı. İlk uygulama, sayfa verilerini bir <code><script type="application/json" data-page="true"/></code> etiketi içerisine yerleştirdi (v2 geleneği). Beyaz ekran. Sonra <code>#app</code> divi üzerinde bir <code>data-page</code> özniteliği. Yine beyaz ekran — JSON iyi bir şekilde ayrıştırıldı, ama Inertia bulamadı.</p>
<p>Inertia v3 kaynak kodunu okumak, çözümü ortaya koydu:<br/></p>
<div class="highlight js-code-highlight">
<pre class="highlight javascript"><code><span class="kd">const</span> <span class="nx">scriptEl</span> <span class="o">=</span> <span class="nb">document</span><span class="p">.</span><span class="nf">querySelector</span><span class="p">(</span>
<span class="s2">`script[data-page="</span><span class="p">${</span><span class="nx">id</span><span class="p">}</span><span class="s2">"][type="application/json"]`</span>
<span class="p">);</span>
</code></pre>
</div>
<p>V3, <code>data-page="app"</code>'i arar (montaj elemanının ID'si), <code>data-page="true"</code>'yi değil. Tek bir öznitelik düzeltmesi, ancak bunu bulmak için framework kaynağını okumak gerekti.</p>
<h3>
<a name="phpfpm-doesnt-inherit-docker-env-vars" href="#phpfpm-doesnt-inherit-docker-env-vars"></a>
PHP-FPM Docker Çevre Değişkenlerini Miras Almaz
</h3>
<p>PHP uygulaması ve Go API arasındaki HMAC paylaşılan gizli anahtarı üretim ortamında boştu — <code>$_ENV</code> PHP-FPM'de çalışmıyordu çünkü FPM varsayılan olarak ortamı temizler. İki düzeltme: FPM konfigürasyonunda <code>clear_env = no</code> ayarlamak ve bir yardımcı fonksiyon ile <code>$_ENV</code>'den <code>getenv()</code>'ye geçmek.</p>
<h2>
<a name="whats-actually-verified" href="#whats-actually-verified"></a>
Gerçekte Ne Doğrulandı?
</h2>
<p>Her akış, sadece cURL ile değil, Playwright MCP (tarayıcı otomasyonu) ile test edildi. Giriş akışı, uçtan uca çalışıyor: giriş sayfasını GET et → e-posta ve şifreyi doldur → "Giriş Yap" butonuna tıkla → dashboard'a yönlendiril, Vue uygulaması render ediliyor, navigasyon çalışıyor, kullanıcı verileri görüntüleniyor.</p>
<p>HMAC doğrulaması Go API’ye çalışıyor — Go API imzaları kabul ediyor ve istekleri işliyor. Formlar sayfası, test kullanıcısında forma sahip olmadığı için "Henüz form yok" mesajını gösteriyor.</p>
<h2>
<a name="whats-left" href="#whats-left"></a>
Geride Kalanlar
</h2>
<p>Uygulama yapısal olarak tamam ama üretim için hazır değil. Kalan işler:</p>
<ul>
<li>Form.io oluşturucu entegrasyon testleri (gerektirir: <code>@goformx/formio</code> npm link)</li>
<li>Stripe webhook testleri test anahtarlarıyla</li>
<li>Profil/şifre güncelleme POST işleyicileri (formlar render edilecek, gönderimler bağlanacak)</li>
<li>Üretim için Ansible vault gizli anahtarları</li>
<li>7 günlük güven dönemine geçiş planı (zaten GitHub sorunlarıyla belgelenmiş)</li>
</ul>
<h2>
<a name="the-reusable-skill" href="#the-reusable-skill"></a>
Tekrar Kullanılabilir Beceriler
</h2>
<p>En değerli belge, belki de <code>laravel-to-waaseyaa</code> becerisidir — yeni Waaseyaa paketleri oluşturmak için tekrarlanabilir bir 6 aşamalı pipeline. Bu, bu migrasyon sırasında keşfedilen tam desenleri, gelenekleri ve dikkat edilmesi gereken noktaları kodlar. Bir sonraki sefer Laravel'dan Waaseyaa'ya bir özellik taşırken, bu beceri el kitabını sunar.</p>
<h2>
<a name="takeaway" href="#takeaway"></a>
Sonuç
</h2>
<p>Migrasyon, üç ana sebep yüzünden başarılı oldu:</p>
<ol>
<li>
<p><strong>Ayrıntılı bir spesifikasyon önceden yazıldı.</strong> Migrasyon tasarım belgesi, her bir rotayı, her bir varlık alanını, her bir API uç noktasını belirtti. Claude Code spesifikasyona göre çalıştı, belirsiz niyetlere göre değil.</p>
</li>
<li>
<p><strong>TDD, geri bildirim döngüsü olarak kullanıldı.</strong> Her bileşen bir hata veren test ile başladı. Ajan, test başarılı olduğunda işin tamamlandığını bilir. Belirsizlik yok.</p>
</li>
<li>
<p><strong>Artımlı doğrulama.</strong> Her görevden sonra bir taahhüt. Her bileşenden sonra test. 10 şeyi topluca yapıp hepsinin çalışmasını umma.</p>
</li>
</ol>
<p>Oturum boyunca toplam test sayısı: 148 test, hepsi yeşil. Bir gün için fena değil.</p>
<p>Baamaapii</p>Kaynak: Orijinal Makale


