Multi-Tenant Tema Sistemi - Slider, Leonardo AI, Animated Gradient, Zorluklar
t-{id} = Tenant temasi. Sadece ozel dosyalar burada.
simple = Fallback (mevcut, zaten var). t-{id}'de yoksa buradan alir.
Ornek: t-3/homepage.blade.php var -> onu kullan, t-3/blog/show.blade.php yok -> simple'dan al
UPDATE tenants SET data = '{"theme": "t-3"}' WHERE id = 3;
-- Cache temizle
php artisan cache:clear && php artisan view:clear && php artisan responsecache:clear
Homepage'deki slider gorselleri Spatie Media Library ile yonetilir. Homepage sayfasinin slider collection'ina eklenir.
@php
// Homepage sayfasini bul - DOGRU YONTEM
$homepagePage = \Modules\Page\App\Models\Page::where('is_homepage', true)->first();
// Hero ve slider gorselleri
$homepageHero = $homepagePage?->getFirstMediaUrl('hero');
$sliderImages = $homepagePage?->getMedia('slider')
->sortBy(fn($m) => $m->getCustomProperty('slider_order', 0)) ?? collect();
@endphp
// YANLIS - slug degisebilir! $homepagePage = Page::where('slug', 'anasayfa')->first(); // DOGRU - is_homepage flag'i kullan $homepagePage = Page::where('is_homepage', true)->first();
<section x-data="{
currentSlide: 0,
totalSlides: {{ $sliderImages->count() ?: 1 }},
autoplay: null,
init() {
if (this.totalSlides > 1) {
this.autoplay = setInterval(() => { this.nextSlide() }, 4000);
}
},
nextSlide() { this.currentSlide = (this.currentSlide + 1) % this.totalSlides; },
prevSlide() { this.currentSlide = (this.currentSlide - 1 + this.totalSlides) % this.totalSlides; }
}">
@foreach($sliderImages as $index => $slide)
<div x-show="currentSlide === {{ $index }}" x-transition>
<img src="{{ $slide->getUrl() }}">
</div>
@endforeach
</section>
$homepagePage = Page::where('is_homepage', true)->first();
// Gorsel ekle
$homepagePage->addMedia($imagePath)
->preservingOriginal()
->withCustomProperties(['slider_order' => 1])
->toMediaCollection('slider');
Leonardo AI ile otomatik gorsel uretip Spatie Media Library'ye kaydedebilirsin. Slider, hero, cover gorselleri icin kullan.
use App\Services\Media\LeonardoAIService; $leonardo = app(LeonardoAIService::class); // Prompt ile gorsel uret $result = $leonardo->generateFromPrompt( 'Modern luxury apartment with white roller shutters, Mediterranean architecture, 8k photorealistic', [ 'width' => 1920, 'height' => 1080, 'style' => 'stock_photo', ] ); // Sonuc $result['content'] // Binary gorsel icerigi $result['url'] // Leonardo CDN URL $result['generation_id']
// Tenant storage path storage/tenant{id}/app/public/hero-slider/ // Public symlink public/storage/tenant{id}/ -> storage/tenant{id}/app/public/ // URL (cdn helper ile) {{ cdn('storage/tenant3/hero-slider/image.jpg') }}
Modern luxury apartment building exterior with white motorized roller shutters, Mediterranean architecture, warm sunset lighting, 8k photorealistic, Istanbul cityscape
Luxurious modern villa with automatic garage door, sleek metal roller shutter, contemporary Turkish architecture, evening ambiance, 8k photorealistic
Baslik metinlerine hareketli turuncu gradient efekti ekle. Kayma animasyonu ile dikkat cekici basliklar.
/* Animated Gradient Text */ .gradient-text-animated { background: linear-gradient( 90deg, #f97316 0%, /* orange-500 */ #fb923c 15%, /* orange-400 */ #fdba74 30%, /* orange-300 */ #ea580c 50%, /* orange-600 */ #c2410c 65%, /* orange-700 */ #f97316 80%, #fb923c 100% ); background-size: 200% auto; -webkit-background-clip: text; background-clip: text; -webkit-text-fill-color: transparent; animation: gradientShift 4s ease-in-out infinite; } @keyframes gradientShift { 0% { background-position: 0% center; } 50% { background-position: 100% center; } 100% { background-position: 0% center; } }
{{-- Hero Basligi --}} <h1> <span class="gradient-text-animated">Panjur Tamiri</span><br> <span class="text-gray-900 dark:text-white">ve Montaj Hizmetleri</span> </h1> {{-- Section Basliklari --}} <h2>Profesyonel <span class="gradient-text-animated">Panjur Cozumleri</span></h2> <h2>Nasil <span class="gradient-text-animated">Calisir?</span></h2>
/* Dark mode - daha acik tonlar */ .dark .gradient-text-animated { background: linear-gradient( 90deg, #fb923c 0%, #fdba74 15%, #fed7aa 30%, #f97316 50%, #ea580c 65%, #fb923c 80%, #fdba74 100% ); /* ... ayni ayarlar */ }
$sliderImages->count() hep 0 donuyordu.
// YANLIS - slug degisebilir, her tenant'ta farkli olabilir $homepagePage = Page::where('slug', 'anasayfa')->first(); // DOGRU - is_homepage flag'i kullan $homepagePage = Page::where('is_homepage', true)->first();
asset('storage/...') 404 veriyordu.
// YANLIS - tenant klasoru eksik asset('storage/hero-slider/image.jpg') // DOGRU - tenant{id} klasorunu ekle cdn('storage/tenant3/hero-slider/image.jpg') // Symlink yapisi: public/storage/tenant3/ -> storage/tenant3/app/public/
// Collection ismi TUTARLI olmali // Ekleme: $page->addMedia($path)->toMediaCollection('slider'); // Okuma: $page->getMedia('slider'); // YANLIS - farkli isimler kullanma! toMediaCollection('hero-slider') vs getMedia('slider')
# Nuclear cache temizleme
php artisan cache:clear && \
php artisan view:clear && \
php artisan config:clear && \
php artisan route:clear && \
php artisan responsecache:clear
Logo varsa SADECE logo gosterilir. Logo yoksa icon + site adi.
$logoService = app(\App\Services\LogoService::class);
$logos = $logoService->getLogos();
$hasLogo = $logos['has_light'] || $logos['has_dark'];
@if($hasLogo)
<img src="{{ $logos['light_logo_url'] }}" class="dark:hidden h-10">
<img src="{{ $logos['dark_logo_url'] }}" class="hidden dark:block h-10">
@else
<i class="fa-blinds"></i>
<span>{{ $siteName }}</span>
@endif
Laravel once Modules/ altindaki view'lara bakar. Homepage icin Modules/Page/ konumunu guncelle!
1. ONCELIKLI (Modules): Modules/Page/resources/views/themes/t-3/homepage.blade.php 2. Fallback (resources): resources/views/themes/t-3/homepage.blade.php