Laravel 4 Türkçe Dokümantasyon (v. 4.2) (Ücretsiz) Laravel 4 Türkiye Forumları Çeviri Ekibi tarafından yapılan çeviriler Sinan Eldem Bu kitap şu adreste satılmaktadır http://leanpub.com/laravel42-tr Bu versiyon şu tarihte yayımlandı 2014-08-04 This is a Leanpub book. Leanpub empowers authors and publishers with the Lean Publishing process. Lean Publishing is the act of publishing an in-progress ebook using lightweight tools and many iterations to get reader feedback, pivot until you have the right book and build traction once you do. ©2014 Sinan Eldem İçindekiler Editörün Notu . . . . . . . . . . . . . . . . . . . . . . . . . i Tanıtım . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Nereden Başlamalı . . . . . . . . . . . . . . . . . . . . . Laravel Felsefesi . . . . . . . . . . . . . . . . . . . . . . . iii iii iv Laravel Hızlı Başlangıç . . . . . Kurulum . . . . . . . . . . . . Local Geliştirme Ortamı . . . Rotalandırma (Routing) . . . . Bir View Oluşturma . . . . . Bir Migrasyon Oluşturma . . Eloquent ORM . . . . . . . . Veri Gösterme . . . . . . . . . Uygulamanızın Yayımlanması . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . v . v . vii . vii . viii . x . xii . xiii . xiv Sürüm Notları . . . . . . . . . . . . . . . . . . . . . . . . . xv Laravel 4.2 . . . . . . . . . . . . . . . . . . . . . . . . . . xv Laravel 4.1 . . . . . . . . . . . . . . . . . . . . . . . . . . xix Yükseltme Rehberi . . . . . . . . . . . . . 4.1’den 4.2’ye Yükseltme . . . . . . . . . 4.1.x ve Öncesinden 4.1.29’a Yükseltme . 4.1.25 ve Öncesinden 4.1.26’ye Yükseltme 4.0’dan 4.1’e Yükseltme . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . xxiii xxiii xxv xxv xxvii İÇINDEKILER Kurulum . . . . . . . . . Composer Kurulumu . Laravel Yükleme . . . Sunucu Gereksinimleri Yapılandırma . . . . . Zarif URL’ler . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1 1 1 2 2 3 Yapılandırma . . . . . . . . . . . . . Giriş . . . . . . . . . . . . . . . . Ortam Yapılandırması . . . . . . Hassas Yapılandırmaları Korumak Bakım Modu . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5 5 6 8 10 Laravel Homestead . . . Giriş . . . . . . . . . . Dahil Edilen Yazılımlar Yükleme & Kurulum . Günlük Kullanım . . . Portlar . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12 12 12 13 16 17 İstek Yaşam Döngüsü . . . . . . Genel Bakış . . . . . . . . . . İstek Yaşam Döngüsü . . . . . Start Dosyaları . . . . . . . . Application Olayları (Events) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18 18 18 20 22 Rotalar . . . . . . . . . . . . . . . . . . Temel Rotalama . . . . . . . . . . . . Rota Parametreleri . . . . . . . . . . Rota Filtreleri . . . . . . . . . . . . . İsimli Rotalar . . . . . . . . . . . . . Rota Grupları . . . . . . . . . . . . . Alt Alanadı (Subdomain) Rotalaması Rotalarda Ön-ek . . . . . . . . . . . Rotalara Model Bağlama . . . . . . . 404 Hatası Fırlatma . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24 24 25 27 31 32 33 33 34 35 İÇINDEKILER Denetçilere (Controller) Rotalama . . . . . . . . . . . . . İstekler (Requests) ve Girdi (Input) Temel Girdi . . . . . . . . . . . . Çerezler (Cookies) . . . . . . . . Önceki Girdi . . . . . . . . . . . Dosyalar . . . . . . . . . . . . . . İstek Bilgileri . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37 37 38 39 40 42 Görünümler (Views) ve Cevaplar (Responses) Temel Cevaplar . . . . . . . . . . . . . . . . Yönlendirmeler (Redirects) . . . . . . . . . . Görünümler (Views) . . . . . . . . . . . . . Görünüm Kompozitörleri . . . . . . . . . . . Özel Cevaplar . . . . . . . . . . . . . . . . . Cevap Makroları . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46 46 47 48 51 53 54 Denetçiler (Controllers) . . . . . . . . . . . . . . . . . . . Temel Denetçiler . . . . . . . . . . . . . . . . . . . . . . Denetçi Filtreleri . . . . . . . . . . . . . . . . . . . . . . TEDA-uyumlu (Temsili Durum Aktarma uyumlu, RESTful) Denetçiler . . . . . . . . . . . . . . . . . . . . Kaynak (Resource) Denetçileri . . . . . . . . . . . . . . . Eksik Olan Metodların İşlenmesi . . . . . . . . . . . . . . 56 56 58 Hatalar ve Günlüğe Ekleme Yapılandırma . . . . . . . Hataların İşlenmesi . . . . HTTP İstisnaları . . . . . 404 Hatalarının İşlenmesi . Günlüğe Ekleme . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 66 66 67 68 69 69 Cepheler (Facades) Giriş . . . . . . . Açıklama . . . . Pratik Kullanım . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 71 71 71 72 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36 60 62 64 İÇINDEKILER Cephe Oluşturma . . . . . . . . . . . . . . . . . . . . . . Cepheleri Taklit Etme . . . . . . . . . . . . . . . . . . . . Facade Sınıf Referansı . . . . . . . . . . . . . . . . . . . Laravel Cashier . . . . . . . . . . . . . . Giriş . . . . . . . . . . . . . . . . . . . Yapılandırma . . . . . . . . . . . . . . Bir Plana Abone Olunması . . . . . . . Kredi Kartsız . . . . . . . . . . . . . . Aboneliklerin Takas Edilmesi . . . . . Abonelik Miktarı . . . . . . . . . . . . Bir Aboneliğin İptal Edilmesi . . . . . . Bir Aboneliğe Geri Dönülmesi . . . . . Abonelik Durumunun Yoklanması . . . Başarısız Ödemelerin Halledilmesi . . . Diğer Stripe Webhook’larının İşlenmesi Faturalar . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 79 79 79 80 82 82 83 83 84 84 86 87 87 Formlar & HTML . . . . . . . . . . . . . . . Form Açmak . . . . . . . . . . . . . . . . CSRF Koruması . . . . . . . . . . . . . . . Forma Model Bağlanması . . . . . . . . . Label Elementi . . . . . . . . . . . . . . . Text, Textarea, Password & Hidden Alanlar Onay Kutuları ve Seçenek Düğmeleri . . . File Inputu . . . . . . . . . . . . . . . . . . Aşağı Açılır Listeler . . . . . . . . . . . . . Düğmeler . . . . . . . . . . . . . . . . . . Özel Makrolar . . . . . . . . . . . . . . . . URL Oluşturma . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 89 89 90 91 92 92 93 93 94 94 95 95 Frameworkün Genişletilmesi Giriş . . . . . . . . . . . . . Manager’lar & Factory’ler . Genişletme Nereye Konacak . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 96 96 97 97 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 73 75 75 . . . . . . . . İÇINDEKILER Cache . . . . . . . . . Session . . . . . . . . . Authentication . . . . IoC Temelli Genişletme Request Genişletmesi . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 98 100 102 105 106 Geçerlilik Denetimi . . . . . . . Temel Kullanım . . . . . . . . Hata Mesajlarıyla Çalışmak . Hata Mesajları & Görünümler Mevcut Geçerlilik Kuralları . Duruma Göre Kurallar Ekleme Özel Hata Mesajları . . . . . . Özel Geçerlilik Kuralları . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 108 108 110 111 113 121 123 125 Güvenlik . . . . . . . . . . . . . . . . . Yapılandırma . . . . . . . . . . . . . Şifrelerin Saklanması . . . . . . . . . Kullanıcı Kimliklerinin Doğrulanması Elle Kullanıcı Girişi . . . . . . . . . . Rotaların Korunması . . . . . . . . . HTTP Basic Kimlik Doğrulaması . . Şifre Hatırlatıcıları & Yenileme . . . . Kriptolama . . . . . . . . . . . . . . Kimlik Doğrulama Sürücüleri . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 128 128 129 129 133 134 135 136 140 141 IoC Konteyneri . . . . . . . . . . . . . Giriş . . . . . . . . . . . . . . . . . . Temel Kullanım . . . . . . . . . . . . Bağlamaların Kayda Geçirileceği Yer Otomatik Çözümleme . . . . . . . . Pratik Kullanım . . . . . . . . . . . . Hizmet Sağlayıcıları . . . . . . . . . Konteyner Olayları . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 142 142 142 143 144 145 147 148 Güvenlik . . . . . . . . . . . . . . . . . . . . . . . . . . . . 150 İÇINDEKILER Yapılandırma . . . . . . . . . . . . . Şifrelerin Saklanması . . . . . . . . . Kullanıcı Kimliklerinin Doğrulanması Elle Kullanıcı Girişi . . . . . . . . . . Rotaların Korunması . . . . . . . . . HTTP Basic Kimlik Doğrulaması . . Şifre Hatırlatıcıları & Yenileme . . . . Kriptolama . . . . . . . . . . . . . . Kimlik Doğrulama Sürücüleri . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 150 151 151 155 156 157 158 162 163 Kuyruklar . . . . . . . . . . . . . . . . Yapılandırma . . . . . . . . . . . . . Temel Kullanım . . . . . . . . . . . . Kuyruğa Closure Fonksiyonu Ekleme Kuyruk Dinleyicileri Çalıştırma . . . Daemon Kuyruk İşçisi . . . . . . . . Push Kuyrukları . . . . . . . . . . . . Başarısız İşler . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 164 164 164 168 169 170 172 173 Olaylar (Events) . . . . . . . . . . . . Temel Kullanım . . . . . . . . . . . Joker Dinleyiciler . . . . . . . . . . Dinleyici Olarak Sınıfları Kullanma Olayları Sıraya Sokma . . . . . . . Olay Abonecileri . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 175 175 177 177 178 179 Oturum . . . . . . . . . . Yapılandırma . . . . . Oturum Kullanımı . . Flaş Verisi . . . . . . . Veritabanı Oturumları Oturum Sürücüleri . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 181 181 181 183 183 184 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Önbellekleme (Cache) . . . . . . . . . . . . . . . . . . . . . 186 Yapılandırma . . . . . . . . . . . . . . . . . . . . . . . . 186 Önbellekleme Kullanımı . . . . . . . . . . . . . . . . . . 186 İÇINDEKILER Arttırma & Azaltma . . . . . . . . . . . . . . . . . . . . 189 Önbellek Etiketleri (Tags) . . . . . . . . . . . . . . . . . . 189 Veritabanı Önbelleği . . . . . . . . . . . . . . . . . . . . 191 Paket Geliştirme . . . . . . Giriş . . . . . . . . . . . Bir Paket Oluşturma . . Paket Yapısı . . . . . . . Hizmet Sağlayıcıları . . Ertelenmiş Sağlayıcılar . Paket Gelenekleri . . . . Geliştirme İş Akışı . . . Paket Rotaları . . . . . . Paket Yapılandırması . . Paket View’leri . . . . . Paket Migrasyonları . . Paket Varlıkları . . . . . Paketlerin Yayımlanması . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 192 192 193 194 195 196 197 198 198 199 201 201 202 203 Posta . . . . . . . . . . . . . . . . . . Yapılandırma . . . . . . . . . . . . Temel Kullanım . . . . . . . . . . . Ataşmanların Yazı İçine Gömülmesi Postaların Sıraya Sokulması . . . . Posta & Yerel Geliştirme . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 204 204 205 207 208 209 Sayfalama . . . . . . . . . . . . . . . . Yapılandırma . . . . . . . . . . . . . Kullanım . . . . . . . . . . . . . . . Sayfalama Linklerine Ekleme Yapmak JSON’a Dönüştürme . . . . . . . . . Özel Sunumcular . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 211 211 211 214 215 215 Şablonlar . . . . . . . . . . . . . . . . . . . . . . . . . . . . 217 Denetçi (Controller) Düzenleri . . . . . . . . . . . . . . . 217 Blade Şablonları . . . . . . . . . . . . . . . . . . . . . . . 218 İÇINDEKILER Diğer Blade Kontrol Yapıları . . . . . . . . . . . . . . . . 219 Blade’in Genişletilmesi . . . . . . . . . . . . . . . . . . . 222 SSH . . . . . . . . . . . . . . . Yapılandırma . . . . . . . . Temel Kullanım . . . . . . . Görevler . . . . . . . . . . . SFTP Dosya İndirmeleri . . SFTP Dosya Göndermeleri . Uzak Günlüklerin İzlenmesi Envoy Görev Çalıştırıcısı . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 224 224 224 225 226 226 227 227 Unit Testing . . . . . . . . . . . . . . . . Giriş . . . . . . . . . . . . . . . . . . . Testleri Tanımlamak ve Çalıştırmak . . Test Ortamı . . . . . . . . . . . . . . . Testlerin İçerisinden Rotaları Çağırmak Facade’ları Taklit Etmek . . . . . . . . Çatının Assert Metodları . . . . . . . Yardımcı Metodlar . . . . . . . . . . . Application’ın Tazelenmesi . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 234 234 234 235 235 237 238 241 242 Yardımcı (Helper) Fonksiyonları . Arrayler (Diziler) . . . . . . . . Dosya Yolları . . . . . . . . . . Yazı İşlemleri . . . . . . . . . . URL İşlemleri . . . . . . . . . . Diğer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 243 243 249 250 253 255 Yerelleştirme . . . . . . . . . . . . . . Giriş . . . . . . . . . . . . . . . . . Dil Dosyaları . . . . . . . . . . . . Temel Kullanım . . . . . . . . . . . Çoğullaştırma . . . . . . . . . . . . Geçerlilik Denetimi Yerelleştirmesi Paket Dil Dosyalarının Ezilmesi . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 257 257 257 258 259 260 260 İÇINDEKILER Temel Veritabanı Kullanımı . Yapılandırma . . . . . . . . Okuma / Yazma Bağlantıları Sorguları Çalıştırma . . . . Veritabanı İşlemleri . . . . . Bağlantılara Erişme . . . . . Sorgu Günlükleme . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 262 262 262 263 265 266 266 Sorgu Oluşturucusu . . . . . . . . Giriş . . . . . . . . . . . . . . . Seçmeler . . . . . . . . . . . . . Joinler . . . . . . . . . . . . . . İleri Where Cümleleri . . . . . . Kümeleme (Aggregate) İşlemleri Ham İfadeler . . . . . . . . . . Eklemeler . . . . . . . . . . . . Güncellemeler . . . . . . . . . . Silmeler . . . . . . . . . . . . . Birleştirmeler . . . . . . . . . . Pesimistik Kilitleme . . . . . . . Sorguların Bellekte Saklanması . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 268 268 268 271 273 274 275 276 277 277 277 278 278 Eloquent ORM . . . . . . . . Giriş . . . . . . . . . . . . Temel Kullanım . . . . . . Toplu Atama . . . . . . . Ekleme, Güncelleme, Silme Belirsiz Silme . . . . . . . Zaman Damgaları . . . . . Sorgu Kapsamları . . . . . Küresel Kapsamlar . . . . İlişkiler . . . . . . . . . . İlişkilerin Sorgulanması . . Ateşli (Eager) Yüklemeler İlişkili Modelleri Ekleme . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 280 280 280 284 285 289 291 292 294 296 308 310 313 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . İÇINDEKILER Ebeveyn Zaman Damgalarına Dokunma . . . . . . Pivot Tablolarla Çalışmak . . . . . . . . . . . . . . Koleksiyonlar . . . . . . . . . . . . . . . . . . . . . Erişimciler & Değiştiriciler (Accessors & Mutators) . Tarih Değiştiricileri . . . . . . . . . . . . . . . . . . Model Olayları . . . . . . . . . . . . . . . . . . . . Model Gözlemcileri . . . . . . . . . . . . . . . . . . Diziye / JSON’a Çevirme . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 315 316 318 321 323 323 325 325 Şema Oluşturucusu . . . . . . . . . . . . . . . . . . . . Giriş . . . . . . . . . . . . . . . . . . . . . . . . . . . Tabloların Oluşturulması ve Yok Edilmesi . . . . . . . Sütunların Eklenmesi . . . . . . . . . . . . . . . . . . Sütun İsimlerinin Değiştirilmesi . . . . . . . . . . . . Sütunların Yok Edilmesi . . . . . . . . . . . . . . . . Mevcutluk Yoklanması . . . . . . . . . . . . . . . . . İndeks Eklenmesi . . . . . . . . . . . . . . . . . . . . Yabancı Anahtar (Foreign Key) . . . . . . . . . . . . . İndekslerin Yok Edilmesi . . . . . . . . . . . . . . . . Zaman Damgaları ve Belirsiz Silmelerin Yok Edilmesi Depolama Motorları . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 328 328 328 329 331 331 332 332 333 333 334 334 Migrasyon (Migration) ve Veri Ekme (Seeding) Giriş . . . . . . . . . . . . . . . . . . . . . . . Migrasyonların Oluşturulması . . . . . . . . . Migrasyonların Çalıştırılması . . . . . . . . . Migrasyonların Geriye Döndürülmesi . . . . . Veritabanına Veri Ekme . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 335 335 335 336 337 337 Redis . . . . . . . . . Giriş . . . . . . . . Yapılandırma . . . Kullanım . . . . . Pipeline Kullanma . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 340 340 340 341 343 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Artisan CLI . . . . . . . . . . . . . . . . . . . . . . . . . . . 344 İÇINDEKILER Giriş . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 344 Kullanım . . . . . . . . . . . . . . . . . . . . . . . . . . 344 Artisan’ın Geliştirilmesi . . . . Giriş . . . . . . . . . . . . . . Komut Oluşturulması . . . . . Komutların Kayıt Ettirilmesi . Diğer Komutların Çağırılması . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 346 346 346 350 351 Editörün Notu Bu kitap, orijinal Laravel dokümantasyonunun (belgelerinin), Laravel Türkiye Forumları’nda oluşturan çeviri ekibi tarafından Türkçe’ye çevirilen kullanma kılavuzudur. Bu kitap Laravel Versiyon 4.2 içindir. Sonraki dağıtımları kapsamamaktadır. Laravel ile tanıştıktan kısa bir süre sonra çatının Php kullanıcılarına sağladığı kolaylıkları gördüm ve bunun Türkiye’de kullanılması için gereken adımları attım. Öncesinde bir forum, ardından da dokümantasyonun çevirilmesi geldi. Her şey beklediğimden daha hızlı gerçekleşti ve bu dokümantasyon haricinde altı kitabın da çevirisini tamamladım. Bütün süreç boyunca yanımda olan sevgili eşim Bilge ve gözümün ışığı kızım Tuana Şeyma’ya teşekkürler. İyi ki varsınız! Çeviri ekibine tek tek teşekkür eder, kattıklarından dolayı minettarlığımı bildiririm. Gerek dokümantasyonun, gerekse bu kitapların çevirisinde tüm süreç boyunca yanımda olan ve çok katkı sağlayan değerli Sergin Arı’ya, kattıklarından dolayı minnettarım. Çeviri sürecinde ekibimiz çok ince eleyip sık dokudu ancak yine de hatalar yapmış olabiliriz, bu sebeple karşılaşmanız muhtemel hataları bana aşağıdaki kanallardan bildirirseniz sevinirim. Dilerseniz Github ambarından¹ değişiklikleri kendiniz de çekme isteği ile gönderebilirsiniz. Sinan Eldem E-posta: sinan@sinaneldem.com.tr Web: www.sinaneldem.com.tr² ¹https://github.com/laravel-tr/docs ²http://www.sinaneldem.com.tr/ Editörün Notu Twitter: twitter.com/sineld³ ³http://twitter.com/sineld ii Tanıtım Nereden Başlamalı Yeni bir frameworkün öğrenilmesi zorlayıcı olabilir ama aynı zamanda heyecan vericidir. Geçişinizi kolaylaştırmak için çok temiz, özlü bir Laravel dokümantasyonu oluşturmaya çalıştık. İşte ilk önce neyi okuyacağınız konusunda bazı öneriler: • • • • • Kurulum⁴ ve Yapılandırma⁵ Rotalar⁶ İstekler (Requests) ve Girdi (Input)⁷ Görünümler (Views) ve Cevaplar (Responses)⁸ Denetçiler (Controllers)⁹ Bu belgeleri iyice okuduktan sonra, Laravelde temel istek / cevap işleyişi üzerinde iyi bir kavrayışa sahip olacaksınız. Daha sonra, veritabanınızın yapılandırılması¹⁰, fluent sorgu oluşturucusu¹¹ ve Eloquent ORM¹² konularını okumak isteyebilirsiniz. Ya da, insanları uygulamanızda oturum açmaya başlatabilmek için kimlik doğrulama ve güvenlik¹³ konularını okumak isteyebilirsiniz. ⁴/docs/installation ⁵/docs/configuration ⁶/docs/routing ⁷/docs/requests ⁸/docs/responses ⁹/docs/controllers ¹⁰/docs/database ¹¹/docs/queries ¹²/docs/eloquent ¹³/docs/security iv Tanıtım Laravel Felsefesi Laravel etkileyici ve zarif sözdizimine sahip bir web uygulama çatısıdır (framework). Bizler geliştirmenin gerçekten tatmin edici olması için keyifli ve üretken bir deneyim olması gerektiğine inanıyoruz. Laravel birçok web uygulamasında kullanılan yetkilendirme, rotalama, oturum yönetimi ve ön bellekleme gibi ortak görevleri kolaylaştırarak, geliştiriciliğin zorluklarını ortadan kaldırmak amacını gütmektedir. Laravel, geliştiriciler için, uygulama işlevselliğinden ödün vermeden geliştirme aşamasını memnuniyet verici hale getirmeyi amaç edinmiştir. En iyi kodu mutlu geliştiriciler yazar. Bu hedefe varmak için, başka dillerde yazılmış Ruby on Rails, ASP.NET MVC ve Sinatra gibi çatılar da dahil olmak üzere, diğer çatılarda gördüğümüz en iyi özellikleri birleştirmeye çalıştık. Laravel büyük, kapsamlı uygulamalar için gereken araçları içeren erişilebilir, aynı zamanda güçlü bir çatıdır. Mükemmel IoC konteyneri, etkileyici migrasyon sistemi ve sağlam bir yerleşik ünite test desteği size geliştirmeyi amaçladığınız uygulama için gerekli araçları sağlayacaktır. Laravel Hızlı Başlangıç Kurulum Laravel Installer Aracılığıyla İlk olarak, Laravel installer PHAR arşivini indirin¹⁴. Kolaylık açısından ismini laravel olarak değiştirin ve /usr/local/bin yoluna taşıyın. Bir kere kurduktan sonra, laravel new komutu, istediğiniz klasöre yeni bir laravel kurulumunu yapacaktır. Örneğin, laravel new blog komutu, içinde tüm bağımlılıkları yüklenmiş yeni bir laravel kurulumu barındıran blog klasörünü oluşturacaktır. Bu yolla kurulum yapmak Composer ile yapmaktan çok daha hızlıdır. Composer Aracılığıyla Laravel framework kurulumu ve bağımlılık yönetimi için Composer¹⁵ kullanır. Şayet sizde yoksa Composer yüklemesi¹⁶ ile başlayın. Artık terminalinizden aşağıdaki komutu vermek suretiyle Laravel yükleyebilirsiniz: 1 2 composer create-project laravel/laravel sizin-projenizi\ n-ismi --prefer-dist Bu komut sizin geçerli dizininiz içerisindeki yeni bir sizin-projenizin-ismi klasörüne Laravel’in yepyeni bir kopyasını indirecek ve yükleyecektir. ¹⁴http://laravel.com/laravel.phar ¹⁵http://getcomposer.org ¹⁶http://getcomposer.org00-intro.md vi Laravel Hızlı Başlangıç Eğer isterseniz, alternatif olarak Github’daki Laravel ambarının¹⁷ bir kopyasını elle indirebilirsiniz. Sonra da elle oluşturduğunuz proje dizininizin kökünde composer install komutunu çalıştırın. Bu komut, frameworkün bağımlılıklarını indirecek ve yükleyecektir. İzinler Laravel yüklenmesinden sonra, app/storage dizinlerine web sunucu yazma izinleri hakları tanımanız gerekebilir. Yapılandırma konusunda daha fazla ayrıntılar için Kurulum¹⁸ dokümantasyonuna bakınız. Laravel’in Hizmete Sokulması Tipik olarak, Laravel uygulamalarınızı sunmak için Apache veya Nginx gibi bir web sunucusu kullanabilirsiniz. Eğer sizde PHP 5.4+ var ve PHP’nin yerleşik geliştirme sunucusunu kullanmak isterseniz, serve Artisan komutunu kullanabilirsiniz: 1 php artisan serve Dizin Yapısı Frameworkün yüklenmesinden sonra, dizin yapısıyla aşina olmak için projenize bir göz atın. Projenizdeki app dizini views, controllers ve models gibi klasörler içerir. Uygulamanızın kodlarının çoğu bu dizin içindeki bir yerlerde ikamet eder. Ayrıca, app/config dizinini de inceleyip sizin için sunulmuş yapılandırma seçeneklerini keşfetmek isteyebilirsiniz. ¹⁷https://github.com/laravel/laravel/archive/master.zip ¹⁸/docs/installation Laravel Hızlı Başlangıç vii Local Geliştirme Ortamı Geçmişte, makineniz üzerinde lokal bir PHP geliştirme ortamı yapılandırılması bir başağrısıydı. PHP, gerekli uzantılar ve gerekli diğer bileşenlerin doğru sürümlerinin yüklenmesi zaman harcayıcı ve kafa karıştırıcıdır. Bunun yerine Laravel Homestead¹⁹ kullanmayı düşünün. Homestead Laravel ve Vagrant²⁰ için tasarlanmış basit bir sanal makinedir. Homestead Vagrant kutusu güçlü ve sağlam PHP uygulamaları inşa etmeniz için gerekli yazılımların hepsiyle birlikte önceden paketlendiği için, sanallaştırılmış, izole bir geliştirme ortamını saniyeler içerisinde oluşturabilirsiniz. İşte Homestead’a dahil edilen araçlardan bazılarından oluşan bir liste: • • • • • • Nginx PHP 5.5 MySQL Redis Memcached Beanstalk “Sanallaştırılmış” biraz karışık geliyorsa da merak etmeyin, sancısızdır. Homestead’ın bağımlılıkları olan VirtualBox ve Vagrant’ın her ikisi de popüler tüm işletim sistemleri için grafiksel program yükleyicileri içermektedir. Başlamak için Homestead dokümantasyonunu²¹ kontrol ediniz. Rotalandırma (Routing) Başlangıç olarak Laravel’de ilk Route’umuzu yazalım. Laravel’de rota oluşturmak için en basit yol bir closure (anonim fonksiyon) ¹⁹/docs/homestead ²⁰http://vagrantup.com ²¹/docs/homestead Laravel Hızlı Başlangıç viii kullanmaktır. app/routes.php dosyasını açın ve aşağıdaki kod parçacığını sayfanın en altına yapıştırın: 1 2 3 4 Route::get('kullanicilar', function() { return 'Kullanıcılar!'; }); Şimdi, eğer web tarayıcınızda /kullanicilar adresine girerseniz, ekranda Kullanıcılar! yazısını görmüş olmanız gerekir. Eğer gördüyseniz çok iyi! İlk rotanızı başarıyla oluşturdunuz. Route’lar ayrıca controller sınıflarına da bağlanabilir. Örneğin: 1 2 Route::get('kullanicilar', 'KullaniciController@getInde\ x'); Bu Route Laravel’e şunu belirtiyor: /kullanicilar rotasına yapılan bir istek KullaniciController sınıfındaki getIndex metodunu çağırmalıdır. Controller Routing hakkında daha fazla bilgi almak için Controller Dökümantasyonu’na²² bir göz atın. Bir View Oluşturma Şimdi basit bir view dosyası oluşturup, kullanıcı bilgilerini ekrana view üzerinden yazdıracağız. View dosyaları app/views dizini içerisinde bulunmakta olup projenizin HTML dosyalarını barındırır. Şimdi bu dizin içerisine 2 tane dosya oluşturacağız: layout.blade.php ve kullanicilar.blade.php. Önce layout.blade.php dosyamızı oluşturalım: ²²/docs/controllers Laravel Hızlı Başlangıç 1 ix <html> <body> 2 <h1>Laravel Hızlı Başlangıç</h1> 3 4 @yield('content') 5 </body> 6 7 </html> Şimdiki adımda ise kullanicilar.blade.php view dosyasını oluşturalım: 1 @extends('layout') 2 3 4 5 @section('content') Kullanıcılar! @stop Bu sözdizimi size ilk etapta biraz yabancı gelebilir. Bunun sebebi Laravel’in güçlü şablonlama sisteminin (Blade) kullanılmasıdır. Blade son derece hızlı çalışır çünkü sadece birkaç tane regex kodları kullanıp Blade sözdizimini PHP skriptlerine dönüştürür. Blade kullanıcılarına çok büyük fonksiyonellik sağlar. Şablon kalıtımı (Template inheritance) ve PHP’nin if ve for gibi temel kontrol yapılarını Blade üzerinden kullanabilirsiniz. Daha fazla bilgi için Blade Dökümantasyonu’na²³ bakınız. Şimdi gerekli view dosyalarımızı oluşturduğumuza göre, oluşturduğumuz viewi /kullanicilar isteğine bir cevap olarak döndürelim. Kullanıcılar! stringini döndürmek yerine, bu kez oluşturduğumuz view dosyalarını döndüreceğiz: ²³/docs/templates Laravel Hızlı Başlangıç 1 2 3 4 x Route::get('kullanicilar', function() { return View::make('kullanicilar'); }); Harika! Bir layoutu genişleten bir view oluşturdunuz. Bir sonraki bölümümümüzde Veritabanı Katmanı (Database Layer) üzerinde duracağız. Bir Migrasyon Oluşturma Bir veritabanı tablosu oluşturmak için Laravel’in migrasyon (migration) özelliğini kullanacağız. Migrationlar çok kolay bir şekilde veritabanında değişiklikler yapmayı ve bunları takım arkadaşlarınızla paylaşmanızı sağlar. Öncelikle bir veritabanı konfigürasyonu ayarlayalım. Tüm veritabanı konfigürasyonlarınızı app/config/database.php dosyası içerisinde değiştirebilirsiniz. Laravel öntanımlı olarak MySQL kullanmaya ayarlanmıştır, veritabanı konfigürasyonlarınızı app/config/database.php dosyası içerisinde tanımlamanız gerekecektir. Dilerseniz driver değerini sqlite yapıp app/database dizininde bulunan SQLite veritabanını kullanabilirsiniz. Sonra, bir migration oluşturmak için Artisan CLI²⁴ kullanacağız. Projenizin ana dizinine gelerek, aşağıdaki kodu terminal üzerinde yazın: 1 php artisan migrate:make create_users_table Şimdi, oluşturulan migration dosyasını app/database/migrations dizininde bulun. Bu dosya 2 metoddan oluşmaktadır: up ve down. ²⁴/docs/artisan Laravel Hızlı Başlangıç xi up metodunda, tablonuzdaki değişiklikleri yapmalısınız. down me- todunda ise yaptığınız değişiklikleri geri almalısınız. Şuna benzeyen bir migration oluşturalım: 1 2 3 4 5 6 7 8 9 10 public function up() { Schema::create('users', function($table) { $table->increments('id'); $table->string('email')->unique(); $table->string('name'); $table->timestamps(); }); } 11 12 13 14 15 public function down() { Schema::drop('users'); } Şimdi bu migrationu Artisan CLI üzerinde migrate komutu kullanarak çalıştıralım. Projenizin ana dizinine gelip aşağıdaki kodu çalıştırın: 1 php artisan migrate Eğer bir migrationu geri almak isterseniz migrate:rollback komutunu çalıştırmanız yeterli olacaktır. Şimdi bir veritabanı tablosu oluşturduğumuza göre, tablomuzdan veri çekmeyi öğrenerek devam edelim! xii Laravel Hızlı Başlangıç Eloquent ORM Laravel mükemmel bir ORM aracıyla beraber gelmektedir: Eloquent. Eğer daha önce Ruby on Rails frameworkü üzerinde çalıştıysanız Eloquent size çok tanıdık gelecektir, çünkü veritabanı işlemleri için ActiveRecord stilini kullanır. Öncelikle, modeli tanımlayalım. Bir Eloquent modeli ilgili veritabanı tablosunu sorgulamak için kullanılabilir, aynı zamanda bu tablo içindeki belirli bir satırı temsil eder. Merak etmenize gerek yok, örnekleri görünce ne kadar kolay olduğunu anlayacaksınız! Model dosyaları app/models dizininde bulunmaktadır. Şimdi o dizinde bir User.php modeli oluşturalım: 1 class User extends Eloquent {} Lütfen dikkat edin, herhangi bir veritabanı tablosu belirtmedik. Eloquent’in içerisinde çeşitli gelenekler vardır, bunlardan birisi modelin veritabanı tablosu olarak model adının çoğul halini kullanmaktır. Kullanışlı, değil mi? Tercih ettiğiniz veritabanı yönetim aracını kullanarak, users tablosuna birkaç satır ekleyin. Ondan sonra Eloquent’i kullanarak o tablodan bazı verileri çekip view dosyamıza göndereceğiz. Şimdi /kullanicilar rotamızda değişiklik yapalım ve şuna benzer bir hale getirelim: xiii Laravel Hızlı Başlangıç 1 2 3 4 Route::get('kullanicilar', function() { $users = User::all(); //Users tablosundaki tüm veriler\ i $users değişkenine atar 5 return View::make('kullanicilar')->with('users', $user\ 6 7 8 s); }); Şimdi bu scripti biraz inceleyelim. Öncelikle, User modelindeki all metodu users tablosundaki tüm verileri çekecektir. Daha sonra bu veriler with metodu kullanılarak view dosyasına gönderilir. with metodu bir anahtar ve bir değer almaktadır, böylece gönderilen veriyi view dosyası tanıyabilir. Harika. Artık kullanıcıları view dosyamızda göstermeye hazırız! Veri Gösterme Şimdi view’imizde users değişkenini kullanılabilir yaptığımıza göre, onu şuna benzer bir şekilde gösterebiliriz: 1 @extends('layout') 2 3 4 5 6 7 @section('content') @foreach($users as $user) <p>{{ $user->name }}</p> @endforeach @stop echo ifadesinin nerede olduğunu merak ediyor olabilirsiniz. Blade kullanırken, küme parantezi arasına yazılan değişkenler aynı echo ifadesindeki gibi ekrana bastırılır. Şimdi /kullanicilar adresine Laravel Hızlı Başlangıç xiv girip veritabanınızda kayıtlı olan tüm kullanıcıların listesinin ekrana bastırıldığını görebilirsiniz. Bu sadece bir başlangıç. Bu derste Laravel’in en temel konularını gördünüz, ancak daha göreceğiniz birçok heyecan verici özellikler var! Dökümantasyonu okumaya devam edin ve Laravel içerisinde gelen birçok farklı özellik hakkında daha fazla bilgiye sahip olun. Örneğin Eloquent²⁵ ve Blade²⁶. Belki de sizin ilginizi Queues²⁷ ve Unit Testing²⁸ çekiyordur? Ya da IoC Container²⁹ kullanarak uygulamanızın mimarisini güçlendirmek istiyorsunuzdur? Seçim sizin! Uygulamanızın Yayımlanması Laravel’in amaçlarından biri de PHP uygulama geliştirmeyi indirmekten yayımlamaya kadar keyifli bir hale getirmektir ve Laravel Forge³⁰ Laravel uygulamalarınızı süper hızlı sunucular üzerinde yayımlamak için basit bir yol sağlar. Forge DigitalOcean, Linode, Rackspace ve Amazon EC2 üzerinde sunucuları yapılandırabilir ve karşılayabilir. Tıpkı Homestead gibi, gerekli en son araçlar dahil edilmiştir: Nginx, PHP 5.5, MySQL, Postgres, Redis, Memcached ve başkaları. Hatta, Forge “Quick Deploy” özelliğiyle değişikliklerinizi Github veya Bitbucket’e push ettiğiniz her seferinde kodunuzu yayımlamış olursunuz! Forge bunlar yanında kuyruk işçileri, SSL, Cron işleri, sub-domainler ve daha birçok şeyi yapılandırmanıza yardım edebilir. Daha fazla bilgi için Forge websitesini³¹ ziyaret ediniz. ²⁵/docs/eloquent ²⁶/docs/templates ²⁷/docs/queues ²⁸/docs/testing ²⁹/docs/ioc ³⁰https://forge.laravel.com ³¹https://forge.laravel.com Sürüm Notları Laravel 4.2 Bu sürümün tam değişiklik listesi bir 4.2 yüklemesinden php artisan changes komutunu vererek veya Github’daki değişiklik dosyasına³² bakarak görülebilir. Bu notlar sadece bu sürümdeki önemli geliştirmeleri ve değişiklikleri kapsamaktadır. Not: 4.2 salınım döngüsü süresince, çeşitli Laravel 4.1 nokta salımlarına birçok küçük hata düzeltmeleri ve geliştirmeler katılmıştır. Bu yüzden, Laravel 4.1 için değişiklik listesini de kontrol ettiğinizden emin olun! PHP 5.4 Gerekliliği Laravel 4.2 PHP 5.4 veya daha üstünü gerektirir. Bu yükseltilmiş PHP gerekliliği bize Laravel Cashier³³ benzeri araçlar için daha anlamlı ve etkileyici interface’ler için trait’ler gibi yeni PHP özelliklerini kullanmamıza imkan verir. PHP 5.4 aynı zamanda PHP 5.3’e göre önemli bir hız ve performans iyileştireleri de getirmektedir. Laravel Forge Laravel Forge, web tabanlı yeni bir uygulama olup, aralarında Linode, DigitalOcean, Rackspace ve Amazon EC2’nin yer aldığı istediğiniz bir bulut üzerinde PHP sunucuları oluşturmak ve yönetmek için kolay bir yol sağlar. Otomatize Nginx yapılandırması, SSH key ³²https://github.com/laravel/framework/blob/4.2/src/Illuminate/Foundation/changes. json ³³/docs/billing xvi Sürüm Notları erişimi, Cron job otomasyonu, NewRelic & Papertrail aracılığıyla sunucu takibi, “Yayımlamak için Bas (Push To Deploy)”, Laravel kuyruk işçisi yapılandırması ve pek çok şeyi desteklemek suretiyle, Forge sizin tüm Laravel uygulamalarınızın başlatılmasının en basit ve en uygun fiyatlı yolunu sağlar. Varsayılan Laravel 4.2 yüklemenizin app/config/database.php yapılandırma dosyası, yepyeni uygulamalarınızı platforma daha uygun yayımlamanıza imkan verecek şekilde artık ön tanımlı olarak Forge kullanımı için yapılandırılmıştır. Laravel Forge hakkında daha fazla bilgi resmi Forge web sitesinde³⁴ bulunabilir. Laravel Homestead Laravel Homestead sağlam ve güçlü Laravel ve PHP uygulamaları geliştirilmesi için resmi bir Vagrant ortamıdır. Box’ların ihtiyaçlarının büyük çoğunluğu box dağıtım için paketlenmeden önce halledilir, böyleye box’un boot edilmesi son derece hızlıdır. Homestead’da Nginx 1.6, PHP 5.5.12, MySQL, Postgres, Redis, Memcached, Beanstalk, Node, Gulp, Grunt ve Bower yer almaktadır. Homestead birden çok Laravel uygulamasının tek bir box’ta yönetilmesi için basit bir Homestead.yaml yapılandırma dosyası içerir. Varsayılan Laravel 4.2 yüklemesi şimdi artık box’un Homestead veritabanını kullanması, böylece Laravel’in ilk yükleme ve yapılandırmasının daha kolay olması için yapılandırılmış bir app/config/local/database.php yapılandırma dosyası taşımaktadır. Ayrıca resmi dokümantasyon Homestead³⁵ dokümantasyonunu içerecek şekilde güncellenmiştir. ³⁴https://forge.laravel.com ³⁵/docs/homestead xvii Sürüm Notları Laravel Cashier Laravel Cashier, Stripe ile abonelik faturalaması yönetilmesi için basit, ifade edici bir kitaplıktır. Laravel 4.2’nin başlamasıyla birlikte biz Cashier dokümantasyonunu ana Laravel dokümantasyonuna dahil ediyoruz, ancak bu bileşenin yüklenmesi hala isteğe bağlıdır. Cashier’in bu salınımı çok sayıda hata düzeltmeleri, birden çok para birimi desteği ve en son Stripe API ile uyumluluk getirmektedir. Daemon Kuyruk İşçileri Artisan queue:work komutu “deamon modunda” bir işçi başlatmak için şimdi bir --daemon seçeneğini destekliyor, bunun anlamı bu işçinin framework yeniden boot edilmesi hiç olmaksızın işleri işlemeye devam edeceğidir. Bu, hafifçe daha karmaşık bir uygulama yayımlama süreci maliyetiyle birlikte, CPU kullanımında önemli bir azalmayla sonuçlanır. Daemon kuyruk işçileriyle ilgili daha fazla bilgi queue documentation³⁶ dokümantasyonunda bulunabilir. Mail API Sürücüleri Laravel 4.2, Mail fonksiyonları için yeni Mailgun ve Mandrill API sürecilerini getirdi. Bu birçok uygulama için, e-mailler göndermenin SMTP seçeneğinden daha hızlı ve daha güvenilir bir yöntemini sağlar. Bu yeni sürücüler Guzzle 4 HTTP kitaplığını kullanmaktadır. Belirsiz Silme Trait’leri PHP 5.4 trait’ler sayesinde “soft delete”ler ve diğer “global scope”ler için çok daha temiz bir mimari sunulmuştur. Bu yeni mimari ³⁶/docs/queues#daemon-queue-worker xviii Sürüm Notları benzer global trait’lerin daha kolay inşa edilmesini ve frameworkün kendisi içerisinde daha temiz bir “ilgilerin ayrılığı” sağlar. Yeni SoftDeletingTrait hakkında daha fazla bilgi Eloquent³⁷ dokümantasyonunda bulunabilir. Uygun Auth & Remindable Trait’leri Varsayılan Laravel 4.2 yüklemesi authentication ve password reminder user interface’lerinin gerekli özellikleri içermesi için artık basit trait’ler kullanmaktadır. Bu, Laravel’le gelen default User model dosyasının çok daha temiz olmasını sağlamaktadır. “Basit Sayfalandırma” Sayfalandırma view’inizde basit “Sonraki” ve “Önceki” linkleri kullanıyorken daha verimli sorgulara imkan vermek amacıyla Sorgu oluşturucusu ve Eloquent’e yeni bir simplePaginate metodu eklenmiştir. Migration Teyidi Üretim ortamında, yıkıcı migrasyon işlemleri artık teyit isteyeceklerdir. --force seçeneği kullanılarak, komutlar herhangi bir teyit istemeksizin çalıştırılmaya zorlanabilir. ³⁷/docs/eloquent#soft-deleting xix Sürüm Notları Laravel 4.1 Değişikliklerin Tam Listesi Bu sürümün tam değişiklik listesi bir 4.1 yüklemesinden php artisan changes komutunu vererek veya Github’daki değişiklik dosyasına³⁸ bakarak görülebilir. Bu notlar sadece bu sürümdeki önemli geliştirmeleri ve değişiklikleri kapsamaktadır. Yeni SSH Bileşeni Bu sürümle birlikte tamamen yeni bir SSH bileşeni getirilmiştir. Bu özellik sizin uzak suncuculara kolaylıkla SSH iletişimi kurmanıza ve komut çalıştırmanıza imkan verir. Daha fazla öğrenmek için SSH bileşeni dokümantasyonuna³⁹ bakın. Yeni php artisan tail komutu yeni SSH bileşenini kullanmaktadır. Daha fazla bilgi için, tail komut dokümantasyonuna⁴⁰ bakın. Tinker’de Boris Eğer sisteminiz destekliyorsa php artisan tinker komutu şimdi Boris REPL⁴¹ kullanmaktadır. Bu özelliği kullanmak için readline ve pcntl PHP uzantıları başlatılmış olmalıdır. Bu uzantılara sahip değilseniz, 4.0’daki kabuk kullanılacaktır. ³⁸https://github.com/laravel/framework/blob/4.1/src/Illuminate/Foundation/changes. json ³⁹/docs/ssh ⁴⁰/docs/ssh#tailing-remote-logs ⁴¹https://github.com/d11wtq/boris xx Sürüm Notları Eloquent Geliştirmeleri Eloquent’e yeni bir hasManyThrough ilişkisi eklenmiştir. Bunun nasıl kullanılacağını öğrenmek için Eloquent dokümantasyonuna⁴² bakın. Modelleri ilişki sınırlandırmalarına dayalı getirmeye⁴³ imkan vermek amacıyla yeni bir whereHas metodu kullanıma girmiştir. Veritabanı Okuma / Yazma Bağlantıları Sorgu oluşturucu ve Eloquent de dahil olmak üzere veritabanı katmanı boyunca artık okuma / yazma bağlantılarının otomatik olarak ayrı ayrı ele alınması mümkün bulunmaktadır. Daha fazla bilgi için dokümantasyonuna⁴⁴ bakın. Kuyruk (Queue) Önceliği Kuyruk öncelikleri şimdi queue:listen komutuna virgülle ayrılmış bir liste geçilmesi şeklinde desteklenmektedir. Gerçekleştirilememiş Kuyruk İşinin İşlenmesi Kuyruk araçları şimdi queue:listen üzerinde yeni --tries anahtarı kullanılması halinde, başarısız kalmış işlerin otomatik işlenmesini içermektedir. Başarısız kalmış işlerin işlenmesiyle ilgili daha fazla bilgi kuyruklar dokümantasyonunda⁴⁵ bulunabilir. ⁴²/docs/eloquent#has-many-through ⁴³/docs/eloquent#querying-relations ⁴⁴/docs/database#read-write-connections ⁴⁵/docs/queues#failed-jobs xxi Sürüm Notları Cache Tagları Cache “section”larının yerini “tag”lar almıştır. Cache tagları bir cache öğesine birden çok “tag” atamanıza ve tek bir tag’a atanmış tüm öğeleri boşaltmanıza (flush) imkan verir. Cache taglarının kullanılması üzerine daha fazla bilgi cache dokümantasyonunda⁴⁶ bulunabilir. Esnek Şifre Hatırlatıcıları Şifre hatırlatıcı motoru şifreler geçerlilik denetiminden geçirilirken, session’a durum mesajları flaşlanırken v.b., geliştiriciye daha büyük esneklik sağlayacak şekilde değiştirilmiştir. Gelişmiş şifre hatırlatıcı motorunun kullanımı hakkında daha fazla bilgi için dokümantasyonuna⁴⁷ bakın. Gelişmiş Rotalama Motoru Laravel 4.1 tamamen yeniden yazılmış bir rotalama katmanına sahiptir. API aynıdır; ancak, rotaların kayda geçirilmesi 4.0 ile karşılaştırıldığında tam % 100 daha hızlıdır. Bütün motor büyük ölçüde basitleştirilmiştir ve rota ifadelerinin derlenmesinde Symfony Routing Katmanına bağımlılık en aza indirilmiştir. Gelişmiş Session Motoru Bu yeni sürümde biz aynı zamanda tamamen yeni bir session motorunu da kullanıma sokuyoruz. Rotalama geliştirmelerine benzer şekilde, yeni session katmanı da daha yalın ve daha hızlıdır. Artık Symfony’nin (ve dolayısıyla PHP’nin) session işleme araçlarını kullanmıyoruz ve daha basit ve sürdürülmesi daha kolay olan özel bir çözüm kullanıyoruz. ⁴⁶/docs/cache#cache-tags ⁴⁷/docs/security#password-reminders-and-reset xxii Sürüm Notları Doctrine DBAL Eğer migrasyonlarınızda renameColumn fonksiyonunu kullanıyorsanız, composer.json dosyanıza doctrine/dbal bağımlılığını eklemeniz gerekecek. Bu paket artık ön tanımlı olarak Laravel’e dahil edilmemektedir. Yükseltme Rehberi 4.1’den 4.2’ye Yükseltme PHP 5.4+ Laravel 4.2, PHP 5.4.0 veya daha üstünü gerektirir. Kriptolama Varsayılanları app/config/app.php yapılandırma dosyanıza yeni bir cipher seçeneği ekleyin. Bu seçeneğin değeri MCRYPT_RIJNDAEL_256 olmalıdır. 1 'cipher' => MCRYPT_RIJNDAEL_256 Bu ayar, Laravel kriptolama araçları tarafından kullanılan varsayılan cipher’i (kriptolama sistemini) kontrol etmek için kullanılabilir. Not: Laravel 4.2’de, default cipher en güvenli cipher olarak kabul edilen MCRYPT_RIJNDAEL_128 (AES)’dir. Laravel <= 4.1’de kriptolanmış cookies/values’leri dekript etmek için bu cipher’i tekrar MCRYPT_RIJNDAEL_256‘e değiştirmek gereklidir Modellerdeki Soft Silmeler Artık Trait Kullanıyor Modellerde soft silmeler kullanıyorsanız, softDeletes propertisi çıkartılmıştır. Artık aşağıdakine benzer şekilde SoftDeletingTrait kullanmalısınız: Yükseltme Rehberi 1 xxiv use Illuminate\Database\Eloquent\SoftDeletingTrait; 2 3 4 5 class User extends Eloquent { use SoftDeletingTrait; } Ayrıca, dates propertisine deleted_at sütununu elle eklemek zorundasınız: 1 2 class User extends Eloquent { use SoftDeletingTrait; 3 protected $dates = ['deleted_at']; 4 5 } Tüm soft silme işlemlerinin API’si aynı kalmıştır. Not: Bu SoftDeletingTrait base modele uygulanamaz. Gerçek bir model sınıfı üzerinde kullanılmalıdır. View / Pagination Environment Sınıflarının Adı Değişti Şayet Illuminate\View\Environment sınıfını veya Illuminate\Pagination\Environ sınıfını doğrudan referans ediyorsanız, kodunuzu bunlar yerine Illuminate\View\Factory ve Illuminate\Pagination\Factory sınıflarını referans verecek şekilde güncellemelisiniz. Bu iki sınıfın isimleri, işlevlerini daha iyi yansıtması için değiştirilmiştir. Pagination Sunumcusunda Ek Parametre Eğer Illuminate\Pagination\Presenter sınıfını genişletiyorsanız, getPageLinkWrapper abstract metodunun kalıbı rel parametresi eklenecek şekilde değiştirilmiştir: xxv Yükseltme Rehberi 1 2 abstract public function getPageLinkWrapper($url, $page\ , $rel = null); Iron.Io Queue Kriptolama Eğer Iron.io queue sürücüsü kullanıyorsanız, bu durumda queue yapılandırma dosyanıza yeni bir encrypt seçeneği eklemeniz gerekecektir. 1 'encrypt' => true 4.1.x ve Öncesinden 4.1.29’a Yükseltme Laravel 4.1.29 tüm veritabanı sürücüleri için sütunların tırnak içine alınmasını iyileştirmiştir. Bu iyileştirme, modellerde fillable özelliğini kullanmıyorken uygulamalarınızı bazı toplu atama açıklarından korur. Eğer siz toplu atamaya karşı korumak için modellerinizde fillable özelliğini kullanıyorsanız, uygulamanız korunmasız değildir. Buna karşın, eğer guarded kullanıyorsanız ve “update” veya “save” tipindeki bir fonksiyona kullanıcının kontrolündeki bir dizi geçiyorsanız, uygulamanız toplu atama riskinde olacağı için hemen 4.1.29‘e yükseltmelisiniz. Laravel 4.1.29’ye yükseltmek için, basitçe composer update komutunu verin. Bu salınımda başka düzeltmeler gereken bir değişiklik yapılmamıştır. 4.1.25 ve Öncesinden 4.1.26’ye Yükseltme Laravel 4.1.26 “remember me” cookie’leri için güvenlik iyileştirmeleri getirdi. Bu güncellemeler öncesinde, eğer bir remember xxvi Yükseltme Rehberi cookie kötü niyetli başka bir kullanıcı tarafından gasp edilmişse (“hijacked”), hesabın gerçek sahibi kendi şifresini yeniledikten, çıkış yaptıktan (logged out) v.b sonra bile ilgili cookie uzun bir zaman süresince geçerli kalırdı. Bu değişiklik users (veya dengi olan) veritabanı tablonuza yeni bir remember_token sütunu eklenmesini gerektirmektedir. Bu değişiklikten sonra, uygulamanıza giriş (login) yaptıkları her seferinde kullanıcıya yepyeni bir token atanacaktır. Bu token ayrıca kullanıcı uygulamadan çıkış yaptığı zaman da yenilenecektir. Bu değişikliğin etkileri şunlardır: eğer bir “remember me” cookie gasp edilirse, sadece uygulamadan çıkış yapılması bu cookie’yi geçersiz kılacaktır. Yükseltme Adımları Öncelikle, users tablonuza VARCHAR(100), TEXT veya dengi yeni bir nullable remember_token sütunu ekleyin. Daha sonra, eğer Eloquent authentication sürücüsü kullanıyorsanız, User sınıfınızı aşağıdaki üç metodla güncelleyin: 1 2 3 4 public function getRememberToken() { return $this->remember_token; } 5 6 7 8 9 public function setRememberToken($value) { $this->remember_token = $value; } 10 11 12 13 14 public function getRememberTokenName() { return 'remember_token'; } xxvii Yükseltme Rehberi Not: Bu değişiklikle mevcut tüm “remember me” oturumları geçersiz kılınacaktır, bu nedenle tüm kullanıcılar uygulamanıza yeniden authenticate olmaya (kimliği doğrulanmaya) zorlanacaklardır. Paket Sürdürücüleri Illuminate\Auth\UserProviderInterface interface’ine iki yeni metod eklenmiştir. Örnek implementationlar ön tanımlı sürücülerde bulunabilir: 1 public function retrieveByToken($identifier, $token); 2 3 4 public function updateRememberToken(UserInterface $user\ , $token); Ayrıca, Illuminate\Auth\UserInterface de “Yükseltme Adımları” kesiminde açıklanan üç yeni metodu almıştır. 4.0’dan 4.1’e Yükseltme Composer Bağımlılığının Yükseltilmesi Uygulamanızı Laravel 4.1’e yükseltmek için, composer.json dosyanızdaki laravel/framework sürümünü 4.1.* olarak değiştirin. Dosyaların Değiştirilmesi Uygulamanızdaki public/index.php dosyasını ambardaki bu yeni kopya⁴⁸ ile değiştirin. ⁴⁸https://github.com/laravel/laravel/blob/master/public/index.php xxviii Yükseltme Rehberi Uygulamanızdaki artisan dosyasını ambardaki bu yeni kopya⁴⁹ ile değiştirin. Yapılandırma Dosya ve Seçeneklerinin Eklenmesi Uygulamanızdaki app/config/app.php yapılandırma dosyanızdaki aliases ve providers dizilerini güncelleyin. Bu dizilerin güncellenmiş değerleri bu dosyada⁵⁰ bulunabilir. Kendi özel ve paket servis sağlayıcılarını / aliasları tekrar eklemeyi unutmayın. Ambardaki⁵¹ yeni app/config/remote.php dosyasını ekleyin. Uygulamanızdaki app/config/session.php dosyanıza yeni expire_on_close yapılandırma seçeneğini ekleyin. Ön tanımlı değer false olmalıdır. Uygulamanızdaki app/config/queue.php dosyanıza yeni failed yapılandırma kesimini ekleyin. Bu kesimin default değerleri şöyledir: 1 2 3 'failed' => array( 'database' => 'mysql', 'table' => 'failed_jobs', ), (İsteğe Bağlı) Uygulamanızdaki app/config/view.php dosyanızdaki pagination yapılandırma seçeneğini pagination::slider-3 olarak güncelleyin. Controller Güncellemeleri Eğer app/controllers/BaseController.php dosyasında en üstte bir use cümlesi varsa, buradaki use Illuminate\Routing\Controllers\Controller; ⁴⁹https://github.com/laravel/laravel/blob/master/artisan ⁵⁰https://github.com/laravel/laravel/blob/master/app/config/app.php ⁵¹https://github.com/laravel/laravel/blob/master/app/config/remote.php Yükseltme Rehberi xxix olan yeri use Illuminate\Routing\Controller; olarak güncelleyin. Password Reminders Güncellemeleri Şifre hatırlatıcıları daha büyük esneklik olması için elden geçirilmiştir. Artisan php artisan auth:reminders-controller komutunu çalıştırmak suretiyle yeni iskelet controlleri inceleyebilirsiniz. Ayrıca güncellenmiş dokümantasyonu⁵² da okuyabilir ve uygulamanızı ona göre güncelleyebilirsiniz. Uygulamanızdaki app/lang/en/reminders.php dil dosyasını güncellenen bu dosyaya⁵³ uyacak şekilde güncelleyin. Ortam Saptama Güncellemeleri Güvenlik sebepleri nedeniyle, uygulama ortamınızı tespit etmek için URL domainleri artık kullanılmayabilir. Bu değerler kolaylıkla kafeslenebilir ve saldırganların bir istek için ortamı modifiye etmesine imkan verebilir. Ortam tespitinizi makine host adları (Mac, Linux ve Windows üzerinde hostname komutu) kullanacak şekilde değiştirmelisiniz. Daha Sade ve Basit Günlük Dosyaları Laravel artık tek bir log dosyası üretir: app/storage/logs/laravel.log. Bununla birlikte, bu davranışı yine de app/start/global.php dosyanızda yapılandırabilirsiniz. ⁵²/docs/security#password-reminders-and-reset ⁵³https://github.com/laravel/laravel/blob/master/app/lang/en/reminders.php xxx Yükseltme Rehberi En Sonda Bölü Varsa Yeniden Yönlendirin Çıkartılması Uygulamanızın bootstrap/start.php dosyasından $app->redirectIfTrailingSlas çağrısını çıkartın. Bu işlevsellik şimdi frameworkle gelen .htaccess dosyası tarafından halledildiği için bu metod artık gerekli değildir. Sonra da, sizin Apache .htaccess dosyanızın yerine, sondaki bölüleri halleden bu yenisini⁵⁴ koyun. Güncel Rotaya Erişim Güncel rotaya Route::getCurrentRoute() yerine şimdi Route::current() ile erişilmektedir. Composer Güncellemesi Yukarıdaki değişiklikleri tamamladıktan sonra, çekirdek application dosyalarını güncellemek için composer update fonksiyonunu çalıştırabilirsiniz! Eğer sınıf yükleme (class load) hataları alırsanız, update komutunu şu şekilde etkinleştirilmiş --no-scripts seçeneği ile kullanmayı deneyin: composer update --no-scripts. Joker Olay Dinleyiciler Joker Olay Dinleyiciler artık handler fonksiyon parametrelerinize event’i eklemez. Şayet ateşlenen olayı bulmanız gerekiyorsa, Event::firing() kullanmalısınız. ⁵⁴https://github.com/laravel/laravel/blob/master/public/.htaccess Kurulum Composer Kurulumu Laravel bağımlılıklarını yönetmek için Composer⁵⁵ kullanır. Öncelikle composer.phar dosyasını indiriniz. PHAR arşivini yerel proje dosyanızda tutabileceğiniz gibi usr/local/bin içerisine taşıyarak sisteminizde evrensel olarak da kullanabilirsiniz. Windows’ta Composer Windows kurulumu⁵⁶nu kullanabilirsiniz. Setup Composer’i PATH değişkeni olarak kaydedecektir, böylece terminal üzerinde composer yazdığınızda Composer’i direkt olarak kullanabilirsiniz. Laravel Yükleme Laravel Installer Aracılığıyla İlk olarak, Laravel installer PHAR arşivini indirin⁵⁷. Kolaylık açısından ismini laravel olarak değiştirin ve /usr/local/bin yoluna taşıyın. Bir kere kurduktan sonra, laravel new komutu, istediğiniz klasöre yeni bir laravel kurulumunu yapacaktır. Örneğin, laravel new blog komutu, içinde tüm bağımlılıkları yüklenmiş yeni bir laravel kurulumu barındıran blog klasörünü oluşturacaktır. Bu yolla kurulum yapmak Composer ile yapmaktan çok daha hızlıdır. Composer’ın Create-Project Komutuyla Terminalinizde Composer create-project komutunu vererek Laravel’i yükleyebilirsiniz: ⁵⁵http://getcomposer.org ⁵⁶https://getcomposer.org/Composer-Setup.exe ⁵⁷http://laravel.com/laravel.phar 2 Kurulum 1 composer create-project laravel/laravel --prefer-dist Elle İndirerek Composer yüklendikten sonra, Laravel framework’ün son sürümünü⁵⁸ indirip, içeriğini sunucunuzdaki bir dizine çıkarınız. Ardından, Laravel uygulamanızın ana dizininde, Laravel gereksinimlerini yüklemek için, php composer.phar install (veya composer install) komutunu çalıştırınız. Bu işlemin başarıyla tamamlanabilmesi için sunucunuzda Git⁵⁹ yüklü olması gerekmektedir. Laravel’i güncellemek isterseniz php composer.phar update komutunu verebilirsiniz. Sunucu Gereksinimleri Laravel framework’un birkaç sistem gereksinimi bulunmaktadır: • PHP >= 5.4 • MCrypt PHP Eklentisi PHP 5.5 için, bazı OS yayımlamaları PHP JSON eklentisinin elle yüklenmesini gerektirebilir. Ubuntu kullanırken, bu apt-get install php5-json aracılığı ile yapılabilir. Yapılandırma Laravel’in çalışabilmesi için neredeyse hiç yapılandırma ayarı gerekmez. Geliştirmeye hemen başlayabilirsiniz! Ancak app/config/app.php dosyasını ve dokümantasyonunu gözden geçirebilirsiniz. Buradaki ⁵⁸https://github.com/laravel/laravel/archive/master.zip ⁵⁹http://git-scm.com/downloads 3 Kurulum timezone (saat dilimi) ve locale gibi değerleri uygulamanızın ihtiyaçlarına göre düzenleyebilirsiniz. Laravel yüklendikten sonra, local ortamınızı yapılandırmanız⁶⁰ da gerekmektedir. Bu size local makinenizde geliştirme yaparken ayrıntılı hata mesajları alma imkanı verecektir. Ön tanımlı olarak, üretim yapılandırma dosyanızdaki ayrıntılı hata bildirimi devre dışı durumdadır. Not: Bir üretim ortamında app.debug değerini asla true ayarlamamalısınız. Bunu hiçbir zaman yapmayın. İzinler Laravel app/storage dizin içeriğinin web sunucu tarafından yazılabilir olmasını gerektirmektedir. Dosya Yolları Framework dizin yollarının birkaçı yapılandırılabilirdir. Bu dizin yollarını değiştirebilmek için bootstrap/paths.php dosyasını gözden geçiriniz. Zarif URL’ler Apache Laravel framework, URL’lerin index.php olmadan kullanımına imkan vermek için kullanılan bir public/.htaccess dosyası ile birlikte gelmektedir. Laravel uygulamanızın sunumu için Apache ⁶⁰/docs/configuration#environment-configuration 4 Kurulum kullanıyorsanız mod_rewrite modülünün etkin olduğundan emin olunuz. Eğer Laravel ile birlikte gelen .htaccess dosyası Apache kurulumunuz ile işlev göstermezse, bunu deneyiniz: 1 2 Options +FollowSymLinks RewriteEngine On 3 4 5 6 RewriteCond %{REQUEST_FILENAME} !-d RewriteCond %{REQUEST_FILENAME} !-f RewriteRule ^ index.php [L] Nginx Nginx kullanıyorsanız, ekteki ayar “zarif url”lerin çalışmasını sağlamaya yeterlidir: 1 2 3 location / { try_files $uri $uri/ /index.php?$query_string; } Yapılandırma Giriş Laravel’in tüm yapılandırma dosyaları app/config dizini içindedir. Tüm dosyalardaki yapılandırma seçenekleri açıklanmıştır, dosyalara göz gezdirip size sunulan seçeneklere göz atabilirsiniz. Bazen yapılandırma değerlerine run-time (çalışma anı) esnasında erişmeniz gerekir. Bunu Config sınıfını kullanarak yapabilirsiniz: Bir Yapılandırma Değerine Erişmek 1 Config::get('app.timezone'); Eğer yapılandırma değeri bulunamazsa dönecek değeri ise, ikinci bir parametreyle belirleyebilirsiniz: 1 $timezone = Config::get('app.timezone', 'UTC'); Bir Yapılandırma Değeri Ayarlamak Lütfen dikkat edin, “nokta” şeklindeki kullanım biçimi tüm yapılandırma dosyalarına erişmenizi sağlar. Dilerseniz yapılandırma değerlerini run-time (çalışma anı) esnasında da ayarlayabilirsiniz: 1 Config::set('database.default', 'sqlite'); Çalışma zamanında ayarlanan yapılandırma değerleri sadece güncel istek süresince ayarlanırlar ve sonraki isteklere aktarılmayacaklardır. 6 Yapılandırma Ortam Yapılandırması Uygulamanın çalışma ortamına göre farklı yapılandırma değerlerine sahip olmak çoğu zaman iyidir. Örneğin, kişisel bilgisayarınızda, sunucudan farklı bir önbellekleme uygulaması kullanmak isteyebilirsiniz. Bunu ortam tabanlı yapılandırmalar oluşturarak sağlayabilirsiniz. Bunu yapmak çok basit! config dizini içerisinde, ortam isminizi kullandığınız (örneğin local) bir dizin daha oluşturun. Şimdi, belirttiğiniz ortam için üzerine yazmak istediğiniz yapılandırma dosyalarınızı ve seçeneklerinizi geçirin. Örneğin, önbellekleme yapılandırmasının üzerine yazmak için, app/config/local dizini içerisinde cache.php dosyası oluşturmanız gerekir. Oluşturduğunuz dosyanın içerisine şunları yazın: 1 <?php 2 3 return array( 4 'driver' => 'file', 5 6 7 ); Not: ‘testing’ adını ortam ismi olarak kullanmayın. Bu isim Unit Testing amacıyla rezerve edilmiştir. Dikkat ederseniz, bu dosyada bütün değerleri yazmanıza gerek yok. Sadece üzerine yazmak istediklerinizi eklemeniz yeterli. Geri kalan değerler, öntanımlı yapılandırma değerlerinden alınacaktır. Şimdi yapmamız gereken Laravel’e hangi ortamda çalıştığını belirtmek. Öntanımlı ortam daima production ortamıdır. Ancak ana dizindeki bootstrap/start.php dosyası içerisine eklemeler yaparak farklı ortamlar oluşturmak mümkündür. Bu dosya içerisinde Yapılandırma 7 $app->detectEnvironment adında bir tanım bulacaksınız. Bu me- toda eklenen bir parametre ile Laravel’e hangi ortamda çalıştığını belirtebilirsiniz. Hatta ihtiyacınız olursa, diğer ortam ve makine isimlerini de dizi olarak ekleyebilirsiniz: 1 <?php 2 3 $env = $app->detectEnvironment(array( 4 'local' => array('bilgisayarınızın-ismi'), 5 6 7 )); Bu örnekte, ‘local’ ortamın ismi ve ‘bilgisayarınızın-ismi’ sunucunuzun makine ismidir. Linux ve Mac işletim sistemlerinde, terminalde hostname komutunu çalıştırarak sunucunuzun makine ismini öğrenebilirsiniz. Dilerseniz, detectEnvironment methoduna Closure ekleyip ortam algılama özelliğini kendiniz de yazabilirsiniz: 1 2 3 4 $env = $app->detectEnvironment(function() { return $_SERVER['MY_LARAVEL_ENV']; }); Şu anki Uygulama Ortamına Erişmek Şu anki uygulama ortamına environment metoduyla erişebilirsiniz: 1 $environment = App::environment(); Ayrıca environment metoduna bir veya daha fazla parametre girerek, ortamın girilen parametrelerden biriyle eşleşip eşleşmediğini kontrol edebilirsiniz: 8 Yapılandırma 1 2 3 4 if (App::environment('local')) { // Ortam 'local' } 5 6 7 8 9 if (App::environment('local', 'staging')) { // Ortam 'local' veya 'staging' } Sağlayıcı Yapılandırması Ortam yapılandırması kullanırken ana app yapılandırma dosyanıza ortam hizmet sağlayıcıları⁶¹ eklemek isteyebilirsiniz. Denediğinizde, ortama ait sağlayıcıların, ana app yapılandırmasındaki sağlayıcıları geçersiz kıldığını fark edeceksiniz. Ortama ait sağlayıcıların, diğerlerini geçersiz kılmak yerine onlara eklenmesini sağlamak için ortam yapılandırma dosyalarınızda append_config yardımcı fonksiyonunu kullanmanız gerekir: 1 2 3 'providers' => append_config(array( 'LocalOnlyServiceProvider', )) Hassas Yapılandırmaları Korumak “Gerçek” uygulamalarda, hassas yapılandırmaları yapılandırma dosyalarında tutmamanız önerilir. Veritabanı şifreleri, Stripe API anahtarları ve kriptolama anahtarları mümkün olduğunca yapılandırma dosyalarının dışında tutulmalıdır. O zaman nerede tutacağız bu bilgileri? Neyse ki, Laravel bu tip bilgilerin korunabilmesi için ⁶¹/docs/ioc#service-providers Yapılandırma 9 “nokta” yapılandırma dosyaları adında oldukça basit bir çözüm sağlıyor. Öncelikle uygulamanızı ‘local’ ortamınızı tanıyacak şekilde yapılandır⁶²malısınız. Sonra projenizin kök dizininde, yani composer.json dosyanızın bulunduğu dizinde .env.local.php dosyanızı oluşturmalısınız. Bu dosya tıpkı diğer Laravel yapılandırma dosyaları gibi anahtar-değer çiftlerine sahip bir dizi döndürmelidir. 1 <?php 2 3 return array( 4 'TEST_STRIPE_KEY' => 'super-secret-sauce', 5 6 7 ); Bu dosyadaki tüm anahtar-değer çiftleri PHP’nin $_ENV ve $_SERVER “süperküresel” değişkenlerinde erişilebilir olacaktır. Artık yapılandırma dosyalarınızda bu değişkenlere erişebilirsiniz: 1 'key' => $_ENV['TEST_STRIPE_KEY'] .env.local.php dosyasını .gitignore dosyasına eklemeyi unutmayın. Bu, dosyanın kaynak kontrol sistemine (Git) girmesini ve ortamınızın kişisel bilgilerine erişilmesini engeller. Şimdi bir de projenizi yayınladığınız sunucuda .env.php dosyası oluşturup gerekli yapılandırmaları aynı formatta girin. Aynı .env.local.php dosyası gibi, bu .env.php üretim ortamı dosyası da hiçbir zaman kaynak kontrolde bulunmamalıdır. Not: Her bir ortam için gerekli yapılandırma dosyasını oluşturabilirsiniz. Örneğin, development ortamında ⁶²/docs/configuration#environment-configuration 10 Yapılandırma çalışan proje, eğer varsa .env.development.php dosyasını sisteme dahil edecektir. Bakım Modu Uygulamanız bakım modundayken, her istek için standart bir view gösterilir. Böylece uygulamanız güncellenirken, bir süreliğine uygulamayı “çalışmaz hale” getirebilirsiniz. Halihazırda App::down methoduna yapılan bir istek app/start/global.php dosyasında bulunmaktadır. Uygulamanız bakım modunda olduğunda, kullanıcılara bu metoddan dönen yanıt gönderilecektir. Bakım modunu açmak için down komutunu Artisan üzerinde çalıştırın: 1 php artisan down Bakım modunu kapatmak içinse, up komutunu çalıştırabilirsiniz: 1 php artisan up Uygulamanız bakım modundayken kullanıcılara özel bir view göstermek için app/start/global.php dosyası içerisindeki down methodunu dilediğiniz gibi değiştirebilirsiniz: 1 2 3 4 App::down(function() { return Response::view('bakim_sayfasi', array(), 503); }) Eğer down metoduna girilen anonim fonksiyon (Closure) NULL değeri döndürürse, bakım modu o istek için görmezden gelinecektir. 11 Yapılandırma Bakım Modu ve Kuyruklar Uygulamanız bakım modunda iken, hiçbir kuyruk işlemi⁶³ uygulanmaz. Tüm işlemler, uygulama bakım modundan çıktığında normal bir şekilde devam eder. ⁶³/docs/queues Laravel Homestead Giriş Laravel sizin lokal geliştirme ortamınız da dahil olmak üzere bütün PHP geliştirme deneyimini zevkli bir hale getirmeye çalışmaktadır. Vagrant⁶⁴ Sanal Makinelerin yönetilmesi ve hazırlanması için basit, zekice bir yol sağlamaktadır. Laravel Homestead lokal makinenizde PHP, bir web sunucusu ve diğer herhangi bir sunucu yazılımı yüklemenizi gerektirmeksizin size harika bir geliştirme ortamı sağlayan resmi, ambalajlanmış bir Vagrant “box”tur. İşletim sisteminizi karışmasını daha artık dert etmeyin! Vagrant box’ları tamamen kontrol altındadır. Eğer bir şeyler yanlış giderse, onu yok edebilir ve dakikalar içerisinde yeniden oluşturabilirsiniz! Homestead herhangi bir Windows, Mac ve Linux’te çalışır ve Nginx web sunucusu, PHP 5.5, MySQL, Postgres, Redis, Memcached ve muhteşem Laravel uygulamaları geliştirmek için gerekli diğer tüm güzellikleri içerir. Homestead hali hazırda Vagrant 1.6 kullanılarak inşa ve test edilmiştir. Dahil Edilen Yazılımlar • • • • Ubuntu 14.04 PHP 5.5 Nginx MySQL ⁶⁴http://vagrantup.com 13 Laravel Homestead • • • • • • • Postgres Node (Bower, Grunt ve Gulp ile) Redis Memcached Beanstalkd Laravel Envoy⁶⁵ Fabric + HipChat Uzantısı Yükleme & Kurulum VirtualBox & Vagrant Yüklemesi Homestead ortamınızı başlatabilmek için, VirtualBox⁶⁶ ve Vagrant⁶⁷ yüklemelisiniz. Bu yazılım paketlerinin her ikisi de tüm popüler işletim sistemleri için kullanımı kolay görsel yükleyiciler sağlar. Vagrant Box Eklenmesi VirtualBox ve Vagrant yüklendikten sonra, terminalinizde aşağıdaki komutu kullanarak Vagrant yüklemenize laravel/homestead box’ını eklemelisiniz. Bu kutunun indirilmesi, internet bağlantı hızınıza bağlı olarak birkaç dakika alacaktır: 1 vagrant box add laravel/homestead Homestead Ambarını Klonlayın Kutuyu Vagrant yüklemenize ekledikten sonra, bu ambarı klonlamalı veya indirmelisiniz. Homestead kutusu sizin tüm Laravel (ve ⁶⁵/docs/ssh#envoy-task-runner ⁶⁶https://www.virtualbox.org/wiki/Downloads ⁶⁷http://www.vagrantup.com/downloads.html Laravel Homestead 14 PHP) projelerinizin host’u olarak hizmet edeceği için, bu ambarı tüm Laravel projelerinizi tuttuğunuz merkezi bir Homestead dizinine klonlamayı düşünün. 1 2 git clone https://github.com/laravel/homestead.git Home\ stead SSH Anahtarınızı Ayarlayın Ondan sonra da, ambarda bulunan Homestead.yaml dosyasını düzenleyin. Bu dosyada, public SSH anahtarınızın, bunun yanı sıra ana makineniz ile Homestead sanal makineniz arasında paylaşılmasını istediğiniz klasörlerin yolunu ayarlayabilirsiniz. Bir SSH anahtarınız yok mu? Mac ve Linux’te, genel olarak aşağıdaki komutu kullanarak bir SSH anahtar çifti oluşturabilirsiniz: 1 ssh-keygen -t rsa -C "your@email.com" Windows’ta, Git⁶⁸ yükleyebilir ve yukarıdaki komutu vermek için Git’le birlikte bulunan Git Bash kabuğunu kullanabilirsiniz. Alternatif olarak, PuTTY⁶⁹ ve PuTTYgen⁷⁰ kullanabilirsiniz. Bir SSH anahtarı oluşturduktan sonra, Homestead.yaml dosyanızın authorize özelliğinde anahtarın yolunu belirtin. Paylaşılan Klasörlerinizi Yapılandırın Homestead.yaml dosyanızın folders özelliği Homestead ortamınız- da paylaşmak istediğiniz klasörlerin tümünü listeler. Bu klasörler içindeki dosyalar değiştikçe, bunlar lokal makineniz ile Homestead ortamı arasında senkronize tutulacaktır. Ne kadar gerekiyorsa o kadar paylaşılan klasör yapılandırabilirsiniz! ⁶⁸http://git-scm.com/ ⁶⁹http://www.chiark.greenend.org.uk/~sgtatham/putty/download.html ⁷⁰http://www.chiark.greenend.org.uk/~sgtatham/putty/download.html 15 Laravel Homestead Nginx Sitelerinizi Yapılandırın Nginx size tanıdık değil mi? Problem değil. sites özelliği, Homestead ortamınızdaki bir klasöre kolaylıkla bir “domain” eşleştirmenize imkan verir. Örnek bir site yapılandırması Homestead.yaml dosyasına dahil edilmiştir. Aynı şekilde, Homestead ortamınıza gerektiği kadar çok sayıda site ekleyebilirsiniz. Homestead, üzerinde çalışmakta olduğunuz her Laravel projesi için kullanışlı, sanallaştırılmış bir ortam olarak hizmet edebilir! Bash Alias’ları Homestead kutunuza Bash aliasları eklemek için, basitçe Homestead dizininin köküne aliases dosyası ekleyin. Vagrant Box’ı Başlatın Homestead.yaml dosyasını istediğiniz gibi düzenledikten sonra, terminalinizde Homestead dizininden vagrant up komutunu çalıştı- rın. Vagrant sanal makineyi boot edecektir ve paylaşılan klasörlerinizi ve Nginx sitelerinizi otomatik olarak yapılandıracaktır! Nginx siteleriniz için “domain”leri makinenizdeki hosts dosyasına eklemeyi unutmayın! Bu hosts dosyası local domain’lerinize gelen istekleri Homestead ortamınıza yönlendirecektir. Mac ve Linux’te, bu dosya /etc/hosts konumundadır. Windows’ta, C:\Windows\System32\drivers\e konumundadır. Bu dosyaya eklediğiniz satırlar aşağıdaki gibi gözükecektir: 1 127.0.0.1 homestead.app Domain’i hosts dosyanıza ekledikten sonra, siteye tarayıcınız aracılığıyla port 8000 üzerinden erişebilirsiniz! 16 Laravel Homestead 1 http://homestead.app:8000 Veritabanlarınıza nasıl bağlanacağınızı öğrenmek için, okumaya devam edin! Günlük Kullanım SSH Aracılığıyla Bağlanma Homestead ortamınıza SSH aracılığıyla bağlanmak için, Homestead.yaml dosyanızda belirttiğiniz SSH anahtarını kullanarak port 2222 üzerinde 127.0.0.1‘e bağlanmalısınız. Ayrıca, basitçe Homestead dizininizden vagrant ssh komutunu da çalıştırabilirsiniz. Eğer daha fazla kolaylık istiyorsanız ∼/.bash_aliases veya ∼/.bash_profile‘inize aşağıdaki aliası eklemek yararlı olabilir: 1 alias vm='ssh vagrant@127.0.0.1 -p 2222' Veritabanlarınıza Bağlanma Laravel’in geliş halinde hem MySQL hem de Postgres için bir homestead veritabanı yapılandırılmıştır. Hatta daha fazla kolaylık için Laravel’in local “database” yapılandırma dosyası ön tanımlı olarak bu veritabanını kullanacak şekilde ayarlanmıştır. Navicat veya Sequel Pro aracılığıyla ana makinenizdeki MySQL veya Postgres veritabanlarınıza bağlanmak için, 127.0.0.1 ve 33060 (MySQL) veya 54320 (Postgres) portuna bağlanmalısınız. Her iki veritabanı için username ve password homestead / secret‘dir. Not: Standart dışı bu portları sadece ana makinenizdeki veritabanlarına bağlanırken kullanmalısınız. Laravel, Sanal Makine içerisinde çalıştığı için, Laravel 17 Laravel Homestead veritabanı yapılandırma dosyanızda ön tanımlı 3306 ve 5432 portlarını kullanacaksınız. İlave Sitelerin Eklenmesi Homestead ortamınızı hazırladıktan ve çalıştırdıktan sonra, Laravel uygulamalarınız için başka Nginx siteleri eklemek isteyebilirsiniz. Tek bir Homestead ortamında istediğiniz kadar çok sayıda Laravel yüklemesi çalıştırabilirsiniz. Bunu yapmanın iki yolu vardır. İlk olarak, basitçe bu siteleri Homestead.yaml dosyanıza ekleyebilir ve ondan sonra da vagrant provision çalıştırabilirsiniz. Alternatif olarak, Homestead ortamınızda bulunan serve skriptini kullanabilirsiniz. Bu serve skriptini kullanmak için, Homestead ortamınıza SSH ile girin ve aşağıdaki komutu çalıştırın: 1 2 serve domain.app /home/vagrant/Code/path/to/public/dire\ ctory Not: serve komutunu çalıştırdıktan sonra, ana makinenizdeki hosts dosyanıza yeni siteyi eklemeyi unutmayın! Portlar Aşağıdaki portlar Homestead ortamınıza yönlendirilir: • • • • SSH: 2222 -> 22’ye yönlendirilir HTTP: 8000 -> 80’e yönlendirilir MySQL: 33060 -> 3306’ya yönlendirilir Postgres: 54320 -> 5432’ye yönlendirilir İstek Yaşam Döngüsü Genel Bakış “Gerçek dünyada” bir alet kullanırken, aletin nasıl kullanıldığını bilirseniz kendinizi daha güvende hissedersiniz. Uygulama geliştirme farklı değildir. Geliştirme aletlerinizin nasıl fonksiyon gördüklerini bilirseniz bunları kullanırken kendinizi daha rahat ve güvende hissedersiniz. Bu dokümanın amacı Laravel frameworkünün nasıl “çalıştığının” iyi, yüksek düzeyli bir özetini vermektir. Tüm frameworkün daha iyi tanınmasıyla, her şey daha az “büyülü” hissedilecek ve uygulamanızı inşa ederken daha güvenli olacaksınız. İstek yaşam döngüsünün yüksek düzeyli bir özetine ek olarak “start” dosyalarını ve application olaylarını da anlatacağız. Terimlerin hepsini hemencecik anlamadıysanız, inancınızı kaybetmeyin! Sadece ne olup bittiğini temel olarak kavrayama çalışın. Dokümantasyonun diğer kesimlerini inceledikçe bilginiz giderek büyüyecektir. İstek Yaşam Döngüsü Uygulamanıza gelen tüm istekler public/index.php skripti aracılığı ile yönetilir. Apache kullanırken, Laravel’le gelen .htaccess dosyası tüm isteklerin index.php‘ye geçirilmesi işini halletmektedir. Bu noktadan itibaren, Laravel istekleri işleme ve istemciye bir cevap döndürme sürecine başlar. Laravel bootstrap süreci hakkında genel bir fikir elde edilmesi yararlı olacaktır, bu nedenle şimdi onu anlatacağız! Laravel’in bootstrap sürecini öğrenirken kavranması gereken en önemli kavram Servis Sağlayıcılarıdır. Kendinizin app/config/app.php İstek Yaşam Döngüsü 19 yapılandırma dosyasını açıp, buradaki providers dizisine bakarak servis sağlayıcılarının bir listesini görebilirsiniz. Bu sağlayıcılar Laravel için başlıca bootstrapping mekanizması olarak hizmet ederler. Fakat, servis sağlayıcıları konusuna daha fazla girmeden önce index.php dosyasına geri dönelim. Bir istek sizin index.php dosyasına girdikten sonra, bootstrap/start.php dosyası yüklenecektir. Bu dosya, aynı zamanda bir IoC konteyneri⁷¹ olarak hizmet eden yeni bir Laravel Application nesnesi oluşturur. Application nesnesi oluşturulduktan sonra, birkaç proje path’i ayarlanacak ve ortam tespiti⁷² yapılacaktır. Ondan sonra, dahili bir Laravel bootstrap skripti çağrılacaktır. Bu dosya Laravel kaynağının derinliklerinde yaşar ve yapılandırma dosyalarınıza dayalı olarak zaman dilimi (timezone), hata bildirimi ve benzeri birkaç ayarı daha ayarlar. Fakat, oldukça önemsiz yapılandırma seçeneklerinin ayarlanmasına ek olarak, aynı zamanda çok önemli bir şey daha yapar: uygulamanız için yapılandırılmış servis sağlayıcılarının hepsini kayda geçirir. Basit servis sağlayıcılarında sadece bir metod vardır: register. Bu register metodu, Application nesnesi tarafından Application’un kendi register metodu aracılığıyla bir servis sağlayıcısı kayda geçirildiği zaman çağrılır. Bu metod içerisinde, servis sağlayıcıları bir şeyleri IoC konteynerinde⁷³ kayda geçirirler. Esasında, her servis sağlayıcı konteynere bir veya daha fazla closure⁷⁴ (anonim fonksiyon) bağlar ki, bu closure’lar uygulamanız içinde bağlanmış hizmetlere erişmenize imkan verirler. Yani, örnek olarak QueueServiceProvider servis sağlayıcısı Kuyruk (Queue)⁷⁵ ile ilgili çeşitli sınıfları çözümleyen closure’leri kayda geçirmektedir. Pek tabii, servis sağlayıcıları sadece bir şeyleri IoC konteynerinde kayda geçirmekte değil, her türlü bootstrapping işi için kullanılabilirler. ⁷¹/docs/ioc ⁷²/docs/configuration#environment-configuration ⁷³/docs/ioc ⁷⁴http://us3.php.net/manual/en/functions.anonymous.php ⁷⁵/docs/queues 20 İstek Yaşam Döngüsü Bir servis sağlayıcı olay dinleyicilerini, view composer’lerini, Artisan komutlarını ve başkalarını kayda geçirebilirler. Servis sağlayıcılarının hepsi kayda geçirildikten sonra, app/start dosyalarınız yüklenecektir. Son olarak, app/routes.php dosyanız yüklenecektir. routes.php dosyanız yüklendikten sonra, Request nesnesi bir rotaya sevk edilebilmesi için “application”a gönderilir. Özetleyecek olursak: 1. İstek public/index.php dosyasına girer. 2. bootstrap/start.php dosyası “Application”ı oluşturur ve ortamı tespit eder. 3. Dahili framework/start.php dosyası ayarları yapılandırır ve servis sağlayıcılarını yükler. 4. Application app/start dosyaları yüklenir. 5. Application app/routes.php dosyası yüklenir. 6. Request nesnesi Application’a gönderilir, o da Response nesnesi döndürür. 7. Response nesnesi istemciye geri gönderilir. Artık bir Laravel uygulamasına gelen bir isteğin nasıl işlendiği konusunda iyi bir fikre sahip olduğunuza göre, “start” dosyalarına daha yakından bakabiliriz! Start Dosyaları Uygulamanızın start dosyaları app/start dizininde bulunmaktadır. Varsayılan olarak bunlardan üçü uygulamanızın içine dahil edilmiştir. Bunlar global.php, local.php ve artisan.php‘dir. artisan.php hakkında daha fazla bilgiye sahip olmak için Artisan komut satırı⁷⁶ dökümanlarına bakınız. ⁷⁶/docs/commands#registering-commands İstek Yaşam Döngüsü 21 Bunlardan global.php start dosyası Günlüklerin⁷⁷ kayda geçirilmesi ve app/filters.php dosyanızın dahil edilmesi gibi ön tanımlı birkaç temel öğe içerir. Ancak, bu dosyaya istediğiniz her şeyi ekleyebilirsiniz. Bu dosya ortam ne olursa olsun uygulamanıza gelen her istekte otomatik olarak dahil edilecektir. Öte yandan local.php dosyası yalnızca uygulamanız local ortamda çalışırken çağrılır. Ortamlar hakkında daha fazla bilgi için Yapılandırma⁷⁸ belgelerine bakınız. local‘e ilaveten başka ortamlarınız da varsa, pek tabii bu or- tamlar için de start dosyaları oluşturabilirsiniz. Uygulamanız o ortamda çalıştığı zaman bunlar otomatik olarak dahil edileceklerdir. Dolayısıyla, örneğin eğer bootstrap/start.php dosyanızda yapılandırılmış olan bir development ortamına sahipseniz, bir app/start/development.php dosyası oluşturabilirsiniz; herhangi bir istek uygulamaya bu ortamda girdiği zaman bu dosya dahil edilecektir. Start Dosyalarına Koyulacak Şeyler Start dosyaları her türlü “bootstrapping” kodun koyulacağı basit bir yer olarak hizmet ederler. Örneğin, bir View composer’ı kayda geçirebilir, günlükleme tercihlerinizi yapılandırabilir, bazı PHP ayarlarını ve benzerlerini yapabilirsiniz. Bu tamamen size kalmış. Tabii ki, tüm önyükleme kodunuzun start dosyalarına atılması bir karışıklık ve dağınıklık oluşturabilir. Büyük uygulamalar için veya eğer start dosyalarınızın karışmaya başladığını hissederseniz, bootstrapping kodunuzun bir kısmını servis sağlayıcılarına⁷⁹ taşımayı düşünün. ⁷⁷/docs/errors ⁷⁸/docs/configuration ⁷⁹/docs/ioc#service-providers İstek Yaşam Döngüsü 22 Application Olayları (Events) Uygulama Olaylarının Kayda Geçirilmesi Bunlara ek olarak before, after, close, finish ve shutdown uygulama olaylarını kayda geçirmek suretiyle istek öncesinde ve sonrasında bazı işlemler de yapabilirsiniz: 1 2 3 4 App::before(function($request) { //İstek öncesi olayları }); 5 6 7 8 9 App::after(function($request, $response) { //İstek sonrası olayları }); Bu olay dinleyicileri, uygulamanıza yapılan her istek öncesinde (before) ve sonrasında (after) çalışacaktır. Bu olaylar cevapların global filtrelenmesi veya global modifikasyonu için yardımcı olabilirler. Bunları start dosyalarınızın birinde veya bir servis sağlayıcısında⁸⁰ kayda geçirebilirsiniz. Bir dinleyiciyi matched eventinde de kayda geçirebilirsiniz; bu, gelen bir istek bir rotayla eşleştirildiğinde, ancak rota daha henüz çalıştırılmadan önce ateşlenecektir: 1 2 3 4 Route::matched(function($route, $request) { // }); ⁸⁰/docs/ioc#service-providers İstek Yaşam Döngüsü 23 finish eventi bir cevap sizin uygulamanızdan istemciye geri gön- derildikten sonra çağrılır. Burası uygulamanızın gerektirdiği bir son dakika işlemini yapmak için iyi bir yerdir. shutdown eventi ise tüm finish olay işleyicileri işlemlerini bitirdikten hemen sonra çağrılır ve skript sona ermeden önce herhangi bir iş yapmak için son fırsattır. Büyük ihtimalle, bu olaylardan birini kullanma ihtiyacınız olmayacaktır. Rotalar Temel Rotalama Uygulamanızdaki rotaların çoğu app/routes.php dosyasında tanımlanır. En temel Laravel rotası “URL deseni” ve closure (anonim fonksiyon)‘dan oluşur. Temel GET Rotası 1 2 3 4 Route::get('/', function() { return 'Merhaba Laravel!'; }); Temel POST Rotası 1 2 3 4 Route::post('bir/sey', function() { return 'Merhaba Laravel!'; }); Bir Rotanın Birden Çok HTTP Fiili İçin Kayda Geçirilmesi 1 2 3 4 Route::match(array('GET', 'POST'), '/', function() { return 'Merhaba Laravel!'; }); Tüm HTTP Metodları (GET, POST gibi) İçin Rota Yazımı 25 Rotalar 1 2 3 4 Route::any('falan', function() { return 'Merhaba Laravel!'; }); Rotanın Zorunlu Olarak HTTPS Üzerinden Kullanılmasını Sağlamak 1 2 3 4 Route::get('falan', array('https', function() { return 'HTTPS üzerinde olmalı!'; })); Çoğu zaman, rotalarınız için URL’ler üretmeniz gerekecek. Bunu URL::to metoduyla yapabilirsiniz: 1 $url = URL::to('falan'); Rota Parametreleri 1 2 3 4 Route::get('kullanici/{id}', function($id) { return 'Kullanıcı NO: '.$id; }); İsteğe Bağlı Rota Parametreleri 1 2 3 4 Route::get('kullanici/{isim?}', function($isim = null) { return $isim; }); Öntanımlı Değerli İsteğe Bağlı Rota Parametreleri 26 Rotalar 1 2 3 4 Route::get('kullanici/{isim?}', function($isim = 'Ali') { return $isim; }); Rotalarda Düzenli İfade Kontrolü 1 2 3 4 5 Route::get('kullanici/{isim}', function($isim) { // }) ->where('isim', '[A-Za-z]+'); 6 7 8 9 10 11 Route::get('kullanici/{id}', function($id) { // }) ->where('id', '[0-9]+'); Bir Where’ler Dizisi Geçilmesi Tabii ki kuralları bir dizi hâlinde tanımlayabilirsiniz: 1 2 3 4 5 Route::get('kullanici/{id}/{isim}', function($id, $isim) { // }) ->where(array('id' => '[0-9]+', 'isim' => '[a-z]+')) Global Desenler Tanımlanması Bir rota parametresinin her zaman için verilen bir düzenli ifadeyle sınırlandırılmasını istiyorsanız, pattern metodunu kullanabilirsiniz: 27 Rotalar 1 Route::pattern('id', '[0-9]+'); 2 3 4 5 6 Route::get('kullanici/{id}', function($id) { // Sadece {id} sayısal ise çağrılır. }); Bir Rota Parametre Değerine Erişmek Bir rotanın dışında bir rota parametre değerine erişmeniz gerekirse Route::input metodunu kullanabilirsiniz: 1 2 3 4 5 6 7 Route::filter('falan', function() { if (Route::input('id') == 1) { // } }); Rota Filtreleri Rota filtreleri, sitenizin yetkilendirme gereken alanlarına erişimi kısıtlamak için uygun bir yoldur. Laravel frameworkte aralarında bir auth filtresi, bir auth.basic filtresi, bir guestfiltresi ve bir csrf filtresinden oluşan birkaç filtre dahil edilmiştir. Bunlar app/filters.php dosyasında bulunmaktadır. Rota Filtresi Tanımlama 28 Rotalar 1 2 3 4 5 6 7 Route::filter('yas', function() { if (Input::get('yas') < 200) { return Redirect::to('anasayfa'); } }); Eğer filtreden bir yanıt (Redirect::to gibi) döndürülürse, bu cevap cevap olarak kabul edilecek ve rota çalıştırılmayacaktır. Rotada olabilecek after filtreleri de iptal edilecektir. Bir Rotaya Bir Filtre Bağlanması 1 2 3 4 5 Route::get('kullanici', array('before' => 'yas', functi\ on() { return '200 yaş üzerisin!'; })); Bir Controller Eylemine Bir Filtre Bağlanması 1 2 Route::get('kullanici', array('before' => 'yas', 'uses'\ => 'UserController@showProfile')); Rotaya Birden Çok Filtre Bağlanması 1 2 3 4 5 Route::get('kullanici', array('before' => 'auth|yas', f\ unction() { return '200 yaşın üzerisin ve giriş yetkin var!'; })); Birden Çok Filtrenin Dizi Yoluyla Bağlanması 29 Rotalar 1 2 3 4 5 Route::get('kullanici', array('before' => array('auth',\ 'yas'), function() { return '200 yaşın üzerisin ve giriş yetkin var!'; })); Filtre Parametrelerinin Belirtilmesi 1 2 3 4 Route::filter('yas', function($route, $request, $value) { // }); 5 6 7 8 9 10 Route::get('kullanici', array('before' => 'yas:200', fu\ nction() { return 'Merhaba Laravel!'; })); After filtreleri filtreye üçüncü parametre olarak geçilen bir $response parametresi alırlar: 1 2 3 4 5 Route::filter('log', function($route, $request, $respon\ se) { // }); Desen Temelli Filtreler URL desenine göre de rotalara filtre ataması yapabilirsiniz. 30 Rotalar 1 2 3 4 Route::filter('admin', function() { // }); 5 6 Route::when('admin/*', 'admin'); Yukarıdaki örnekte, admin filtresi admin/ ile başlayan tüm rotalara uygulanacaktır. * karakteri tüm karakterleri yakalamak için kullanılır. Filtreleri HTTP metodlarına (GET, POST gibi) göre uygulayabilirsiniz. 1 Route::when('admin/*', 'admin', array('post')); Filtre Sınıfları Daha gelişmiş filtreler için Closure yerine sınıfları kullanmak isteyebilirsiniz. Filtre sınıfları uygulama IoC Konteyneri⁸¹nde çözümlendikleri için, daha fazla test edilebilirlik için bu filtrelerde bağımlılık enjeksiyonu kullanmanız mümkün olabilecektir. Sınıf Temelli Filtrenin Kayda Geçirilmesi 1 Route::filter('falan', 'FalanFiltresi'); Ön tanımlı olarak, FalanFiltresi sınıfındaki filter metodu çağrılacaktır: ⁸¹/docs/ioc 31 Rotalar 1 class FalanFiltresi { 2 public function filter() { // Filtre işlemleri... } 3 4 5 6 7 8 } Bu filter metodunu kullanmak istemiyorsanız, başka bir metod belirtebilirsiniz: 1 Route::filter('falan', 'FalanFiltresi'); İsimli Rotalar İsimli rotalar link veya yönlendirme oluştururken kolaylık sağlar. Bir rotayı şöyle isimlendirebilirsiniz: 1 2 3 4 5 Route::get('kullanici/profil', array('as' => 'profil', \ function() { // })); Denetçi metodları için de rota isimleri belirleyebilirsiniz: 1 2 Route::get('kullanici/profil', array('as' => 'profil', \ 'uses' => 'KullaniciController@profilGoster')); Şimdi, rota isimlerini link veya yönlendirme oluştururken kullanabilirsiniz: 32 Rotalar 1 $url = URL::route('profil'); 2 3 $yonlendirme = Redirect::route('profil'); Çalışan rotanın ismine currentRouteName metoduyla ulaşabilirsiniz: 1 $isim = Route::currentRouteName(); Rota Grupları Bazen bir grup rotaya filtre atamanız gerekebilir. Her birine ayrı filtre atamaktansa, rota gruplarını kullanabilirsiniz: 1 2 3 4 5 6 Route::group(array('before' => 'auth'), function() { Route::get('/', function() { // Yetki gerekir. ("auth" filtresi) }); 7 Route::get('user/profile', function() { // Yetki gerekir. ("auth" filtresi) }); 8 9 10 11 12 }); Ayrıca, grup içindeki tüm controllerlerin verilen bir aduzayında olacağını belirtmek için group array’iniz içerisinde namespace parametresini kullanabilirsiniz: 33 Rotalar 1 2 3 4 Route::group(array('namespace' => 'Admin'), function() { // }); Alt Alanadı (Subdomain) Rotalaması Laravel rotaları joker alt alanadlarını da işleyebilirler ve joker parmetreleri alanadına geçebilirsiniz. Alt Alanadı Rotası Tanımlama 1 2 3 Route::group(array('domain' => '{hesapadi}.uygulamam.co\ m'), function() { 4 Route::get('kullanici/{id}', function($hesapadi, $id) { // }); 5 6 7 8 9 10 }); Rotalarda Ön-ek Bir grubun nitelikler dizisinde prefix seçeneğini kullanarak gruptaki rotalara ön-ek ekleyebilirsiniz: 34 Rotalar 1 2 Route::group(array('prefix' => 'admin'), function() { 3 Route::get('kullanici', function() { // }); 4 5 6 7 8 9 }); Rotalara Model Bağlama Model bağlama model sınıflarının rotalarda kullanılması için kolaylık sağlar. Mesela, bir kullanıcının ID’sinin aktarılması yerine, ID ile eşleşen Kullanici modelini aktarabilirsiniz. İlk olarak, girilen parametreler için kullanılacak modelleri Route::model metoduyla belirleyin: Parametrelere Model Bağlama 1 Route::model('kullanici', 'Kullanici'); Daha sonra, {kullanici} parametresini içeren bir rota belirleyin: 1 2 3 4 5 Route::get('profil/{kullanici}', function(Kullanici $ku\ llanici) { // }); {kullanici} parametresi ile Kullanici modelini eşleştirdiğimizden, bir Kullanici nesnesi rotaya aktarılacaktır. Yani, profil/1 şeklindeki istek, ID’si 1 olan Kullanici nesnesini aktaracaktır. 35 Rotalar Not: Eğer model için veritabanında eşleşme yapılamazsa, 404 hatası fırlatılır. Eğer eşleşmeme durumunda yapılacak işlemi kendiniz belirlemek istiyorsanız, model metoduna 3. argüman olarak bir Closure ekleyebilirsiniz: 1 2 3 4 Route::model('kullanici', 'Kullanici', function() { throw new NotFoundHttpException; }); Bazen, rota parametreleri için kendi çüzümleyicinizi kullanmak isteyebilirsiniz. Bunun için Route::bind metodu kullanılır: 1 2 3 4 Route::bind('kullanici', function($deger, $route) { return Kullanici::where('isim', $deger)->first(); }); 404 Hatası Fırlatma Rotadan 404 hatasını fırlatmanın iki yolu vardır. İlk olarak, App::abort metodunu kullanabilirsiniz. 1 App::abort(404); İkinci, Symfony\Component\HttpKernel\Exception\NotFoundHttpException nesnesi fırlatmaktır. 404 hatalarının yakalanması ve özel yanıtla oluşturulması hakkında daha fazla bilgiye dokümantasyonun hatalar⁸² bölümünden ulaşabilirsiniz. ⁸²/docs/errors#handling-404-errors Rotalar 36 Denetçilere (Controller) Rotalama Laravel sadece Closure’lara değil, aynı zamanda denetçi sınıflarına rotalamaya da imkan verir ve hatta kaynak denetçileri⁸³ oluşturulması da mümkündür. Daha fazla bilgi için Denetçiler⁸⁴ konusunu inceleyin. ⁸³/docs/controllers#resource-controllers ⁸⁴/docs/controllers İstekler (Requests) ve Girdi (Input) Temel Girdi Tüm kullanıcı girdisine birkaç basit metodla erişebilirsiniz. İstek için kullanılmış olan HTTP eylemi için endişe etmenize gerek yoktur, bütün eylemler için girdi bilgisine erişim aynıdır. Bir Girdi Değerinin Öğrenilmesi 1 $ismi = Input::get('ismi'); Bir Girdi Değerinin (Eksik Olması Durumunda Varsayılacak Olan Bir “Ön Değer” Belirtilerek) Öğrenilmesi 1 $ismi = Input::get('ismi', 'Saliha'); Bir Girdi Değerinin Mevcut Olduğunun Test Edilmesi 1 2 3 4 if (Input::has('ismi')) { // } İstekteki Tüm Girdi Değerlerinin Öğrenilmesi İstekler (Requests) ve Girdi (Input) 1 38 $girdi = Input::all(); İstek Girdisinin Sadece Bazı Değerlerinin Öğrenilmesi 1 $girdi = Input::only('kullaniciadi', 'sifre'); 2 3 $girdi = Input::except('kredi_karti'); “Dizi” girdileri olan formlarda çalışırken dizilere erişim için nokta gösterimini kullanabilirsiniz: 1 $input = Input::get('products.0.name'); Not: Bazı JavaScript kütüphaneleri, örneğin Backbone, girdi bilgisini uygulamaya JSON olarak gönderir. Bu girdi verisine de yine normal şekilde Input::get ile erişebilirsiniz. Çerezler (Cookies) Laravel çerçevesi tarafından oluşturulan tüm çerezler, bir kimlik doğrulama kodu ile şifrelenir ve imzalanır. Kullanıcı tarafından değiştirilmesi halinde geçersiz kabul edilecektir. Bir Çerez Değerinin Öğrenilmesi 1 $deger = Cookie::get('ismi'); Cevaba (Response) Yeni Bir Çerez İliştirilmesi İstekler (Requests) ve Girdi (Input) 1 39 $yanit = Response::make('Merhaba Dünya'); 2 3 4 $yanit->withCookie(Cookie::make('ismi', 'degeri', $daki\ ka)); Sonraki Cavap İçin Kuyruğa Bir Çerez İliştirilmesi Cevap oluşturulmadan önce bir çerez oluşturmak isterseniz, Cookie::queue() metodunu kullanın. Uygulamanızdan gelen son cevaba yeni bir çerez iliştirilecektir. 1 Cookie::queue($name, $value, $minutes); Süresiz Bir Çerez Oluşturulması 1 $cerez = Cookie::forever('ismi', 'degeri'); Önceki Girdi Bazı durumlarda bir isteğin girdisini bir sonraki isteğe kadar tutmanız gerekebilir. Örneğin, doğrulama hataları için kontrol ettikten sonra bir formu yeniden bu önceki girdi bilgisi ile doldurmak gerekebilir. Girdinin Oturuma(Session) Geçici Olarak Yansıtılması (flash) 1 Input::flash(); Girdinin Sadece Bazı Değerlerinin Oturuma Geçici Olarak Yansıtılması 40 İstekler (Requests) ve Girdi (Input) 1 2 Input::flashOnly('kullaniciadi', 'email'); irtilenler //sadece bel\ 3 4 Input::flashExcept('sifre'); //belirtilenler hariç Girdinin geçici olarak oturuma yansıtılmasını, sık şekilde bir önceki sayfaya tekrar-yönlendirme (redirect) ile birlikte yapacağınız için, bu yansıtmayı (redirect)’e zincir ek yapabilirsiniz. 1 2 return Redirect::to('form')->withInput(); eğerleri ile beraber //tüm girdi d\ 3 4 5 return Redirect::to('form')->withInput(Input::except('s\ ifre')); //belirtilenler hariç Not: Diğer verilerin istekler arasında geçici yansıtmasını (flash), Oturum Session⁸⁵ sınıfını kullanarak yapabilirsiniz. Önceki Girdi Verisinin Elde Edilmesi 1 Input::old('kullaniciadi'); Dosyalar Yollanan Bir Dosyanın Öğrenilmesi 1 $dosya = Input::file('foto'); Bir Dosya Yollanmış Olup Olmadığının Belirlenmesi ⁸⁵/docs/session İstekler (Requests) ve Girdi (Input) 1 2 3 4 41 if (Input::hasFile('foto')) { // } Dosya file metodu tarafından döndürülen nesne, PHP SplFileInfo sınıfının bir uzantısı olan ve dosya ile etkileşim için çeşitli metodlar sağlayan Symfony\Component\HttpFoundation\File\UploadedFile sınıfının bir olgusudur. Yüklenmiş Olan Bir Dosyanın Geçerli Olup Olmadığının Belirlenmesi 1 2 3 4 if (Input::file('foto')->isValid()) { // } Yüklenmiş Olan Bir Dosyanın Taşınması 1 Input::file('foto')->move($hedefDizinPatikasi); 2 3 4 Input::file('foto')->move($hedefDizinPatikasi, $dosyaAd\ i); Yüklenmiş Olan Bir Dosyanın Dosya Yolunun Öğrenilmesi 1 $patika = Input::file('foto')->getRealPath(); Yüklenmiş Olan Bir Dosyanın Orijinal Adının Öğrenilmesi İstekler (Requests) ve Girdi (Input) 1 42 $name = Input::file('foto')->getClientOriginalName(); Yüklenmiş Olan Bir Dosyanın Uzantısının Öğrenilmesi 1 2 $uzanti = Input::file('foto')->getClientOriginalExtensi\ on(); Yüklenmiş Olan Bir Dosyanın Boyutunun Öğrenilmesi 1 $buyukluk = Input::file('foto')->getSize(); Yüklenmiş Olan Bir Dosyanın MIME Türünün Öğrenilmesi 1 $mime = Input::file('foto')->getMimeType(); İstek Bilgileri İstek Request sınıfı, uygulamanıza gelecek olan HTTP isteğini incelemeniz için birçok metod sunar ve Symfony\Component\HttpFoundation\Request sınıfının bir uzantısıdır. Bunlardan bazıları şöyledir. İstek URI’nın Öğrenilmesi 1 $uri = Request::path(); Retrieving The Request Method İstekler (Requests) ve Girdi (Input) 1 43 $method = Request::method(); 2 3 4 5 6 if (Request::isMethod('post')) { // } İstek Patikasının Bir Desene Uygunluğunun Test Edilmesi 1 2 3 4 if (Request::is('admin/*')) { // } İstek URL’nin Öğrenilmesi 1 $url = Request::url(); İstek URI’nın Herhangi Bir Bölümünün Öğrenilmesi 1 $segment = Request::segment(1); Bir İstek Başlığı(Header) Değerinin Öğrenilmesi 1 $deger = Request::header('Content-Type'); Sunucu bilgileri için $_SERVER Değerlerinin Öğrenilmesi 1 $deger = Request::server('PATH_INFO'); İsteğin HTTPS Üzerinden Olup Olmadığının Belirlenmesi İstekler (Requests) ve Girdi (Input) 1 2 3 4 44 if (Request::secure()) { // } İsteğin AJAX Kullanıyor Olup Olmadığının Belirlenmesi 1 2 3 4 if (Request::ajax()) { // } İsteğin JSON Content Tipine Sahip Olup Olmadığının Belirlenmesi 1 2 3 4 if (Request::isJson()) { // } İsteğin JSON İstiyor Olup Olmadığının Belirlenmesi 1 2 3 4 if (Request::wantsJson()) { // } İstenen Cevap Biçiminin Kontrol Edilmesi Request::format metodu HTTP Accept header’ine dayalı olarak, istenen cevap formatını döndürecektir: İstekler (Requests) ve Girdi (Input) 1 2 3 4 if (Request::format() == 'json') { // } 45 Görünümler (Views) ve Cevaplar (Responses) Temel Cevaplar Rotalardan String Döndürme 1 2 3 4 Route::get('/', function() { return 'Merhaba dünya!'; }); Özel Cevaplar Oluşturma Bir cevap (Response) olgusu Symfony\Component\HttpFoundation\Response sınıfından türer ve HTTP cevapları oluşturmak için çeşitli metodlar sağlar. 1 $cevap = Response::make($contents, $statusCode); 2 3 $cevap->header('Content-Type', $deger); 4 5 return $cevap; Eğer Response sınıfının metodlarına erişmeniz gerekiyor, ama cevap içeriği olarak bir view döndürmek istiyorsanız, kolaylık açısından Response::view metodunu kullanabilirsiniz: Görünümler (Views) ve Cevaplar (Responses) 1 2 47 return Response::view('hello')->header('Content-Type', \ $type); Cevaplara Çerez Bağlanması 1 $cerez = Cookie::make('isim', 'deger'); 2 3 return Response::make($content)->withCookie($cerez); Yönlendirmeler (Redirects) Bir Yönlendirme Döndürme 1 return Redirect::to('uye/giris'); Flaş Veri Eşliğinde Bir Yönlendirme Döndürme 1 2 return Redirect::to('uye/giris')->with('mesaj', 'Giriş \ başarısız!'); Not: with metodu veriyi oturum bilgisine flaşlayacağından, bu veriyi tipik Session::get metodu ile alabilirsiniz. İsimli Bir Rotaya Yönlendirme Döndürme 1 return Redirect::route('giris'); Parametre Geçerek İsimli Bir Rotaya Yönlendirme Döndürme Görünümler (Views) ve Cevaplar (Responses) 1 48 return Redirect::route('profil', array(1)); İsimli Parametre Kullanarak İsimli Bir Rotaya Yönlendirme Döndürme 1 return Redirect::route('profil', array('uye' => 1)); Bir Kontrolör Eylemine Yönlendirme Döndürme 1 return Redirect::action('HomeController@index'); Parametre Geçerek Bir Kontrolör Eylemine Yönlendirme Döndürme 1 2 return Redirect::action('UserController@profil', array(\ 1)); İsimli Parametre Kullanarak Bir Kontrolör Eylemine Yönlendirme Döndürme 1 2 return Redirect::action('UserController@profil', array(\ 'uye' => 1)); Görünümler (Views) Görünümler tipik olarak uygulamanızın HTML’sini içerirler ve kontrolörünüzün ve etki alanı mantığınızın gösterim mantığınızdan ayrık tutulmasının uygun bir yoludur. Görünümler app/views dizininde saklanmaktadır. Basit bir görünüm şuna benzer: Görünümler (Views) ve Cevaplar (Responses) 1 2 49 <!-- Görünüm app/views/selamlama.php dosyasında bulunsu\ n--> 3 4 <html> <body> 5 <h1>Merhaba <?php echo $isim; ?></h1> 6 </body> 7 8 </html> Bu görünüm web tarayıcısına şu şekilde döndürülebilir: 1 2 3 4 5 Route::get('/', function() { return View::make('selamlama', array('isim' => 'Tuana \ Şeyma')); }); View::make metodundaki ikinci parametre görünümde kullanılma- sı gereken bir veri dizisidir. Görünümlere Veri Geçilmesi 1 2 3 // Geleneksel yaklaşım kullanmak $view = View::make('selamlama')->with('isim', 'Tuana Şe\ yma'); 4 5 6 7 // Sihirli Metodları kullanmak $view = View::make('selamlama')->withIsim('Tuana Şeyma'\ ); Yukarıdaki örnekte $isim değişkeni görünümden erişilebilir olacak ve Tuana Şeyma bilgisini taşıyacaktır. Dilerseniz, make metoduna ikinci parametre olarak veriler dizisi geçebilirsiniz: Görünümler (Views) ve Cevaplar (Responses) 1 50 $view = View::make('selamlama', $data); Bir parça veriyi tüm görünümler arasında paylaşmanız da mümkündür: 1 View::share('isim', 'Tuana Şeyma'); Bir Görünüme Bir Alt Görünüm Geçirilmesi Bazen bir görünümü başka bir görünümün içine geçirmek isteyebilirsiniz. Örneğin, app/views/evlat/view.php‘de saklanan belli bir görünüm olsun ve biz bunu şu şekilde başka bir görünüme geçirebiliriz: 1 2 $view = View::make('selamlama')->nest('evlat', 'evlat.v\ iew'); 3 4 5 $view = View::make('selamlama')->nest('evlat', 'evlat.v\ iew', $data); Bundan sonra bu alt görünüm ebeveyn görünümde gösterilebilir: 1 <html> <body> 2 <h1>Merhaba!</h1> <?php echo $evlat; ?> 3 4 </body> 5 6 </html> Bir Görünümün Mevcut Olmadığının Belirlenmesi Bir view’in mevcut olup olmadığını yoklamanız gerekirse, View::exists metodunu kullanın: Görünümler (Views) ve Cevaplar (Responses) 1 2 3 51 if (View::exists('emails.customer')) { // } Görünüm Kompozitörleri Görünüm kompozitörleri görünüm oluşturulduğu zaman çağrılan isimsiz fonksiyonlar veya sınıf metodlarıdır. Eğer belli bir görünüm, uygulamanız boyunca her oluşturulduğunda bu görünüme bağlamak istediğiniz bir veri varsa, bir görünüm kompozitörü kodun tek bir yere koyulabilmesi imkanı verebilir. Bu nedenle, görünüm kompozitörleri “görünüm modelleri” veya “sunum yapıcı” gibi iş görürler. Bir Görünüm Kompozitörü Tanımlanması 1 2 3 4 View::composer('profil', function($view) { $view->with('navigasyon', Sayfa::all()); }); Şimdi profil görünümü her oluşturulduğunda, navigasyon verisi bu görünüme bağlanacaktır. Bir görünüm kompozitörüne bir defada birden çok görünüm bağlamanız da mümkündür: Görünümler (Views) ve Cevaplar (Responses) 1 2 3 4 5 52 View::composer(array('profil','pano','bildirim'), funct\ ion($view) { $view->with('navigasyon', Sayfa::all()); }); Bunun yerine sınıf tabanlı bir kompozitör kullanmak isterseniz, ki uygulama IoC Konteyneri⁸⁶ ile çözümlenebilme yararı sağlar, şöyle yapabilirsiniz: 1 View::composer('profil', 'ProfileComposer'); Bir görünüm kompozitörü sınıfı şöyle tanımlanmalıdır: 1 class ProfileComposer { 2 public function compose($view) { $view->with('adet', Uye::count()); } 3 4 5 6 7 8 } Birden Çok Composer Tanımlanması Bir grup composer’i bir defada kayda geçirmek için composers metodunu kullanabilirsiniz: ⁸⁶/docs/ioc Görünümler (Views) ve Cevaplar (Responses) 1 2 3 4 5 53 View::composers(array( 'AdminComposer' => array('admin.index', 'admin.profile\ '), 'UserComposer' => 'user', )); Not: Kompozitör sınıfının nerede saklanacağı konusunda bir gelenek olmadığına dikkat edin. composer.json dosyanızdaki yönergeleri kullanarak otomatik yüklenebildikleri sürece, bunları istediğiniz yerde depolayabilirsiniz. Görünüm Oluşturucular Görünüm oluşturucuları tam olarak görünüm kompozitörleri gibi çalışırlar; ancak bunlar görünüm oluşturulur oluşturulmaz aktifleştirilirler. Görünüm oluşturucusu kaydetmek için, basitçe creator metodunu kullanınız: 1 2 3 4 View::creator('profil', function($view) { $view->with('adet', Uye::count()); }); Özel Cevaplar Bir JSON Cevabı Oluşturma 1 2 return Response::json(array('isim' => 'Tuana Şeyma', 'i\ l' => 'Bursa')); Bir JSONP Cevabı Oluşturma Görünümler (Views) ve Cevaplar (Responses) 1 2 54 return Response::json(array('isim' => 'Tuana Şeyma', 'i\ l' => 'Bursa'))->setCallback(Input::get('callback')); Bir Dosya İndirme Cevabı Oluşturma 1 return Response::download($indirilecekDosyaYolu); 2 3 4 return Response::download($indirilecekDosyaYolu, $isim,\ $basliklar); Not: Dosya indirmelerini yöneten Symfony HttpFoundation, indirilecek olan dosyanın bir ASCII dosya ismi olmasını gerektirir. Cevap Makroları Çeşitli rota ve controllerlerinizde tekrar tekrar kullanabileceğiniz özel bir cevap tanımlamak isterseniz, Response::macro metodunu kullanabilirsiniz: 1 2 3 4 Response::macro('caps', function($value) { return Response::make(strtoupper($value)); }); Bu macro fonksiyonu birinci parametre olarak bir isim ve ikinci parametre olarak bir Closure kabul eder. Response sınıfı üzerinde makro ismi çağrıldığı zaman makronun Closure fonksiyonu çalıştırılacaktır: 1 return Response::caps('falan'); Görünümler (Views) ve Cevaplar (Responses) 55 Makrolarınızı app/start dosyalarınızın birinde tanımlayabilirsiniz. Alternatif olarak, makrolarınızı ayrı bir dosya içerisinde organize edip, bu dosyayı start dosyalarınızın birisinden “include” edebilirsiniz. Denetçiler (Controllers) Temel Denetçiler Bütün rotalandırma mantığını, tüm rotaları tek tek routes.php dosyasında tanımlamak yerine, bu davranışlarını Denetçiler (Controllers) sınıflarını kullanarak organize edebilirsiniz. Denetçiler, ilişkin oldukları rotaların mantığını bir sınıfta gruplar. Aynı zamanda, daha ileri çerçeve (framework) özelliklerini kullanma avantajına sahiptirler, örneğin otomatik dependency injection⁸⁷ (bağımlılık enjeksiyonu) gibi. Denetçiler genelde app/controllers dizininde konumlandırılır ve varsayılan olarak bu dizin composer.json dosyanızın classmap seçeneğinde kayda geçirilmiştir. Basit bir denetçi (controller) sınıfı örneği şöyledir: 1 class KullaniciController extends BaseController { 2 /** * Verilen kullanıcının profilini göster. */ public function showProfile($id) { $kullanici = Kullanici::find($id); 3 4 5 6 7 8 9 10 11 12 return View::make('kullanici.profil', array('kullanic\ i' => $kullanici)); } 13 14 } ⁸⁷/docs/ioc Denetçiler (Controllers) 57 Bütün denetçilerin BaseController sınıfından türetilmiş olması gerekir. BaseController ın kendisi de app/controllers dizininde bulunur ve bütün denetçiler için geçerli olacak ortak mantığın içine yerleştirilmesinde kullanılabilir. BaseController sınıfı, framework’ün Controller sınıfının uzantısıdır. Bu durumda, oluşturmuş olduğumuz denetçi fonksiyonuna rotalandırmayı şu şekilde yapabiliriz: 1 2 Route::get('kullanici/{id}', 'KullaniciController@showP\ rofile'); Eğer bir denetçinizi, dizin içerisinde yuvalandırarak (nest) veya PHP aduzayları (namespaces) kullanarak organize etmek isterseniz, bu durumda rotayı tanımlarken, tam nitelendirilmiş (yani, aduzayıyla birlikte) sınıf adını kullanınız: 1 2 Route::get('falanca', 'Namespace\FalancaController@meto\ dAdi'); Not: PHP sınıflarımızı otomatik yüklemek için Composer⁸⁸ kullandığımız için, composer onların nasıl yükleneceğini bildiği sürece controllerler dosya sistemindeki herhangi bir yerde bulunabilir. Controller dizini uygulamanız için herhangi bir klasör yapısını zorlamaz. Controller’lara rotalama dosya sisteminden tamamen ayrık tutulmuştur. Denetçi rotalarına isimler de verebilirsiniz: ⁸⁸http://getcomposer.org Denetçiler (Controllers) 1 2 3 58 Route::get('falanca', array('uses' => 'FalancaControlle\ r@metodAdi', 'as' => 'rotaAdi')); Herhangi bir denetçi eylemine ait bir URL üretmek için, URL::action metodunu veya action helper metodunu kullanabilirsiniz: 1 $url = URL::action('FalancaController@metodAdi'); 2 3 $url = action('FalancaController@metodAdi'); Çalıştırılmakta olan bir denetçi eyleminin ismine currentRouteAction metodu ile erişebilirsiniz: 1 $action = Route::currentRouteAction(); Denetçi Filtreleri Denetçi rotalarına, diğer rotalarda olduğuna benzer şekilde, filtreler Filters⁸⁹ belirlenebilir: 1 2 Route::get('profile', array('before' => 'auth', 'uses' => 'KullaniciController@showProfile')); Filtreleri, denetçinizin içerisinden de belirtebilirsiniz: ⁸⁹/docs/routing#route-filters Denetçiler (Controllers) 1 59 class KullaniciController extends BaseController { 2 /** * Yeni bir KullaniciController olgusu başlat. */ public function __construct() { $this->beforeFilter('auth', array('except' => 'getGir\ 3 4 5 6 7 8 9 is')); 10 $this->beforeFilter('csrf', array('on' => 'post')); 11 12 $this->afterFilter('log', array('only' => array('falancaMetod', 'filancaMetod'))); 13 14 } 15 16 17 } Denetçi filtrelerini bir Closure kullanarak da belirtebilirsiniz: 1 class KullaniciController extends BaseController { 2 /** * Yeni bir KullaniciController olgusu başlat. */ public function __construct() { $this->beforeFilter(function() { // }); } 3 4 5 6 7 8 9 10 11 12 13 14 } Denetçiler (Controllers) 60 Eğer filtre olarak denetçi sınıfın bir metodunu kullanmak isterseniz, filtre isminin önüne @ koymalısınız. 1 class UserController extends BaseController { 2 /** * Yeni bir KullaniciController olgusu başlat. */ public function __construct() { $this->beforeFilter('@filterRequests'); } 3 4 5 6 7 8 9 10 /** * Gelen istekleri filtrele. */ public function filterRequests($route, $request) { // } 11 12 13 14 15 16 17 18 19 } TEDA-uyumlu (Temsili Durum Aktarma uyumlu, RESTful) Denetçiler Laravel size, basit TEDA (REST) isimlendirme gelenekleri kullanarak, belirleyeceğiniz tek bir rota ile, denetçilerinizin içindeki her eylemi kullanabilme imkanını tanır. İlk olarak, Route::controller metodu ile bu rotayı tanımlayınız: Denetçiler (Controllers) 1 2 61 Route::controller('kullanicilar', 'KullaniciController'\ ); controller metodu iki argüman alır. Birincisi denetçinin yönetece- ği taban URI olup, ikincisi denetçinin sınıf ismidir. Akabinde sadece, isimlerine HTTP eyleminin ön ek olarak ekleneceği ve bunlara cevap verecek olan metodlarınızı denetçinize ilave ediniz: 1 class KullaniciController extends BaseController { 2 public function getIndex() { // } 3 4 5 6 7 public function postProfile() { // } 8 9 10 11 12 public function anyLogin() { // } 13 14 15 16 17 18 } index metodları, denetçi tarafından yönetilmekte olan kök URI’a cevap verir. Örneğimizde bu, kullanicilar dır. Denetçinizdeki bir eylem metodunun ismi birden fazla kelimeden oluşuyorsa, bu eylem metoduna, URI da kelime aralarına tire işareti “-“ eklenmiş şekilde yazarak erişebilirsiniz. Örneğin, ‘KullaniciController’ denetçimizdeki aşağıdaki şekilde isimlendirilmiş olan metod, kullanici/yonetici-profili URI’na cevap verecektir. Denetçiler (Controllers) 1 62 public function getYoneticiProfili() {} Kaynak (Resource) Denetçileri Kaynak denetçileri, kaynaklar etrafında TEDA-uyumlu denetçiler oluşturulmasını kolaylaştırır. Artisan KSA’daki (Artisan Komut Satırı Arayüzü) controller:make komutunu ve de Route::resource metodunu kullanmak sureti ile böyle bir denetçiyi çabucak oluşturabiliriz. Denetçiyi komut satırını kullanarak oluşturmak için şu komutu kullanınız: 1 php artisan controller:make FotoController Şimdi bu controller için resourceful bir rotayı kayda geçirebiliriz (routes.php dosyasında): 1 Route::resource('foto', 'FotoController'); Bu tek bir rota deklarasyonu, foto kaynağınız üzerinde çalıştıracağınız çeşitli TEDA-uyumlu eylem metodlarına erişeceğiniz rotalar oluşturur. Aynı zamanda, oluşturulmuş olan denetçide, bu eylemlerin her biri için metodları hazır olarak oluşturulmuş ve hangi URI’ı ve eylemi yönettikleri yanlarına not olarak yazılmış olacaktır. Kaynak Denetçisinin Yöneteceği Eylemler HTTP Fiili | Patika | Eylem | Rota İsmi ———–|———————–|— —————|————— GET | /kaynak | index | kaynak.index GET | /kaynak/create | create (oluştur) | kaynak.create POST | /kaynak | store (kaydet) | kaynak.store GET | /kaynak/{id} | show (göster) | kaynak.show GET | /kaynak/{id}/edit | edit (düzenle) | kaynak.edit Denetçiler (Controllers) 63 PUT/PATCH | /kaynak/{id} | update (güncelle)| kaynak.update DELETE | /kaynak/{id} | destroy (imha et)| kaynak.destroy Bazen bu eylemlerin sadece bazılarına ihtiyaç duyabilirsiniz: 1 2 php artisan controller:make FotoController --only=index\ ,show //sadece belirtilenleri 3 4 5 php artisan controller:make FotoController --except=ind\ ex //belirtilenler hariç Ve, aynı zamanda rotasında da eylemlerin sadece bazılarını yönetmesini belirleyebilirsiniz: 1 2 Route::resource('foto', 'FotoController', array('only' => array('index', 'show'))); 3 4 5 6 Route::resource('foto', 'FotoController', array('except' => array('create', 'store', 'update', \ 'destroy'))); Varsayılan olarak tüm kaynak denetçilerinin bir rota ismi bulunur; ancak bu isimleri üçüncü parametrede gireceğiniz dizi ile kendiniz belirleyebilirsiniz. 1 2 Route::resource('foto', 'FotoController', array('names' => array('create' => 'foto Yuvalanmış Resource Controller’lerin Halledilmesi Resource controlleri “yuvalamak” için, rota yazımında “dot” (nokta) sözdizimi kullanın: Denetçiler (Controllers) 1 2 64 Route::resource('photos.comments', 'PhotoCommentControl\ ler'); Bu rota “yuvalanmış” bir rota olarak kayda geçirilecek ve photos/{photoResource}/c benzeri URI’larla erişilebilecektir: 1 class PhotoCommentController extends BaseController { 2 public function show($photoId, $commentId) { // } 3 4 5 6 7 8 } Resource Controller’lere Başka Rotalar Eklenmesi Bir bir resource controller’e ön tanımlı resource rotaları dışında başka rotalar eklemeniz gerekli bir hale gelirse, bu rotaları Route::resource metodunu çağırmadan önce tanımlamalısınız: 1 2 Route::get('foto/populer'); Route::resource('foto', 'FotoController'); Eksik Olan Metodların İşlenmesi Denetçide tanımlanmamış olan metodlara gelecek olan çağrıları işlemek için bir “hepsini yakala” metodu tanımlanabilir. Bu metodun isminin missingMethod olması gerekir ve istek için metod ve parametre dizisi alır: Bir Hepsini Yakala Metodunun Tanımlanması Denetçiler (Controllers) 1 2 3 4 public function missingMethod($parameters = array()) { // } 65 Hatalar ve Günlüğe Ekleme Yapılandırma Uygulamanız için günlük işleyicisi app/start/global.php start dosyasında⁹⁰ kayda geçirilir. Ön tanımlı olarak, bu logger tek bir günlük dosyası kullanacak şekilde yapılandırılmıştır; bununla birlikte siz bu davranışı gereken şekilde özelleştirebilirsiniz. Laravel popüler Monolog⁹¹ günlükleme kitaplığını kullandığığı için, Monolog’un sunduğu çeşitli işleyicilerin avantajından yararlanabilirsiniz. Örneğin, tek bir büyük dosya yerine günlük log dosyaları kullanmak istiyorsanız, start dosyanızda aşağıdaki değişikliği yapabilirsiniz: 1 $logFile = 'laravel.log'; 2 3 Log::useDailyFiles(storage_path().'/logs/'.$logFile); Hata Ayrıntısı Ön tanımlı olarak hata ayrıntısı uygulamanızda etkindir. Yani bir hata oluştuğu zaman ayrıntılı bir sorun listesi ve hata iletisi gösterebileceksiniz. app/config/app.php dosyanızdaki debug seçeneğini false ayarlayarak hata ayrıntılarını devre dışı bırakabilirsiniz. Not: Bir üretim (production) ortamında hata ayrıntılarını devre dışı bırakmanız kuvvetle önerilir. ⁹⁰/docs/lifecycle#start-files ⁹¹https://github.com/Seldaek/monolog Hatalar ve Günlüğe Ekleme 67 Hataların İşlenmesi Ön tanımlı olarak, app/start/global.php dosyasında tüm istisnalar için bir hata işleyici bulunmaktadır: 1 2 3 4 App::error(function(Exception $exception) { Log::error($exception); }); En temel hata işleyici budur. Ancak siz gerektiği kadar işleyici belirleyebilirsiniz. İşleyicilere işledikleri istisnaların tipine işaret eden isimler verilir. Örneğin, sadece RuntimeException olgularını işleyen bir işleyici oluşturabilirsiniz: 1 2 3 4 App::error(function(RuntimeException $exception) { // İstisnayı işle... }); Bir istisna işleyicisinin bir cevap döndürmesi halinde, bu cevap tarayıcıya gönderilecek ve başka bir hata işleyici çağrılmayacaktır: 1 2 3 App::error(function(InvalidUserException $exception) { Log::error($exception); 4 return 'Maalesef bu hesapla ilgili yanlış bir şeyler v\ 5 6 7 ar!'; }); PHP’nin önemli hatalarını (fatal error) izlemek için, App::fatal metodunu kullanabilirsiniz: Hatalar ve Günlüğe Ekleme 1 2 3 4 68 App::fatal(function($exception) { // }); Eğer birkaç istisna işleyiciniz varsa, bunlar en genelde en spesifik olana doğru tanımlanmalıdır. Bu yüzden, örneğin, Exception tipindeki tüm istisnaları işleyen bir işleyici Illuminate\Encryption\DecryptException gibi özel bir istisna tipinin işleyicisinden daha önce tanımlanmalıdır. Hata İşleyicileri Nereye Konacak Hata işleyici kayıtları için ön tanımlı bir “konum” yoktur. Laravel bu alanda size seçme hakkı verir. Bir seçenek işleyicileri start/global.php dosyanızda tanımlamaktır. Genelde, burası her türlü “bootstrapping” (önce yüklenen) kodun koyulması için uygun bir yerdir. Eğer bu dosya çok kalabalık bir hale gelirse, bir app/errors.php dosyası oluşturabilir ve bu dosyayı start/global.php skriptinizde require yapabilirsiniz. Üçüncü bir seçenek, işleyicileri kayda geçiren bir servis sağlayıcı⁹² oluşturmaktır. Tekrar belirtelim, tek bir “doğru” cevap yoktur. Rahat edeceğiniz bir konum seçin. HTTP İstisnaları HTTP istisnaları bir istemci isteği sırasında oluşabilecek hatalar demektir. Bu bir sayfa bulunamadı hatası (404), bir yetkisizlik hatası (401), hatta genel 500 hatası olabilir. Böyle bir cevap döndürmek için aşağıdaki biçimi kullanın: ⁹²/docs/ioc#service-providers Hatalar ve Günlüğe Ekleme 1 69 App::abort(404); İsteğe bağlı olarak, bir cevap verebilirsiniz: 1 App::abort(401, 'Yetkili değilsiniz.'); Bu istisnalar, isteğin yaşam döngüsü boyunca herhangi bir zamanda kullanılabilir. 404 Hatalarının İşlenmesi Uygulamanızdaki tüm “404 Not Found” hatalarını işleyerek özel 404 hata hata sayfaları döndürmenize imkan veren bir hata işleyici kaydı yapabilirsiniz: 1 2 3 4 App::missing(function($exception) { return Response::view('errors.missing', array(), 404); }); Günlüğe Ekleme Laravel’in günlüğe ekleme imkanları güçlü Monolog⁹³ üstünde basit bir katman sağlar. Laravel, ön tanımlı olarak uygulamanız için tek bir günlük dosyası oluşturacak şekilde yapılandırılmıştır ve bu dosya app/storage/logs/laravel.log içinde tutulmaktadır. Bu günceye aşağıdakilere benzer şekilde bilgi yazabilirsiniz: ⁹³http://github.com/seldaek/monolog Hatalar ve Günlüğe Ekleme 1 70 Log::info('İşte bu yararlı bir bilgidir.'); 2 3 Log::warning('Yanlış giden bir şeyler olabilir.'); 4 5 Log::error('Gerçekten yanlış giden bir şey var.'); Günlük tutucu, RFC 5424⁹⁴‘de tanımlanmış yedi günlük ekleme düzeyi sağlamaktadır: debug, info, notice, warning, error, critical ve alert. Log metodlarına bağlamsal bir veri dizisi de geçilebilir: 1 2 Log::info('Günce mesajı', array('context' => 'Diğer yar\ dımcı bilgi')); Monolog, günlüğe ekleme için kullanabileceğiniz bir takım başka işleyicilere de sahiptir. Gerektiğinde, Laravel tarafından kullanılan Monolog olgusuna şu şekilde ulaşabilirsiniz: 1 $monolog = Log::getMonolog(); Ayrıca, günlüğe geçirilen tüm mesajları yakalamak için bir olay kaydı da yapabilirsiniz: Bir günlük izleyici kaydı yapılması 1 2 3 4 Log::listen(function($level, $message, $context) { // }); ⁹⁴http://tools.ietf.org/html/rfc5424 Cepheler (Facades) Giriş Cepheler uygulamanızın IoC konteynerinde⁹⁵ bulunan sınıflar için “statik” bir arayüz sağlar. Laravel birçok cephe ile gelmektedir ve büyük bir ihtimalle daha ne olduklarını bilmeden onları kullanıyorsunuzdur! Laravel “facade’ları” IoC konteynerindeki altta yatan sınıflara “static proksiler” olarak hizmet ederek, geleneksel static metodlardan daha fazla test edilebilirlik ve esneklik sürdürürken özlü ve anlamlı sözdizimi yararını sağlarlar. Zaman zaman, uygulama ve paketleriniz için kendi cephelerinizi oluşturmak isteyebilirsiniz, bu itibarla bu sınıfların kavramlarını, geliştirilmesini ve kullanımını inceleyelim. Not: Cepheler konusunu incelemeden önce Laravel IoC konteyneri⁹⁶ ile çok aşina olmanız kuvvetle önerilir. Açıklama Bir Laravel uygulaması bağlamında bir cephe bir nesneye onun konteynerinden erişim sağlayan bir sınıf demektir. Bu işi yapan mekanizmalar Facade sınıfında tanımlıdır. Laravel’in cepheleri ve sizin oluşturduğunuz kendi cepheleriniz bu temel Facade sınıfından türeyecektir. ⁹⁵/docs/ioc ⁹⁶/docs/ioc 72 Cepheler (Facades) Sizin cephe sınıfınız sadece tek bir metoda tatbikat getirmesi gerekiyor: getFacadeAccessor. getFacadeAccessor methodunun tanımlayacağı iş konteynerden ne çözeceğidir. Facade temel sınıfı sizin cephelerinizden, çözülmüş nesneye yapılan çağrıları ertelemek için __callStatic() sihirli-metodunu kullanır. Böylece, siz Cache::get gibi bir facade çağrısı yaptığınız zaman, Laravel IoC konteynerindeki Cache manager sınıfını çözümler ve o sınıftaki get metodunu çağırır. Teknik açıdan ifade edilirse, Laravel Facade’ları bir hizmet bulucu olarak Laravel IoC konteynerinin kullanılması için pratik bir sözdizimidir. Pratik Kullanım Aşağıdaki örnekte, Laravel önbellekleme sistemine bir çağrı yapılmış. Bu koda göz attığınızda, Cache sınıfında statik bir metod olan get‘in çağrılıyor olduğunu düşünebilirsiniz. 1 $deger = Cache::get('anahtar'); Ancak, eğer Illuminate\Support\Facades\Cache sınıfına bakacak olursak, orada get adında statik bir metod olmadığını görürüz: 1 class Cache extends Facade { 2 3 4 5 6 7 8 9 /** * Get the registered name of the component. * * @return string */ protected static function getFacadeAccessor() { return\ 'cache'; } 10 11 } 73 Cepheler (Facades) Bu Cache sınıfı temel Facade sınıfından türetilmiş ve getFacadeAccessor() adında bir metod tanımlamış. Bu metodun işinin bir IoC bağlamasının adını döndürmek olduğunu hatırlayın. Bir kullanıcı Cache cephesinde herhangi bir statik metoda başvurduğunda, Laravel, IoC konteynerinden cache bağlamasını çözecek ve istenen metodu (bu örnekte get) bu nesneden çalıştıracaktır. Yani bizim Cache::get çağrımız şu şekilde yeniden yazılabilir: 1 $value = $app->make('cache')->get('anahtar'); Cephe Oluşturma Kendi uygulama veya paketiniz için bir cephe oluşturulması kolaydır. Sadece üç şeye ihtiyacınız vardır: • Bir IoC bağlayıcısı. • Bir cephe sınıfı. • Bir cephe takma adı yapılandırması. Bir örnek bakalım. Burada, OdemeGecidi\Odeme olarak tanımlanmış bir sınıfımız var. 1 namespace OdemeGecidi; 2 3 class Odeme { 4 public function process() { // } 5 6 7 8 9 10 } Cepheler (Facades) 74 Bu sınıf sizin app/models dizininizde veya Composer’in nasıl otomatik yükleneceğini bildiği diğer herhangi bir dizinde konumlandırılabilir. Bu sınıfı IoC konteynerinden çözebiliyor olmamız lazım. Öyleyse, bir bağlama ekleyelim: 1 2 3 4 App::bind('odeme', function() { return new \OdemeGecidi\Odeme; }); Bu bağlamayı kayda geçirmek için harika bir yer OdemeServiceProvider adında yeni bir hizmet sağlayıcı⁹⁷ oluşturmak ve bu bağlamayı register metoduna eklemek olacaktır. Daha sonra Laravel’i sizin hizmet sağlayıcınızı app/config/app.php yapılandırma dosyasından yükleyecek şekilde yapılandırın. Daha sonra, kendi cephe sınıfımızı oluşturabiliriz: 1 use Illuminate\Support\Facades\Facade; 2 3 class Odeme extends Facade { 4 5 6 protected static function getFacadeAccessor() { return\ 'odeme'; } 7 8 } Son olarak, eğer istiyorsak, app/config/app.php yapılandırma dosyasındaki aliases dizisine kendi cephe’miz için bir takma ad ekleyebiliriz. Artık, process metodunu Odeme sınıfının bir olgusunda çağırabiliriz. ⁹⁷/docs/ioc#service-providers 75 Cepheler (Facades) 1 Odeme::process(); Alias (Takma Ad)’ların Otomatik Yüklenmesi Üzerine Bir Bilgi Notu PHP, tanımlanmamış tip dayatmalı sınıfları otomatik olarak yüklemeye çalışmayacağı için⁹⁸ app\config\app.php dosyasının aliases dizisindeki sınıflar bazı durumlarda kullanılamamaktadır. \ServiceWrapper\ApiTime sınıfı eğer ApiTimeoutException olarak aliaslanmış ise, namespace \ServiceWrapper aduzayının dışındaki bir catch(ApiTimeoutException $e) ifadesi bu istisnayı hiçbir zaman, hatta istisna çıkması durumunda bile yakalamayacaktır. Benzer bir durum, aliaslanmış sınıflara tip dayatması olan Model’lerde de bulunmuştur. Tek geçici çözüm, aliaslamaktan vazgeçmek ve tip dayatması yapmak istediğiniz sınıfları bunları gerektiren her dosyanın en başında use etmektir. Cepheleri Taklit Etme Ünite testi cephelerin nasıl çalıştıkları konusunda önemli bir husustur. Gerçekten, cephelerin varlıkları için bile ilk neden test edilebilirliktir. Daha fazla bilgi için, belgelerdeki Cepheleri Taklit Etme⁹⁹ kesimine bakın. Facade Sınıf Referansı Aşağıda, her facade’ı ve onun altında yatan sınıfı bulacaksınız. Bu, verilen bir facade kökü için API dokümantasyonuna hızla girme ⁹⁸https://bugs.php.net/bug.php?id=39003 ⁹⁹/docs/testing#mocking-facades Cepheler (Facades) 76 için yararlı bir araçtır. Uygun olduğunda IoC bağlama¹⁰⁰ anahtarı da dahil edilmiştir. Facade | Sınıf | IoC Bağlaması ————- | ————- | ————- App | IlluminateFoundationApplication¹⁰¹ | app Artisan | IlluminateConsoleApplication¹⁰² | artisan Auth | IlluminateAuthAuthManager¹⁰³ | auth Auth (Instance) | IlluminateAuthGuard¹⁰⁴ | Blade | IlluminateViewCompilersBladeCompiler¹⁰⁵ | blade.compiler Cache | IlluminateCacheRepository¹⁰⁶ | cache Config | IlluminateConfigRepository¹⁰⁷ | config Cookie | IlluminateCookieCookieJar¹⁰⁸ | cookie Crypt | IlluminateEncryptionEncrypter¹⁰⁹ | encrypter DB | IlluminateDatabaseDatabaseManager¹¹⁰ | db DB (Instance) | IlluminateDatabaseConnection¹¹¹ | Event | IlluminateEventsDispatcher¹¹² | events File | IlluminateFilesystemFilesystem¹¹³ | files Form | IlluminateHtmlFormBuilder¹¹⁴ | form Hash | IlluminateHashingHasherInterface¹¹⁵ | hash HTML | IlluminateHtmlHtmlBuilder¹¹⁶ | html Input | IlluminateHttpRequest¹¹⁷ | request Lang | IlluminateTranslationTranslator¹¹⁸ | translator Log | IlluminateLogW¹⁰⁰/docs/ioc ¹⁰¹http://laravel.com/api/4.2/Illuminate/Foundation/Application.html ¹⁰²http://laravel.com/api/4.2/Illuminate/Console/Application.html ¹⁰³http://laravel.com/api/4.2/Illuminate/Auth/AuthManager.html ¹⁰⁴http://laravel.com/api/4.2/Illuminate/Auth/Guard.html ¹⁰⁵http://laravel.com/api/4.2/Illuminate/View/Compilers/BladeCompiler.html ¹⁰⁶http://laravel.com/api/4.2/Illuminate/Cache/Repository.html ¹⁰⁷http://laravel.com/api/4.2/Illuminate/Config/Repository.html ¹⁰⁸http://laravel.com/api/4.2/Illuminate/Cookie/CookieJar.html ¹⁰⁹http://laravel.com/api/4.2/Illuminate/Encryption/Encrypter.html ¹¹⁰http://laravel.com/api/4.2/Illuminate/Database/DatabaseManager.html ¹¹¹http://laravel.com/api/4.2/Illuminate/Database/Connection.html ¹¹²http://laravel.com/api/4.2/Illuminate/Events/Dispatcher.html ¹¹³http://laravel.com/api/4.2/Illuminate/Filesystem/Filesystem.html ¹¹⁴http://laravel.com/api/4.2/Illuminate/Html/FormBuilder.html ¹¹⁵http://laravel.com/api/4.2/Illuminate/Hashing/HasherInterface.html ¹¹⁶http://laravel.com/api/4.2/Illuminate/Html/HtmlBuilder.html ¹¹⁷http://laravel.com/api/4.2/Illuminate/Http/Request.html ¹¹⁸http://laravel.com/api/4.2/Illuminate/Translation/Translator.html Cepheler (Facades) 77 riter¹¹⁹ | log Mail | IlluminateMailMailer¹²⁰ | mailer Paginator | IlluminatePaginationFactory¹²¹ | paginator Paginator (Instance) | IlluminatePaginationPaginator¹²² | Password | IlluminateAuthRemindersPasswordBroker¹²³ | auth.reminder Queue | IlluminateQueueQueueManager¹²⁴ | queue Queue (Instance) | IlluminateQueueQueueInterface¹²⁵ | Queue (Base Class) | IlluminateQueueQueue¹²⁶ | Redirect | IlluminateRoutingRedirector¹²⁷ | redirect Redis | IlluminateRedisDatabase¹²⁸ | redis Request | IlluminateHttpRequest¹²⁹ | request Response | IlluminateSupportFacadesResponse¹³⁰ | Route | IlluminateRoutingRouter¹³¹ | router Schema | IlluminateDatabaseSchemaBlueprint¹³² | Session | IlluminateSessionSessionManager¹³³ | session Session (Instance) | IlluminateSessionStore¹³⁴ | SSH | IlluminateRemoteRemoteManager¹³⁵ | remote SSH (Instance) | IlluminateRemoteConnection¹³⁶ | URL | IlluminateRoutingUrlGenerator¹³⁷ | url Validator | IlluminateValidationFactory¹³⁸ | validator Validator (Instance) | IlluminateValidationValidator¹³⁹ | View | IlluminateViewFactory¹⁴⁰ | view View (Instance) | IlluminateViewVi¹¹⁹http://laravel.com/api/4.2/Illuminate/Log/Writer.html ¹²⁰http://laravel.com/api/4.2/Illuminate/Mail/Mailer.html ¹²¹http://laravel.com/api/4.2/Illuminate/Pagination/Factory.html ¹²²http://laravel.com/api/4.2/Illuminate/Pagination/Paginator.html ¹²³http://laravel.com/api/4.2/Illuminate/Auth/Reminders/PasswordBroker.html ¹²⁴http://laravel.com/api/4.2/Illuminate/Queue/QueueManager.html ¹²⁵http://laravel.com/api/4.2/Illuminate/Queue/QueueInterface.html ¹²⁶http://laravel.com/api/4.2/Illuminate/Queue/Queue.html ¹²⁷http://laravel.com/api/4.2/Illuminate/Routing/Redirector.html ¹²⁸http://laravel.com/api/4.2/Illuminate/Redis/Database.html ¹²⁹http://laravel.com/api/4.2/Illuminate/Http/Request.html ¹³⁰http://laravel.com/api/4.2/Illuminate/Support/Facades/Response.html ¹³¹http://laravel.com/api/4.2/Illuminate/Routing/Router.html ¹³²http://laravel.com/api/4.2/Illuminate/Database/Schema/Blueprint.html ¹³³http://laravel.com/api/4.2/Illuminate/Session/SessionManager.html ¹³⁴http://laravel.com/api/4.2/Illuminate/Session/Store.html ¹³⁵http://laravel.com/api/4.2/Illuminate/Remote/RemoteManager.html ¹³⁶http://laravel.com/api/4.2/Illuminate/Remote/Connection.html ¹³⁷http://laravel.com/api/4.2/Illuminate/Routing/UrlGenerator.html ¹³⁸http://laravel.com/api/4.2/Illuminate/Validation/Factory.html ¹³⁹http://laravel.com/api/4.2/Illuminate/Validation/Validator.html ¹⁴⁰http://laravel.com/api/4.2/Illuminate/View/Factory.html Cepheler (Facades) ew¹⁴¹ | ¹⁴¹http://laravel.com/api/4.2/Illuminate/View/View.html 78 Laravel Cashier Giriş Laravel Cashier Stripe’in¹⁴² abonelik faturalama hizmetleri için anlamlı, akıcı bir arayüz sağlar. Sizin yazmaktan ürktüğünüz klişe abonelik faturalama kodunun hemen tümünü halleder. Cashier, temel abonelik yönetimine ek olarak kuponları, abonelik takasını, abonelik “miktarlarını”, ödemesiz dönemlerin iptal edilmesini halledebilir ve hatta fatura PDF’leri üretebilir. Yapılandırma Composer Öncelikle, composer.json dosyanıza Cashier paketini ekleyin: 1 "laravel/cashier": "~2.0" Service Provider Daha sonra, app yapılandırma dosyanızda Laravel\Cashier\CashierServiceProvid kayda geçirin. Migration Cashier kullanabilmemiz için, veritabanımıza birkaç sütun eklememiz gerekiyor. Endişe etmeyin, gerekli sütunları ekleyecek bir ¹⁴²https://stripe.com 80 Laravel Cashier migrasyon oluşturmak için cashier:table Artisan komutunu kullanabilirsiniz. Örneğin, bu alanı users tablosuna eklemek için php artisan cashier:table users kullanın. Bu migrasyonu oluşturduktan sonra basitçe migrate komutunu çalıştırın. Model Ayarı Ondan sonra da model tanımlamanıza BillableTrait ve uygun tarih değiştiricilerini ekleyin: 1 2 use Laravel\Cashier\BillableTrait; use Laravel\Cashier\BillableInterface; 3 4 5 class User extends Eloquent implements BillableInterfac\ e { 6 use BillableTrait; 7 8 protected $dates = ['trial_ends_at', 'subscription_end\ 9 10 s_at']; 11 12 } Stripe Key Son olarak, bootstrap dosyalarınızın birinde Stripe anahtarınızı ayarlayın: 1 User::setStripeKey('stripe-key'); Bir Plana Abone Olunması Bir model olgusuna sahip olduktan sonra o kullanıcıyı verilen bir Stripe planına kolaylıkla abone edebilirsiniz: Laravel Cashier 1 81 $user = User::find(1); 2 3 4 $user->subscription('monthly')->create($creditCardToken\ ); Bir abonelik oluştururken bir kupon uygulamak isterseniz, withCoupon metodunu kullanabilirsiniz: 1 2 3 $user->subscription('monthly') ->withCoupon('code') ->create($creditCardToken); Bu subscription metodu ilgili Stripe aboneliğini otomatik olarak oluşturacaktır, bunun yanında veritabanınızı Stripe müşteri ID’si ve ilgili diğer faturalama bilgisiyle güncelleyecektir. Eğer planınızda Stripe’de yapılandırılmış olan bir trial (deneme) varsa, kullanıcı kaydında deneme bitiş tarihi (trial end date) de otomatik olarak ayarlanacaktır. Eğer planınız Stripe’de yapılandırılmış olmayan bir deneme süresine sahipse, deneme bitiş tarihini abonelikten sonra elle ayarlamak zorundasınız: 1 $user->trial_ends_at = Carbon::now()->addDays(14); 2 3 $user->save(); Ek Kullanıcı Ayrıntılarının Belirtilmesi Ek müşteri ayrıntılarını geçmek isterseniz, onları create metoduna ikinci parametre olarak geçmek suretiyle bunu yapabilirsiniz: 82 Laravel Cashier 1 2 3 4 5 $user->subscription('monthly')->create($creditCardToken\ , [ 'email' => $email, 'description' => 'Our First Custome\ r' ]); Stripe tarafından desteklenen ek alanlar hakkında daha fazlasını öğrenmek için, Stripe’ın müşteri oluşturma dokümantasyonuna¹⁴³ bakınız. Kredi Kartsız Eğer uygulamanız kredi kartı olmaksızın bedava bir deneme teklif ediyorsa, modelinizde cardUpFront özelliğini false olarak ayarlayın: 1 protected $cardUpFront = false; Hesap oluşturulmasında, modelde deneme bitiş tarihi ayarladığınızdan emin olun: 1 $user->trial_ends_at = Carbon::now()->addDays(14); 2 3 $user->save(); Aboneliklerin Takas Edilmesi Bir kullanıcıyı yeni bir aboneliğe takas etmek için, swap metodunu kullanın: ¹⁴³https://stripe.com/docs/api#create_customer 83 Laravel Cashier 1 $user->subscription('premium')->swap(); Eğer kullanıcı deneme (trial) durumundaysa, deneme normal şekilde sürdürülecektir. Ayrıca abonelik için eğer bir “miktar (quantity)” mevcutsa, miktar da sürdürülecektir. Abonelik Miktarı Bazen abonelikler “miktar” ile etkilenir. Örneğin, uygulamanız bir hesap üzerinde kullanıcı başına ayda $10 ücretlendirme yapabilir. Abonelik miktarını kolayca artırmak ve azaltmak için increment ve decrement metodlarını kullanın: 1 $user = User::find(1); 2 3 $user->subscription()->increment(); 4 5 6 // Aboneliğin mevcut miktarına beş ekle... $user->subscription()->increment(5); 7 8 $user->subscription()->decrement(); 9 10 11 // Aboneliğin mevcut miktarından beş çıkar... $user->subscription()->decrement(5); Bir Aboneliğin İptal Edilmesi Bir aboneliğin iptal edilmesi parkta bir yürüyüştür: 1 $user->subscription()->cancel(); Laravel Cashier 84 Bir abonelik iptal edildiği zaman, Cashier veritabanınızdaki subscription_ends_at sütununu otomatik olarak ayarlayacaktır. Bu sütun, subscribed metodunun ne zaman false döndürmeye başlaması gerektiğini bilmek için kullanılır. Örneğin, eğer bir müşteri 1 Martta bir aboneliği iptal ederse ama aboneliğin sona ermesi 5 Marta kadar planlanmamışsa, subscribed metodu 5 Marta kadar true döndürmeye devam edecektir. Bir Aboneliğe Geri Dönülmesi Eğer bir kullanıcı aboneliğini iptal etmiş ve bu aboneliğe kaldığı yerden devam etmesini istiyorsanız, resume metodunu kullanın: 1 2 $user->subscription('monthly')->resume($creditCardToken\ ); Eğer kullanıcı bir aboneliği iptal eder ve daha sonra bu abonelik tam olarak sona ermeden geri dönerse, onlara hemen fatura edilmeyecektir. Abonelikleri sadece tekrar etkinleştirilecektir ve orijinal faturalama döngüsüne göre fatura edilecektir. Abonelik Durumunun Yoklanması Bir kullanıcının uygulamanıza abone olduğunu doğrulamak için, subscribed komutunu kullanın: 1 2 3 4 if ($user->subscribed()) { // } Bu subscribed metodu bir rota filtresi için harika bir adaydır: Laravel Cashier 1 2 3 4 5 6 7 85 Route::filter('subscribed', function() { if (Auth::user() && ! Auth::user()->subscribed()) { return Redirect::to('billing'); } }); Ayrıca, onTrial metodunu kullanmak suretiyle kullanıcının hala deneme süresinde olup olmadığını (uygunsa) da tayin edebilirsiniz: 1 2 3 4 if ($user->onTrial()) { // } Kullanıcının daha önce aktif bir abone olduğunu ama aboneliğini iptal etmiş olduğunu tayin etmek için cancelled metodunu kullanabilirsiniz: 1 2 3 4 if ($user->cancelled()) { // } Ayrıca, bir kullanıcının aboneliğini iptal etmiş ama hala aboneliği tam sona erinceye kadar “yetkisiz kullanım süresinde (grace period)” olup olmadıklarını da belirleyebilirsiniz. Örneğin, bir kullanıcı 10 Martta sona ereceği planlanmış bir aboneliği 5 Martta iptal ederse, bu kullanıcı 10 Marta kadar “yetkisiz kullanım süresindedir”. Subscribed metodunun bu zaman süresinde hala true döndürdüğüne dikkat ediniz. Laravel Cashier 1 2 3 4 86 if ($user->onGracePeriod()) { // } Bir kullanıcının uygulamanızdaki bir plana hiç abone olup olmadığını tayin etmek için everSubscribed metodu kullanılabilir: 1 2 3 4 if ($user->everSubscribed()) { // } Bir kullanıcının verilen bir plana abone olup olmadığını ID’sine dayalı olarak tayin etmek için onPlan metodu kullanılabilir: 1 2 3 4 if ($user->onPlan('monthly')) { // } Başarısız Ödemelerin Halledilmesi Şayet bir müşterinin kredi kartı süresi dolarsa ne olur? Endişeye gerek yok - Cashier sizin için müşterinin üyeliğini kolaylıkla iptal edebileceğiniz bir Webhook controller içermektedir. Sadece bir rotada bu controlleri belirtin: 1 2 Route::post('stripe/webhook', 'Laravel\Cashier\WebhookC\ ontroller@handleWebhook'); Hepsi bu kadar! Gerçekleşmemiş ödemeler bu controller tarafından yakalanacak ve halledilecektir. Bu controller üç başarısız ödeme 87 Laravel Cashier girişiminden sonra ilgili müşterinin aboneliğini iptal edecektir. Bu örnekteki stripe/webhook URI sadece örnek içindir. Kendi Stripe ayarlarınızda bu URI’ı yapılandırmanız gerekir. Diğer Stripe Webhook’larının İşlenmesi İşlemek istediğiniz başka Stripe webhook olaylarına sahipseniz, Webhook controller’i basitçe genişletin. Metod isminiz Cashier’in beklenen geleneğine uygun olmalıdır, burası için özel olarak, metod ismi işlemek istediğiniz Stripe webhook’un ismi ve önüne handle getirilmiş hali olmalıdır. Örneğin, eğer invoice.payment_succeeded webhook’unu işlemek istiyorsanız controllerinize bir handleInvoicePaymentSucceeded metodu eklemelisiniz. 1 2 class WebhookController extends Laravel\Cashier\Webhook\ Controller { 3 public function handleInvoicePaymentSucceeded($payload) { // Olayı işle... } 4 5 6 7 8 9 } Not: Webhook controller veritabanınızdaki abonelik bilgilerini güncellemeye ek olarak Stripe API aracılığıyla aboneliği de iptal edecektir. Faturalar invoices metodunu kullanarak bir kullanıcının faturalarından olu- şan bir diziyi kolaylıkla elde edebilirsiniz: Laravel Cashier 1 88 $invoices = $user->invoices(); Müşterinin faturalarını listelerken, ilgili fatura bilgisini göstermek için şu helper metodlarını kullanabilirsiniz: 1 {{ $invoice->id }} 2 3 {{ $invoice->dateString() }} 4 5 {{ $invoice->dollars() }} Bir faturanın indirilebilir bir PDF’sini üretmek için downloadInvoice metodunu kullanın. Evet, bu gerçekten bu kadar kolaydır: 1 2 3 4 return $user->downloadInvoice($invoice->id, [ 'vendor' => 'Şirketiniz', 'product' => 'Ürününüz', ]); Formlar & HTML Form Açmak Form Açmak 1 2 3 {{ Form::open(array('url' => 'falan/filan')) }} // {{ Form::close() }} Varsayılan olarak, POST metodu kullanılır; ancak, istediğiniz bir metodu da belirtebilirsiniz: 1 2 echo Form::open(array('url' => 'falan/filan', 'method' \ => 'put')) Not: HTML formları, sadece POST ve GET metotlarını desteklediği için, PUT ve DELETE metotları formunuza otomatik olarak bir _method gizli alanı eklenmek suretiyle taklit edilecektir. İsimli rotalara veya controller eylemlerine işaret eden formlar da açabilirsiniz: 1 echo Form::open(array('route' => 'route.name')) 2 3 echo Form::open(array('action' => 'Controller@method')) Ayrıca, rota parametreleri de geçebilirsiniz: 90 Formlar & HTML 1 2 echo Form::open(array('route' => array('route.name', $u\ ser->id))) 3 4 5 echo Form::open(array('action' => array('Controller@met\ hod', $user->id))) Formunuz dosya yüklemelerini kabul edecekse, diziye files seçeneğini ekleyin: 1 2 echo Form::open(array('url' => 'falan/filan', 'files' =\ > true)) CSRF Koruması Bir Forma CSRF Değeri Eklemek Laravel, uygulamanızı siteler arası istek sahtekarlıklarından korumak için kolay bir metot sunar. Öncelikle, kullanıcının oturumuna rastgele bir değer yerleştirilir. Merak etmeyin, bu otomatik olarak yapılır. CSRF değeri, formlarınıza gizli bir alan olarak otomatik olarak yerleştirilir. Yine de, gizli alan için HTML kodunu oluşturmak isterseniz, token metodunu kullanabilirsiniz: 1 echo Form::token(); Bir Rotaya CSRF Filtresi Eklemek 91 Formlar & HTML 1 2 3 4 5 Route::post('profil', array('before' => 'csrf', functio\ n() { // })); Forma Model Bağlanması Bir Model Formu Açmak Sıklıkla, bir modelin içeriğine dayanan bir form oluşturmak isteyebilirsiniz. Bunu yapmak için, Form::model metodunu kullanın: 1 2 echo Form::model($user, array('route' => array('user.up\ date', $user->id))) Şimdi, bir form elementi oluşturduğunuzda, mesela bir text input, elementin ismiyle eşleşen modelin değeri, otomatik olarak alanın değeri olarak belirlenir. Yani, örneğin, email ismine sahip bir text alanı için, kullanıcı modelinin email niteliği değer olarak atanır. Bununla birlikte, dahası da var! Oturum flaş verisinde inputa uyan bir öğe mevcutsa, bu değer, model’in değerine nazaran öncelik alacaktır. Yani, öncelik şu şekildedir: 1. Oturum Flaş Verisi (Önceki Girdi) 2. Doğrudan Atanmış Değer 3. Model Nitelik Değeri Bu size model değerlerine bağlanan formları sadece çabukça oluşturmanıza imkan vermekle kalmaz, sunucu tarafında bir geçerlilik hatası olduğunda tekrar kolayca doldurmanızı da sağlayacaktır! Not: Form::model kullanıyor olduğunuzda, Form::close ile formunuzu kapatmayı unutmayın! 92 Formlar & HTML Label Elementi Bir Label Elementi Üretilmesi 1 echo Form::label('email', 'E-Mail Adresi'); Ek HTML Nitelikleri Belirtme 1 2 echo Form::label('email', 'E-Mail Adresi', array('class\ ' => 'awesome')); Not: Bir label oluştururken, label ismiyle aynı isimde oluşturduğunuz bir form elementi otomatik olarak label ile aynı isimde bir ID de alacaktır. Text, Textarea, Password & Hidden Alanlar Bir Text Inputu Üretilmesi 1 echo Form::text('uyeadi'); Ön Tanımlı Bir Değer Belirtilmesi 1 echo Form::text('email', 'ornek@gmail.com'); Not: hidden ve textarea metodları text metodu ile aynı şekilde yazılır. Bir Password Inputu Üretilmesi 93 Formlar & HTML 1 echo Form::password('parola'); Diğer Inputlar Üretilmesi 1 2 3 echo Form::email($name, $value = null, $attributes = ar\ ray()); echo Form::file($name, $attributes = array()); Onay Kutuları ve Seçenek Düğmeleri Bir Checkbox Veya Radio Inputu Üretilmesi 1 echo Form::checkbox('isim', 'deger'); 2 3 echo Form::radio('isim', 'deger'); Seçilmiş Bir Checkbox Veya Radio Inputu Üretilmesi 1 echo Form::checkbox('isim', 'deger', true); 2 3 echo Form::radio('isim', 'deger', true); File Inputu Bir File Inputu Üretilmesi 1 echo Form::file('resim'); Not: Bu form files opsiyonu true ayarlanmış olarak açılmış olmalıdır. 94 Formlar & HTML Aşağı Açılır Listeler Aşağı Açılır Bir Liste Üretilmesi 1 2 echo Form::select('boyut', array('B' => 'Büyük', 'K' =>\ 'Küçük')); Ön Tanımlı Seçilmiş Bir Aşağı Açılır Liste Üretilmesi 1 2 echo Form::select('size', array('B' => 'Büyük', 'K' => \ 'Küçük''), 'K'); Gruplanmış Bir Liste Üretilmesi 1 2 3 4 echo Form::select('hayvan', array( 'Kediler' => array('tekir' => 'Tekir'), 'Köpekler' => array('kangal' => 'Kangal'), )); Bir Aralık Olan Bir Aşağı Açılır Liste Üretilmesi 1 echo Form::selectRange('number', 10, 20); Ay İsimleri Olan Bir Liste Üretilmesi 1 echo Form::selectMonth('month'); Düğmeler Bir Submit Düğmesinin Üretilmesi 95 Formlar & HTML 1 echo Form::submit('Tıkla beni!'); Not: Bir button elemanı üretmeniz gerekiyorsa, button metodunu kullanın. Bu aynı submit gibi yazılır. Özel Makrolar Bir Form Makrosunun Kayda Geçirilmesi “Makrolar” denen kendi özel Form sınıf yardımcılarınızı tanımlamak kolaydır. Nasıl çalıştığını görün: Önce belli bir isim ve Closure fonksiyonu ile makroyu kayda geçirin: 1 2 3 4 Form::macro('makroAlan', function() { return '<input type ="awesome">'; }); Şimdi adını kullanarak makronuzu çağırabilirsiniz: Özel Bir Form Makrosunun Çağırılması 1 echo Form::makroAlan(); URL Oluşturma URL oluşturma ile ilgili detaylı bilgi için dokümantasyonun Yardımcı (Helper) Fonksiyonları¹⁴⁴ bölümüne bakınız. ¹⁴⁴helpers#urls Frameworkün Genişletilmesi Giriş Laravel, frameworkün çekirdek bileşenlerinin davranışlarını isteğinize göre özelleştirebilmeniz, hatta tümden değiştirebilmeniz için size birçok genişletme noktası sağlar. Örneğin, hash yapma araçları bir HasherInterface sözleşmesi ile sağlanmış olup, kendi uygulamanızın gereksinimlerine dayalı olarak implemente edebilirsiniz. Ayrıca, sizin kendi uygun “helper” metodlarınızı eklemenize imkan vermek üzere Request nesnesini de genişletebilirsiniz. Hatta tamamen yeni kimlik doğrulama, cache ve session sürücüleri bile ekleyebilirsiniz! Laravel bileşenleri genel olarak iki şekilde genişletilir: IoC konteynerinde yeni implementasyonlar bağlayarak veya bir ekstensiyonu “Factory” tasarım deseninin implementasyonları olan bir Manager sınıfı ile register ederek. Bu bölümde, frameworkün genişletilmesi için çeşitli yöntemleri keşfedeceğiz ve gerekli kodları inceleyeceğiz. Not: Aklınızda tutun, Laravel bileşenleri tipik olarak iki yoldan biriyle genişletilir: IoC bağlamaları ve Manager sınıfları. Manager sınıfları “factory” tasarım deseninin bir implementasyonu olarak hizmet eder ve cache ve session gibi sürücü temelli araçların başlatılmasından sorumludur. Frameworkün Genişletilmesi 97 Manager’lar & Factory’ler Laravel sürücü temelli bileşenlerin oluşturulmasını yöneten birkaç Manager sınıfıyla gelir. Bunlar cache, session, authentication ve queue bileşenleridir. Manager sınıfı, uygulamanın yapılandırmasına dayalı olarak belirli bir sürücü implementasyonunun oluşturulmasından sorumludur. Örneğin, CacheManager sınıfı APC, Memcached, Native ve diğer cache sürücü implementasyonlarını oluşturabilir. Bu managerlerin her birisinde, managere kolaylıkla yeni sürücü çözünürlük işlevselliği enjekte edilmesi için kullanılabilen bir extend metodu bulunmaktadır. Aşağıda, bu managerlerin her birini, onların her birine özel bir sürücü desteğinin nasıl enjekte edildiğinin örnekleriyle birlikte göreceğiz. Not: Laravel’le gelen CacheManager ve SessionManager gibi çeşitli Manager sınıflarını keşfetmek için biraz zaman ayırın. Bu sınıfların baştan sona okunması Laravel’in örtü altında nasıl çalıştığı konusunda size daha kapsamlı bir anlayış verecektir. Tüm manager sınıfları Illuminate\Support\Manager taban sınıfını genişletir, bu taban sınıf her manager için yararlı, ortak bazı işlevsellik sağlar. Genişletme Nereye Konacak Bu dokümantasyon çeşitli Laravel bileşenlerinin nasıl genişletileceğini anlatmaktadır, ancak genişletme kodunuzu nereye koyacağınızı merak ediyor olabilirsiniz. Diğer pek çok bootstrapping koduna benzer şekilde, bazı genişletmelerinizi start dosyalarınıza koyabilirsiniz. Cache ve Auth genişletmeleri bu yaklaşım için iyi adaylardır. Diğer genişletmeler, örneğin Session, bir servis sağla- 98 Frameworkün Genişletilmesi yıcısının register metoduna yerleştirilmelidir, çünkü bunlar istek yaşam döngüsünde çok başlarda gereklidirler. Cache Laravel cache aracını genişletmek için, CacheManagerdeki managera özel bir sürücü çözümleyicisi bağlamak için kullanılan ve tüm manager sınıfları çapında ortak olan extend metodunu kullanacağız. Örneğin, “mongo” adında yeni bir cache sürücüsü register etmek için, şöyle yapacağız: 1 2 3 4 Cache::extend('mongo', function($app) { // Illuminate\Cache\Repository olgusu döndür... }); extend metoduna geçilen ilk parametre sürücünün adıdır. Bu, sizin app/config/cache.php yapılandırma dosyanızdaki driver opsiyonuna tekabül edecektir. İkinci parametre bir Illuminate\Cache\Repository olgusu döndürmesi gereken bir Closure’dur. Bu Closure’a Illuminate\Foundation\A bir olgusu ve bir IoC konteyneri olan bir $app olgusu geçilecektir. Özel cache sürücümüzü oluşturmak için, öncelikle Illuminate\Cache\StoreInterfa sözleşmesini implemente etmemiz gerekiyor. Yani, bizim MongoDB cache implementasyonumuz şöyle bir şey olacaktır: 99 Frameworkün Genişletilmesi 1 2 class MongoStore implements Illuminate\Cache\StoreInter\ face { 3 public public public public public public public 4 5 6 7 8 9 10 function function function function function function function get($key) {} put($key, $value, $minutes) {} increment($key, $value = 1) {} decrement($key, $value = 1) {} forever($key, $value) {} forget($key) {} flush() {} 11 12 } Sadece bir MongoDB bağlantısı kullanarak bu metodların her birini implemente etmemiz gerekiyor. Implementasyonumuzu tamamladıktan sonra, özel sürücümüzün kaydını bitirebiliriz: 1 use Illuminate\Cache\Repository; 2 3 4 5 6 Cache::extend('mongo', function($app) { return new Repository(new MongoStore); }); Yukarıdaki örnekte görebileceğiniz gibi, özel cache sürücüleri oluştururken taban Illuminate\Cache\Repository sınıfını kullanabilirsiniz. Tipik olarak kendi repository sınıfınızı oluşturma zorunluğu söz konusu değildir. Özel cache sürücü kodunuzu nereye koyacağınızı merak ediyorsanız, onu Packagist’te bulundurmayı düşünün! Veya, uygulamanızın birincil klasörü içinde bir Extensions aduzayı oluşturabilirsiniz. Örneğin, uygulama Snappy adındaysa, cache ekstensiyonunu app/Snappy/Extensions/MongoStore.php içine koyabilirsiniz. Bununla birlikte, Laravel’in katı bir uygulama yapısına sahip olma- 100 Frameworkün Genişletilmesi dığını ve uygulamanızı sizin tercihlerinize göre organize etmekte özgür olduğunuzu aklınızda tutun. Not: Şayet kod parçalarınızı nereye koyacağınızı merak ediyorsanız, her zaman bir hizmet sağlayıcı düşünün. Daha önce tartıştığımız gibi, framework ekstensiyonlarını organize etmek için bir hizmet sağlayıcı kullanmak kodunuzu organize etmek için harika bir yoldur. Session Laravel’i özel bir session sürücüsü ile genişletmek, tıpkı cache sisteminin genişletilmesi kadar kolaydır. Aynı şekilde, özel kodumuzu register etmek için extend metodunu kullanacağız: 1 2 3 4 Session::extend('mongo', function($app) { // SessionHandlerInterface'in implementasyonunu döndür }); Session Genişletmesi Nereye Konacak Session genişletmelerinin Cache ve Auth benzeri diğer genişletmelerden farklı biçimde kayda geçirilmesi gerekir. Sessionlar istek yaşam döngüsünde çok erken dönemde başlatıldıkları için, bu uzantıların bir start dosyasında kayda geçirilmesi çok geç olacaktır. Bunun yerine bir servis sağlayıcısı¹⁴⁵ gerekli olacaktır. Session genişletme kodunuzu servis sağlayıcınızın register metoduna koymalısınız ve bu servis sağlayıcının adı providers yapılandırma dizisindeki default Illuminate\Session\SessionServiceProvider‘den altta konmalıdır. ¹⁴⁵/docs/ioc#service-providers 101 Frameworkün Genişletilmesi Session Genişletmesi Yazılması Dikkat ederseniz bizim özel session sürücümüz SessionHandlerInterfacei implemente edecektir. Bu interface PHP 5.4+ çekirdeğine dahil edilmiştir. Eğer siz PHP 5.3 kullanıyorsanız, ileriye yönelik uyumluluğa sahip olmanız için bu interface Laravel tarafından sizin için tanımlanmış olacaktır. Bu interface, implemente etmemiz gereken sadece birkaç basit metod içermektedir. Bir MongoDB implementation kalıbı şöyle bir şeydir: 1 class MongoHandler implements SessionHandlerInterface { 2 public public public public public public 3 4 5 6 7 8 function function function function function function open($savePath, $sessionName) {} close() {} read($sessionId) {} write($sessionId, $data) {} destroy($sessionId) {} gc($lifetime) {} 9 10 } Bu metodlar cache StoreInterface kadar kolay anlaşılabilir olmadıklarından, en iyisi bu metodların her birinin yaptıklarını kısaca keşfedelim: • open metodu tipik olarak dosya tabanlı oturum depolama sistemlerinde kullanılacaktır. Laravel oturumlar için PHP’nin natif dosya depolamasını kullanan native bir session sürücüsü ile geldiğinden, bu metoda neredeyse hiçbir şey koymanız gerekmeyecektir. Onu boş bir kalıp olarak bırakabilirsiniz. PHP’nin bizden bu metodu implemente etmemizi istemesi, gerçekte sadece kötü bir interface tasarımıdır (bunu ileride tartışacağız). • close metodu, open metoduna benzer şekilde genellikle gözardı edilebilir. Çoğu sürücü için, bu metod gerekli değildir. Frameworkün Genişletilmesi 102 • read metodu verilen bir $sessionId ile eşlik eden oturum verisinin string versiyonunu döndürecektir. Serileştirmeyi Laravel sizin yerinize yapacağı için, sürücünüzde oturum verisini elde ederken veya depolarken herhangi bir serileştirme veya başka kodlamalar yapmanıza gerek yoktur. • write metodu $sessionId ile eşlik eden belirli bir $data stringini MongoDB, Dynamo vb gibi kalıcı depo sistemlerine yazacaktır. • destroy metodu $sessionId ile eşlik eden veriyi kalıcı depodan kaldıracaktır. • gc metodu bir UNIX timestamp türünde verilen bir $lifetime süresinden daha eski tüm oturum verisini imha edecektir. Memcached ve Redis gibi süresi kendiliğinden dolan sistemler için bu metod boş bırakılabilir. SessionHandlerInterface implemente edildikten sonra, onu Ses- sion manager ile register etmeye hazırız: 1 2 3 4 Session::extend('mongo', function($app) { return new MongoHandler; }); Session sürücüsü kayda geçirildikten sonra app/config/session.php yapılandırma dosyamızda mongo sürücüsünü kullanabiliriz. Not: Unutmayın, özel bir session işleyici yazarsanız, onu Packagist’te paylaşın! Authentication Authentication (kimlik doğrulama) da cache ve session araçlarıyla aynı yolla genişletilebilir. Burada da yine aşina olduğumuz extend metodunu kullanacağız: 103 Frameworkün Genişletilmesi 1 2 3 4 5 Auth::extend('riak', function($app) { // Illuminate\Auth\UserProviderInterface'un implementa\ syonunu döndür }); Bu UserProviderInterface implementasyonlarının tek sorumluluğu MySQL, Riak vb gibi kalıcı bir depolama sisteminin bir UserInterface implementasyonunu getirmektir. Bu iki interface Laravel authentication mekanizmalarının kullanıcı verisinin nerede depolandığına veya onu temsil etmek için kullanılan sınıf tipine bakılmaksızın fonksiyon görmeye devam etmesini sağlar. UserProviderInterfacee bir göz atalım: 1 interface UserProviderInterface { 2 3 4 5 6 7 8 9 10 public function public function public function r, $token); public function ls); public function r, array $credentials); retrieveById($identifier); retrieveByToken($identifier, $token); updateRememberToken(UserInterface $use\ retrieveByCredentials(array $credentia\ validateCredentials(UserInterface $use\ 11 12 } retrieveById fonksiyonu tipik olarak kullanıcıyı temsil eden sayı- sal bir anahtar alır (örneğin bir MySQL veritabanındaki otomatik artan ID gibi). Metod tarafından, bu ID’e uyan UserInterface implementasyonu getirilecek ve döndürülecektir. retrieveByToken fonksiyonu bir kullanıcıyı onun benzersiz $identifier i ve bir remember_token alanında saklanan “remember me” $token Frameworkün Genişletilmesi 104 i ile elde eder. Önceki metodta olduğu gibi, bir UserInterface implementasyonu döndürmelidir. updateRememberToken metodu $user in remember_token alanını bu yeni $token ile günceller. Bu yeni token ya başarılı “remember me” login girişiminde atanan yepyeni bir token olabilir ya da kullanıcı log out yaptığı zaman bir null olabilir. retrieveByCredentials metodu bir uygulamaya giriş yapma girişiminde bulunulduğu zaman Auth::attempt metoduna geçilen kimlik bilgilerinden oluşan diziyi alır. Bu metod daha sonra bu kimlik bilgilerine uyan kullanıcıyı altta yatan kalıcı depolama sisteminden “sorgulamalıdır”. Tipik olarak, bu metod $credentails['username'] üzerine bir “where” koşulu olan bir sorgu çalıştıracaktır. Bu metod herhangi bir şifre doğrulaması veya authentication yapmaya kalkışmamalıdır. validateCredentials metodu kullanıcı kimliğini doğrulamak için verilen bir $user ile $credentialsi karşılaştırır. Örneğin, bu metod $user->getAuthPassword() stringini $credentials['password']in bir Hash::make hali ile karşılaştırabilir. Artık UserProviderInterface metodlarının her birini keşfettiğimize göre, bir de UserInterfacee göz atalım. Hatırlayınız, providerin retrieveById ve retrieveByCredentials metodları bu interface’in implementasyonlarını döndürecektir: 1 interface UserInterface { 2 public function getAuthIdentifier(); public function getAuthPassword(); 3 4 5 6 } Bu interface basittir. getAuthIdentifier metodu kullanıcının “birincil anahtarını” döndürmelidir. Bir MySQL back-endinde, bu yine otomatik artan birincil anahtar olacaktır. getAuthPassword Frameworkün Genişletilmesi 105 kullanıcının hash’lenmiş şifresini döndürmelidir. Bu interface, sizin kullandığınız ORM veya depolama soyutlama katmanı ne olursa olsun, authentication sisteminin herhangi bir User sınıfı ile çalışmasına imkan verir. Ön tanımlı olarak Laravel app/models klasörü içinde bu interface’i implemente eden bir User sınıfı bulundurur, bu yüzden bir implementasyon örneğini görmek için bu sınıfa başvurabilirsiniz. Son olarak, UserProviderInterface implemente edildikten sonra, genişletmemizi Auth facade’ı ile kayda geçirmeye hazırız: 1 2 3 4 Auth::extend('riak', function($app) { return new RiakUserProvider($app['riak.connection']); }); Sürücüyü extend metodu ile register ettikten sonra, app/config/auth.php yapılandırma dosyanızda yeni sürücüyü belirtin. IoC Temelli Genişletme Laravel frameworke dahil edilen hemen her hizmet sağlayıcı IoC konteynerine nesneler bağlar. Uygulamanızın hizmet sağlayıcılarının bir listesini app/config/app.php yapılandırma dosyasında bulabilirsiniz. Vaktiniz oldukça bu sağlayıcıların her birinin kaynak koduna baştan sona göz gezdiriniz. Bunu yapmakla, her bir sağlayıcının frameworke neler eklediğini çok daha iyi anlayacaksınız, bunun yanı sıra IoC konteynerine çeşitli hizmetleri bağlamak için hangi anahtarların kullanıldığını da öğreneceksiniz. Örneğin, HashServiceProvider IoC konteynerine bir hash anahtarı bağlar ve bu bir Illuminate\Hashing\BcryptHasher olgusuna çözümlenir. Siz kendi uygulamanız içinde bu sınıfı genişleletebilir ve bu IoC bağlamasını ezmek suretiyle bu sınıf yerine kendi genişletmenizi kullanabilirsiniz. Örneğin: Frameworkün Genişletilmesi 1 2 106 class SnappyHashProvider extends Illuminate\Hashing\Has\ hServiceProvider { 3 public function boot() { App::bindShared('hash', function() { return new Snappy\Hashing\ScryptHasher; }); 4 5 6 7 8 9 10 parent::boot(); 11 } 12 13 14 } Bu sınıfın default ServiceProvider sınıfını değil HashServiceProvider sınıfını genişlettiğine dikkat ediniz. Service providerinizi genişlettikten sonra, app/config/app.php yapılandırma dosyanızdaki HashServiceProvider yerine sizin genişletmiş olduğunuz sağlayıcının ismini koyun. Konteynerde bağlanan herhangi bir çekirdek sınıfın genişletilmesi için genel yöntem budur. Esasında, her çekirdek sınıf konteynerde bu tarzda bağlanır ve override edilebilir. Tekrar ifade edeyim, frameworkte yer alan hizmet sağlayıcılarının baştan sona okunması çeşitli sınıfların konteynerde nerede bağlandığı ve onu bağlamak için hangi anahtarın kullanıldığı konusunda sizi bilgilendirecektir. Laravelin nasıl biraraya getirildiğini daha çok öğrenmek için harika bir yoldur. Request Genişletmesi Request, frameworkün çok temel bir parçası olduğu ve istek döngüsünde çok erken başlatıldığı için, Request sınıfının genişletilmesi önceki örneklerden biraz farklı yapılır. Frameworkün Genişletilmesi 107 İlk olarak, sınıfı normaldeki gibi genişletin: 1 <?php namespace QuickBill\Extensions; 2 3 class Request extends \Illuminate\Http\Request { 4 // Burada özel, yararlı metodlar olacak... 5 6 7 } Sınıfı genişlettikten sonra, bootstrap/start.php dosyasını açın. Bu dosya, uygulamanıza yapılan her istekte en başta dahil edilen dosyalardan biridir. Dikkat ederseniz, bu dosyada yapılan ilk eylem Laravel’in $app olgusunun oluşturulmasıdır: 1 $app = new \Illuminate\Foundation\Application; Yeni bir application olgusu oluşturulduğu zaman, yeni bir Illuminate\Http\Request olgusu oluşturacak ve request anahtarını kullanarak onu IoC konteynerine bağlayacaktır. Bu yüzden, “default” istek tipi olarak kullanılması gereken özel bir sınıfı belirten bir yola ihtiyacımız var, değil mi? Ve, ne mutlu ki, application olgusundaki requestClass metodu tam bunu yapar! Yani, bootstrap/start.php dosyamızın en üstüne şu satırı ekleyebiliriz: 1 use Illuminate\Foundation\Application; 2 3 4 Application::requestClass('QuickBill\Extensions\Request\ '); Özel istek sınıfı belirtildikten sonra, Laravel bir Request olgusu oluşturduğu her zaman bu sınıfı kullanacaktır, böylece sizin özel request sınıfı olgunuzun, unit testlerde bile, her zaman kullanılabilir olmasına imkan verecektir! Geçerlilik Denetimi Temel Kullanım Laravel, Validation sınıfı aracığıyla verilerin geçerlilik denetimi ve geçerlilik hata mesajlarının gösterilmesi için temel ve kullanışlı bir araçla birlikte gelmektedir. Temel Bir Geçerlilik Denetimi Örneği 1 2 3 4 $gecerlilikYoklayici = Validator::make( array('isim' => 'Tuana Şeyma'), array('yas' => 'required|min:5') ); Buradaki make metoduna geçilen ilk parametre, geçerli olup olmadığına bakılacak veridir. İkinci parametre ise, bu veriye tatbik edilecek geçerlilik kurallarıdır. Kuralları Belirtmek İçin Dizi Kullanımı Birden çok kural ya bir “pipe” karakteri (|) ile ayrılır, ya da ayrı dizi elemanları olarak verilebilir. 1 2 3 4 $gecerlilikYoklayici = Validator::make( array('isim' => 'Tuana Şeyma'), array('yas' => array('required', 'min:5')) ); Birçok Alana Tek Seferde Geçerlilik Denetimi Yapmak Geçerlilik Denetimi 1 2 3 4 5 6 7 8 9 10 11 12 109 $validator = Validator::make( array( 'name' => 'Tuana Şeyma', 'password' => 'aksakşifre', 'email' => 'tuanaseyma@eldem.com' ), array( 'name' => 'required', 'password' => 'required|min:8', 'email' => 'required|email|unique' ) ); Bir Validator olgusu oluşturulduktan sonra, geçerlilik denetimi yapmak için fails veya passes metodları kullanılabilir. 1 2 3 4 if ($gecerlilikYoklayici->fails()) { // İlgili veri geçerlik denetimini geçememiştir } Şayet geçerlilik denetimi başarısız olursa, geçerlik yoklayıcısından hata mesajları alabilirsiniz: 1 $mesajlar = $gecerlilikYoklayici->messages(); Ayrıca, başarısız olan geçerlilik kurallarına bir dizi olarak da erişebilirsiniz. Bunu yapmak için failed metodunu kullanabilirsiniz: 1 $kalanlar = $gecerlilikYoklayici->failed(); Geçerlilik Denetimi 110 Dosyalar İçin Geçerlilik Denetimi Validator sınıfı dosyaların geçerliliği konusunda size, mimes ve benzeri kurallar sağlar. Dosyaları geçerlilikten geçirirken, tıpkı diğer verilerde olduğu gibi bunları da geçerlilik denetçisine parametre olarak geçersiniz. Hata Mesajlarıyla Çalışmak Bir Validator olgusunda messages metodunu çağırdıktan sonra, bir MessageBag olgusu alacaksınız. MessageBag sınıfında hata mesajlarıyla çalışmak için bir takım yararlı metodlar vardır. Bir Alan İçin İlk Hata Mesajının Elde Edilmesi 1 echo $mesajlar->first('email'); Bir Alan İçin Tüm Hata Mesajlarının Elde Edilmesi 1 2 3 4 foreach ($mesajlar->get('email') as $mesaj) { // } Tüm Alanlar İçin Tüm Hata Mesajlarının Elde Edilmesi 1 2 3 4 foreach ($mesajlar->all() as $mesaj) { // } Bir Alan İçin Hata Mevcut Olup Olmadığının Tespiti Geçerlilik Denetimi 1 2 3 4 111 if ($mesajlar->has('email')) { // } Bir Hata Mesajının Biçimlendirilmiş Olarak Alınması 1 echo $mesajlar->first('email', '<p>:message</p>'); Not: Ön tanımlı olarak, mesajlar Bootstrap’a uyumlu bir söz dizimiyle biçimlendirilir. Tüm Hata Mesajlarının Biçimlendirilmiş Olarak Alınması 1 2 3 4 foreach ($mesajlar->all('<li>:message</li>') as $mesaj) { // } Hata Mesajları & Görünümler Geçerlilik denetimi yaptıktan sonra aldığınız hata mesajlarını görünümlerinize gönderecek kolay bir yola ihtiyacınız olacak. Bu iş Laravel tarafından pratik bir şekilde halledilmektedir. Bir örnek olarak şu rotaları ele alalım: Geçerlilik Denetimi 1 2 3 4 112 Route::get('kayit', function() { return View::make('uye.kayit'); }); 5 6 7 8 Route::post('kayit', function() { $kurallar = array(...); 9 10 11 $gecerlilikYoklayici = Validator::make(Input::all(), $\ kurallar); 12 13 14 15 16 17 18 if ($gecerlilikYoklayici->fails()) { return Redirect::to('kayit')->withErrors($gecerlilikY\ oklayici); } }); Dikkat ederseniz, geçerlilik başarısız olduğunda, Validator olgusunu withErrors metodunu kullanarak Redirect’e geçiriyoruz. Bu metod, hata mesajlarını oturuma flaş tipinde aktaracak, yani bir sonraki isteğe kadar kullanılabilir olacaktır. Buna karşın, yine dikkat ederseniz GET rotamızda hata mesajlarını görünüme açık olarak bağlamak zorunda değiliz. Bunun nedeni, Laravel’in oturum verisinde hatalar olup olmadığını her zaman yoklaması ve olduğunu tespit etmesi halinde bunları otomatik olarak görünüme bağlamasıdır. Bu itibarla, her istekte tüm görünümleriniz için bir $errors değişkeni mevcut olacağını unutmayın, dolayısıyla siz $errors değişkeninin her zaman tanımlanmış olduğunu iç rahatı ile varsayıp, güvenle kullanabilirsiniz. Bu $errors değişkeni MessageBag sınıfından bir olgu olacaktır. Bu durumda, yeniden yön verme sonrasında, otomatikman bağlanan $errors değişkenini görünümlerinizde kullanabilirsiniz: 113 Geçerlilik Denetimi 1 <?php echo $errors->first('email'); ?> İsimli Hata Çantaları Eğer tek bir sayfa üzerinde birden çok formunuz varsa, hata MessageBag‘lerini isimlendirmek isteyebilirsiniz. Bu size belirli bir form için olan hata mesajlarını elde etme imkanı verecektir. Yapacağınız tek şey withErrors metoduna ikinci bir parametre olarak bir isim geçmektir: 1 2 return Redirect::to('register')->withErrors($validator,\ 'login'); Ondan sonra $errors değişkeninden isimli MessageBag olgusuna erişebilirsiniz: 1 <?php echo $errors->login->first('email'); ?> Mevcut Geçerlilik Kuralları Mevcut tüm geçerlilik kuralları ve bunların işlevleri aşağıda verilmiştir: • • • • • • • • • Accepted Active URL After (Date) Alpha Alpha Dash Alpha Numeric Array Before (Date) Between Geçerlilik Denetimi • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • Boolean Confirmed Date Date Format Different Digits Digits Between E-Mail Exists (Database) Image (File) In Integer IP Address Max MIME Types Min Not In Numeric Regular Expression Required Required If Required With Required With All Required Without Required Without All Same Size Timezone Unique (Database) URL 114 115 Geçerlilik Denetimi accepted Geçerlilik bakılan alan yes, on veya 1 olmalıdır. Bu, “Hizmet Şartlarının” kabul edildiğinin doğrulanmasında işe yarar. active_url Geçerlilik bakılan alan checkdnsrr PHP fonksiyonuna göre geçerli bir URL olmalıdır. after: tarih Geçerlilik bakılan alan verilen bir tarihten sonraki bir değer olmalıdır. Tarihler PHP strtotime fonksiyonuna geçirilecektir. alpha Geçerlilik bakılan alan tamamen alfabe harfleri olmalıdır. alpha_dash Geçerlilik bakılan alan alfa-numerik karakterler yanında tire ve alt tire de olabilir. alpha_num Geçerlilik bakılan alan tamamen alfa-numerik karakterler olmalıdır. array Geçerlili bakılan alan array tipinde olmalıdır. 116 Geçerlilik Denetimi before: tarih Geçerlilik bakılan alan verilen bir tarihten önceki bir değer olmalıdır. Tarihler PHP strtotime fonksiyonuna geçirilecektir. between: min, max Geçerlilik bakılan alan verilen min ile max arasında bir büyüklükte olmalıdır. Stringler, sayılar ve dosyalar size kuralıyla aynı tarzda değerlendirilir. confirmed Geçerlilik bakılan alana uyan eden bir falan_confirmation alanı olmalıdır. Örneğin, geçerlilik bakılan alan parola ise, inputta karşılık gelen bir parola_confirmation alanı olmalıdır. date Geçerlilik bakılan alan strtotime PHP fonksiyonua göre uygun bir tarih olmalıdır. date_format: format Geçerlilik bakılan alan date_parse_from_format PHP fonksiyona göre tanımlanmış bir format‘a uygun olmalıdır. different: alan Verilen alan, geçerlilik bakılan alandan farklı olmalıdır. digits: value Geçerlilik bakılan alan numerik olmalıdır ve tam value uzunluğunda olmalıdır. 117 Geçerlilik Denetimi digits_between:min,max Geçerlilik bakılan alan verilen min ile max arasında bir uzunlukta olmalıdır. boolean Geçerlilik bakılan alan bir boolean olarak çevrilebilmelidir. Kabul edilen girdiler true, false, 1, 0, "1" ve "0" dır. email Geçerlilik bakılan alan bir e-mail adresi şeklinde biçimlendirilmiş olmalıdır. exists: tablo, sütun Geçerlilik bakılan alan verilen bir veritabanı tablosunda mevcut olmalıdır. Exists Kuralının Basit Kullanım Şekli 1 'il' => 'exists:iller' Özel Bir Sütun İsminin Belirtilmesi 1 'il' => 'exists:iller,kisa_hali' Sorguya “where” cümleciği olarak eklenecek daha fazla şart da belirtebilirsiniz: 1 'email' => 'exists:personel,email,hesap_id,1' Bir “where” cümle parçası olarak NULL geçilmesi bir NULL veritabanı değeri yönünden kontrol ekleyecektir: 118 Geçerlilik Denetimi 1 'email' => 'exists:staff,email,deleted_at,NULL' image Geçerlilik bakılan alan bir görsel (jpeg, png, bmp veya gif) olmalıdır. in: falan, filan,… Geçerlilik bakılan alan verilen bir değerler listesinde olmalıdır. integer Geçerlilik bakılan alan bir tamsayı olmalıdır. ip Geçerlilik bakılan alan bir IP adresi olarak biçimlendirilmiş olmalıdır. max: deger Geçerlilik bakılan alan bir maksimum deger‘e eşit veya ondan az olmalıdır. Stringler, sayılar ve dosyalar size kuralıyla aynı tarzda değerlendirilir. mimes: falan, filan,… Geçerlilik bakılan alan listelenen uzantılardan birine tekabül eden bir MIME tipinde olmalıdır. MIME Kuralının Basit Kullanım Şekli 1 'resim' => 'mimes:jpeg,bmp,png' 119 Geçerlilik Denetimi min: deger Geçerlilik bakılan alan bir asgari deger‘den büyük olmalıdır. Stringler, sayılar ve dosyalar size kuralıyla aynı tarzda değerlendirilir. not_in: falan,filan,… Geçerlilik bakılan alan verilen değerler listesinde yer almamalıdır. numeric Geçerlilik bakılan alan sayısal bir değer olmalıdır. regex: desen Geçerlilik bakılan alan verilen düzenli ifadeye uygun olmalıdır. Not: regex deseni kullanırken, özellikle düzenli ifade bir pipe karakteri (|) içeriyorsa, kuralları belirtmek için pipe ayıracı kullanmak yerine bir dizide belirtmek gerekli olabilir. required Geçerlilik bakılan alan input verisinde bulunmak zorundadır. required_if: alan, deger Şayet alan alanı deger‘e eşit ise, geçerlilik bakılan alan girilmek zorundadır. required_with: falan, filan,… Geçerlilik bakılan alan, sadece belirtilen alanların bulunması durumunda bulunmak zorundadır. 120 Geçerlilik Denetimi required_with_all:foo,bar,… Geçerlilik bakılan alan, sadece belirtilen diğer alanların tümünün mevcut olması durumunda bulunmalıdır. required_without: falan, filan,… Geçerlilik bakılan alan, sadece diğer belirtilen alanlar olmadığı takdirde bulunmak zorundadır. required_without_all:foo,bar,… Geçerlilik bakılan alan, sadece belirtilen diğer alanların hiçbirinin mevcut olmaması durumunda bulunmalıdır. same: alan Verilen alan geçerlilik bakılan alanla aynı olmalıdır. size: deger Geçerlilik bakılan alan verilen deger‘le aynı büyüklükte olmalıdır. String veriler için, deger harf sayısı anlamına gelir. Numerik veriler için, deger verilen bir tamsayı değeridir. Dosyalar için, size kilobayt cinsinden dosya boyutuna karşılık gelir. timezone Geçerlilik bakılan alan timezone_identifiers_list PHP fonksiyonuna göre geçerli bir timezone tanımlayıcısı olmalıdır. unique: tablo, sütun, haric, idSütunu Geçerlilik bakılan alan verilen bir veritabanı tablosunda benzersiz olmalıdır. Eğer sütun seçeneği belirtilmemişse, geçerlilik bakılan alan aynı zamanda sütun adı olarak kabul edilecektir. 121 Geçerlilik Denetimi Unique Kuralının Basit Kullanım Şekli 1 'email' => 'unique:uyeler' Özel Bir Sütun Adının Belirtilmesi 1 'email' => 'unique:uyeler,email_adresi' Verilen Bir ID İçin Unique Kuralının Göz Ardı Edilmesi 1 'email' => 'unique:uyeler,email_adresi,10' Ek olarak Where Cümlecikleri Ekleme Bir sorguya “where” cümlecikleri ekler gibi daha fazla şart ekleyebilirsiniz: 1 2 'email' => 'unique:users,email_address,NULL,id,account_\ id,1' Yukarıdaki kuralda, sadece account_id‘si 1 olan satırlar unique yoklamasına dahil edilecektir. url Geçerlilik bakılan alan bir URL şeklinde biçimlendirilmiş olmalıdır. Not: Bu fonksiyon PHP’nin filter_var metodunu kullanır. Duruma Göre Kurallar Ekleme Bazı durumlarda, bir alanla ilgili geçerlilik denetimini yalnızca bu alan input dizisinde mevcut olduğu zaman çalıştırmak isteyebilirsiniz. Bunu hızla gerçekleştirmek için kural listenize sometimes ekleyiniz: Geçerlilik Denetimi 1 2 3 122 $v = Validator::make($data, array( 'email' => 'sometimes|required|email', )); Yukarıdaki örnekte email alanı sadece bu alan $data dizisinde mevcutsa geçerlilik denetiminden geçirilecektir. Karmaşık Şartlı Geçerlilik Denetimi Bazen belli bir alanın başka bir alan 100’den büyük bir değere sahip olduğunda gerekli olmasını isteyebilirsiniz. Bu geçerlilik kurallarının eklenmesi sorun oluşturmak zorunda değildir. Öncelikle, asla değişmeyecek statik kuralları nızın olduğu bir Validator olgusu oluşturun: 1 2 3 4 $v = Validator::make($data, array( 'email' => 'required|email', 'games' => 'required|numeric', )); Diyelim ki, game toplayıcıları için bir web uygulamamız var. Eğer bir game toplayıcısı uygulamamıza üye olursa ve onun 100’den fazla oyunu varsa, neden bu kadar çok oyunu olduğunu açıklamasını isteyelim. Örneğin, belki oyunları yeniden satan bir dükkanı vardır veya sadece toplamaktan hoşlanıyor olabilir. Bu gereksinimi, duruma göre eklemek için Validator olgusunda sometimes metodunu kullanabiliriz. 1 2 3 4 5 $v->sometimes('reason', 'required|max:500', function($i\ nput) { return $input->games >= 100; }); 123 Geçerlilik Denetimi Bu sometimes metoduna geçirilen ilk parametre duruma bağlı olarak geçerlilik denetiminden geçireceğimiz alanın adıdır. İkinci parametre ise, eklemek istedğimiz kurallardır. Üçüncü parametre olarak geçirilen Closure true döndürürse, ilgili kural eklenecektir. Bu metod, karmaşık şartlı geçerlilikler inşa edilmesini çok kolaylaştırır. Bir defada birden çok alan için şartlı geçerlilik eklemeniz de mümkündür: 1 2 3 4 5 $v->sometimes(array('reason', 'cost'), 'required', func\ tion($input) { return $input->games >= 100; }); Not: Closure‘a geçirilen $input parametresi Illuminate\Support\Fluent‘ın bir olgusu olacaktır ve input ve dosyalarınıza erişeceğiniz bir nesne olarak kullanılabilir. Özel Hata Mesajları Gerek duyduğunuzda, geçerlilik için ön tanımlı hata mesajları yerine özel hata mesajları kullanabilirsiniz. Özel mesaj belirtmek için birkaç yol var. Validator’e Özel Mesaj Geçilmesi 124 Geçerlilik Denetimi 1 2 3 $mesajlar = array( 'required' => ':attribute alanı gereklidir.', ); 4 5 6 $gecerlilikYoklayici = Validator::make($input, $kuralla\ r, $mesajlar); Not: Buradaki :attribute yer tutucusu geçerlilik bakılan alanın gerçek adıyla değiştirilecektir. Geçerlilik mesajlarınızda diğer yer tutucuları da kullanabilirsiniz. Diğer Geçerlilik Yer Tutucuları 1 2 3 4 5 6 7 8 $mesajlar = array( 'same' => 'size' => 'between' => dır.', 'in' => : :values', ); ':attribute ve :other aynı olmalıdır.', ':attribute tam olarak :size olmalıdır.', ':attribute :min ile :max arasında olmalı\ ':attribute şu tiplerden birisi olmalıdır\ Belli Bir Attribute İçin Özel Mesaj Belirlenmesi Bazen sadece belirli bir alan için özel hata mesajları belirlemek isteyebilirsiniz: 1 2 3 4 $mesajlar = array( 'email.required' => 'e-mail adresinizi bilmemiz gereki\ yor!', ); Geçerlilik Denetimi 125 Özel Mesajların Dil Dosyalarında Belirtilmesi Bazı durumlarda, özel hata mesajlarınızı doğrudan Validator‘e geçirmek yerine bir dil dosyasında belirtmek isteyebilirsiniz. Bunu yapmak için, mesajlarınızı app/lang/xx/validation.php dil dosyasındaki custom dizisine ekleyiniz. 1 2 3 4 5 'custom' => array( 'email' => array( 'required' => 'e-mail adresinizi bilmemiz gerekiyor!', ), ), Özel Geçerlilik Kuralları Özel Bir Geçerlilik Kuralını Kayda Geçirme Laravel’de her biri yararlı çok sayıda geçerlilik kuralı bulunmaktadır; bununla birlikte siz kendiniz de bazı kurallar belirlemek isteyebilirsiniz. Özel geçerlilik kuralı kayda geçirmenin bir yolu Validator::extend metodunu kullanmaktır: 1 2 3 4 5 Validator::extend('falan', function($attribute, $value,\ $parameters) { return $value === 'falan'; }); Özel bir geçerlilik anonim fonksiyonu (Closure) üç parametre alır: geçerlilik bakılacak $attribute‘ın adı, bu niteliğin $value‘i ve kurala geçilecek bir $parameters dizisi. Bu extend metoduna bir isimsiz fonksiyon yerine bir sınıf ve metod da geçebilirsiniz: Geçerlilik Denetimi 1 126 Validator::extend('falan', 'FalanValidator@validate'); Özel kurallarınız için aynı zamanda bir hata mesajı da tanımlamanız gerekeceğini unutmayın. Bunu, ya aynı satırda özel hata mesaj dizisi kullanarak ya da geçerlilik dil dosyasına bir giriş eklemek suretiyle yapabilirsiniz. Validator Sınıfının Genişletilmesi Validator’ü genişletmek için bir isimsiz fonksiyon çağrısı kullanmak yerine, Validator sınıfının kendisini de genişletebilirsiniz. Bunu yapmak için, Illuminate\Validation\Validator‘ü genişleten bir Validator sınıfı yazın. Validation metodlarınızı, başına validate getirerek bu sınıfa ekleyebilirsiniz: 1 <?php 2 3 4 class OzelValidator extends Illuminate\Validation\Valid\ ator { 5 6 7 8 9 10 public function validateFalan($attribute, $value, $par\ ameters) { return $value === 'falan'; } 11 12 } Özel Bir Validator Çözümleyicisinin Kayda Geçirilmesi Daha sonra, özel Validator uzantınızı kayda geçirmeniz gerekiyor: Geçerlilik Denetimi 1 2 3 4 5 6 127 Validator::resolver(function($translator, $data, $rules\ , $messages) { return new OzelValidator($translator, $data, $rules, $\ messages); }); Özel bir geçerlilik kuralı oluştururken, bazı durumlarda, hata mesajlarıyla değiştirilecek özel yer tutucular tanımlamanız gerekebilir. Bunu, aynen yukarıda tarif edildiği gibi özel bir Validator oluşturup, bu validatore bir replaceXXX fonksiyonu ekleyerek gerçekleştirebilirsiniz. 1 2 3 4 5 protected function replaceFalan($message, $attribute, $\ rule, $parameters) { return str_replace(':falan', $parameters[0], $message); } Şayet Validator sınıfını genişletmeksizin özel bir mesaj “değiştirici” eklemek isterseniz, Validator::replacer metodunu kullanabilirsiniz: 1 2 3 4 5 Validator::replacer('rule', function($message, $attribu\ te, $rule, $parameters) { // }); Güvenlik Yapılandırma Laravel, kimlik doğrulanması işlerini çok basit hale getirmeyi amaçlamaktadır. Aslında, hemen her şey hazır yapılandırılmış durumdadır. Kimlik doğrulaması yapılandırma dosyası app/config/auth.php yerleşiminde bulunmaktadır ve kimlik doğrulama araçlarının davranışlarına nasıl ince ayarlar yapılacağı üzerine iyi belgelenmiş çeşitli seçenekler barındırır. Ön tanımlı olarak, Laravel app/models dizininde bir User modeli içermektedir ve bu model ön tanımlı Eloquent kimlik doğrulama sürücüsü ile kullanıma hazırdır. Bu modelin şemasını oluştururken şifre alanının en az 60 karakter olmasını temin etmeniz gerektiğini unutmayın. Şayet sizin uygulamanız Eloquent kullanmıyorsa, Laravel sorgu oluşturucusunu kullanan database kimlik doğrulama sürücüsünü kullanabilirsiniz. Not: Başlamadan önce users (veya dengi olan) tablonuzun 100 karakterlik string tipinde nullable bir remember_token sütunu taşıdığından emin olun. Bu sütun, uygulamanız tarafından sürdürülecek olan “remember me (beni hatırla)” session’ları için bir token saklamak amacıyla kullanılacaktır. Bu, bir migrasyonda $table->rememberToken(); kullanılarak yapılabilir. 129 Güvenlik Şifrelerin Saklanması Laravel’deki Hash sınıfı güvenli Bcrypt karıştırması (hashing) sağlar: Bcrypt Kullanılarak Bir Şifrenin Karıştırılması 1 $parola = Hash::make('secret'); Bir Şifrenin Karıştırılmışa Göre Doğrulanması 1 2 3 4 if (Hash::check('secret', $karistirilmisParola)) { // Parola doğrulanmıştır... } Bir Şifrenin Yeniden Karıştırılması Gerekip Gerekmediğinin Yoklanması 1 2 3 4 if (Hash::needsRehash($karistirilmis)) { $karistirilmis = Hash::make('secret'); } Kullanıcı Kimliklerinin Doğrulanması Bir kullanıcının uygulamanıza girişi için Auth::attempt metodunu kullanabilirsiniz. Güvenlik 1 2 3 4 5 130 if (Auth::attempt(array('email' => $email, 'password' =\ > $parola))) { return Redirect::intended('pano'); } Buradaki email‘in gerekli bir seçenek değil, sadece örnek olsun diye kullanılmış olduğunu bilin. Veritabanınızda bir “kullanıcı adı”na (“username”e) karşılık gelen sütunu kullanmanız gerekiyor. Redirect::intended fonksiyonu, kullanıcıları kimlik doğrulama filtresi tarafından yakalanmadan önce erişmeye çalıştıkları URL’ye yönlendirecektir. Kullanıcının önceden girmeye çalıştığı bir url olmayan durumlarda kullanılabilsin diye bu metoda bir dönüş URI parametresi verilebilir. attempt metodu çağrıldığında, auth.attempt olayı¹⁴⁶ ateşlenecektir. Şayet kimlik doğrulama girişimi başarılı olur ve kullanıcı giriş yapmış olursa, auth.login olayı da ateşlenecektir. Bir Kullanıcının Doğrulanmış Olup Olmadığının Tayin Edilmesi Bir kullanıcının uygulamanıza zaten giriş yapmış olduğunu tayin etmek için check metodunu kullanabilirsiniz: 1 2 3 4 if (Auth::check()) { // Kullanıcı giriş yapmıştır... } Bir Kullanıcının Kimliğinin Doğrulanması ve “Hatırlanması” Şayet uygulamanıza “beni hatırla” işlevselliği vermek istiyorsanız, attempt metoduna ikinci parametre olarak true geçebilirsiniz, ¹⁴⁶/docs/events Güvenlik 131 böylece bu kullanıcı süresiz olarak “doğrulanmış” tutulacaktır (ya da manuel olarak çıkış işlemi yapıncaya kadar). Tabi ki, users tablonuz “remember me” tokenini saklamakta kullanılacak olan string remember_token sütunu içermelidir. 1 2 3 4 5 if (Auth::attempt(array('email' => $email, 'password' =\ > $parola), true)) { // Bu kullanıcı hatırlanacak... } Not: attempt metodu true döndürürse, kullanıcı uygulamanıza girmiş kabul edilir. Kullanıcının Remember Aracılığıyla mı Doğrulanmış Olduğunun Tayin Edilmesi Eğer kullanıcı girişlerini “hatırlıyorsanız”, bir kullanıcının “remember me” (beni hatırla) çerezi kullanılarak doğrulanmış olup olmadığını belirlemek için viaRemember metodunu kullanabilirsiniz: 1 2 3 4 if (Auth::viaRemember()) { // } Bir Kullanıcının Ek Şartlara Göre Doğrulanması Kimlik doğrulama sorgusuna ekstra şartlar da ekleyebilirsiniz: 132 Güvenlik 1 2 3 4 5 6 if (Auth::attempt(array('email' => $email, 'password' =\ > $parola, 'aktif' => 1))) { // Bu kullanıcı aktiftir, üyeliği askıya alınmış de\ ğildir ve mevcuttur. } Not: Oturum sabitlemesine karşı koruma amacıyla, kimlik doğrulaması sonrasında kullanıcının oturum ID’si otomatik olarak yeniden üretilecektir. Login Yapmış Kullanıcıya Erişme Bir kullanıcının kimliği doğrulandıktan sonra, bu kullanıcının modeline / kaydına ulaşabilirsiniz: 1 $email = Auth::user()->email; Kimliği doğrulanmış bir kullanıcının ID’sini elde etmek için id metodunu kullanabilirsiniz: 1 $id = Auth::id(); Bir kullanıcıyı sadece ID’si ile uygulamanıza giriş yaptırtmak için loginUsingId metodunu kullanın: 1 Auth::loginUsingId(1); Login Olmaksızın Kullanıcı Bilgilerinin Geçerlilik Denetimi validate metodu gerçekte uygulamaya giriş yapılmaksızın bir kul- lanıcının kimlik bilgilerinin geçerlilik denetiminden geçirilmesine imkan verir: 133 Güvenlik 1 2 3 4 if (Auth::validate($kimlikbilgileri)) { // } Bir Kullanıca Tek Bir İstek İçin Giriş Yapma Bir kullanıcıyı uygulamanıza tek bir istek için giriş yapmak için de once metodunu kullanabilirsiniz. Bu durumda oturum veya çerezler kullanılmayacaktır. 1 2 3 4 if (Auth::once($kimlikbilgileri)) { // } Bir Kullanıcıya Uygulamadan Çıkış Yapma 1 Auth::logout(); Elle Kullanıcı Girişi Şayet, mevcut bir kullanıcı olgusunu uygulamanıza giriş yaptırmak istiyorsanız, bu olguda login metodunu çağırmanız yeterlidir: 1 $uye = Uye::find(1); 2 3 Auth::login($uye); Bu metod, bir kullanıcıyı attempt metodu kullanarak kimlik bilgileri ile giriş yaptırmaya eşdeğerdir. 134 Güvenlik Rotaların Korunması Belli bir rotaya sadece kimliği doğrulanmış kullanıcıların erişebilmesini sağlamak amacıyla rota filtreleri kullanılabilir. Laravel ön tanımlı olarak auth filtresi sağlamıştır ve app/filters.php içinde tanımlanmıştır. Bir Rotanın Korunması 1 2 3 4 5 Route::get('profil', array('before' => 'auth', function\ () { // Sadece kimliği doğrulanmış üyeler girebilir... })); CSRF Koruması Laravel, uygulamanızı siteler arası istek sahtekarlıklarından (crosssite request forgeries [CSRF]) korumak için kolay bir metod sağlamaktadır. Forma CSRF Jetonunun Eklenmesi 1 2 <input type="hidden" name="_token" value="<?php echo cs\ rf_token(); ?>"> Gönderilmiş CSRF Jetonunun Geçerlilik Yoklaması 135 Güvenlik 1 2 3 4 5 Route::post('register', array('before' => 'csrf', funct\ ion() { return 'Geçerli bir CSRF jetonu verdiniz!'; })); HTTP Basic Kimlik Doğrulaması HTTP Basic Kimlik Doğrulaması, kullanıcıları özel bir “giriş” sayfası açmadan uygulamanıza giriş yapabilmeleri için hızlı bir yoldur. Bunun için, rotanıza auth.basic filtresi tutturun: HTTP Basic İle Bir Rotanın Korunması 1 2 3 4 5 Route::get('profil', array('before' => 'auth.basic', fu\ nction() { // Sadece kimliği doğrulanmış üyeler girebilir... })); Ön tanımlı olarak, bu basic filtresi kimlik doğrulaması yaparken kullanıcı kaydındaki email sütununu kullanacaktır. Siz başka bir sütunu kullanmak istiyorsanız, basic metoduna birinci parametre olarak bu sütunun adını geçirin: 1 2 3 4 Route::filter('auth.basic', function() { return Auth::basic('username'); }); Durum Bilgisi Olmaksızın Bir HTTP Basic Filtresi Ayarlanması HTTP Basic Kimlik Doğrulamasını oturumda kullanıcı tanıtıcı bir çerez ayarlamadan da kullanabilirsiniz, bu daha çok API kimlik 136 Güvenlik doğrulamalarında işe yarayacaktır. Bunu yapmak için, onceBasic metodu döndüren bir filtre tanımlayın: 1 2 3 4 Route::filter('basic.once', function() { return Auth::onceBasic(); }); Eğer PHP FastCGI kullanıyorsanız, HTTP Basic kimlik doğrulaması ön tanımlı durumda düzgün çalışmayacaktır. Aşağıdaki satırlar .htaccess dosyanıza eklenmelidir: 1 2 3 RewriteCond %{HTTP:Authorization} ^(.+)$ RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authoriza\ tion}] Şifre Hatırlatıcıları & Yenileme Model & Table Çoğu web uygulaması, kullanıcılarına unutulmuş şifrelerini yenileyecek bir yol verir. Her uygulamada bunu tekrar tekrar yapmaya zorlamak yerine Laravel size şifre hatırlatıcı mektup gönderme ve şifre yenilemesi yapılması için pratik metodlar sağlar. Başlamak için sizin User modelinizin Illuminate\Auth\Reminders\RemindableInterface sözleşmesini yerine getirdiğini doğrulayın. Tabii ki, Laravel’le gelen User modeli bu arayüz kontratını zaten yerine getirmektedir ve bu interface’i implemente etmek için gerekli metodları içermek için Illuminate\Auth\Reminders\RemindableTrait trait’ini kullanmaktadır. RemindableInterface Implementasyonu 137 Güvenlik 1 2 use Illuminate\Auth\Reminders\RemindableTrait; use Illuminate\Auth\Reminders\RemindableInterface; 3 4 5 class User extends Eloquent implements RemindableInterf\ ace { 6 use RemindableTrait; 7 8 9 } Hatırlatıcı Tablo Migrasyonunun Üretilmesi Daha sonra, şifre yenileme jetonlarının saklanacağı bir tablo oluşturulmalıdır. Bu tablo için bir migrasyon üretmek için yapacağınız tek şey auth:reminders-table Artisan komutunu çalıştırmaktır: 1 php artisan auth:reminders-table 2 3 php artisan migrate Şifre Hatırlatıcı Controller Artık şifre hatırlatıcı controller üretmeye geçebiliriz. Bir controlleri otomatik olarak üretmek için, auth:reminders-controller Artisan komutunu kullanabilirsiniz, bu komut sizin app/controllers dizininizde bir RemindersController.php dosyası oluşturacaktır. 1 php artisan auth:reminders-controller Üretilen controllerde şifre hatırlatıcı formunuzu gösterilmesini halleden bir getRemind metodu olacaktır. Sizin yapmanız gereken tek şey bir password.remind viewi¹⁴⁷ oluşturmaktır. Bu view, bir email ¹⁴⁷/docs/responses#views Güvenlik 138 alanı olan basit bir form olmalıdır. Bu form RemindersController@postRemind metoduna POST edilmelidir. password.remind view’inde basit bir form bunun gibi olabilir: 1 2 3 4 5 <form action ="{{ action('RemindersController@postRemind\ ') }}" method ="POST"> <input type ="email" name ="email"> <input type ="submit" value ="Hatırlatıcı Gönder"> </form> Üretilen controllerde getRemind metoduna ek olarak kullacılarınıza şifre hatırlatıcı e-postalar gönderilmesini halleden bir postRemind metodu da olacaktır. Bu metod POST değişkenlerinde bir email alanı mevcut olmasını bekler. Eğer bir hatırlatıcı e-postası kullanıcıya başarıyla gönderilirse, oturuma bir status mesajı flaşlanacaktır. Eğer hatırlatıcı yapılamazsa o zaman bunun yerine bir error mesajı flaşlanacaktır. Bu postRemind controller metodu içerisinde, kullanıcıya göndermeden önce mesaj olgusu üzerinde değişiklik yapabilirsiniz: 1 2 3 4 5 Password::remind(Input::only('email'), function($messag\ e) { $message->subject('Şifre Hatırlatıcı'); }); Kullanıcınız, controllerin getReset metodunu işaret eden bir bağlantısı olan bir e-posta alacaktır. Ayrıca, ilgili bir şifre hatırlatıcı girişimini tanımlamakta kullanılan bir şifre hatırlatıcı tokeni bu controller metoduna geçilecektir. Bu controller metodu bir password.reset view’i döndürecek şekilde zaten yapılandırılmıştır, ancak bu view’i sizin oluşturmanız gerekiyor. İlgili token view’e geçilecektir ve siz bu tokeni token adlı “hidden” bir form 139 Güvenlik alanına koymanız gerekiyor. Sizin şifre reset (yenileme) formunuz bu token‘e ek olarak email, password ve password_confirmation alanlarını da içermelidir. Bu form RemindersController@postReset metoduna post edilmelidir. password.reset view’indeki basit bir form şöyle bir şey olabilir: 1 2 3 4 5 6 7 8 <form action ="{{ action('RemindersController@postReset'\ ) }}" method ="POST"> <input type ="hidden" name ="token" value ="{{ $token }}"> <input type ="email" name ="email"> <input type ="password" name ="password"> <input type ="password" name ="password_confirmation"> <input type ="submit" value ="Şifreyi Yenile"> </form> Son olarak, veritabanındaki şifrenizin gerçekten değiştirilmesinden bu postReset metodu sorumludur. Bu controller eyleminde, Password::reset metoduna geçilen Closure, User‘in password niteliğini ayarlar ve save metodunu çağırır. Pek tabii, bu Closure sizin User modelinizin bir Eloquent modeli¹⁴⁸ olmasını beklemektedir; bununla birlikte siz bu Closure üzerinde uygulamanızın veritabanı depolama sistemiyle uyumlu olması için gerekli değişiklikler yapmakta özgürsünüz. Eğer şifre başarılı bir biçimde yenilenirse, kullanıcı uygulamanızın köküne yönlendirilecektir. Aynı şekilde, siz bu redirect URL’sini de değiştirme serbestisine sahipsiniz. Eğer şifre yenileme başarısız olursa, kullanıcı tekrar reset formuna yönlendirilecektir ve session’a bir error mesajı flaşlanacaktır. Şifre Geçerlilik Denetimi Ön tanımlı olarak, Password::reset metodu şifrelerin eşleşiyor ve >= altı karakter olmasını soruşturacaktır. Siz, parametre olarak ¹⁴⁸/docs/eloquent 140 Güvenlik bir Closure alan Password::validator metodunu kullanarak bu kuralları özelleştirebilirsiniz. Bu Closure içerisinde, istediğiniz her türlü şifre geçerlilik denetimini yapabilirsiniz. Şuna dikkat ediniz: şifrelerin eşleşiyor olduğunu doğrulamanız gerekmiyor, çünkü bu kısım framework tarafından otomatik olarak yapılacaktır. 1 2 3 4 Password::validator(function($credentials) { return strlen($credentials['password']) >= 8; }); Not: Ön tanımlı olarak, şifre yenileme tokenlerinin ömrü bir saat sonra sona erer. Siz app/config/auth.php dosyanızın reminder.expire seçeneği aracılığıyla bunu değiştirebilirsiniz. Kriptolama Laravel, mcrypt PHP uzantısı aracılığıyla güçlü AES kriptolama imkanı sağlamaktadır: Bir Değerin Kriptolanması 1 $kriptolu = Crypt::encrypt('secret'); Not: app/config/app.php dosyasının key seçeneğinde 16, 24 veya 32 karakterli rastgele bir string ayarladığınızdan emin olun. Aksi takdirde kriptolanmış değerler güvenli olmayacaktır. Kriptolu Bir Değerin Çözülmesi 141 Güvenlik 1 $cozuk = Crypt::decrypt($kriptolu); Cipher ve Mod Ayarlanması Ayrıca, kriptocu tarafından kullanılan cipher ve mod da ayarlayabilirsiniz 1 Crypt::setMode('crt'); 2 3 Crypt::setCipher($cipher); Kimlik Doğrulama Sürücüleri Laravel kutusunda database ve eloquent kimlik doğrulama sürücüleriyle gelir. Diğer kimlik doğrulama sürücüleri eklenmesiyle ilgili daha fazla bilgi için Authentication genişletme dokümantasyonu¹⁴⁹ kesimini kontrol ediniz. ¹⁴⁹/docs/extending#authentication IoC Konteyneri Giriş Laravel’in “inversion of control (kontrolün tersine çevrilmesi)” konteyneri, sınıf bağımlılıklarının yönetiminde güçlü bir araçtır. Bağımlılık enjeksiyonu ağır kodlanmış sınıf bağımlılıklarının kaldırılması için bir yöntemdir. Bunun yerine, bağımlılıklar çalışma zamanında enjekte edilmekte, bağımlılık işlemleri kolayca takas edilebildiği için daha büyük esneklik sağlamaktadır. Laravel IoC konteyner’inin anlaşılması hem güçlü, büyük bir uygulama oluşturmak için hem de Laravel’in kendi çekirdeğine katkıda bulunmak için esastır. Temel Kullanım Bir Tipin Konteynere Bağlanması IoC konteyneri bağımlılıkları iki yolla çözebilmektedir: ya Closure geri çağrıları yoluyla ya da otomatik çözülüm yoluyla. Önce Closure geri çağrılarını ele alalım. Birincisi, bir “tip”, konteynere bağlanabilir: 1 2 3 4 App::bind('falan', function($app) { return new FalanFilan; }); Bir Tipin Konteynerden Çözümlenmesi IoC Konteyneri 1 143 $deger = App::make('falan'); App::make metodu çağrıldığı zaman, ilgili Closure callback’i çalış- tırılacak ve sonuç döndürülecektir. Konteynere “Paylaşılan” Bir Tip Bağlama Bazen, konteyner içine sadece bir kez çözümlenmesi ve konteynere sonraki çağrılarda aynı olgunun döndürülmesi gereken bir şeyler bağlamak isteyebilirsiniz: 1 2 3 4 App::singleton('falan', function() { return new FalanFilan; }); Mevcut Bir Olgunun Konteynere Bağlanması instance metodunu kullanarak, konteynere mevcut bir nesne olgu- sunu da bağlayabilirsiniz: 1 $falan = new Falan; 2 3 App::instance('falan', $falan); Bağlamaların Kayda Geçirileceği Yer IoC bağlamaları tıpkı olay işleyiciler ve rota filtreleri gibi genelde “bootstrap (önce yüklenmesi gereken) kodu” başlığı altına düşer. Başka bir deyişle, bunlar uygulamanızı istekleri gerçekten işlemeye hazırlarlar ve genel olarak bunların bir rota veya controller gerçekten çağrılmadan önce çalıştırılması gereklidir. Diğer çoğu bootstrap koduna benzer olarak, IoC bağlamalarının kayda geçirilmesi için 144 IoC Konteyneri bir seçenek her zaman olduğu gibi start dosyalarıdır. Alternatif olarak, bir app/ioc.php (dosya adının ne olduğu önemli değildir) dosyası oluşturabilir ve bu dosyayı start dosyanızdan “require” yapabilirsiniz. Eğer uygulamanızda çok büyük bir sayıda IoC bağlaması varsa veya siz basitçe IoC bağlamalarınızı kategorilere göre ayrı dosyalarda organize etmek istiyorsanız, bağlamalarınızı bir servis sağlayıcısında kayda geçirebilirsiniz. Otomatik Çözümleme Bir Sınıfın Çözümlenmesi IoC konteyneri birçok durumda hiçbir yapılandırmaya gerek kalmadan sınıfları çözümleyecek kadar güçlüdür. Örneğin: 1 class FalanFilan { 2 public function __construct(Baz $baz) { $this->baz = $baz; } 3 4 5 6 7 8 } 9 10 $falanFilan = App::make('FalanFilan'); Dikkat ederseniz, FalanFilan sınıfını konteynerde kayıt etmemiş olsak bile konteyner bu sınıfı hala çözümleyecek, hatta Baz bağımlılığını otomatik olarak enjekte edebilecektir! Bir tip konteynerde bağlı olmadığı durumlarda, sınıfı görmek ve sınıf yapıcısının tip dayatmalarını okumak için PHP’nin Reflection 145 IoC Konteyneri araçlarını kullanacaktır. Konteyner bu bilgiyi kullanmak suretiyle sınıfın bir olgusunu otomatik olarak inşa edecektir. Bir Implementasyona Bir Interface Bağlanması Buna karşın, bazı durumlarda, bir sınıf “somut tipte” olmayıp, arayüz tatbikatına (implementasyonuna) bağımlı olabilir. Böyle olduğu takdirde, hangi arayüz tatbikatının enjekte edileceği konusunda konteyneri bilgilendirmek için App::bind metodu kullanılmalıdır: 1 App::bind('UyeRepositoryInterface', 'DbUyeRepository'); Şimdi şu denetçiyi ele alalım: 1 class UyeController extends BaseController { 2 public function __construct(UyeRepositoryInterface $uy\ 3 4 eler) { 5 $this->uyeler = $uyeler; 6 } 7 8 9 } Biz UyeRepositoryInterface‘i somut bir tipe bağlamış olduğumuz için, UyeController oluşturulduğu zaman DbUserRepository otomatik olarak bu controllere enjekte edilecektir. Pratik Kullanım Laravel uygulamanızın esneklik ve test edilebilirliğini artırmak amacıyla IoC konteyneri kullanmak için çeşitli fırsatlar sağlar. En başta gelen örnek, denetçilerin çözümlenmesidir. Bütün denetçiler 146 IoC Konteyneri IoC konteyneri tarafından çözümlenir, yani bir kontroller sınıfının yapıcı metodunda tip dayatmalı bağımlılıklar verebilirsiniz ve bunlar otomatik olarak enjekte edilecektir. Tip Dayatmalı Controller Bağımlılıkları 1 class SiparisController extends BaseController { 2 public function __construct(SiparisRepository $siparis\ 3 4 ler) { 5 $this->siparisler = $siparisler; 6 } 7 8 public function getIndex() { $all = $this->siparisler->all(); 9 10 11 12 return View::make('siparisler', compact('all')); 13 } 14 15 16 } Bu örnekteki SiparisRepository sınıfı kontroller’e otomatik olarak enjekte edilecektir. Bu şu anlama gelir: unit testi¹⁵⁰ sırasında “sahte” bir SiparisRepository konteynere bağlanabilir ve denetçiye enjekte edilebilir, böylece sorunsuz bir veritabanı katmanı etkileşimi mümkün olur. ¹⁵⁰/docs/testing 147 IoC Konteyneri Diğer IoC Kullanım Örnekleri Filtreler¹⁵¹, kompozitörler¹⁵² ve olay işleyicileri¹⁵³ de IoC konteynerinde çözülebilirler. Bunları kayda geçirdiğiniz zaman, sadece kullanılması gereken sınıfın adını vermeniz yeterlidir: 1 Route::filter('falan', 'FalanFilter'); 2 3 View::composer('falan', 'FalanComposer'); 4 5 Event::listen('falan', 'FalanHandler'); Hizmet Sağlayıcıları Hizmet Sağlayıcıları birbirine yakın IoC kayıtlarını tek bir yerleşimde gruplamak için harika bir yoldur. Bunları uygulamanızdaki bileşenleri önceden yüklemenin bir yolu olarak düşünün. Bir hizmet sağlayıcısının içinde özel kimlik doğrulama sürücünüzü kayda geçirebilir, uygulamanızın ambar sınıflarını IoC konteyneri ile kayda geçirebilir, hatta özel bir Artisan komutu dahi kurabilirsiniz. Aslında, çekirdek Laravel bileşenlerinin pek çoğu hizmet sağlayıcıları içermektedir. Uygulamanızdaki kayıtlı hizmet sağlayıcılarının hepsi, app/config/app.php yapılandırma dosyasının providers dizisinde listelenmektedir. Bir Hizmet Sağlayıcı Tanımlanması Bir hizmet sağlayıcı oluşturmak için, sadece Illuminate\Support\ServiceProvider sınıfını genişletin ve bir register metodu tanımlayın: ¹⁵¹/docs/routing#route-filters ¹⁵²/docs/responses#view-composers ¹⁵³/docs/events#using-classes-as-listeners 148 IoC Konteyneri 1 use Illuminate\Support\ServiceProvider; 2 3 class FalanServiceProvider extends ServiceProvider { 4 public function register() { $this->app->bind('falan', function() { return new Falan; }); } 5 6 7 8 9 10 11 12 13 } Bu register metodunda, uygulama IoC konteynerinin $this->app özelliği aracılığıyla kullanılabildiğini unutmayın. Bir sağlayıcı oluşturdunuz ve uygulamanızla kayda geçirmeye hazırsanız, yapmanız gereken şey onu app yapılandırma dosyanızdaki providers dizisine eklemektir. Bir Hizmet Sağlayıcının Çalışma Zamanında Kayda Geçirilmesi Bir hizmet sağlayıcıyı App::register metodunu kullanarak çalışma zamanında da kayda geçirebilirsiniz: 1 App::register('FalanServiceProvider'); Konteyner Olayları Bir Resolving Dinleyicisinin Kayda Geçirilmesi Konteyner ne zaman bir nesne çüzümlese bir olay ateşler. resolving metodunu kullanarak bu olayı dinleyebilirsiniz: IoC Konteyneri 1 2 3 4 App::resolvingAny(function($object) { // }); 5 6 7 8 9 App::resolving('falan', function($falan) { // }); Çözülen nesnenin geri çağrıya geçirileceğini unutmayın. 149 Güvenlik Yapılandırma Laravel, kimlik doğrulanması işlerini çok basit hale getirmeyi amaçlamaktadır. Aslında, hemen her şey hazır yapılandırılmış durumdadır. Kimlik doğrulaması yapılandırma dosyası app/config/auth.php yerleşiminde bulunmaktadır ve kimlik doğrulama araçlarının davranışlarına nasıl ince ayarlar yapılacağı üzerine iyi belgelenmiş çeşitli seçenekler barındırır. Ön tanımlı olarak, Laravel app/models dizininde bir User modeli içermektedir ve bu model ön tanımlı Eloquent kimlik doğrulama sürücüsü ile kullanıma hazırdır. Bu modelin şemasını oluştururken şifre alanının en az 60 karakter olmasını temin etmeniz gerektiğini unutmayın. Şayet sizin uygulamanız Eloquent kullanmıyorsa, Laravel sorgu oluşturucusunu kullanan database kimlik doğrulama sürücüsünü kullanabilirsiniz. Not: Başlamadan önce users (veya dengi olan) tablonuzun 100 karakterlik string tipinde nullable bir remember_token sütunu taşıdığından emin olun. Bu sütun, uygulamanız tarafından sürdürülecek olan “remember me (beni hatırla)” session’ları için bir token saklamak amacıyla kullanılacaktır. Bu, bir migrasyonda $table->rememberToken(); kullanılarak yapılabilir. 151 Güvenlik Şifrelerin Saklanması Laravel’deki Hash sınıfı güvenli Bcrypt karıştırması (hashing) sağlar: Bcrypt Kullanılarak Bir Şifrenin Karıştırılması 1 $parola = Hash::make('secret'); Bir Şifrenin Karıştırılmışa Göre Doğrulanması 1 2 3 4 if (Hash::check('secret', $karistirilmisParola)) { // Parola doğrulanmıştır... } Bir Şifrenin Yeniden Karıştırılması Gerekip Gerekmediğinin Yoklanması 1 2 3 4 if (Hash::needsRehash($karistirilmis)) { $karistirilmis = Hash::make('secret'); } Kullanıcı Kimliklerinin Doğrulanması Bir kullanıcının uygulamanıza girişi için Auth::attempt metodunu kullanabilirsiniz. Güvenlik 1 2 3 4 5 152 if (Auth::attempt(array('email' => $email, 'password' =\ > $parola))) { return Redirect::intended('pano'); } Buradaki email‘in gerekli bir seçenek değil, sadece örnek olsun diye kullanılmış olduğunu bilin. Veritabanınızda bir “kullanıcı adı”na (“username”e) karşılık gelen sütunu kullanmanız gerekiyor. Redirect::intended fonksiyonu, kullanıcıları kimlik doğrulama filtresi tarafından yakalanmadan önce erişmeye çalıştıkları URL’ye yönlendirecektir. Kullanıcının önceden girmeye çalıştığı bir url olmayan durumlarda kullanılabilsin diye bu metoda bir dönüş URI parametresi verilebilir. attempt metodu çağrıldığında, auth.attempt olayı¹⁵⁴ ateşlenecektir. Şayet kimlik doğrulama girişimi başarılı olur ve kullanıcı giriş yapmış olursa, auth.login olayı da ateşlenecektir. Bir Kullanıcının Doğrulanmış Olup Olmadığının Tayin Edilmesi Bir kullanıcının uygulamanıza zaten giriş yapmış olduğunu tayin etmek için check metodunu kullanabilirsiniz: 1 2 3 4 if (Auth::check()) { // Kullanıcı giriş yapmıştır... } Bir Kullanıcının Kimliğinin Doğrulanması ve “Hatırlanması” Şayet uygulamanıza “beni hatırla” işlevselliği vermek istiyorsanız, attempt metoduna ikinci parametre olarak true geçebilirsiniz, ¹⁵⁴/docs/events Güvenlik 153 böylece bu kullanıcı süresiz olarak “doğrulanmış” tutulacaktır (ya da manuel olarak çıkış işlemi yapıncaya kadar). Tabi ki, users tablonuz “remember me” tokenini saklamakta kullanılacak olan string remember_token sütunu içermelidir. 1 2 3 4 5 if (Auth::attempt(array('email' => $email, 'password' =\ > $parola), true)) { // Bu kullanıcı hatırlanacak... } Not: attempt metodu true döndürürse, kullanıcı uygulamanıza girmiş kabul edilir. Kullanıcının Remember Aracılığıyla mı Doğrulanmış Olduğunun Tayin Edilmesi Eğer kullanıcı girişlerini “hatırlıyorsanız”, bir kullanıcının “remember me” (beni hatırla) çerezi kullanılarak doğrulanmış olup olmadığını belirlemek için viaRemember metodunu kullanabilirsiniz: 1 2 3 4 if (Auth::viaRemember()) { // } Bir Kullanıcının Ek Şartlara Göre Doğrulanması Kimlik doğrulama sorgusuna ekstra şartlar da ekleyebilirsiniz: 154 Güvenlik 1 2 3 4 5 6 if (Auth::attempt(array('email' => $email, 'password' =\ > $parola, 'aktif' => 1))) { // Bu kullanıcı aktiftir, üyeliği askıya alınmış de\ ğildir ve mevcuttur. } Not: Oturum sabitlemesine karşı koruma amacıyla, kimlik doğrulaması sonrasında kullanıcının oturum ID’si otomatik olarak yeniden üretilecektir. Login Yapmış Kullanıcıya Erişme Bir kullanıcının kimliği doğrulandıktan sonra, bu kullanıcının modeline / kaydına ulaşabilirsiniz: 1 $email = Auth::user()->email; Kimliği doğrulanmış bir kullanıcının ID’sini elde etmek için id metodunu kullanabilirsiniz: 1 $id = Auth::id(); Bir kullanıcıyı sadece ID’si ile uygulamanıza giriş yaptırtmak için loginUsingId metodunu kullanın: 1 Auth::loginUsingId(1); Login Olmaksızın Kullanıcı Bilgilerinin Geçerlilik Denetimi validate metodu gerçekte uygulamaya giriş yapılmaksızın bir kul- lanıcının kimlik bilgilerinin geçerlilik denetiminden geçirilmesine imkan verir: 155 Güvenlik 1 2 3 4 if (Auth::validate($kimlikbilgileri)) { // } Bir Kullanıca Tek Bir İstek İçin Giriş Yapma Bir kullanıcıyı uygulamanıza tek bir istek için giriş yapmak için de once metodunu kullanabilirsiniz. Bu durumda oturum veya çerezler kullanılmayacaktır. 1 2 3 4 if (Auth::once($kimlikbilgileri)) { // } Bir Kullanıcıya Uygulamadan Çıkış Yapma 1 Auth::logout(); Elle Kullanıcı Girişi Şayet, mevcut bir kullanıcı olgusunu uygulamanıza giriş yaptırmak istiyorsanız, bu olguda login metodunu çağırmanız yeterlidir: 1 $uye = Uye::find(1); 2 3 Auth::login($uye); Bu metod, bir kullanıcıyı attempt metodu kullanarak kimlik bilgileri ile giriş yaptırmaya eşdeğerdir. 156 Güvenlik Rotaların Korunması Belli bir rotaya sadece kimliği doğrulanmış kullanıcıların erişebilmesini sağlamak amacıyla rota filtreleri kullanılabilir. Laravel ön tanımlı olarak auth filtresi sağlamıştır ve app/filters.php içinde tanımlanmıştır. Bir Rotanın Korunması 1 2 3 4 5 Route::get('profil', array('before' => 'auth', function\ () { // Sadece kimliği doğrulanmış üyeler girebilir... })); CSRF Koruması Laravel, uygulamanızı siteler arası istek sahtekarlıklarından (crosssite request forgeries [CSRF]) korumak için kolay bir metod sağlamaktadır. Forma CSRF Jetonunun Eklenmesi 1 2 <input type="hidden" name="_token" value="<?php echo cs\ rf_token(); ?>"> Gönderilmiş CSRF Jetonunun Geçerlilik Yoklaması 157 Güvenlik 1 2 3 4 5 Route::post('register', array('before' => 'csrf', funct\ ion() { return 'Geçerli bir CSRF jetonu verdiniz!'; })); HTTP Basic Kimlik Doğrulaması HTTP Basic Kimlik Doğrulaması, kullanıcıları özel bir “giriş” sayfası açmadan uygulamanıza giriş yapabilmeleri için hızlı bir yoldur. Bunun için, rotanıza auth.basic filtresi tutturun: HTTP Basic İle Bir Rotanın Korunması 1 2 3 4 5 Route::get('profil', array('before' => 'auth.basic', fu\ nction() { // Sadece kimliği doğrulanmış üyeler girebilir... })); Ön tanımlı olarak, bu basic filtresi kimlik doğrulaması yaparken kullanıcı kaydındaki email sütununu kullanacaktır. Siz başka bir sütunu kullanmak istiyorsanız, basic metoduna birinci parametre olarak bu sütunun adını geçirin: 1 2 3 4 Route::filter('auth.basic', function() { return Auth::basic('username'); }); Durum Bilgisi Olmaksızın Bir HTTP Basic Filtresi Ayarlanması HTTP Basic Kimlik Doğrulamasını oturumda kullanıcı tanıtıcı bir çerez ayarlamadan da kullanabilirsiniz, bu daha çok API kimlik 158 Güvenlik doğrulamalarında işe yarayacaktır. Bunu yapmak için, onceBasic metodu döndüren bir filtre tanımlayın: 1 2 3 4 Route::filter('basic.once', function() { return Auth::onceBasic(); }); Eğer PHP FastCGI kullanıyorsanız, HTTP Basic kimlik doğrulaması ön tanımlı durumda düzgün çalışmayacaktır. Aşağıdaki satırlar .htaccess dosyanıza eklenmelidir: 1 2 3 RewriteCond %{HTTP:Authorization} ^(.+)$ RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authoriza\ tion}] Şifre Hatırlatıcıları & Yenileme Model & Table Çoğu web uygulaması, kullanıcılarına unutulmuş şifrelerini yenileyecek bir yol verir. Her uygulamada bunu tekrar tekrar yapmaya zorlamak yerine Laravel size şifre hatırlatıcı mektup gönderme ve şifre yenilemesi yapılması için pratik metodlar sağlar. Başlamak için sizin User modelinizin Illuminate\Auth\Reminders\RemindableInterface sözleşmesini yerine getirdiğini doğrulayın. Tabii ki, Laravel’le gelen User modeli bu arayüz kontratını zaten yerine getirmektedir ve bu interface’i implemente etmek için gerekli metodları içermek için Illuminate\Auth\Reminders\RemindableTrait trait’ini kullanmaktadır. RemindableInterface Implementasyonu 159 Güvenlik 1 2 use Illuminate\Auth\Reminders\RemindableTrait; use Illuminate\Auth\Reminders\RemindableInterface; 3 4 5 class User extends Eloquent implements RemindableInterf\ ace { 6 use RemindableTrait; 7 8 9 } Hatırlatıcı Tablo Migrasyonunun Üretilmesi Daha sonra, şifre yenileme jetonlarının saklanacağı bir tablo oluşturulmalıdır. Bu tablo için bir migrasyon üretmek için yapacağınız tek şey auth:reminders-table Artisan komutunu çalıştırmaktır: 1 php artisan auth:reminders-table 2 3 php artisan migrate Şifre Hatırlatıcı Controller Artık şifre hatırlatıcı controller üretmeye geçebiliriz. Bir controlleri otomatik olarak üretmek için, auth:reminders-controller Artisan komutunu kullanabilirsiniz, bu komut sizin app/controllers dizininizde bir RemindersController.php dosyası oluşturacaktır. 1 php artisan auth:reminders-controller Üretilen controllerde şifre hatırlatıcı formunuzu gösterilmesini halleden bir getRemind metodu olacaktır. Sizin yapmanız gereken tek şey bir password.remind viewi¹⁵⁵ oluşturmaktır. Bu view, bir email ¹⁵⁵/docs/responses#views Güvenlik 160 alanı olan basit bir form olmalıdır. Bu form RemindersController@postRemind metoduna POST edilmelidir. password.remind view’inde basit bir form bunun gibi olabilir: 1 2 3 4 5 <form action ="{{ action('RemindersController@postRemind\ ') }}" method ="POST"> <input type ="email" name ="email"> <input type ="submit" value ="Hatırlatıcı Gönder"> </form> Üretilen controllerde getRemind metoduna ek olarak kullacılarınıza şifre hatırlatıcı e-postalar gönderilmesini halleden bir postRemind metodu da olacaktır. Bu metod POST değişkenlerinde bir email alanı mevcut olmasını bekler. Eğer bir hatırlatıcı e-postası kullanıcıya başarıyla gönderilirse, oturuma bir status mesajı flaşlanacaktır. Eğer hatırlatıcı yapılamazsa o zaman bunun yerine bir error mesajı flaşlanacaktır. Bu postRemind controller metodu içerisinde, kullanıcıya göndermeden önce mesaj olgusu üzerinde değişiklik yapabilirsiniz: 1 2 3 4 5 Password::remind(Input::only('email'), function($messag\ e) { $message->subject('Şifre Hatırlatıcı'); }); Kullanıcınız, controllerin getReset metodunu işaret eden bir bağlantısı olan bir e-posta alacaktır. Ayrıca, ilgili bir şifre hatırlatıcı girişimini tanımlamakta kullanılan bir şifre hatırlatıcı tokeni bu controller metoduna geçilecektir. Bu controller metodu bir password.reset view’i döndürecek şekilde zaten yapılandırılmıştır, ancak bu view’i sizin oluşturmanız gerekiyor. İlgili token view’e geçilecektir ve siz bu tokeni token adlı “hidden” bir form 161 Güvenlik alanına koymanız gerekiyor. Sizin şifre reset (yenileme) formunuz bu token‘e ek olarak email, password ve password_confirmation alanlarını da içermelidir. Bu form RemindersController@postReset metoduna post edilmelidir. password.reset view’indeki basit bir form şöyle bir şey olabilir: 1 2 3 4 5 6 7 8 <form action ="{{ action('RemindersController@postReset'\ ) }}" method ="POST"> <input type ="hidden" name ="token" value ="{{ $token }}"> <input type ="email" name ="email"> <input type ="password" name ="password"> <input type ="password" name ="password_confirmation"> <input type ="submit" value ="Şifreyi Yenile"> </form> Son olarak, veritabanındaki şifrenizin gerçekten değiştirilmesinden bu postReset metodu sorumludur. Bu controller eyleminde, Password::reset metoduna geçilen Closure, User‘in password niteliğini ayarlar ve save metodunu çağırır. Pek tabii, bu Closure sizin User modelinizin bir Eloquent modeli¹⁵⁶ olmasını beklemektedir; bununla birlikte siz bu Closure üzerinde uygulamanızın veritabanı depolama sistemiyle uyumlu olması için gerekli değişiklikler yapmakta özgürsünüz. Eğer şifre başarılı bir biçimde yenilenirse, kullanıcı uygulamanızın köküne yönlendirilecektir. Aynı şekilde, siz bu redirect URL’sini de değiştirme serbestisine sahipsiniz. Eğer şifre yenileme başarısız olursa, kullanıcı tekrar reset formuna yönlendirilecektir ve session’a bir error mesajı flaşlanacaktır. Şifre Geçerlilik Denetimi Ön tanımlı olarak, Password::reset metodu şifrelerin eşleşiyor ve >= altı karakter olmasını soruşturacaktır. Siz, parametre olarak ¹⁵⁶/docs/eloquent 162 Güvenlik bir Closure alan Password::validator metodunu kullanarak bu kuralları özelleştirebilirsiniz. Bu Closure içerisinde, istediğiniz her türlü şifre geçerlilik denetimini yapabilirsiniz. Şuna dikkat ediniz: şifrelerin eşleşiyor olduğunu doğrulamanız gerekmiyor, çünkü bu kısım framework tarafından otomatik olarak yapılacaktır. 1 2 3 4 Password::validator(function($credentials) { return strlen($credentials['password']) >= 8; }); Not: Ön tanımlı olarak, şifre yenileme tokenlerinin ömrü bir saat sonra sona erer. Siz app/config/auth.php dosyanızın reminder.expire seçeneği aracılığıyla bunu değiştirebilirsiniz. Kriptolama Laravel, mcrypt PHP uzantısı aracılığıyla güçlü AES kriptolama imkanı sağlamaktadır: Bir Değerin Kriptolanması 1 $kriptolu = Crypt::encrypt('secret'); Not: app/config/app.php dosyasının key seçeneğinde 16, 24 veya 32 karakterli rastgele bir string ayarladığınızdan emin olun. Aksi takdirde kriptolanmış değerler güvenli olmayacaktır. Kriptolu Bir Değerin Çözülmesi 163 Güvenlik 1 $cozuk = Crypt::decrypt($kriptolu); Cipher ve Mod Ayarlanması Ayrıca, kriptocu tarafından kullanılan cipher ve mod da ayarlayabilirsiniz 1 Crypt::setMode('crt'); 2 3 Crypt::setCipher($cipher); Kimlik Doğrulama Sürücüleri Laravel kutusunda database ve eloquent kimlik doğrulama sürücüleriyle gelir. Diğer kimlik doğrulama sürücüleri eklenmesiyle ilgili daha fazla bilgi için Authentication genişletme dokümantasyonu¹⁵⁷ kesimini kontrol ediniz. ¹⁵⁷/docs/extending#authentication Kuyruklar Yapılandırma Laravel’in Queue (kuyruk) bileşeni bir takım farklı kuyruk servisleri için tek bir API sağlamaktadır. Kuyruklar e-mail göndermek gibi zaman harcayan görevleri ileri bir zamana kadar ertelemenize imkan verir ve böylece uygulamanıza yapılan web istekleri büyük ölçüde hızlanır. Kuyruk yapılandırma dosyası app/config/queue.php olarak saklanır. Bu dosyada framework’e dahil edilmiş kuyruk sürücülerinin her birisi için bağlantı yapılandırmaları bulacaksınız. Laravel’deki kuyruk sürücüleri arasında Beanstalkd¹⁵⁸, IronMQ¹⁵⁹, Amazon SQS¹⁶⁰, Redis¹⁶¹ ve senkronize (lokal kullanım için) sürücü yer almaktadır. Listelenen bu kuyruk sürücüleri için aşağıdaki bağımlılıklar gereklidir: • Beanstalkd: pda/pheanstalk ∼2.0 • Amazon SQS: aws/aws-sdk-php • IronMQ: iron-io/iron_mq Temel Kullanım Bir İşin Kuyruğa Sokulması Kuyruğa yeni bir iş itmek için Queue::push metodunu kullanın: ¹⁵⁸http://kr.github.com/beanstalkd ¹⁵⁹http://iron.io ¹⁶⁰http://aws.amazon.com/sqs ¹⁶¹http://redis.io 165 Kuyruklar 1 Queue::push('SendEmail', array('message' => $message)); Bir İş İşleyicisinin Tanımlanması push metoduna girilen ilk parametre işi yapmak için kullanılacak sınıfın adıdır. İkinci parametre işleyiciye geçirilecek veri dizisidir. Bir iş işleyicisi şu şekilde tanımlanmalıdır: 1 class SendEmail { 2 public function fire($is, $veri) { // } 3 4 5 6 7 8 } Gerekli olan tek metodun fire olduğuna dikkat edin. Bu metod bir iş olgusu ve bir de kuyruğa sokulacak veri dizisi parametrelerini alır. Özel Bir İşleyici Metodunun Belirlenmesi Eğer iş’in fire‘den başka bir metod kullanmasını istiyorsanız, işi sokarken (yani push metodunda) metodu belirleyebilirsiniz: 1 2 Queue::push('SendEmail@send', array('message' => $messa\ ge)); Bir İş İçin Kuyruk / Tüp Belirtilmesi Bir işin gönderilmesi gereken kuyruğu / tüpü de belirtebilirsiniz: 166 Kuyruklar 1 2 Queue::push('SendEmail@send', array('message' => $messa\ ge), 'emails'); Birden Çok İş İçin Aynı Yükün Geçilmesi Birkaç kuyruk işi için aynı veriyi geçmeniz gerekiyorsa, Queue::bulk metodunu kullanabilirsiniz: 1 Queue::bulk(array('SendEmail', 'NotifyUser'), $payload); Bir İşin Çalıştırılmasının Geciktirilmesi Kimi zaman sıraya sokulmuş bir işin çalıştırılmasını geciktirmek isteyebilirsiniz. Örneğin, bir müşteriye kayıt olduktan 15 dakika sonra bir e-posta gönderen bir işi kuyruğa koymak isteyebilirsiniz. Bunu Queue::later metodunu kullanarak başarabilirsiniz: 1 $date = Carbon::now()->addMinutes(15); 2 3 4 Queue::later($date, 'SendEmail@send', array('message' =\ > $message)); Bu örnekte, işe atamak istediğimiz gecikme süresini belirtmek için Carbon¹⁶² date kitaplığını kullanıyoruz. Alternatif olarak geciktirmek istediğiniz saniye sayısını tam sayı olarak geçebilirsiniz. İşlenmiş Bir İşin Silinmesi Bir iş işlendikten sonra kuyruktan silinmelidir. Silme işlemi ilgili iş olgusunda delete metodu kullanılarak yapılabilir: ¹⁶²https://github.com/briannesbitt/Carbon 167 Kuyruklar 1 2 3 public function fire($is, $veri) { // İşi işle... 4 $is->delete(); 5 6 } Bir İşin Tekrar Kuyruğa Koyulması Bir işi tekrar kuyruğa devretmek isterseniz, bunu release metodu aracılığıyla yapabilirsiniz: 1 2 3 public function fire($is, $veri) { // İş sürecini yürüt... 4 $is->release(); 5 6 } İş tekrar salınmadan önce kaç saniye bekleneceğini de belirleyebilirsiniz: 1 $is->release(5); Çalıştırma Girişimlerinin Sayısını Yoklama İş işlenirken bir istisna oluşursa, otomatik olarak kuyruğa tekrar salınacaktır. attempts metodunu kullanarak, işi çalıştırmak için yapılmış olan girişim sayısını da yoklayabilirsiniz: 168 Kuyruklar 1 2 3 4 if ($is->attempts() > 3) { // } Bir İşin ID’sine Erişme İş tanımlayıcılarına da erişebilirsiniz: 1 $is->getJobId(); Kuyruğa Closure Fonksiyonu Ekleme Kuyruğa bir Closure de push edebilirsiniz. Bu, kuyruğa sokulması gerekecek hızlı, basit görevler için çok uygundur: Kuyruğa Bir Closure Sokulması 1 2 3 Queue::push(function($is) use ($id) { Account::delete($id); 4 $is->delete(); 5 6 }); Not: Kuyruğa sokulmuş Closure’lar için nesneleri use direktifi aracılığıyla kullanılabilir yapmak yerine, birincil anahtarları geçmeyi ve ilgili modeli kuyruk işiniz içinden tekrar çekmeyi düşünün. Bu, beklenmedik serileştirme davranışlarını çoğu keresinde önleyecektir. Iron.io push kuyrukları kullanılıyorken, Closure’ların kuyruğa sokulmasında daha fazla önlem almalısınız. Kuyruk mesajlarızı alan 169 Kuyruklar son nokta, isteğin gerçekten Iron.io’den mi geldiğini doğrulayacak bir jeton yoklaması yapmalıdır. Örneğin, sizin push kuyruk son noktanız şuna benzer bir şey olmalıdır: https://uygulamaniz.com/queue/receive?t Böylece, kuyruk istek sıralamasından önce uygulamanızdaki gizli jetonun değerini kontrol edebilirsiniz. Kuyruk Dinleyicileri Çalıştırma Laravel, kuyruğa itildikçe yeni işler çalıştıran bir Artisan görevi içermektedir. Bu görevi çalıştırmak için queue:listen komutunu kullanabilirsiniz: Kuyruk Dinleyici Başlatılması 1 php artisan queue:listen Ayrıca dinleyicinin kullanacağı kuyruk bağlantısını da belirtebilirsiniz: 1 php artisan queue:listen connection Unutmamanız gereken şey, bu görev başlatıldıktan sonra elle durdurulana kadar çalışmaya devam edeceğidir. Kuyruk dinleyicinin çalışmayı durdurmamasından emin olmak için Supervisor¹⁶³ gibi bir süreç monitörü kullanabilirsiniz. Kuyruk önceliklerini ayarlamak için listen komutuna virgülle ayrılmış bir kuyruk bağlantıları listesi geçebilirsiniz: 1 php artisan queue:listen --queue=high,low Bu örnekte, high-connection üzerindeki işler, her zaman için low-connection‘dan gelen işlere geçmeden önce yürütülecektir. ¹⁶³http://supervisord.org/ 170 Kuyruklar İş Zaman Aşımı Parametresi Belirleme Ayrıca her işin çalışmasına izin verilecek zaman süresini (saniye cinsinden) de ayarlayabilirsiniz: 1 php artisan queue:listen --timeout=60 Kuyruk Uyku Süresinin Belirtilmesi Ek olarak, yeni işin eyleme alınmadan önce beklenileceği süreyi saniye cinsinden belirtebilirsiniz: 1 php artisan queue:listen --sleep=5 Not: kuyruk sadece kuyrukta iş olmadığı takdirde “uyur”. Eğer kuyrukta başka işler varsa, kuyruk uyumaksızın onları çalışmaya devam edecektir. Kuyruktaki İlk İşin İşleme Geçirilmesi Kuyruktaki sadece ilk sıradaki işi yürütmek için queue:work komutunu kullanabilirsiniz: 1 php artisan queue:work Daemon Kuyruk İşçisi queue:work ayrıca işlerin işlenmesinin framework tekrar boot edil- meksizin devam etmesi için kuyruk işçisinin zorlanması için bir --daemon seçeneği içermektedir. Bu, queue:listen komutuyla karşılaştırıldığında CPU kullanımında önemli bir azalmayla sonuçlanır ama yayımlama sırasında halihazırda çalışmakta olan kuyrukların drene edilmesi gerekliliği karmaşıklığını ekler. Bir kuyruk işçisini daemon modunda başlatmak için, --daemon flagını kullanın: Kuyruklar 1 171 php artisan queue:work connection --daemon 2 3 php artisan queue:work connection --daemon --sleep=3 4 5 6 php artisan queue:work connection --daemon --sleep=3 --\ tries=3 Gördüğünüz gibi, queue:work komutu queue:listen için kullanılan seçeneklerin pek çoğunu desteklemektedir. Mevcut seçeneklerin tümünü görmek için php artisan help queue:work komutunu kullanabilirsiniz. Daemon Kuyruk İşçileriyle Yayımlama Bir uygulamayı daemon kuyruk işçileri kullanarak yayımlamanın en basit yolu yayımlamanızın en başında uygulamanızı bakım (maintenance) moduna koymaktır. Bu php artisan down komutu kullanılarak yapılabilir. Uygulama bakım moduna alındıktan sonra, Laravel artık kuyruğa yeni işler kabul etmeyecektir ama mevcut işleri işlemeye devam edecektir. Worker’larınızı yeniden başlatmanın en kolay yolu yayımlama scriptinize aşağıdaki komutu dahil etmektir: 1 php artisan queue:restart Bu komut tüm kuyruk işçilerine mevcut işlerini işlemeyi bitirdikten sonra yeniden başlatmaları talimatı verecektir. Daemon Kuyruk İşçileri İçin Kodlama Daemon kuyruk işçileri her biri işlerini işlemeden önce frameworkü yeniden başlatmazlar. Bu nedenle, işlerinizi bitirmeden önce çok büyük kaynakları serbest bırakmaya özen göstermelisiniz. Örneğin, 172 Kuyruklar GD kitaplığıyla resim manipulasyonu yapıyorsanız, yaptıktan sonra imagedestroy ile belleği rahatlatmalısınız. Benzer şekilde, uzun çalışan daemon’larla kullanıldığı zaman veritabanı bağlantınız kopabilir. Taze bir bağlantınız olmasını temin etmek için DB::reconnect metodunu kullanabilirsiniz. Push Kuyrukları Push kuyrukları size herhangi bir art alan veya arka plan dinleyici çalıştırmaksızın güçlü Laravel 4 kuyruk araçlarını kullanmanıza imkan verir. Push kuyrukları şu anda sadece Iron.io¹⁶⁴ sürücüsü tarafından desteklenmektedir. Başlamak için önce bir Iron.io hesabı oluşturun ve Iron kimlik bilgilerinizi app/config/queue.php yapılandırma dosyasına ekleyin. Bir Push Kuyruk Aboneliğinin Kayda Geçirilmesi Daha sonra, yeni push edilmiş kuyruk işlerini alacak bir URL son noktasını kayda geçirmek için queue:subscribe Artisan komutunu kullanabilirsiniz: 1 2 php artisan queue:subscribe queue_name http://falan.com\ /queue/receive Şimdi, sizin Iron panonuza giriş yaptığınız zaman, yeni push kuyruğunuzu ve abone olunan URL’yi göreceksiniz. Verilen bir kuyruk için istediğiniz kadar çok URL kaydedebilirsiniz. Sonra da, queue/receive son noktanız için bir rota oluşturun ve Queue::marshal metodundan cevap döndürün: ¹⁶⁴http://iron.io 173 Kuyruklar 1 2 3 4 Route::post('queue/receive', function() { return Queue::marshal(); }); Doğru iş işleyici sınıfının ateşlenmesiyle marshal metodu ilgilenecektir. Push kuyruğundaki işleri ateşlemek için, konvansiyonal kuyruklar için kullanılan aynı Queue::push metodunu kullanmanız yeterlidir. Başarısız İşler İşler her zaman planladığımız şekilde gitmediğinden, bazen kuyruğa soktuğumuz işler başarılamaz. Dert etmeyin, bu en iyilerimizin bile başına gelir! Laravel bir işin en fazla kaç defa denenmesi gerektiğini belirtmeniz için kolay bir yol içerir. Bir iş bu girişme miktarını aştıktan sonra, failed_jobs (başarısız işler) tablosuna eklenecektir. Başarısız işler tablosunun adını app/config/queue.php yapılandırma dosyasında ayarlayabilirsiniz. failed_jobs tablosu için bir migrasyon oluşturmak için, queue:failed-table komutunu kullanabilirsiniz: 1 php artisan queue:failed-table Bir işin maksimum kaç defa yapılma girişiminde bulunulacağını queue:listen komutunda --tries anahtarını kullanarak belirtebilirsiniz: 1 php artisan queue:listen connection-name --tries=3 Eğer bir kuyruk işi başarısız olduğu takdirde çağrılacak bir olay kayda geçirmek isterseniz, Queue::failing metodunu kullanabi- Kuyruklar 174 lirsiniz. Bu olay ekibinizi bir e-posta veya HipChat¹⁶⁵ aracılığıyla bilgilendirmek için harika bir fırsattır. 1 2 3 4 Queue::failing(function($connection, $job, $data) { // }); Başarısız olmuş işlerinizin tümünü görmek için queue:failed Artisan komutunu kullanabilirsiniz: 1 php artisan queue:failed Bu queue:failed komutu iş ID, bağlantı, kuyruk ve başarısızlık zamanını listeleyecektir. Bunlardan iş ID başarısız işi yeniden denemek için kullanılabilir. Örneğin, ID’si 5 olan başarısız bir işi yeniden denemek için aşağıdaki komut verilmelidir: 1 php artisan queue:retry 5 Başarısız bir işi silmek isterseniz, queue:forget komutunu kullanabilirsiniz: 1 php artisan queue:forget 5 Başarısız işlerinizin tümünü silmek için queue:flush komutunu kullanabilirsiniz: 1 php artisan queue:flush ¹⁶⁵https://www.hipchat.com Olaylar (Events) Temel Kullanım Laravel’in Event sınıfı, uygulamanızdaki olaylara abone olmanıza ve dinlemenize imkan veren basit bir gözlemci aracıdır. Bir Olaya Abone Olma 1 2 3 Event::listen('uye.login', function($uye) { $uye->last_login = new DateTime; 4 $uye->save(); 5 6 }); Bir Olayı Ateşleme 1 $olay = Event::fire('uye.login', array($uye)); Bir Olaya Abone Olurken Öncelik Belirtme Olaylara abone olurken bir öncelik de belirtebilirsiniz. Daha yüksek önceliği olan dinleyiciler daha önce çalışacak, aynı önceliğe sahip dinleyiciler ise abonelik sırasına göre çalışacaklardır. 1 Event::listen('uye.login', 'LoginHandler', 10); 2 3 Event::listen('uye.login', 'DigerHandler', 5); Olaylar (Events) 176 Bir Olayın Yayılımının Durdurulması Bazen bir olayın diğer dinleyicilere yayılmasını durdurmak isteyebilirsiniz. Dinleyicinizden false döndürerek bunu gerçekleştirebilirsiniz: 1 2 3 Event::listen('uye.login', function($event) { // Olayı işle... 4 return false; 5 6 }); Olayların Kayda Geçirileceği Yer Tamam, olayların nasıl kayda geçirileceğini biliyorsunuz ama onların nerede kayda geçirileceğini merak ediyor olabilirsiniz. Dert etmeyin, bu çok sorulan bir şey. Ne yazık ki bu cevaplandırması zor bir soru, çünkü bir olayı neredeyse her yerde kayda geçirebilirsiniz! Fakat, işte bazı ipuçları. Aynı şekilde, diğer pek çok bootstrapping (önce yüklenen) koduna benzer olarak, olayları app/start/global.php gibi start dosyalarınızın birisinde kayda geçirebilirsiniz. Eğer start dosyalarınız çok kalabalık bir hale gelirse, bir start dosyanızda “include” edilen ayrı bir app/events.php dosyası oluşturabilirsiniz. Bu, sizin olay kaydetme işinizi, geri kalan bootstrapping kodundan temiz bir şekilde ayrı tutmanın basit bir çözümüdür. Eğer sınıf temelli bir yaklaşımı tercih ederseniz, olaylarınızı bir servis sağlayıcı¹⁶⁶ ile kayda geçirebilirsiniz. Bu yaklaşımlardan hiçbiri “mutlak” doğru olmadığından, ugulamanızın büyüklüğüne göre rahatlık hissedeceğiniz bir yaklaşımı seçin. ¹⁶⁶/docs/ioc#service-providers 177 Olaylar (Events) Joker Dinleyiciler Joker Olay Dinleyicilerin Kayda Geçirilmesi Bir olay dinleyiciyi kayda geçirirken, joker dinleyicileri belirtmek üzere yıldız işareti kullanabilirsiniz: 1 2 3 4 Event::listen('falan.*', function($param) { // Olayı işle... }); Bu dinleyici falan. ile başlayan tüm olayları işleyecektir. Tam olarak hangi olayın ateşlendiğini tespit etmek için Event::firing metodunu kullanabilirsiniz: 1 2 3 4 5 6 7 Event::listen('falan.*', function($param) { if (Event::firing() == 'falan.filan') { // } }); Dinleyici Olarak Sınıfları Kullanma Bazı durumlarda, bir olayı işlemek için bir anonim fonksiyon yerine bir sınıf kullanmak isteyebilirsiniz. Sınıf olay dinleyicileri Laravel’in IoC konteyneri¹⁶⁷ ile çözümlenecek, böylece size dinleyicileriniz üzerinde tam bir bağımlılık enjeksiyonu gücü verecektir. Bir Sınıf Dinleyicinin Kayda Geçirilmesi ¹⁶⁷/docs/ioc 178 Olaylar (Events) 1 Event::listen('uye.login', 'LoginIsleyici'); Bir Olay Dinleyici Sınıfının Tanımlanması Ön tanımlı olarak, LoginIsleyici sınıfındaki handle metodu çağrılacaktır: 1 class LoginIsleyici { 2 public function handle($data) { // } 3 4 5 6 7 8 } Hangi Metoda Abone Olunduğunun Tanımlanması Eğer ön tanımlı handle metodunu kullanmak istemiyorsanız, abone olunacak metodu belirleyebilirsiniz: 1 Event::listen('uye.login', 'LoginIsleyici@onLogin'); Olayları Sıraya Sokma Sıralı Bir Olayın Kayda Geçirilmesi queue ve flush metodlarını kullanarak, bir olayı hemen ateşlemeyip, ateşlenmek üzere “sıraya” sokabilirsiniz: 1 Event::queue('falan', array($uye)); “flusher”ı çalıştırabilir ve flush metodunu kullanarak sıradaki tüm olayları harekete geçirebilirsiniz: 179 Olaylar (Events) 1 Event::flush('falan'); Olay Abonecileri Bir Olay Abonecisi Tanımlanması Olay abonecileri, sınıfın kendi içinden birden çok olaya abone olabilen sınıflardır. Aboneciler bir subscribe metodu ile tanımlanırlar ve bu metoda parametre olarak bir olay sevkiyatçısı olgusu geçilecektir: 1 class UyeOlayIsleyici { 2 3 4 5 6 7 8 9 /** * Uye login olaylarını işle. */ public function onUyeLogin($event) { // } 10 11 12 13 14 15 16 17 /** * Uye logout olaylarını hallet. */ public function onUyeLogout($event) { // } 18 19 20 21 22 23 /** * Abone dinleyicilerini kayda geçir. * * @param Illuminate\Events\Dispatcher * @return array $events 180 Olaylar (Events) */ public function subscribe($events) { $events->listen('uye.login', 'UyeOlayIsleyici@onUyeLo\ 24 25 26 27 28 gin'); 29 $events->listen('uye.logout', 'UyeOlayIsleyici@onUyeL\ 30 31 ogout'); } 32 33 34 } Bir Olay Abonecisinin Kayda Geçirilmesi Aboneci tanımlandıktan sonra, Event sınıfı kullanılarak kayda geçirilebilir. 1 $aboneci = new UyeOlayIsleyici; 2 3 Event::subscribe($aboneci); Ayrıca abonecinizi çözümlemek için Laravel IoC konteynerini¹⁶⁸ de kullanabilirsiniz. Bunu yapmak için subscribe metoduna sadece abonecinizin ismini geçiniz: 1 Event::subscribe('UyeOlayIsleyici'); ¹⁶⁸/docs/ioc Oturum Yapılandırma HTTP odaklı uygulamalar durum bilgisi taşımadıkları için, oturumlar istekler arasında kullanıcı hakkında bilgi saklamak için bir yol sağlar. Laravel temiz, tek bir API aracılığıyla kullanılabilen çeşitli oturum back-endleri ile birlikte gelir. İçerisinde Memcached¹⁶⁹, Redis¹⁷⁰ ve veritabanları gibi popüler back-end desteği yer almaktadır. Oturum yapılandırma ayarları app/config/session.php dosyasında bulunmaktadır. Bu belgede size sunulan iyi belgelenmiş seçenekleri gözden geçirmeyi unutmayın. Ön tanımlı olarak, Laravel file oturum sürücüsünü kullanmak üzere yapılandırılmıştır ve bu yapılandırma uygulamaların çoğunda iyi çalışacaktır. Ayrılmış (Rezerve) Anahtarlar Laravel framework dahili olarak flash session anahtarını kullanır, bu nedenle siz oturuma bu isimle bir öğe eklememelisiniz. Oturum Kullanımı Oturumda Bir Öğe Saklamak 1 Session::put('anahtar', 'deger'); Dizi Oturum Değerine Bir Değer Eklemek ¹⁶⁹http://memcached.org ¹⁷⁰http://redis.io 182 Oturum 1 Session::push('uyeler.takimlar', 'gelistiriciler'); Oturumdaki Bir Öğeyi Öğrenmek 1 $deger = Session::get('anahtar'); Bir Öğe Almak Veya Varsayılan Bir Değer Döndürmek 1 $deger = Session::get('anahtar', 'default'); 2 3 4 $deger = Session::get('anahtar', function() { return 'd\ efault'; }); Bir Öğenin Elde Edilmesi ve Oturumdan Çıkartılması 1 $value = Session::pull('anahtar', 'default'); Oturumdaki Tüm Verileri Almak 1 $veri = Session::all(); Oturumda Bir Öğenin Olup Olmadığını Tespit Etmek 1 2 3 4 if (Session::has('uyeler')) { // } Oturumdan Bir Öğeyi Çıkartmak 1 Session::forget('anahtar'); Oturumdaki Tüm Öğeleri Çıkartmak 183 Oturum 1 Session::flush(); Tekrar Oturum ID Üretmek 1 Session::regenerate(); Flaş Verisi Bazen oturumda sadece sonraki istek için öğeler saklamak isteyebilirsiniz. Bunu Session::flash metodunu kullanarak gerçekleştirebilirsiniz: 1 Session::flash('anahtar', 'deger'); Mevcut Flaş Verinin Bir Başka İstek İçin Yeniden Flaşlanması 1 Session::reflash(); Flaş Verinin Sadece Bir Alt Kümesinin Yeniden Flaşlanması 1 Session::keep(array('uyeadi', 'email')); Veritabanı Oturumları database oturum sürücüsü kullanıyorken, oturum öğelerini taşıyan bir tablo kurulumu gerekecek. Aşağıda, bu tablo için örnek bir Şema deklarasyonu gösterilmektedir: 184 Oturum 1 2 3 4 5 6 Schema::create('sessions', function($table) { $table->string('id')->unique(); $table->text('payload'); $table->integer('last_activity'); }); Tabii ki, bu migrasyonu üretmek için session:table Artisan komutunu kullanabilirsiniz! 1 php artisan session:table 2 3 composer dump-autoload 4 5 php artisan migrate Oturum Sürücüleri Oturum “driver’ı” her istek için oturum verisinin nerede saklanacağını tanımlamaktadır. Laravel çeşitli harika sürücülerle birlikte gelmektedir. • file - oturumlar app/storage/sessions klasöründe saklanacaktır. • cookie - oturumlar güvenli, kriptolanmış çerezlerde saklanacaktır. • database - oturumlar kendi uygulamanızın kullandığı bir veritabanında saklanacaktır. • memcached / redis - oturumlar bu hızlı, önbellekleme tabanlı depolardan birisinde saklanacaktır. • array - oturumlar basit bir PHP dizisinde saklanacak ve istekler arasında sebat etmeyecektir. Oturum Not: Array sürücüsü tipik olarak unit testler çalıştırmak için kullanılır, bu yüzden oturum verileri sürdürülmeyecektir. 185 Önbellekleme (Cache) Yapılandırma Laravel, çeşitli önbellekleme sistemleri için tümleşik bir API sağlar. Önbellekleme yapılandırma ayarları app/config/cache.php dosyasında bulunmaktadır. Bu dosyada uygulamanızda varsayılan olarak hangi önbellekleme sürücüsünü kullanmak istediğinizi belirtebilirsiniz. Laravel, Memcached¹⁷¹ ve Redis¹⁷² gibi popüler önbellekleme sürücülerini barındırır. Önbellekleme yapılandırma dosyası ayrıca dosyanın içinde açıklanmış çeşitli seçenekleri de içerir, bu yüzden o seçenekleri de okuduğunuzdan emin olun. Varsayılan olarak, Laravel, serileştirilerek önbelleklenmiş öğeleri dosya sisteminde depolayan file (dosya) önbellekleme sürücüsünü kullanmak üzere ayarlanmıştır. Daha büyük uygulamalar için, Memcached ve APC gibi bir önbellekleme uygulaması kullanmanız önerilir. Önbellekleme Kullanımı Bir Öğeyi Önbelleğe Koymak 1 Cache::put('anahtar', 'değer', $dakika); Son Kullanım Zamanını Ayarlamak İçin Carbon Nesneleri Kullanılması ¹⁷¹http://memcached.org ¹⁷²http://redis.io Önbellekleme (Cache) 1 187 $sonZaman = Carbon::now()->addMinutes(10); 2 3 Cache::put('anahtar', 'değer', $sonZaman); Eğer Öğe Önbellekte Yoksa, Öğeyi Önbelleğe Koymak 1 Cache::add('anahtar', 'değer', $dakika); Eğer ilgili öğe önbelleğe gerçekten eklenirse add metodu true döndürecektir. Aksi takdirde bu metod false döndürecektir. Öğenin Önbellekte Var Olup Olmadığını Kontrol Etmek 1 2 3 4 if (Cache::has('anahtar')) { // } Önbellekten Bir Öğeyi Almak 1 $value = Cache::get('anahtar'); Bir Önbellek Değeri Almak Veya Varsayılan Bir Değer Döndürmek 1 $value = Cache::get('anahtar', 'varsayılanDeğer'); 2 3 4 $value = Cache::get('anahtar', function() { return 'var\ sayılanDeğer'; }); Bir Öğeyi Önbelleğe Kalıcı Olarak Koymak Önbellekleme (Cache) 1 188 Cache::forever('anahtar', 'değer'); Bazen, önbellekten bir öğeyi almak isteyebilir ve ayrıca talep edilen öğe yoksa önbellekte varsayılan bir değer saklayabilirsiniz. Bunu, Cache::remember metodunu kullanarak yapabilirsiniz: 1 2 3 4 5 $value = Cache::remember('kullanicilar', $dakika, funct\ ion() { return DB::table('kullanicilar')->get(); }); Ayrıca, remember ve forever methodlarını birlikte kullanabilirsiniz. 1 2 3 4 5 $value = Cache::rememberForever('kullanicilar', functio\ n() { return DB::table('kullanicilar')->get(); }); Önbellekte bütün öğelerin serileştirilmiş şekilde saklandığını unutmayın, yani her türlü veriyi saklayabilirsiniz. Önbellekten Bir Öğe Çekilmesi Eğer önbellekten bir öğeyi elde etmek ve sonra da onu silmeniz gerekirse, pull metodunu kullanabilirsiniz: 1 $value = Cache::pull('anahtar'); Önbellekten Bir Öğeyi Silmek 189 Önbellekleme (Cache) 1 Cache::forget('anahtar'); Arttırma & Azaltma file ve database hariç tüm sürücüler increment (artırma) ve decrement (azaltma) işlemlerini destekler: Bir Değeri Arttırmak 1 Cache::increment('anahtar'); 2 3 Cache::increment('anahtar', $miktar); Bir Değeri Azaltmak 1 Cache::decrement('anahtar'); 2 3 Cache::decrement('anahtar', $miktar); Önbellek Etiketleri (Tags) Not: Önbellek bölümleri file ve database önbellekleme sürücüleri kullanılırken desteklenmemektedir. Ayrıca, “forever” saklanır önbelleklerde birden çok tag kullanmanız halinde, bayat kayıtları otomatik olarak temizleyen memcached gibi bir sürücüyle performans en iyi olacaktır. Etiketlenmiş Bir Önbelleğe Erişim Cache tagları cache’deki birbirine yakın öğeleri etiketlemenize ve daha sonra verilen bir isimle etiketlenmiş tüm cache’leri yok etmenize (flush) imkan verir. Etiketlenmiş bir cache’e erişmek için, tags metodunu kullanın: Önbellekleme (Cache) 190 Parametreler olarak sıralı bir tag isimleri listesi geçerek veya parametre olarak sıralı tag isimlerinden oluşan bir dizi geçerek etiketlenmiş bir cache saklayabilirsiniz. 1 2 Cache::tags('insanlar', 'yazarlar')->put('Can', $can, $\ dakika); 3 4 5 Cache::tags(array('insanlar', 'artistler'))->put('Mine'\ , $mine, $dakika); Tag kombinasyonlarında remember, forever ve rememberForever gibi herhangi bir cache saklama metodunu kullanabilirsiniz. Ayrıca etiketlenmiş cache’lerde önbelleklenmiş öğelere erişebileceğiniz gibi, increment ve decrement gibi diğer önbellek metodlarını da kullanabilirsiniz. Etiketlenmiş Bir Önbellekteki Öğelere Erişmek Etiketlenmiş bir cache’ye erişmek için, onu saklarken kullandığınız aynı sıradaki tag listesini geçiniz. 1 2 $mine = Cache::tags('insanlar', 'artistler')->get('Mine\ '); 3 4 5 $can = Cache::tags(array('insanlar', 'yazarlar'))->get(\ 'Can'); Bir isim veya bir isim listesi ile etiketlenmiş tüm ögeleri yok edebilirsiniz. Örneğin, aşağıdaki cümle insanlar, yazarlar veya her ikisi ile de etiketlenmiş tüm cache’leri çıkarıp atacaktır. Dolayısıyla, cache’den hem “Mine” hem de “Can” çıkartılacaktır: Önbellekleme (Cache) 1 191 Cache::tags('insanlar', 'yazarlar')->flush(); Tersine, şu cümle sadece yazarlar etiketi verilmiş cache’leri çıkartacaktır, yani “Can” çıkartılacak ama “Mine” çıkartılmayacak. 1 Cache::tags('yazarlar')->flush(); Veritabanı Önbelleği database önbellek sürücüsü kullandığınız takdirde, önbellek öğelerini içeren bir tablo kurulumu gerekir. Bu tablo için örnek bir şema aşağıda gösterilmiştir: 1 2 3 4 5 6 Schema::create('cache', function($table) { $table->string('key')->unique(); $table->text('value'); $table->integer('expiration'); }); Paket Geliştirme Giriş Paketler Laravel’e işlevsellik eklemenin esas yollarıdır. Paketler tarihlerle çalışmanın harika bir yolu olan Carbon¹⁷³ gibi bir şey ya da Behat¹⁷⁴ gibi tam bir BDD test framework’ü olabilir. Farklı paket türleri bulunmaktadır. Bazı paketler kendi başınadır, yani sadece Laravel değil herhangi bir framework ile çalışırlar: Carbon ve Behat her ikisi de bu tür stand-alone paket örnekleridir. Bu paketler sadece composer.json dosyasında istek yapılmak suretiyle Laravel’le kullanılabilmektedir. Öte yandan, diğer bazı paketler özellikle Laravel ile kullanım için tasarlanmıştır. Önceki Laravel sürümlerinde, bu tip paketlere “bundle” deniyordu. Bu paketlerde özellikle bir Laravel uygulamasını güçlendirmeyi amaçlamış rotalar, denetçiler (controllers), görünümler, yapılandırmalar ve migrasyonlar olabilir. Kendi başına türde bir paket geliştirmek için gerekli özel bir süreç olmadığı için, bu kılavuz esas itibarıyla Laravel’e özgü olanların geliştirilmesini kapsamaktadır. Tüm Laravel paketleri Packagist¹⁷⁵ ve Composer¹⁷⁶ aracılığıyla dağıtılır, bu yüzden bu harika PHP paket dağıtım araçlarını öğrenmek esastır. ¹⁷³https://github.com/briannesbitt/Carbon ¹⁷⁴https://github.com/Behat/Behat ¹⁷⁵http://packagist.org ¹⁷⁶http://getcomposer.org 193 Paket Geliştirme Bir Paket Oluşturma Laravel’le kullanmak üzere yeni bir paket oluşturmanın en kolay yolu workbench Artisan komutudur. Öncelikle, app/config/workbench.php dosyasında birkaç seçeneği ayarlamanız gerekiyor. Bu dosyada, bir name ve email seçeneği bulacaksınız. Bu değerler sizin yeni paketiniz için bir composer.json dosyası üretmekte kullanılacaktır. Bu değerleri girdikten sonra, bir tezgah (workbench) paketi oluşturmaya hazırsınız! Workbench Artisan Komutunun Verilmesi 1 php artisan workbench satıcıadı/paketadı --resources Satıcıadı sizin paketinizi farklı yazarlardan gelen aynı isimli diğer paketlerden ayırt etmenin bir yoludur. Örneğin ben (Taylor Otwell) “Zapper” adında yeni bir paket oluşturacaksam, satıcıadı Taylor, paketadı ise Zapper olacaktır. Ön tanımlı olarak, bu workbench komutu framework bilinemez paketler oluşturur; ancak, resources komutu workbench’e migrations, views, config ve bunlar gibi Laravel’e özgü dizinleri olan paketler üretmesini söyler. workbench komutu çalıştırıldıktan sonra sizin paketiniz Laravel kurulumunuzun workbench dizini içerisinde hazırlanmış olacaktır. Daha sonra, paketiniz için oluşturulmuş olan ServiceProvider‘i kayda geçireceksiniz. Bu hizmet sağlayıcının adını app/config/app.php dosyasındaki providers dizisine ekleyerek kayda geçirebilirsiniz. Bu, Laravel’e uygulamanız başladığı zaman sizin paketinizi yüklemesi talimatı verecektir. Hizmet sağlayıcıları [Paket]ServiceProvider şeklinde bir isimlendirme geleneği kullanırlar. Öyleyse, yukarıdaki örnek için providers dizisine Taylor\Zapper\ZapperServiceProvider ekleyeceğiz. Sağlayıcıyı kayda geçirdikten sonra artık paketinizi geliştirmeye başlayabilirsiniz! Bununla birlikte, bu konuya geçmeden önce, paket 194 Paket Geliştirme yapısı ve geliştirme iş akışını daha yakından tanımak için aşağıdaki kesimleri gözden geçirmenizde yarar var. Not: Servis sağlayıcınız bulunamıyorsa uygulamanızın ana dizininde php artisan dump-autoload komutunu çalıştırınız. Paket Yapısı workbench komutu kullanılırken, paketiniz, paketinizin Laravel fra- meworkün diğer kısımlarıyla iyi bütünleşmesine imkan veren geleneklerle kurulur: Temel Paket Dizin Yapısı 1 /src /Satici 2 /Paket 3 PaketServiceProvider.php 4 /config /lang /migrations /views 5 6 7 8 9 10 /tests /public Bu yapıyı biraz daha açalım. Buradaki src/Satici/Paket dizini sizin paketinizin ServiceProvider de dahil olmak üzere tüm sınıflarının evidir. config, lang, migrations ve views dizinleri ise, tahmin edebileceğiniz gibi paketinizdeki kaynakların kendilerine tekabül edenlerini içermektedir. Paketlerde, tıpkı “normal” uygulamalarda olduğu gibi bu kaynaklardan birileri olabilir. 195 Paket Geliştirme Hizmet Sağlayıcıları Hizmet sağlayıcıları paketleriniz için tamamen önceden yükleme (bootstrap) sınıflarıdır. Ön tanımlı olarak bunlar iki metod taşırlar: boot ve register. Bu metodların içerisinde, istediğiniz her şeyi yapabilirsiniz: bir rota dosyası dahil etmek, IoC konteynerinde bağlayıcı kayda geçirmek, olaylar tutturmak veya istediğiniz daha başka bir şey. Bunlardan register metodu, hizmet sağlayıcı kayıt edilir edilmez çağrılır, boot komutu ise sadece bir istek rotalandırılmadan önce çağrılır. Bu nedenle, eğer sizin hizmet sağlayıcınızdaki eylemler, zaten kaydı yapılmış başka bir hizmet sağlayıcısına dayanıyorsa veya başka bir sağlayıcı tarafından bağlanan hizmetleri geçersiz bırakıyorsanız, boot metodunu kullanmalısınız. workbench kullanarak bir paket oluşturulurken, boot komutu zaten bir eylem içerir: 1 $this->package('satici/paket'); Bu metod Laravel’in uygulamanız için görünüm, konfigürasyon ve diğer kaynakları nasıl düzgünce yükleyeceğini bilmesine imkan verir. Genelde, paket kurulumunu workbench gelenekleri kullanarak yapacağı için bu kod satırını değiştirmenin bir gereği yoktur. Ön tanımlı olarak, bir paketin kayda geçirilmesinden sonra, onun kaynakları satici/paket‘in “paket” yarısı kullanılarak erişilebilir olacaktır. Bununla birlikte, bu davranışı geçersiz kılıp değiştirmek için package metoduna ikinci bir parametre geçebilirsiniz. Örneğin: 196 Paket Geliştirme 1 2 // Package metoduna özel aduzayı geçilmesi $this->package('satici/paket', 'ozel-aduzay'); 3 4 5 6 // Paket kaynaklarına artık özel aduzayı aracılıyla eri\ şilir $view = View::make('ozel-aduzay::falan'); Servis sağlayıcı sınıfları için “varsayılan yer” söz konusu değildir. Bunları istediğiniz yere konumlandırabilirsiniz, belki bunları app dizini içinde Providers aduzayı ile organize edersiniz. Dosya, Composer’ın otomatik yükleme araçları¹⁷⁷ sınıfı yükleyebilmek için dosyanın nerede bulunduğunu bildiği sürece istediğiniz yere konumlandırılabilir. Paketinizin kaynaklarının, örneğin yapılandırma dosyaları veya view’lerin konumunu değiştirirseniz, package metoduna kaynaklarınızın konumunu belirten üçüncü bir parametre geçmelisiniz: 1 2 $this->package('satici/paket', null, '/kaynaklara/dosya\ /yolu'); Ertelenmiş Sağlayıcılar Eğer yapılandırma dosyaları ve view’ler gibi hiçbir kaynağı kayda geçirmeyen bir hizmet sağlayıcı yazıyorsanız, sağlayıcınızı “ertelenmiş (deferred)” yapmayı seçebilirsiniz. Ertelenmiş bir servis sağlayıcı sadece sağladığı hizmetlerden birisi uygulamanın IoC konteyneri tarafından gerçekten gerektiği zaman yüklenecek ve kayda geçirilecektir. Verilen bir istek döngüsü boyunca bu sağlayıcının servislerinden hiçbirisi gerekli olmazsa, sağlayıcı asla yüklenmeyecektir. Servis sağlayıcınızın çalışmasını ertelemek için sağlayıcının defer özelliğini true olarak ayarlayın: ¹⁷⁷http://getcomposer.org01-basic-usage.md#autoloading 197 Paket Geliştirme 1 protected $defer = true; Ondan sonra da taban Illuminate\Support\ServiceProvider sınıfından gelen provides metodunu override etmeniz ve sağlayıcınızın IoC konteynerine eklediği bağlamaların tamamından oluşan bir dizi döndürmeniz gerekiyor. Örneğin, eğer sizin sağlayıcınız IoC konteynerine paket.hizmet ve paket.diger-hizmet kayda geçiriyorsa, sizin provides metodu bunun gibi gözükmelidir: 1 2 3 4 public function provides() { return array('paket.hizmet', 'paket.diger-hizmet'); } Paket Gelenekleri Bir paketten gelen kaynaklar kullanılırken, örneğin yapılandırma öğeleri veya görünümler için genelde çift iki nokta üst üste sözdizimi kullanılır: Bir Paketteki Bir Görünümü Yükleme 1 return View::make('package::gorunum.isim'); Bir Paket Yapılandırma Öğesinin Öğrenilmesi 1 return Config::get('package::grup.secenek'); Not: Eğer paketinizde migrasyonlar varsa, başka paketlerle olası sınıf adı çatışmalarını önlemek amacıyla migrasyon isimlerine paketinizin adını ön ek vermeyi düşünün. 198 Paket Geliştirme Geliştirme İş Akışı Bir paket geliştirirken bir uygulama kapsamı içerisinde geliştiriyor olabilmek yararlı olur ve size kolaylıkla görmek ve şablonlarınızla denemek ve benzeri imkanlar verir. Bu nedenle, bu işe başlarken Laravel’in yeni bir kopyasını yükleyin, sonra da paket yapınızı oluşturmak için workbench komutunu kullanın. workbench komutunun paketinizi oluşturmasından sonra, workbench/[satici]/[pak dizininden git init yapabilir ve paketinizi doğrudan workbench’tan git push yapabilirsiniz! Bu size sürekli composer update komut- larıyla batağa saplanmaksızın bir uygulama bağlamında uygun bir şekilde paket geliştirmenize imkan verecektir. Sizin paketleriniz workbench dizininde olduğundan, Composer’in sizin paketinizin dosyalarını otomatik yüklemeyi nereden bileceğini merak ediyor olabilirsiniz. Bu workbench dizini mevcut olduğu zaman, Laravel akıllı bir şekilde paket var mı diye bu dizini tarayacak, uygulama başladığında bunların Composer autoload dosyalarını yükleyecektir! Eğer paketinizin autoload dosyalarını tekrar üretmeniz gerekirse, php artisan dump-autoload komutunu kullanabilirsiniz. Bu komut, sizin kök projenizdekiler yanında, oluşturmuş olduğunuz workbench’lerdeki autoload dosyalarını da tekrardan üretecektir. Artisan Autoload Komutunun Çalıştırılması 1 php artisan dump-autoload Paket Rotaları Laravel’in önceki sürümlerinde, bir paketin hangi URI’lere cevap vereceğini belirtmek için handles cümleciği kullanılırdı. Ancak, Laravel 4’te, bir paket her URI’ye cevap verebilir. Paketiniz için bir 199 Paket Geliştirme rota dosyasını yüklemek için, hizmet sağlayıcınızın boot metodu içerisinde onu include etmeniz yeterlidir. Bir Hizmet Sağlayıcısından Bir Rota Dosyasının Dahil Edilmesi 1 2 3 public function boot() { $this->package('satici/paket'); 4 include __DIR__.'/../../routes.php'; 5 6 } Not: Şayet paketiniz denetçiler (controllers) kullanıyorsa, bunların sizin composer.json dosyanızın autoload kesiminde düzgün bir şekilde yapılandırılmış olduğundan emin olun. Paket Yapılandırması Paket Yapılandırma Dosyalarına Erişme Bazı paketler yapılandırma dosyaları gerektirebilir. Bu dosyalar tipik uygulama yapılandırma dosyalarıyla aynı şekilde tanımlanmalıdır. Ve, hizmet sağlayıcınızda kaynakları kayda geçirmede ön tanımlı $this->package metodunu kullanıyorken, olağan “çift iki nokta üst üste” sözdizimini kullanarak erişebilirsiniz: 1 Config::get('paket::dosya.secenek'); Tek Dosyalı Paket Yapılandırmasına Erişme Ancak eğer paketiniz tek bir yapılandırma dosyası içeriyorsa, adına sadece config.php diyebilirsiniz. Böyle yapmışsanız, dosya adını belirtmenize gerek kalmadan seçeneklere doğrudan erişebilirsiniz: Paket Geliştirme 1 200 Config::get('paket::secenek'); Bir Kaynak Aduzayının Elle Kayda Geçirilmesi Bazen, görünümler gibi paket kaynaklarınızı tipik $this->package metodundan başka türlü kayda geçirmek isteyebilirsiniz. Tipik olarak bu sadece kaynaklar konvansiyonel bir yerleşimde olmadıkları takdirde yapılacaktır. Bu kaynakları elle kayda geçirmek için View, Lang ve Config sınıflarının addNamespace metodunu kullanabilirsiniz: 1 2 View::addNamespace('paket', __DIR__.'/views/dosya/yolu'\ ); Aduzayı kayda geçirildikten sonra, kaynağa erişmek için aduzayının adını ve “çift iki nokta üst üste” söz dizimini kullanabilirsiniz: 1 return View::make('paket::view.isim'); View, Lang ve Config sınıflarında addNamespace için metod biçimi aynıdır. Basamaklı Yapılandırma Dosyaları Diğer geliştiriciler sizin paketlerinizi yükledikleri zaman yapılandırma seçeneklerinden bir kısmını geçersiz kılmak ve değiştirmek isteyebilirler. Ancak, eğer sizin paket kaynak kodunuzdaki değerleri değiştirirlerse, Composer’in daha sonraki paket güncellemesinde bunun üzerine yazılacaktır, tekrar sizin yazdığınız hale gelecektir. O yüzden, bunun yerine config:publish artisan komutu kullanılmalıdır: 201 Paket Geliştirme 1 php artisan config:publish satici/paket Bu komut çalıştırıldığında, sizin uygulamanız için olan konfigürasyon dosyaları app/config/packages/satici/paket dizinine kopyalanacak, burada geliştiriciler tarafından güvenle değiştirilebilecektir! Not: Geliştiriciler ayrıca onları app/config/packages/satici/paket/environ koyarak sizin paketiniz için ortama özgü yapılandırma dosyaları da oluşturabilirler. Paket View’leri Eğer uygulamanızda bir paket kullanıyorsanız, kimi zaman paketin view’lerini özelleştirmek isteyebilirsiniz. Artisan view:publish komutunu kullanarak paket view’lerini sizin kendi app/views dizininize kolaylıkla ihraç edebilirsiniz: 1 php artisan view:publish satici/paket Bu komut paketin view’lerini app/views/packages dizinine taşıyacaktır. Şayet bu dizin önceden mevcut değilse, komutu çalıştırıldığınız zaman oluşturulacaktır. View’leri bu şekilde yayımladıktan sonra, onlarda kendi zevkinize göre değişiklikler yapabilirsiniz! İhraç edilen view’ler, paketin kendi view dosyalarına göre otomatik olarak öncelik alacaktır. Paket Migrasyonları Workbench Paketleri İçin Migrasyon Oluşturulması Paketleriniz için kolayca migrasyon oluşturabilir ve çalıştırabilirsiniz. workbench’de bir paket için bir migrasyon oluşturmak için --bench seçeneğini kullanın: 202 Paket Geliştirme 1 2 php artisan migrate:make create_users_table --bench="sa\ tici/paket" Workbench Paketleri İçin Migrasyonların Çalıştırılması 1 php artisan migrate --bench="satici/paket" Yüklenmiş Bir Paket İçin Migrasyonların Çalıştırılması vendor dizinine Composer tarafından yüklenmiş bitmiş bir paket için migrasyonlar çalıştırmak için --package yönergesini kullana- bilirsiniz: 1 php artisan migrate --package="satici/paket" Paket Varlıkları Paket Varlıklarının Public Dizinine Taşınması Bazı paketlerde JavaScript, CSS ve resimler gibi varlıklar olabilir. Ancak biz satici veya workbench dizinlerinde varlıklara bağlanamayız, öyleyse bu varlıkları uygulamamızın public dizinine taşıyacak bir yola ihtiyacımız var. Sizin için bununla asset:publish komutu ilgilenecektir: 1 php artisan asset:publish 2 3 php artisan asset:publish satici/paket Eğer paket hala workbench‘de ise, --bench yönergesini kullanın: Paket Geliştirme 1 203 php artisan asset:publish --bench="satici/paket" Bu komut varlıkları satıcı ve paket ismine göre public/packages dizinine taşıyacaktır. Yani, userscape/kudos adındaki bir paket kendi varlıklarını public/packages/userscape/kudos dizinine taşıyacaktır. Bu varlık yayımlama geleneğinin kullanılması, kendi paketlerinizin görünümlerinde varlık path’lerini güvenle kodlamanıza imkan verir. Paketlerin Yayımlanması Paketiniz yayımlanmaya hazır olduğunda, paketi Packagist¹⁷⁸ ambarına yollayacaksınız. Eğer paketiniz Laravel’e özgü ise, paketinizin composer.json dosyasına bir laravel etiketi eklemeyi düşünün. Ayrıca, geliştiriciler kendi composer.json dosyalarında sizin paketinize istek yaptıklarında stabil sürümlere bağlı olabilmeleri için sürümlerinizi de etiketlemeniz hoş ve yardımcı olacaktır. Şayet stabil bir sürüm hazır değilse, branch-alias Composer direktifini kullanmayı düşünün. Paketinizi yayımladıktan sonra, workbench tarafından oluşturulan uygulama bağlamı içinde onu geliştirmeye devam etmekte özgürsünüz. Bu, paketinizi yayımladıktan sonra bile rahat bir şekilde geliştirmek için muazzam bir yoldur. Bazı kuruluşlar kendi geliştiricileri için paketlerini kendi özel ambarlarında barındırmayı tercih ediyorlar. Siz de böyle yapmayı düşünürseniz, Composer ekibi tarafından sağlanan Satis¹⁷⁹ belgelerini inceleyin. ¹⁷⁸http://packagist.org ¹⁷⁹http://github.com/composer/satis Posta Yapılandırma Laravel popüler SwiftMailer¹⁸⁰ kitaplığı üzerinden temiz ve basit bir API sağlamaktadır. Posta yapılandırma dosyası app/config/mail.php‘dir ve sizin SMTP host, port ve kimlik bilgilerizi değiştirmenize, bunun yanında bu kitaplığın yolladığı tüm mesajlar için global bir from adresi ayarlamanıza imkan veren seçenekler içermektedir. İstediğiniz herhangi bir SMTP sunucusunu kullanabilirsiniz. Posta göndermek için şayet PHP’nin mail fonksiyonunu kullanmak istiyorsanız, yapılandırma dosyasındaki driver‘ı mail‘e değiştiriniz. Bir sendmail sürücüsü de bulunmaktadır. API Sürücüleri Laravel ayrıca Mailgun ve Mandrill HTTP API’ları için sürücüler içermektedir. Bu API’lar SMTP sunucularından çoğu kez daha basit ve hızlıdırlar. Bu sürücülerden her ikisi de uygulamanızda Guzzle 4 HTTP kitaplığının yüklenmiş olmasını gerektirir. composer.json dosyanıza aşağıdaki satırı eklemek suretiyle Guzzle 4’ü projenize ekleyebilirsiniz: 1 "guzzlehttp/guzzle": "~4.0" Mailgun Sürücüsü Mailgun sürücüsünü kullanmak için, app/config/mail.php yapılandırma dosyanızdaki driver seçeneğini mailgun olarak ayarlayın. Sonra da, projenizde zaten mevcut değilse bir app/config/services.php ¹⁸⁰http://swiftmailer.org 205 Posta yapılandırma dosyası oluşturun. Bu dosyanın aşağıdaki seçenekleri taşıdığını doğrulayın: 1 2 3 4 'mailgun' => array( 'domain' => 'your-mailgun-domain', 'secret' => 'your-mailgun-key', ), Mandrill Sürücüsü Mandrill sürücüsünü kullanmak için, app/config/mail.php yapılandırma dosyanızdaki driver seçeneğini mandrill olarak ayarlayın. Sonra da, projenizde zaten mevcut değilse bir app/config/services.php yapılandırma dosyası oluşturun. Bu dosyanın aşağıdaki seçenekleri taşıdığını doğrulayın: 1 2 3 'mandrill' => array( 'secret' => 'your-mandrill-key', ), Log Sürücüsü app/config/mail.php yapılandırma dosyanızdaki driver seçeneği log olarak ayarlanmışsa, bütün e-mailler log dosyalarınıza ya- zılacak ve alıcıların hiçbirisine gerçekten gönderilmeyecektir. Bu esas olarak hızlı, local hata ayıklama ve içerik doğrulaması için yararlıdır. Temel Kullanım Bir e-posta mesajı göndermek için Mail::send metodu kullanılabilir: 206 Posta 1 2 3 4 5 Mail::send('emails.welcome', $data, function($message) { $message->to('falan@numune.com', 'Can Simitci')->subje\ ct('Hoş geldiniz!'); }); Burada send metoduna geçilen ilk parametre e-posta gövde metni olarak kullanılacak görünümün (“view”in) ismidir ve ikinci parametre $data ise bu görünüme geçilecek veriyi temsil eder. Üçüncü parametremiz e-posta mesajında çeşitli seçenekler belirlememize imkan veren bir anonim fonksiyondur. Not: E-posta görünümlerine mutlaka bir $message değişkeni geçilir ve bu değişken bize ataşmanların yazı içine gömülmesi imkanı verir. Dolayısıyla sizin görünüm elemanlarınız arasında bir message değişkeni olmaması iyi olur. Bir HTML görünümüne ek olarak düz metin görünümü kullanmayı da belirtebilirsiniz: 1 2 Mail::send(array('html.view', 'text.view'), $data, $cal\ lback); Veya, html ya da text keylerini kullanmak suretiyle sadece bir tip görünüm belirleyebilirsiniz: 1 Mail::send(array('text' => 'view'), $data, $callback); E-posta mesajınızda bunlar yanında, karbon kopyalar veya ataşmanlar gibi başka seçenekler de belirtebilirsiniz: 207 Posta 1 2 3 Mail::send('emails.welcome', $data, function($message) { $message->from('bizden@numune.com', 'Laravel'); 4 $message->to('falan@numune.com')->cc('filan@numune.com\ 5 6 '); 7 $message->attach($eklenecekDosyaVeriYolu); 8 9 }); Bir mesaja dosya eklediğinizde, bir MIME tipi ve / veya ne adla görüneceğini de belirleyebilirsiniz: 1 2 $message->attach($eklenecekDosya, array('as' => $gorune\ cekAd, 'mime' => $mime)); Not: Bir Mail::send closure fonksiyonuna geçilen “message” olgusu, SwiftMailer’in message sınıfını genişleterek, e-posta mesajlarınızı oluşturmak için sınıf üzerinden her türlü metodu çağırabilmenize imkan verir. Ataşmanların Yazı İçine Gömülmesi Ataşmanların yazı içine gömülmesi tipik olarak zahmetlidir; ama Laravel size e-postalarınıza resimler eklemek ve uygun CID elde etmeniz için pratik bir yol sağlar. Bir E-Posta Görünümüne Bir Resim Gömülmesi 208 Posta 1 <body> İşte bir resim: 2 3 <img src ="<?php echo $message->embed($resimDosyaYolu);\ 4 5 6 ?>"> </body> Bir E-Posta Görünümüne Ham Veri Gömülmesi 1 <body> Burada ise ham veriden elde edilen resim görüyoruz: 2 3 <img src ="<?php echo $message->embedData($data, $name)\ 4 5 6 ; ?>"> </body> Mail sınıfı tarafından e-mail görünümlerine bu $message değişke- ninin MUTLAKA geçileceğini unutmayın. Postaların Sıraya Sokulması E-mail mesajlarının gönderilmesi uygulamanızın cevap zamanını önemli ölçüde uzatabileceği için, birçok geliştirici e-posta mesajlarını arka planda gönderilmek üzere kuyruğa sokmayı tercih eder. Laravel, dahili kuyruk API¹⁸¹‘sini kullanarak bunu kolaylaştırır. Bir e-posta mesajını kuyruğa sokmak için tek yapmanız gereken şey, Mail sınıfının queue metodunu kullanmaktır: Bir Mail Mesajının Kuyruğa Sokulması ¹⁸¹/docs/queues 209 Posta 1 2 3 4 5 Mail::queue('emails.welcome', $data, function($message) { $message->to('falan@numune.com', 'Can Simitci')->subje\ ct('Hoş geldiniz!'); }); later metodunu kullanarak mail mesajınızın gönderilmek için bekleyeceği saniye sayısını da belirleyebilirsiniz: 1 2 3 4 5 6 Mail::later(5, 'emails.welcome', $data, function($messa\ ge) { $message->to('falan@numune.com', 'Can Simitci')->subje\ ct('Hoş geldiniz!'); }); Mesajı yollamak için belirli bir kuyruk veya “tüpgeçit” belirlemek istiyorsanız bunu queueOn ve laterOn metodlarını kullanarak gerçekleştirebilirsiniz: 1 2 3 4 5 6 Mail::queueOn('queue-name', 'emails.welcome', $data, fu\ nction($message) { $message->to('falan@numune.com', 'Can Simitci')->subje\ ct('Hoş geldiniz!'); }); Posta & Yerel Geliştirme E-posta gönderen bir uygulama geliştirilirken, genelde lokal veya geliştirme ortamında mesaj göndermenin devre dışı bırakılması arzu edilmektedir. Bunu yapmak için, ya Mail::pretend metodunu çağırın ya da app/config/mail.php yapılandırma dosyanızdaki 210 Posta pretend seçeneğini true olarak ayarlayın. Mailer pretend modun- da olduğu zaman, mesajlar alıcıya gönderilmek yerine uygulamanızın günlük dosyalarına yazılacaktır. Taklit Posta Modunun Etkinleştirilmesi 1 Mail::pretend(); Sayfalama Yapılandırma Diğer frameworkler’de, sayfalama oldukça sıkıntılı olabilir. Laravel bu işi çocuk oyuncağı gibi yapar. app/config/view.php dosyasında bir tek yapılandırma seçeneği bulunmaktadır. Bu dosyadaki pagination seçeneği sayfalama bağlantıları (links) oluşturmak için kullanılması gereken görünümü (view) belirtir. Varsayılan olarak, Laravel iki görünüm içerir. pagination::slider görünümü mevcut sayfaya dayalı olarak akıllı bir bağlantı aralığı gösterirken, pagination::simple görünümü sadece “önceki” ve “sonraki” butonlarını gösterecektir. Her iki görünüm de Twitter Bootstrap ile uyumludur Kullanım Öğeleri sayfalamak için çeşitli yollar vardır. En basiti sorgu oluşturucusunda veya bir Eloquent modelinde paginate metodunu kullanmaktır. Veritabanı Sonuçlarının Sayfalandırılması 1 $uyeler = DB::table('users')->paginate(15); Not: Şu an için, bir groupBy cümlesi kullanan pagination işlemleri Laravel tarafından verimli bir biçimde çalıştırılamamaktadır. Eğer sayfalanmış bir sonuç kümesinde bir groupBy kullanmanız gerekiyorsa, veritabanını elle sorgulamanız ve Paginator::make kullanmanız önerilir. Sayfalama 212 Bir Eloquent Modelinin Sayfalandırılması Eloquent¹⁸² modellerini de sayfalandırabilirsiniz: 1 $uyeler = User::paginate(15); 2 3 $uyeler = User::where('votes', '>', 100)->paginate(15); paginate metoduna geçilen argüman sayfa başına görüntülemek istediğiniz öğelerin sayısıdır. Bir kez sonuçları aldıktan sonra görünümde görüntüleyebilir ve links metodunu kullanarak sayfalama bağlantıları oluşturabilirsiniz: 1 2 3 4 5 <div class ="container"> <?php foreach ($uyeler as $uye): ?> <?php echo $uye->isim; ?> <?php endforeach; ?> </div> 6 7 <?php echo $uyeler->links(); ?> Sayfalama sistemi oluşturmak işte bu kadar! Unutmayın, mevcut sayfa için frameworke bilgi vermedik. Laravel bunu sizin için otomatik olarak belirleyecektir. Sayfalama için kullanılacak özel bir view belirtmek isterseniz, links metoduna bir view geçebilirsiniz: 1 <?php echo $uyeler->links('view.ismi'); ?> Ayrıca aşağıdaki metodlar aracılığıyla diğer sayfalama bilgilerine erişebilirsiniz: ¹⁸²/docs/eloquent 213 Sayfalama • • • • • • • getCurrentPage getLastPage getPerPage getTotal getFrom getTo count “Basit Sayfalandırma” Eğer sayfalandırma view’inizde sadece “Sonraki” ve “Önceki” linklerini gösteriyorsanız, daha etkin bir sorgulama gerçekleştirmek için simplePaginate metodunu kullanma seçeneğine sahipsiniz. Bu, view’inizde tam sayfa numaraları gösterilmesi gerekmediğinde, büyük veri setleri için kullanışlıdır: 1 2 $uyeler = User::where('votes', '>', 100)->simplePaginat\ e(15); Elle Bir Sayfalandırıcı Oluşturmak Bazen bir sayfalama olgusunu kendiniz bir öğeler dizisi geçerek oluşturmak isteyebilirsiniz. Bunu Paginator::make metodunu kullanarak yapabilirsiniz: 1 2 $sayfalandirici = Paginator::make($ogeler, $toplamOgeAd\ edi, $sayfaBasinaAdet); Sayfalama URI’ını Özelleştirmek setBaseUrl metodu aracılığıyla, sayfalandırıcı tarafından URI’yi de özelleştirebilirsiniz: Sayfalama 1 214 $uyeler = Uye::paginate(); 2 3 $uyeler->setBaseUrl('ozel/url'); Yukarıdaki örnek böyle bir URL oluşturacaktır: http://ornek.com/ozel/url?page =2 Sayfalama Linklerine Ekleme Yapmak Sayfalandırıcı üzerinde appends metodunu kullanarak sayfalama linklerinize sorgu katarı (query string) ekleyebilirsiniz: 1 2 <?php echo $uyeler->appends(array('sira' => 'oylar'))->\ links(); ?> Bu kod, sayfalama linkine “&sira =oylar” ekleyecek ve şöyle bir URL üretecektir: 1 http://ornek.com/birsey?page =2&sira =oylar Eğer sayfalandırıcının URL’sine bir “hash fragmanı” eklemek istiyorsanız, fragment metodunu kullanabilirsiniz: 1 <?php echo $uyeler->fragment('falan')->links(); ?> Bu metod bunun gibi gözüken URL’ler üretecektir: 1 http://ornek.com/birsey?page =2#falan 215 Sayfalama JSON’a Dönüştürme Paginator sınıfı Illuminate\Support\Contracts\JsonableInterface sözleşmesini implemente eder ve toJson metoduna sahiptir. Bir Paginator olgusunu bir rotadan döndürerek de onu JSON’a çevirebilirsiniz. Bu olgunun JSON’lanmış biçimi total, current_page, last_page, from ve to gibi bazı “meta” bilgilerini de içerecektir. Olgunun verileri JSON dizisindeki data anahtarı aracılığı ile erişebilir olacaktır. Özel Sunumcular Laravelle geldiği haliyle ön tanımlı sayfalama sunumcusu Bootstrap uyumludur; ancak siz bunu kendi seçeceğiniz bir sunumcu ile özelleştirebilirsiniz. Soyut Sunumcunun Genişletilmesi Illuminate\Pagination\Presenter sınıfını genişletin ve onun so- yut (abstract) metodlarını implemente edin. Zurb Foundation için örnek bir sunumcu bunun gibi gözükebilir: 1 2 class ZurbPresenter extends Illuminate\Pagination\Prese\ nter { 3 4 5 6 7 8 public function getActivePageWrapper($text) { return '<li class ="current"><a href ="">'.$text.\ '</a></li>'; } 9 10 11 public function getDisabledTextWrapper($text) { 216 Sayfalama return '<li class ="unavailable">'.$text.'</li>'; 12 } 13 14 15 16 17 18 19 public function getPageLinkWrapper($url, $page) { return '<li><a href ="'.$url.'">'.$page.'</a></l\ i>'; } 20 21 } Özel Sunumcunun Kullanılması Önce app/views dizininizde sizin özel sunumcunuz olarak hizmet edecek bir view oluşturun. Ondan sonra, app/config/view.php yapılandırma dosyasındaki pagination seçeneğini yeni view’in adıyla değiştirin. Son olarak, özel sunumcu view’inizde aşağıdaki kodu koyacaksınız: 1 2 3 4 <ul class ="pagination"> <?php echo with(new ZurbPresenter($paginator))->ren\ der(); ?> </ul> Şablonlar Denetçi (Controller) Düzenleri Laravel’de şablon kullanma yöntemlerinden birisi denetçi düzenleri üzerinden gerçekleştirilir. İlgili denetçideki layout özelliğinin belirlenmesiyle, belirlemiş olduğunuz görünüm oluşturulacak ve eylemlerden dönmüş cevap olarak kabul edilecektir. Bir Denetçide Bir Düzen Tanımlanması 1 class UyeController extends BaseController { 2 /** * Cevaplar için kullanılacak olan düzen. */ protected $layout = 'layouts.master'; 3 4 5 6 7 /** * Uye profilini göster. */ public function showProfil() { $this->layout->content = View::make('uye.profil'); } 8 9 10 11 12 13 14 15 16 } 218 Şablonlar Blade Şablonları Blade Laravel’le gelen basit ama güçlü bir şablon motorudur. Denetçi düzenlerinden farklı olarak, Blade şablon kalıtımı ve kesimler (sections) ile yürütülür. Tüm Blade şablonlarının uzantısı .blade.php olmalıdır. Bir Blade Düzeninin Tanımlanması 1 2 <!-- app/views/layouts/master.blade.php'de bulunmaktadı\ r--> 3 4 <html> <body> 5 @section('sidebar') This is the master sidebar. @show 6 7 8 9 <div class ="container"> @yield('content') </div> 10 11 12 </body> 13 14 </html> Bir Blade Düzeninin Kullanılması 219 Şablonlar 1 @extends('layouts.master') 2 3 4 @section('sidebar') @parent 5 <p>Burası master sidebar'a eklenmiştir.</p> 6 7 @stop 8 9 10 11 @section('content') <p>Burası kendi content bölümümdür.</p> @stop Bir Blade düzenini genişleten (extend) görünümlerin, düzenden gelen kesimleri değiştirmekten başka bir şey yapmadığını unutmayın. İlgili düzenin içeriği bir kesimde @parent direktifi kullanılarak çocuk görünüme katılabilir, böylece bir kenar çubuğu veya altbilgi gibi bir düzen kesimine eklemeler yapabilirsiniz. Kimi zaman, örneğin bir kesimin tanımlanmış olup olmadığından emin olmadığınız durumlarda, @yield direktifine ön tanımlı bir değer geçmek isteyebilirsiniz. Bu ön tanımlı değer ikinci parametre olarak geçilebilir. 1 @yield('section', 'Ön Tanımlı İçerik'); Diğer Blade Kontrol Yapıları Veri Yazdırılması 1 Merhaba {{{ $isim }}}. 2 3 Şu anki UNIX zaman damgası {{{ time() }}}'dır. Şablonlar 220 Verinin Varlığını Yokladıktan Sonra Yazdırılması Bazen bir değişkeni echo yapmak isteyebilir ama değişkenin ayarlanmış olup olmadığından emin olmayabilirsiniz. Temel olarak bunu yapmak istersiniz: 1 {{{ isset($isim) ? $isim : 'Default' }}} Bununla birlikte, bir ternary cümlesi yazmak yerine, Blade size aşağıdaki kullanışlı kısayolu kullanma imkanu verir: 1 {{{ $isim or 'Default' }}} Küme Parantezi İle Ham Metin Görüntülemek Küme parantezleri ile sarmalanmış bir metni görüntülemek isterseniz, küme parantezi önüne @ sembolü ilave ederek Blade davranışını devredışı bırakabilirsiniz. 1 @{{ Bu metin Blade tarafından işleme alınmayacaktır }} Tabii ki, kullanıcılardan gelen tüm veriler escape edilmeli ya da arındırılmalıdır. Çıktıyı escape etmek için, üçlü küme parantezi sözdizimini kullanabilirsiniz: 1 Merhaba {{{ $isim }}}. Eğer verinin escape edilmesini istemiyorsanız, ikili küme parantezi kullanabilirsiniz: 1 Merhaba, {{ $isim }}. Not: Uygulamanızın kullanıcılarından gelen verileri yazdıracağınız zaman çok dikkatli olun. İçerikte olabilecek HTML antitelerini escape etmek amacıyla her zaman için üçlü küme parantezi sözdizimi kullanın. 221 Şablonlar If Cümleleri 1 2 3 4 5 6 7 @if (count($records) === 1) Tek kayıt var! @elseif (count($records) > 1) Birden çok kayıt var! @else Hiç kayıt yok! @endif 8 9 10 11 @unless (Auth::check()) Giriş yapmadınız. @endunless Döngüler 1 2 3 @for ($i = 0; $i < 10; $i++) Şu anki değer {{ $i }}'dir. @endfor 4 5 6 7 @foreach ($uyeler as $uye) <p>Bu, üye {{ $uye->id }}'dir.</p> @endforeach 8 9 10 11 12 13 @forelse($users as $user) <li>{{ $user->name }}</li> @empty <p>Bir üye yok</p> @endforelse 14 15 16 17 @while (true) <p>Sonsuz döngüdeyim.</p> @endwhile Alt Görünümlerin Dahil Edilmesi 222 Şablonlar 1 @include('view.ismi') Dahil edilen görünüme bir veri dizisi de geçebilirsiniz: 1 @include('view.ismi', array('birsey'=>'veri')) Kesimlerin Üzerine Yazmak Ön tanımlı olarak, section’lar sectionda önceden mevcut olan bir içeriğe eklenirler. Bir section’u, öncekini geçersiz kılarak tümden üzerine yazmak için overwrite cümlesini kullanabilirsiniz: 1 @extends('list.item.container') 2 3 4 5 @section('list.item.content') <p>Bu {{ $item->type }} tipinde bir öğedir</p> @overwrite Dil Satırlarının Gösterilmesi 1 @lang('language.line') 2 3 @choice('language.line', 1); Yorumlar 1 2 {{-- Bu yorum, gösterilen HTML içerisinde olmayacaktır \ --}} Blade’in Genişletilmesi Blade sizin kendi özel kontrol yapılarınızı tanımlamanıza dahi imkan verir. Bir Blade dosyası derlendiği zaman, her bir özel genişletme, görünüm içerikleriyle çağrılarak basit manipülasyonlardan Şablonlar 223 daha karmaşık düzenli ifadelere kadar her türlü şeyi yapmanıza izin verir. Blade derleyicisi sizin kendi özel direktiflerinizi inşa etmeniz için gerekli ifadeleri üreten createMatcher ve createPlainMatcher yardımcı metodlarıyla birlikte gelir. Bunlardan createPlainMatcher metodu bir parametre almayan @endif ve @stop gibi direktifler için kullanılır, createMatcher ise parametreli direktifler için kullanılır. Aşağıdaki örnek, basitçe $var üzerinde ->format() metodunu çağıran bir @datetime($var) direktifi oluşturur: 1 2 3 Blade::extend(function($view, $compiler) { $pattern = $compiler->createMatcher('datetime'); 4 5 6 7 return preg_replace($pattern, '$1<?php echo $2->format\ (\'m/d/Y H:i\'); ?>', $view); }); SSH Yapılandırma Laravel uzak sunuculara SSH (Secure Shell) iletişimi ve komutlar çalıştırmak için basit bir yol içerir ve uzak sunucularda çalışan Artisan görevlerini kolayca inşa etmenize imkan verir. SSH facade’ı uzak sunucularınıza bağlanmanız ve komutlar çalıştırmanız için erişim noktası sağlar. Yapılandırma dosyası app/config/remote.php konumundadır ve uzak bağlantılarınızı yapılandırmak için gerekli tüm seçenekleri içerir. Bu dosyadaki connections dizisi, sürücülerinizin isimlerine göre anahtarlanmış bir listesini taşır. Bu connections dizisindeki host, username, password, key gibi erişim güven bilgilerini (credentials) doldurduktan sonra uzak görevleri çalıştırmaya hazır olacaksınız. Unutmayın, SSH, ya bir password ya da bir SSH key kullanarak kimlik doğrulaması yapabilmektedir. Not: Uzak sunucunuzda çeşitli görevleri kolayca çalıştırma ihtiyacınız mı var? Envoy görev çalıştırıcısına bir bakın! Temel Kullanım Komutları Default Sunucuda Çalıştırmak Komutlarınızı default uzak bağlantınızda çalıştırmak için SSH::run metodunu kullanın: 225 SSH 1 2 3 4 SSH::run(array( 'cd /var/www', 'git pull origin master', )); Komutları Belirli Bir Bağlantıda Çalıştırmak Alternatif olarak, into metodunu kullanmak suretiyle komutları belirli bir bağlantı üzerinde çalıştırabilirsiniz: 1 2 3 4 SSH::into('staging')->run(array( 'cd /var/www', 'git pull origin master', )); Komut Çıktılarını Yakalamak run metoduna bir Closure geçmek suretiyle, uzak komutlarınızın “canlı” çıktısını yakalayabilirsiniz: 1 2 3 4 SSH::run($commands, function($line) { echo $line.PHP_EOL; }); Görevler Eğer her zaman birlikte çalışması gereken bir grup komut tanımlamanız gerekiyorsa, bir task (görev) tanımlamak için define metodunu kullanabilirsiniz: 226 SSH 1 2 3 4 5 SSH::into('staging')->define('deploy', array( 'cd /var/www', 'git pull origin master', 'php artisan migrate', )); Bu şekilde bir task tanımladıktan sonra, onu çalıştırmak için task metodunu kullanabilirsiniz: 1 2 3 4 SSH::into('staging')->task('deploy', function($line) { echo $line.PHP_EOL; }); SFTP Dosya İndirmeleri SSH sınıfı get ve getString metodları kullanılarak, dosyalar indir- mek için basit bir yol sağlar: 1 SSH::into('staging')->get($remotePath, $localPath); 2 3 4 $contents = SSH::into('staging')->getString($remotePath\ ); SFTP Dosya Göndermeleri SSH sınıfı aynı zamanda put ve putString metodları kullanılarak sunucuya dosyalar, hatta stringler upload etmek için de basit bir yol içerir: 227 SSH 1 SSH::into('staging')->put($localFile, $remotePath); 2 3 SSH::into('staging')->putString($remotePath, 'Falan'); Uzak Günlüklerin İzlenmesi Laravel sizin uzak bağlantılarınızın herhangi birindeki laravel.log dosyalarının izlenmesi için yararlı bir komut içermektedir. Bunun için basitçe tail Artisan komutunu kullanın ve izlemek istediğiniz uzak bağlantının adını belirtin: 1 php artisan tail staging 2 3 php artisan tail staging --path=/path/to/log.file Envoy Görev Çalıştırıcısı • • • • • • • Yükleme Görevlerin Çalıştırılması Birden Çok Sunucu Paralel Çalıştırma Task Makroları Bildirimler Envoy’in Güncellenmesi Laravel Envoy, uzak sunucularınızda ortak görevler tanımlanması için temiz, minimal bir sözdizimi sağlar. Blade¹⁸³ tarzı bir sözdizimi kullanarak yayımlama, Artisan komutları ve başka şeyler için kolayca görevler inşa edebilirsiniz. Not: Envoy, PHP versiyon 5.4 veya daha üstünü gerektirir ve sadece Mac / Linux işletim sistemlerinde çalışır. ¹⁸³/docs/templates#blade-templating 228 SSH Yükleme Önce, Composer global komutunu kullanarak Envoy’u yükleyin: 1 composer global require "laravel/envoy =~1.0" Terminalinizde envoy komutunu çalıştırdığınız zaman envoy çalıştırılabilir dosyasının bulunabilmesi için PATH ayarınızda ∼/.composer/vendor/bin dizininin yer aldığından emin olun. Sonra da, projenizin kökünde bir Envoy.blade.php dosyası oluşturun. İşte başlayabileceğiniz bir örnek: 1 @servers(['web' => '192.168.1.1']) 2 3 4 5 @task('falan', ['on' => 'web']) ls -la @endtask Görebileceğiniz gibi, dosyanın en üstünde bir @servers dizisi tanımlanır. Bu sunucuları, task (görev) deklarasyonlarınızın on seçeneğinde refere edebilirsiniz. Bu @task deklarasyonlarınızın içerisine, task çalıştırıldığı zaman sunucunuzda çalıştırılacak olan Bash kodunu koyacaksınız. Bir iskelet Envoy dosyasını kolayca oluşturmak için init komutu kullanılabilir: 1 envoy init user@192.168.1.1 Görevlerin Çalıştırılması Bir görevi çalıştırmak için Envoy yüklemenizin run komutunu kullanın: 229 SSH 1 envoy run falan Eğer gerekliyse, komut satırı seçeneklerini kullanarak Envoy dosyasına değişkenler geçebilirsiniz: 1 envoy run deploy --branch=master Bu seçenekleri, kullandığınız Blade sözdizimi aracılığıyla kullanabilirsiniz: 1 @servers(['web' => '192.168.1.1']) 2 3 4 5 6 7 @task('deploy', ['on' => 'web']) cd site git pull origin {{ $branch }} php artisan migrate @endtask Bootstrapping Envoy dosyasının içinde değişkenler deklare etmek ve genel PHP işi yapmak için @setup direktifini kullanabilirsiniz: 1 2 @setup $now = new DateTime(); 3 4 5 $environment = isset($env) ? $env : "testing"; @endsetup Ayrıca bir PHP dosyası include etmek için @include kullanabilirsiniz: 230 SSH 1 @include('vendor/autoload.php'); Birden Çok Sunucu Bir görevi birden çok sunucuda kolaylıkla çalıştırabilirsiniz. Sadece task deklarasyonunda sunucuları listeleyin: 1 2 @servers(['web-1' => '192.168.1.1', 'web-2' => '192.168\ .1.2']) 3 4 5 6 7 8 @task('deploy', ['on' => ['web-1', 'web-2']]) cd site git pull origin {{ $branch }} php artisan migrate @endtask Ön tanımlı olarak, ilgili görev her bir sunucuda seri olarak çalıştırılacaktır. Yani, görev bir sonraki sunucuda çalışmaya başlamadan önce, önceki çalışmasını tamamlayacaktır. Paralel Çalıştırma Eğer bir görevi birden çok sunucuda paralel olarak çalıştırmak istiyorsanız, yapmanız gereken tek şey task deklarasyonunuza parallel seçeneğini eklemektir: 231 SSH 1 2 @servers(['web-1' => '192.168.1.1', 'web-2' => '192.168\ .1.2']) 3 4 5 6 7 8 9 @task('deploy', ['on' => ['web-1', 'web-2'], 'parallel'\ => true]) cd site git pull origin {{ $branch }} php artisan migrate @endtask Task Makroları Makrolar basit bir komut kullanarak sıralı bir biçimde çalışacak bir görev kümesi tanımlamanıza imkan verirler. Örneğin: 1 @servers(['web' => '192.168.1.1']) 2 3 4 5 6 @macro('deploy') falan filan @endmacro 7 8 9 10 @task('falan') echo "MERHABA" @endtask 11 12 13 14 @task('filan') echo "DÜNYA" @endtask Artık bu deploy makrosu tek, basit bir komut aracılığı ile çalıştırılabilecektir: 232 SSH 1 envoy run deploy Bildirimler HipChat Bir görevi çalıştırdıktan sonra, basit @hipchat direktifini kullanarak ekibinizin HipChat odasına bir bildirim gönderebilirsiniz: 1 @servers(['web' => '192.168.1.1']) 2 3 4 5 @task('falan', ['on' => 'web']) ls -la @endtask 6 7 @after 8 @hipchat('token', 'room', 'Envoy') @endafter 9 Ayrıca hipchat odasına, özel bir mesaj da belirtebilirsiniz. @setup içinde deklare edilen veya @include ile dahil edilen her değişkenin mesajda kullanılması mümkündür: 1 @after 2 @hipchat('token', 'room', 'Envoy', "$task ran on [$env\ ironment]") @endafter 3 4 Bu, ekibinizi sunucu üzerinde çalıştırılan görevler hakkında haberdar tutmak için inanılmaz basit bir yoludur. 233 SSH Slack Slack’a¹⁸⁴ bir bildirim göndermek için aşağıdaki sözdizimi kullanılabilir: 1 @after 2 @slack('team', 'token', 'channel') @endafter 3 Envoy’un Güncellenmesi Envoy’u güncellemek için, tek yapacağınız self-update komutunu çalıştırmaktır: 1 envoy self-update Eğer Envoy yüklediğiniz yer /usr/local/bin ise, sudo kullanmanız gerekebilir: 1 sudo envoy self-update ¹⁸⁴https://slack.com Unit Testing Giriş Laravel hazırlanırken birim testler ile hazırlandı. Açıkçası, PHPUnit ile test desteği halihazırda var ve uygulamanız için hazırlanmış phpunit.xml dosyası da Laravel ile birlikte geliyor. PHPUnit’in haricinde, Laravel ayrıca Symfony HttpKernel, DomCrawler ve BrowserKit bileşenlerinden de yararlanıyor ki, kullanıcılar testler sırasında görünümleri inceleyebilsin ve müdahale edebilsin. Bu bileşenler ile temsili bir tarayıcıya sahip oluyorsunuz. Örnek bir test dosyası app/tests dizininde bulunmaktadır. Yeni bir Laravel uygulaması kurulumundan sonra, komut satırında phpunit komutuyla testlerinizi çalıştırabilirsiniz. Testleri Tanımlamak ve Çalıştırmak Yeni bir test durumu oluşturmak için, app/test dizini içerisinde yeni bir test dosyası oluşturmanız yeterli. Test sınıflarınız TestCase sınıfını extend ediyor olmalıdır. Bu şekilde normalde PHPUnit ile hazırladığınız test metodlarını aynı şekilde oluşturabilirsiniz. Örnek Bir Test Sınıfı 235 Unit Testing 1 class FooTest extends TestCase { 2 public function testSomethingIsTrue() { $this->assertTrue(true); } 3 4 5 6 7 8 } Daha sonra komut satırında phpunit ile uygulamanızın tüm testlerini çalıştırabilirsiniz. Not: Eğer kendi setUp methodunuzu tanımlarsanız, parent::setUp kodunu çalıştırdığınızdan emin olun. Test Ortamı Testleri çalıştırırken, Laravel otomatik olarak ortam yapılandırmasını testing‘e alacaktır. Ayrıca, Laravel’de test ortamında önbellekleme ve oturum için özel ayar dosyaları bulunmaktadır. İki sürücü de bir dizi olacak şekilde ayarlanmış olup, test yaparkenki oturum ve önbellek verilerinin kalıcı olmaması sağlanmıştır. Test ortamı için gerektiğinde başka ayarlar yapmakta özgürsünüz. Testlerin İçerisinden Rotaları Çağırmak Test Dosyasından Bir Rota Çağırmak Testleriniz içerisinde call metodu ile rahatlıkla rotaları çağırabilirsiniz: Unit Testing 1 236 $response = $this->call('GET', 'user/profile'); 2 3 4 $response = $this->call($method, $uri, $parameters, $fi\ les, $server, $content); Daha sonra Illuminate\Http\Response nesnesini inceleyebilirsiniz: 1 2 $this->assertEquals('Hello World', $response->getConten\ t()); Test Dosyasından Bir Denetçi Çağırmak Ayrıca bir test dosyasından denetçileri de çağırabilirsiniz: 1 2 $response = $this->action('GET', 'HomeController@index'\ ); 3 4 5 $response = $this->action('GET', 'UserController@profil\ e', array('user' => 1)); getContent metodu cevap olarak değerlendirilmiş string içeriğini döndürecektir. Eğer rotanız bir Görünüm döndürüyorsa, original özelliği ile buna ulaşabilirsiniz: 1 $view = $response->original; 2 3 $this->assertEquals('Tuana Şeyma', $view['name']); Bir HTTPS rotayı çağırmak için, callSecure metodunu kullanabilirsiniz. 237 Unit Testing 1 $response = $this->callSecure('GET', 'falan/filan'); Not: Testing ortamında olduğunuzda rota filtreleri devre dışı bırakılır. Bunları etkinleştirmek için testinize Route::enableFilters() ekleyin. DOM Böceği Ayrıca bir rota çağırıp, bir DOM Böceği nesnesi alarak içeriği inceleyebilirsiniz: 1 $crawler = $this->client->request('GET', '/'); 2 3 $this->assertTrue($this->client->getResponse()->isOk()); 4 5 6 $this->assertCount(1, $crawler->filter('h1:contains("He\ llo World!")')); Böceği nasıl kullanacağınız hakkında detaylı bilgi için kendi dökümantasyonunu¹⁸⁵ okuyabilirsiniz. Facade’ları Taklit Etmek Test yaparken, sabit Laravel facadelarını taklit etmeniz gerekecektir. Örneğin, şu denetçi aksiyonunu varsayalım: ¹⁸⁵http://symfony.commaster/components/dom_crawler.html 238 Unit Testing 1 2 3 public function getIndex() { Event::fire('falan', array('name' => 'Sergin Arı')); 4 return 'Herşey yolunda!'; 5 6 } Event sınıfına yapılan çağrıyı taklit edebilmek için Facade üzerinde shouldReceive metodunu kullanabilirsiniz, bu metod bir Moc- kery¹⁸⁶ olgusu döndürecek. Bir Facade’ı Taklit Etmek 1 2 3 4 public function testGetIndex() { Event::shouldReceive('fire')->once()->with(array('name\ ' => 'Sergin Arı')); 5 $this->call('GET', '/'); 6 7 } Not: Request metodunu taklit etmemelisiniz. Bunun yerine, testlerinizi çalıştırırken istediğiniz girdileri call metodunda belirtin. Çatının Assert Metodları Laravel test yapımını kolaylaştırmak için halihazırda bazı assert metodlarıyla gelir: Yanıtın Başarıyla Geldiği Ispatlamak ¹⁸⁶https://github.com/padraic/mockery 239 Unit Testing 1 2 3 public function testMethod() { $this->call('GET', '/'); 4 $this->assertResponseOk(); 5 6 } Yanıt Kodlarını Ispatlamak 1 $this->assertResponseStatus(403); Yanıtın Bir Yönlendirme Olduğunu Ispatlamak 1 $this->assertRedirectedTo('falan'); 2 3 $this->assertRedirectedToRoute('route.name'); 4 5 $this->assertRedirectedToAction('Controller@method'); Bir Görünümde Veri Olduğunu Ispatlamak 1 2 3 public function testMethod() { $this->call('GET', '/'); 4 $this->assertViewHas('name'); $this->assertViewHas('age', $value); 5 6 7 } Oturumda Bir Verinin Kayıtlı Olduğunu Ispatlamak Unit Testing 1 2 3 240 public function testMethod() { $this->call('GET', '/'); 4 $this->assertSessionHas('name'); $this->assertSessionHas('age', $value); 5 6 7 } Session’da Hatalar Olup Olmadığını Ispatlama 1 2 3 public function testMethod() { $this->call('GET', '/'); 4 5 $this->assertSessionHasErrors(); 6 7 8 9 // Verilen bir anahtar için sessionda hata olup olmadı\ ğına bakmak... $this->assertSessionHasErrors('name'); 10 11 12 13 14 // Birkaç anahtar için sessionda hata olup olmadığına \ bakmak... $this->assertSessionHasErrors(array('name', 'age')); } Eski Girdide Veri Olduğunu Ispatlamak 241 Unit Testing 1 2 3 public function testMethod() { $this->call('GET', '/'); 4 $this->assertHasOldInput(); 5 6 } Yardımcı Metodlar Test yapımını kolaylaştırmak için TestCase sınıfı bazı yardımcı metodlarla birlikte gelir. Test İçerisinden Oturum Tanımlamak ve Silmek 1 $this->session(['falan' => 'filan']); 2 3 $this->flushSession(); Oturum Açmış Kullanıcıyı Belirleme Mevcut oturum açmış kullanıcıyı be metodu ile belirleyebilirsiniz. 1 $user = new User(array('name' => 'Tuana Şeyma')); 2 3 $this->be($user); Bir test içerisinden seed metoduyla veritabanınıza yeniden veri ekebilirsiniz: Test İçerisinden Veritabanına Yeniden Veri Ekmek 242 Unit Testing 1 $this->seed(); 2 3 $this->seed($connection); Veri Ekmeyle ilgili daha fazla bilgiyi dökümantasyonun migrasyon ve veri ekme¹⁸⁷ bölümünde bulabilirsiniz. Application’ın Tazelenmesi Belki de zaten bildiğiniz gibi, Laravel Application / IoC Konteynerinize herhangi bir test metodundan $this->app aracılığıyla erişebilirsiniz. Bu Application olgusu her test sınıfı için tazelenir. Şayet siz Application’ı verilen bir metod için elle tazelenmeye zorlamak istiyorsanız, test metodunuzdan refreshApplication metodunu kullanabilirsiniz. Bu, test durumu çalıştırılmaya başlandıktan itibaren IoC konteynerine konmuş olan herhangi bir ekstra bağlamayı, örneğin mocks (taklit)’ları resetleyecektir. ¹⁸⁷/docs/migrations#database-seeding Yardımcı (Helper) Fonksiyonları Arrayler (Diziler) array_add array_add fonksiyonu, verilen anahtar / değer çiftini, eğer daha önce eklenmemişse array’e eklemeye yarar. 1 $array = array('foo' => 'bar'); 2 3 $array = array_add($array, 'key', 'value'); array_divide array_divide fonksiyonu, birincisi anahtarlar, ikincisi değerler olacak şekilde iki farklı array döndürür. 1 $array = array('foo' => 'bar'); 2 3 list($keys, $values) = array_divide($array); array_dot array_dot fonksiyonu, çok boyutlu bir array’i derinlikleri ‘nokta (dot)’ notasyonunu sağlayacak şekilde 1 boyutlu array’e çevirir. Yardımcı (Helper) Fonksiyonları 1 244 $array = array('foo' => array('bar' => 'baz')); 2 3 $array = array_dot($array); 4 5 // array('foo.bar' => 'baz'); array_except array_except fonksiyonu, verilen anahtar / değer çiftini array’den siler. 1 2 $array = array_except($array, array('keys', 'to', 'remo\ ve')); array_fetch array_fetch metodu seçilen bir iç elemanı içeren düz bir dizi döndürür. 1 2 3 4 $array = array( array('developer' => array('name' => 'Taylor')), array('developer' => array('name' => 'Dayle')), ); 5 6 $array = array_fetch($array, 'developer.name'); 7 8 // array('Taylor', 'Dayle'); array_first array_first fonksiyonu, verilen doğruluk testine uyan ilk array elemanını döndürür. 245 Yardımcı (Helper) Fonksiyonları 1 $array = array(100, 200, 300); 2 3 4 5 6 $value = array_first($array, function($key, $value) { return $value >= 150; }); Ayrıca varsayılan bir değer, üçüncü eleman olarak verilebilir: 1 $value = array_first($array, $callback, $default); array_last array_last metodu verilen doğruluk testine uyan son array elema- nını döndürür. 1 $array = array(350, 400, 500, 300, 200, 100); 2 3 4 5 6 $value = array_last($array, function($key, $value) { return $value > 350; }); 7 8 // 500 Ayrıca varsayılan bir değer, üçüncü eleman olarak geçilebilir: 1 $value = array_last($array, $callback, $default); array_flatten array_flatten metodu çok boyutlu bir diziyi tek düzey halinde düzleştirir. 246 Yardımcı (Helper) Fonksiyonları 1 2 $array = array('name' => 'Joe', 'languages' => array('P\ HP', 'Ruby')); 3 4 $array = array_flatten($array); 5 6 // array('Joe', 'PHP', 'Ruby'); array_forget array_forget metodu “dot” notasyonu kullanarak, derin bir iç içe diziden belirli bir anahtar / değer çiftini kaldıracaktır. 1 2 $array = array('names' => array('joe' => array('program\ mer'))); 3 4 array_forget($array, 'names.joe'); array_get array_get metodu nokta notasyonu kullanarak derin bir iç içe diziden belirli bir değeri döndürür. 1 2 $array = array('names' => array('joe' => array('program\ mer'))); 3 4 $value = array_get($array, 'names.joe'); Not: array_get gibi birşey ama onun yerine nesneler mi istiyorsunuz? object_get kullanın. array_only array_only fonksiyonu, array’den sadece verilen anahtar / değer çiftlerini döndürür. 247 Yardımcı (Helper) Fonksiyonları 1 2 $array = array('name' => 'Joe', 'age' => 27, 'votes' =>\ 1); 3 4 $array = array_only($array, array('name', 'votes')); array_pluck array_pluck metodu verilen bir anahtar / değer çiftleri listesini diziden koparacaktır. 1 2 $array = array(array('name' => 'Taylor'), array('name' \ => 'Dayle')); 3 4 $array = array_pluck($array, 'name'); 5 6 // array('Taylor', 'Dayle'); array_pull array_pull metodu diziden belirli bir anahtar / değer çifti döndü- recek, aynı zamanda bu çifti diziden çıkartacaktır. 1 $array = array('name' => 'Taylor', 'age' => 27); 2 3 $name = array_pull($array, 'name'); array_set array_set metodu nokta notasyonu kullanarak, derin bir iç içe dizide bir değer ayarlar. Yardımcı (Helper) Fonksiyonları 1 248 $array = array('names' => array('programmer' => 'Joe')); 2 3 array_set($array, 'names.editor', 'Taylor'); array_sort array_sort metodu bir diziyi verilen bir Closure sonuçlarına göre sıralar. 1 2 3 4 $array = array( array('name' => 'Jill'), array('name' => 'Barry'), ); 5 6 7 8 9 10 $array = array_values(array_sort($array, function($valu\ e) { return $value['name']; })); array_where Bir diziyi verilen Closure kullanarak filtreler. 1 $array = array(100, '200', 300, '400', 500); 2 3 4 5 6 $array = array_where($array, function($key, $value) { return is_string($value); }); 7 8 // Array ( [1] => 200 [3] => 400 ) 249 Yardımcı (Helper) Fonksiyonları head Dizideki ilk elemanı döndürür. PHP 5.3.x’deki metod zincirleme işine yarar. 1 $first = head($this->returnsArray('foo')); last Dizideki son elemanı döndürür. Metod zincirlemesinde işe yarar. 1 $last = last($this->returnsArray('foo')); Dosya Yolları app_path app dizininin tam dosya yolunu getirir. 1 $path = app_path(); base_path Uygulamanın ana dizininin tam dosya yolunu getirir. public_path public dizininin tam dosya yolunu getirir. storage_path app/storage dizininin tam dosya yolunu getirir. 250 Yardımcı (Helper) Fonksiyonları Yazı İşlemleri camel_case Yazıyı camelCase olacak şekilde düzenler. 1 $camel = camsel_case('foo_bar'); 2 3 // fooBar class_basename Verilen class’ın namespace’ler olmadan sadece adını dondürür. 1 $class = class_basename('Foo\Bar\Baz'); 2 3 // Baz e Verilen yazıya UTF-8 desteğiyle htmlentities fonksiyonunu uygular. 1 $entities = e('<html>foo</html>'); ends_with Bir stringin verilen değerle bitip bitmediğini tespit eder. 1 $value = ends_with('This is my name', 'name'); snake_case Yazıyı snake_case olacak şekilde düzenler. 251 Yardımcı (Helper) Fonksiyonları 1 $snake = snake_case('fooBar'); 2 3 // foo_bar str_limit Bir stringin karakter sayısını sınırlar. 1 str_limit($value, $limit = 100, $end = '...') Örnek: 1 2 $value = str_limit('The PHP framework for web artisans.\ ', 7); 3 4 // The PHP... starts_with Bir stringin verilen değerle başlayıp başlamadığını tespit eder. 1 $value = starts_with('This is my name', 'This'); str_contains Verilen yazının içinde verilen değerin olup olmadığına karar verir. 1 $value = str_contains('This is my name', 'my'); str_finish Verilen yazının sonuna verilen değeri ekler. Verilen değerden oluşan ekstraları yok eder. 252 Yardımcı (Helper) Fonksiyonları 1 $string = str_finish('this/string', '/'); 2 3 // this/string/ str_is Verilen yazıyla verilen değerin eşleşip eşleşmediğine karar verir. Yıldız işareti (*) genel arama karakteri olarak kullanılabilir. 1 $value = str_is('foo*', 'foobar'); str_plural Verilen kelimeyi çoğul hale getirir (Sadece ingilizce için geçerli). 1 $plural = str_plural('car'); str_random Verilen değer kadar uzunlukta rastgele karakterlerden oluşan bir yazı üretir. 1 $string = str_random(40); str_singular Verilen kelimeyi tekil hale getirir (Sadece ingilizce için geçerli). 1 $singular = str_singular('cars'); studly_case Verilen yazıyı StudlyCase olacak şekilde düzenler. 253 Yardımcı (Helper) Fonksiyonları 1 $value = studly_case('foo_bar'); 2 3 // FooBar trans Verilen dil satırını çevirir. Lang::get fonksiyonunun kısayolu. 1 $value = trans('validation.required'): trans_choice Verilen dil satırını çekimli çevirir. Lang::choice fonksiyonunun kısayolu. 1 $value = trans_choice('foo.bar', $count); URL İşlemleri action Belirli bir denetçi eylemi için bir URL üretir. 1 $url = action('HomeController@getIndex', $params); route Verilen isimli rota için URL oluştur. 1 $url = route('routeName', $params); asset Bir varlık için bir URL üretir. 254 Yardımcı (Helper) Fonksiyonları 1 $url = asset('img/photo.jpg'); link_to Verilen URL’e gerekli HTML linkini oluşturur. 1 2 echo link_to('foo/bar', $title, $attributes = array(), \ $secure = null); link_to_asset Verilen varlık için bir HTML bağlantısı üretir. 1 2 echo link_to_asset('foo/bar.zip', $title, $attributes =\ array(), $secure = null); link_to_route Verilen rota için gerekli HTML linkini oluşturur. 1 2 echo link_to_route('route.name', $title, $parameters = \ array(), $attributes = array()); link_to_action Verilen bir denetçi eylemi için bir HTML linki oluşturur. 1 2 echo link_to_action('HomeController@getIndex', $title, \ $parameters = array(), $attributes = array()); secure_asset Verilen eleman için gerekli HTML linkini HTTPS kullanarak oluşturur. 255 Yardımcı (Helper) Fonksiyonları 1 2 echo secure_asset('foo/bar.zip', $title, $attributes = \ array()); secure_url Verilen URL’e gerekli HTML linkini HTTPS kullanarak oluşturur. 1 echo secure_url('foo/bar', $parameters = array()); url Verilen bir dosya yolu için tam kalifiye bir URL üretir. 1 2 echo url('foo/bar', $parameters = array(), $secure = nu\ ll); Diğer csrf_token CSRF token’inin güncel değerini döndürür. 1 $token = csrf_token(); dd Verilen veriyi ekrana basar ve uygulamayı durdurur. 1 dd($value); 256 Yardımcı (Helper) Fonksiyonları value Eğer verilen değer anonim bir fonksiyonsa, değer olarak anonim fonksiyonun döndürdüğü değeri döndürür. Eğer değilse direkt değeri döndürür. 1 $value = value(function() { return 'bar'; }); with Verilen nesneyi döndürür. PHP 5.3.x kullanımında metod zincirleme işlemi için çok yararlı. 1 $value = with(new Foo)->doWork(); Yerelleştirme Giriş Laravel’in Lang sınıfı farklı dillerdeki yazılara ulaşabileceğiniz bir hizmet verir, bu sayede uygulamanızda rahatlıkla çoklu dil desteği verebilirsiniz. Dil Dosyaları Diller için kayıtlar app/lang dizininin içerisindeki dosyalarda tutulur. Bu dizin içerisinde desteklenen her dil için bir klasör oluşturulmalıdır. 1 2 3 /app /lang /en mesajlar.php 4 5 6 /tr mesajlar.php Örnek Dil Dosyası Dil dosyaları basitçe anahtarlı bir şekilde kayıtları barındıran bir dizi döndürür. Örneğin: 258 Yerelleştirme 1 <?php 2 3 4 5 return array( 'hosgeldiniz' => 'Uygulamamıza hoş geldiniz!' ); Varsayılan Dili Çalışma Esnasında Değiştirmek Uygulamanız için varsayılan dil app/config/app.php ayar dosyasında tutulmaktadır. Bunun dışında, aktif dili App::setLocale metoduyla çalışma esnasında da değiştirebilirsiniz. 1 App::setLocale('tr'); Yedek Dil Ayarı Etkin dil verilen bir dil satırını içermediğinde kullanılacak olan bir “yedek dil” de yapılandırabilirsiniz. Varsayılan dile benzer şekilde, yedek dil de app/config/app.php yapılandırma dosyasında yapılandırılır: 1 'fallback_locale' => 'en', Temel Kullanım Bir Dil Dosyasından Satırları Almak 1 echo Lang::get('mesajlar.hosgeldin'); get metoduna verilen parametrenin ilk kısmı dil dosyasının adını, ikinci kısım ise alınmak istenen satırın anahtarını içerir. Not: Eğer istenen dil satırı bulunmuyorsa, get metodu anahtarı döndürecektir. 259 Yerelleştirme Lang::get() ile aynı parametreleri kullanan ve bunun kısaltması olan trans() yardımcı metodunu kullanabilirsiniz: 1 echo trans('mesajlar.hosgeldin'); Satırlarda Değişiklik Yapmak Ayrıca dil satırlarınızda yer tutucular tanımlayabilirsiniz: 1 'hosgeldin' => 'Hoşgeldin, :isim', Daha sonra, Lang::get metoduna ikinci bir parametreyle yapılacak değişiklikleri belirtin: 1 2 echo Lang::get('mesajlar.hosgeldin', array('isim' => 'E\ krem')); Bir Dil Dosyasının İstenen Satıra Sahip Olup Olmadığını Kontrol Etmek 1 2 3 4 if (Lang::has('mesajlar.hosgeldin')) { // } Çoğullaştırma Çoğullaştırma karmaşık bir problemdir, çünkü her dilin farklı ve karmaşık çoğullaştırma kuralları vardır. Dil dosyalarınızda bunu kolaylıkla yönetebilirsiniz. dik çubuk karakteri ile, bir çevirinin tekil ve çoğul hallerini birbirinden ayırabilirsiniz: Yerelleştirme 1 260 'elmalar' => 'Bir elma var|Bir sürü elma var', Daha sonra Lang::choise metoduyla satırı alabilirsiniz: 1 echo Lang::choice('mesajlar.elmalar', 10); Ayrıca dili belirtmek için bir locale parametresi de verebilirsiniz. Örneğin, eğer Rusca (ru) dili kullanmak istiyorsanız: 1 2 echo Lang::choice('товар|товара|товаров', $count, array\ (), 'ru'); Laravel’in tercümecisi gücünü Symfony’nin tercüme bileşeninden aldığı için, daha belirgin çoğullaştırma kuralları da belirleyebilirsiniz: 1 2 'elmalar' => '{0} Hiç elma yok|[1,19] Bir kaç elma var|\ [20,Inf] Çok fazla elma var', Geçerlilik Denetimi Yerelleştirmesi Geçerlilik Denetimi hatalarının ve mesajlarının yerelleştirmesi için dokümantasyonun Geçerlilik Denetimi¹⁸⁸ bölümüne bakınız. Paket Dil Dosyalarının Ezilmesi Birçok paket kendi dil satırlarıyla gelir. Bu satırları değiştirmek için paketin çekirdek dosyalarıyla oynamak yerine, app/lang/packages/{locale}/{pack dizinine dosyalar koymak suretiyle onları ezebilirsiniz. Dolayısıyla, örneğin, eğer skyrim/hearthfire adındaki bir paket için ¹⁸⁸validation#localization Yerelleştirme 261 messages.php‘yi Türkçe dil satırlarıyla ezmeniz gerekiyorsa koyacağınız dil dosyası şudur: app/lang/packages/tr/hearthfire/messages.php. Bu dosyada sadece ezmek istediğiniz dil satırlarını tanımlayacaksınız. Ezmediğiniz dil satırları paketin dil dosyalarından yüklenmeye devam edecektir. Temel Veritabanı Kullanımı Yapılandırma Laravel, veritabanı bağlantısını ve sorguları çalıştırmayı fazlasıyla kolay kılar. Veritabanı yapılandırma ayarları app/config/database.php dosyasında bulunmaktadır. Bu dosyada hem tüm veritabanı bağlantılarını tanımlayabilir, hem de hangi bağlantının varsayılan olarak kullanılacağını seçebilirsiniz. Bu dosyada, desteklenen veritabanı sistemlerinin tümü için örnekler verilmiştir. Laravel tarafından desteklenen veritabanı sistemleri: MySQL, Postgres, SQLite, ve SQL Server. Okuma / Yazma Bağlantıları Bazen SELECT sorguları için bir bağlantı ve diğer sorgular için başka bir bağlantı kullanmak isteyebilirsiniz. Laravel bunu inanılmaz bir şekilde kolaylaştırır ve ister düz sorgu, ister sorgu oluşturucu (query builder) veya ister Eloquent ORM kullansanız bile hepsi için doğru bağlantıyı kullanır. Okuma / yazma bağlantılarının nasıl yapılandırıldığını görmek için bu örneği inceleyebilirsiniz: Temel Veritabanı Kullanımı 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 263 'mysql' => array( 'read' => array( 'host' => '192.168.1.1', ), 'write' => array( 'host' => '196.168.1.2' ), 'driver' => 'mysql', 'database' => 'database', 'username' => 'root', 'password' => '', 'charset' => 'utf8', 'collation' => 'utf8_unicode_ci', 'prefix' => '', ), Yapılandırma dizisine eklenen iki anahtara dikkat edin: read ve write. İkisi de sadece host anahtarını barındıran bir dizi. read ve write bağlantılarının geri kalan tüm veritabanı seçenekleri ise ana mysql dizisinden alınıp birleştirilecektir. Yani read ve write dizilerine sadece ana dizideki değerlerden değiştirmek istediğimiz kalemleri girmemiz gereklidir. Bu durumda read bağlantısı olarak 192.168.1.1 kullanılırken, write bağlantısı olarak 192.168.1.2 kullanılacaktır. Ana mysql dizisindeki username, password, prefix, character set ve diğer tüm seçenekler her iki bağlantı için paylaşılacaktır. Sorguları Çalıştırma Veritabanı bağlantılarını bir kere yapılandırdıktan sonra DB sınıfını kullanarak sorguları çalıştırabilirsiniz. Kayıt Çekme (Select) Temel Veritabanı Kullanımı 1 2 264 $sonuclar = DB::select('select * from uyeler where id =\ ?', array(1)); select metodu sonuçları her zaman dizi tipinde döndürür. Yeni Kayıt Ekleme (Insert) 1 2 DB::insert('insert into uyeler (id, isim) values (?, ?)\ ', array(1, 'Emre')); Kayıt Güncelleme (Update) 1 2 DB::update('update uyeler set oy = 100 where isim = ?',\ array('Hakan')); Kayıt Silme (Delete) 1 DB::delete('delete from uyeler'); Not: update ve delete sorguları, bu işlemlerden etkilenen satır sayısını döndürür. Genel Bir Sorgu Çalıştırma 1 DB::statement('drop table uyeler'); Sorgu Olaylarını Dinleme DB::listen metodunu kullanarak sorgu olaylarını dinleyebilirsiniz: Temel Veritabanı Kullanımı 1 2 3 4 265 DB::listen(function($sql, $bindings, $time) { // }); Veritabanı İşlemleri Bir veritabanı işleminde, birden fazla işlemi birden gerçekleştirmek için, ‘transaction’ metodunu kullanabilirsiniz: 1 2 3 DB::transaction(function() { DB::table('uyeler')->update(array('votes' => 1)); 4 DB::table('posts')->delete(); 5 6 }); Not: transaction metoduna girilen anonim fonksiyonunda oluşan herhangi bir istisna, transaction işleminin otomatik olarak geri sarılmasına (rollback edilmesine) sebep olur. Transaction’ı elle başlatmanız gerekirse: 1 DB::beginTransaction(); Transaction’ı geri sarmanız gerekirse: 1 DB::rollback(); Transaction’ı tamamlamak için: Temel Veritabanı Kullanımı 1 266 DB::commit(); Bağlantılara Erişme Birden fazla bağlantı kullandığınız durumlarda, bu bağlantılara DB::connection metodu aracılığı ile ulaşabilirsiniz. 1 $uyeler = DB::connection('foo')->select(...); Ayrıca temel PDO örneğine de ulaşabilirsiniz: 1 $pdo = DB::connection()->getPdo(); Bazen veritabanına tekrar bağlanmaya ihtiyacınız olabilir. 1 DB::reconnect('foo'); Veritabanıyla, PDO nesnesinin max_connections limiti aşıldığı için bağlantıyı koparmanız gerekirse disconnect metodunu kullanabilirsiniz: 1 DB::disconnect('foo'); Sorgu Günlükleme Varsayılan olarak, Laravel güncel istek için çalıştırılabilecek tüm sorgular için bellekte bir günlük tutar. Bununla birlikte, bu bazı durumlarda, örneğin çok sayıda satır eklerken, uygulamanın aşırı bellek kullanmasına neden olabilir. Günlüğü devre dışı bırakmak için disableQueryLog metodunu kullanabilirsiniz. Temel Veritabanı Kullanımı 1 267 DB::connection()->disableQueryLog(); Çalıştırılan sorguların listesini bir dizi olarak almak için getQueryLog metodunu kullanabilirsiniz: 1 $queries = DB::getQueryLog(); Sorgu Oluşturucusu Giriş Veritabanı sorgu oluşturucusu veritabanı sorguları oluşturulması ve çalıştırılması için kullanışlı ve akıcı bir arayüz sağlar. Uygulamanızdaki pek çok veritabanı işlemini bununla gerçekleştirebilirsiniz ve desteklenen tüm veritabanı sistemlerinde çalışmaktadır. Not: Laravel sorgu oluşturucusu, uygulamanızı SQL enjeksiyon saldırılarına karşı korumak için PDO parametre bağlayıcı kullanmaktadır. Bağlayıcı olarak geçirilen yazıların temizlenmesine gerek yoktur. Temizlenmeyen yalnızca iki metod vardır, bunlar groupBy ve orderBy‘dır. Kullanıcı girdilerini bu metodlara doğrudan geçmemelisiniz. Seçmeler Bir Tablonun Bütün Satırlarının Alınması 1 $uyeler = DB::table('uyeler')->get(); 2 3 4 5 6 foreach (uyeler as $uye) { var_dump($uye->isim); } Bir Tablonun Tek Bir Satırının Alınması Sorgu Oluşturucusu 1 2 269 $uye = DB::table('uyeler')->where('isim', 'Can')->first\ (); 3 4 var_dump($uye->isim); Bir Satırın Tek Bir Sütununun Alınması 1 2 $isim = DB::table('uyeler')->where('isim', 'Can')->pluc\ k('isim'); Sütun Değerlerinden Oluşan Bir Liste Elde Edilmesi 1 $roller = DB::table('roller')->lists('unvan'); Bu metod rol ünvanlarından oluşan bir dizi döndürecektir. Döndürülen dizi için özel bir anahtar sütun da belirleyebilirsiniz: 1 $roller = DB::table('roller')->lists('unvan', 'isim'); Bir Select Bendinin Belirlenmesi 1 2 $uyeler = DB::table('uyeler')->select('isim', 'email')-\ >get(); 3 4 $uyeler = DB::table('uyeler')->distinct()->get(); 5 6 7 $uyeler = DB::table('uyeler')->select('isim as uye_adi'\ )->get(); Mevcut Bir Sorguya Bir Select Bendinin Eklenmesi 270 Sorgu Oluşturucusu 1 $sorgu = DB::table('uyeler')->select('isim'); 2 3 $uyeler = $query->addSelect('yas')->get(); Where Kullanımı 1 2 $uyeler = DB::table('uyeler')->where('puan', '>', 100)-\ >get(); Or Cümleleri 1 2 3 4 $uyeler = DB::table('uyeler') ->where('puan', '>', 100) ->orWhere('isim', 'Can') ->get(); Where Between Kullanımı 1 2 3 $uyeler = DB::table('uyeler') ->whereBetween('puan', array(1, 100\ ))->get(); Where Not Between Kullanımı 1 2 3 $users = DB::table('users') ->whereNotBetween('puan', array(1, \ 100))->get(); Bir Dizi Aracılığıyla Where In Kullanımı 271 Sorgu Oluşturucusu 1 2 3 $uyeler = DB::table('uyeler') ->whereIn('id', array(1, 2, 3))->ge\ t(); 4 5 6 7 $uyeler = DB::table('uyeler') ->whereNotIn('id', array(1, 2, 3))-\ >get(); Değer Girilmemiş Kayıtları Bulmak için Where Null Kullanımı 1 2 3 $uyeler = DB::table('uyeler') ->whereNull('guncelleme_vakti')->ge\ t(); Order By, Group By ve Having 1 2 3 4 5 $uyeler = DB::table('uyeler') ->orderBy('name', 'desc') ->groupBy('count') ->having('count', '>', 100) ->get(); Offset ve Limit 1 $uyeler = DB::table('uyeler')->skip(10)->take(5)->get(); Joinler Sorgu oluşturucusu join cümleleri yazmak için de kullanılabilir. Şu örneklere bir bakın: Temel Join Cümleleri 272 Sorgu Oluşturucusu 1 2 3 4 5 6 7 8 DB::table('uyeler') ->join('kisiler', 'uyeler.id', '=', 'kisile\ r.uye_id') ->join('siparisler', 'uyeler.id', '=', 'sip\ arisler.uye_id') ->select('uyeler.id', 'kisiler.telefon', 's\ iparisler.fiyat') ->get(); Left Join Cümlesi 1 2 3 4 DB::table('uyeler') ->leftJoin('makaleler', 'uyeler.id', '=', 'makalel\ er.uye_id') ->get(); Daha ileri join cümleleri de tanımlayabilirsiniz: 1 2 3 4 5 6 7 DB::table('uyeler') ->join('kisiler', function($join) { $join->on('uyeler.id', '=', 'kisiler.uye_id')-\ >orOn(...); }) ->get(); Şayet joinlerinizde “where” biçiminde bir cümlecik kullanmak isterseniz, bir join üzerinde where ve orWhere metodlarını kullanabilirsiniz. Bu metodlar iki sütunu karşılaştırmak yerine, sütunu bir değer açısından karşılaştıracaktır: 273 Sorgu Oluşturucusu 1 2 3 4 5 6 7 DB::table('uyeler') ->join('kisiler', function($join) { $join->on('uyeler.id', '=', 'kisiler.uye_id') ->where('kisiler.uye_id', '>', 5); }) ->get(); İleri Where Cümleleri Parametre Gruplaması Kimi zaman “where exists” veya içi içe parametre gruplaması gibi daha ileri where cümleleri oluşturmanız gerekebilir. Laravel sorgu oluşturucusu bunu da halledecektir: 1 2 3 4 5 6 7 8 DB::table('uyeler') ->where('isim', '=', 'Can') ->orWhere(function($query) { $query->where('puan', '>', 100) ->where('unvan', '<>', 'Müdür'); }) ->get(); Yukardaki sorgu aşağıdaki SQL cümlesini oluşturacaktır: 1 2 select * from uyeler where isim = 'Can' or (puan > 100 \ and unvan <> 'Müdür') Exists Cümleleri Sorgu Oluşturucusu 1 2 3 4 5 6 7 8 9 274 DB::table('uyeler') ->whereExists(function($query) { $query->select(DB::raw(1)) ->from('siparisler') ->whereRaw('siparisler.uye_id = uyel\ er.id'); }) ->get(); Yukardaki sorgu aşağıdaki SQL cümlesini oluşturacaktır: 1 2 3 4 5 select * from uyeler where exists ( select 1 from siparisler where siparisler.uye_id = uye\ ler.id ) Kümeleme (Aggregate) İşlemleri Sorgu oluşturucusu count, max, min, avg ve sum gibi çeşitli kümeleme metodları da sağlamaktadır. Aggregate Metodlarının Kullanımı 275 Sorgu Oluşturucusu 1 $uyeler = DB::table('uyeler')->count(); 2 3 $fiyat = DB::table('siparisler')->max('fiyat'); 4 5 $fiyat = DB::table('siparisler')->min('fiyat'); 6 7 $fiyat = DB::table('siparisler')->avg('fiyat'); 8 9 $toplam = DB::table('uyeler')->sum('puan'); Ham İfadeler Bazen bir sorguda ham ifade kullanma ihtiyacı duyabilirsiniz. Bu ifadeler sorguya doğrudan yazı olarak enjekte edileceğinden, bir SQL enjeksiyon noktası oluşturmamaya özen gösteriniz. Ham ifade oluşturmak için DB::raw metodunu kullanabilirsiniz: Ham İfade Kullanımı 1 2 3 4 5 $uyeler = DB::table('uyeler') ->select(DB::raw('count(*) as uye_adedi, durum')) ->where('durum', '<>', 1) ->groupBy('durum') ->get(); Bir Sütun Değerinin Artırılması veya Azaltılması 276 Sorgu Oluşturucusu 1 DB::table('uyeler')->increment('puan'); 2 3 DB::table('uyeler')->increment('puan', 5); 4 5 DB::table('uyeler')->decrement('puan'); 6 7 DB::table('uyeler')->decrement('puan', 5); Ayrıca, güncellenecek ek sütunlar belirtebilirsiniz: 1 2 DB::table('uyeler')->increment('puan', 1, array('isim' \ => 'Tuana Şeyma')); Eklemeler Bir Tabloya Kayıt Eklenmesi 1 2 3 DB::table('uyeler')->insert( array('email' => 'can@numune.com', 'puan' => 0) ); Otomatik Artan Bir Id Alanı Olan Tabloya Kayıt Eklenmesi Şayet tabloda otomatik artan bir id alanı varsa, bir kayıt eklemek ve oluşan otomatik id’i öğrenmek için insertGetId metodu kullanılabilir: 1 2 3 $id = DB::table('uyeler')->insertGetId( array('email' => 'can@numune.com', 'puan' => 0) ); Not: PostgreSQL ile kullanıldığı zaman insertGetId metodu, otomatik artan alanın adının da “id” olmasını bekler. 277 Sorgu Oluşturucusu Bir Tabloya Birden Çok Kayıt Eklenmesi 1 2 3 4 DB::table('uyeler')->insert(array( array('email' => 'sinan@numune.com', 'puan' => 0), array('email' => 'ozan@numune.com', 'puan' => 0), )); Güncellemeler Bir Tablodaki Kayıtların Güncellenmesi 1 2 3 DB::table('uyeler') ->where('id', 1) ->update(array('puan' => 1)); Silmeler Bir Tablodaki Kayıtların Silinmesi 1 DB::table('uyeler')->where('puan', '<', 100)->delete(); Bir Tablodaki Tüm Kayıtların Silinmesi 1 DB::table('uyeler')->delete(); Bir Tablonun Budanması 1 DB::table('uyeler')->truncate(); Birleştirmeler Sorgu oluşturucusu, iki ayrı sorgunun tek bir “birlik” haline getirilmesi için de hızlı bir yol sağlamaktadır: 278 Sorgu Oluşturucusu 1 $ilksorgu = DB::table('uyeler')->whereNull('ismi'); 2 3 4 $uyeler = DB::table('uyeler')->whereNull('soy_ismi')->u\ nion($ilksorgu)->get(); Ayrıca unionAll metodu da mevcut olup, aynı union gibi kullanılır. Pesimistik Kilitleme Sorgu oluşturucusu SELECT cümleleriniz üzerinde “pesimistik kilitleme” yapmanıza yardımcı olacak birkaç fonksiyon içermektedir. Bir SELECT cümlesini bir “shared lock (paylaşılan kilit)” ile çalıştırmak için bir sorgu üzerinde sharedLock metodunu kullanabilirsiniz: 1 2 DB::table('uyeler')->where('puan', '>', 100)->sharedLoc\ k()->get(); Bir SELECT cümlesinde “güncelleme için kilitlemek” için bir sorgu üzerinde lockForUpdate metodunu kullanabilirsiniz: 1 2 DB::table('uyeler')->where('puan', '>', 100)->lockForUp\ date()->get(); Sorguların Bellekte Saklanması Bir sorgunun sonuçları remember metodu kullanılarak bellekte saklanabilir: 1 $uyeler = DB::table('uyeler')->remember(10)->get(); Sorgu Oluşturucusu 279 Bu örnekte, sorgunun sonuçları on dakika süreyle bellekte saklanacaktır. Sonuçlar bellekte tutulduğu süre boyunca bu sorgu artık veritabanında çalıştırılmayacak, onun yerine sonuçlar uygulamanız için belirlediğiniz ön tanımlı bellekleme sürücüsü tarafından yüklenecektir. Eğer cache taglarını destekleyen bir cache sürücüsü¹⁸⁹ kullanıyorsanız, önbelleğe taglar da ekleyebilirsiniz: 1 2 $uyeler = DB::table('uyeler')->cacheTags(array('insanla\ r', 'yazarlar'))->remember(10)->get(); ¹⁸⁹/docs/cache#cache-tags Eloquent ORM Giriş Laravel ile gelen Eloquent ORM, veritabanınızla çalışırken kullanacağınız güzel ve sade bir ActiveRecord uygulaması sağlamaktadır. Her veritabanı tablosu, bu tabloyla etkileşim için kullanılacak kendine has bir “Model” sahibidir. Başlamadan önce, app/config/database.php‘de bir veritabanı bağlantısı yapılandırmış olduğunuzdan emin olun. Temel Kullanım Öncelikle bir Eloquent modeli oluşturunuz. Modeller tipik olarak app/models klasöründe yer alır, fakat siz modellerinizi composer.json dosyanıza göre otomatik yükleme yapabileceğiniz başka bir yere de koyabilirsiniz. Bir Eloquent Modelinin Tanımlanması 1 class Uye extends Eloquent {} Dikkat ederseniz Eloquent’e Uye modelimiz için hangi tabloyu kullanacağımızı söylemedik. Eğer açıkça başka bir isim belirtilmezse tablo isimi olarak sınıf adının ingilizde çoğulunun küçük harf hali kullanılacaktır. Dolayısıyla bizim örneğimizde Eloquent, Uye modelinin uyes tablosundaki kayıtları tutacağını varsayacaktır. Tablo ismini açıkça belirtmek için modelinizde bir table özelliği tanımlayınız: 281 Eloquent ORM 1 class Uye extends Eloquent { 2 protected $table = 'uyeler'; 3 4 5 } Not: Eloquent’in başka bir ön kabulü de her tablonun id adında bir primer key sütunu olduğudur. Bu kuralı aşmak için de bir primaryKey özelliği tanımlamanız gerekecek. Benzer şekilde, modeliniz kullanılacağı zaman kullanılacak veritabanı bağlantısının adını değiştirmek için bir connection özelliği tanımlayabilirsiniz. Bir model tanımladıktan sonra artık tablonuzda kayıt oluşturmaya ve ondan kayıt getirmeye başlayabilirsiniz. Tablolarınıza ön tanımlı olarak updated_at ve created_at sütunları koymanız gerektiğine dikkat ediniz. Şayet bu sütunların otomatik olarak tutulmasını istemiyorsanız, modelinizdeki $timestamps özelliğini false olarak ayarlayınız. Tüm Modellerin Alınması 1 $uyeler = Uye::all(); Birincil Anahtara Göre Bir Kaydın Alınması 1 $uye = Uye::find(1); 2 3 var_dump($uye->isim); Not: Sorgu Oluşturucusu¹⁹⁰‘nda bulunan tüm metodlar Eloquent modellerini sorgularken de kullanılabilir. ¹⁹⁰/docs/queries 282 Eloquent ORM Birincil Anahtara Göre Bir Model Alınması ya da Ortaya Bir İstisna Çıkartılması Bazı durumlarda bir model bulunamadığında bir istisna çıkartmak, böylece bir App::error işleyicisi kullanarak istisnayı yakalayabilmek ve bir 404 sayfası göstermek isteyebilirsiniz. 1 $model = Uye::findOrFail(1); 2 3 $model = Uye::where('oylar', '>', 100)->firstOrFail(); Bu hata işleyicinin kaydını yapmak için ModelNotFoundException‘i dinlemek gerekir. 1 use Illuminate\Database\Eloquent\ModelNotFoundException; 2 3 4 5 6 App::error(function(ModelNotFoundException $e) { return Response::make('Bulunamadı', 404); }); Eloquent Modelleri Kullanarak Sorgu Yapma 1 $uyeler = Uye::where('puan', '>', 100)->take(10)->get(); 2 3 4 5 6 foreach ($uyeler as $uye) { var_dump($uye->isim); } Eloquent Küme Metodları Tabi ki, sorgu oluşturucusunun kümeleme fonksiyonlarını da kullanabilirsiniz. 283 Eloquent ORM 1 $adet = Uye::where('puan', '>', 100)->count(); Gereken sorguyu fluent arayüzüyle üretemediğiniz zaman whereRaw kullanabilirsiniz: 1 2 $uyeler = Uye::whereRaw('yas > ? and puan = 100', array\ (25))->get(); Sonuçları Öbeklere Bölme Eğer bir sürü (binlerce) Eloquent kaydını işlemeniz gerekiyorsa, chunk komutunun kullanılması tüm bunları RAM’inizi yemeden yapmanıza imkan verecektir: 1 2 3 4 5 6 7 Uye::chunk(200, function($uyeler) { foreach ($uyeler as $uye) { // } }); Metoda geçilen birinci parametre “öbek” başına almak istediğiniz kayıt sayısıdır. Veritabanından çekilen her bir öbek için ikinci parametre olarak geçilen Closure çağrılacaktır. Query Bağlantısının Belirtilmesi Bir Eloquent sorgusu çalıştırırken hangi bağlantının kullanılacağını da belirleyebilirsiniz. On metodunu kullanmanız yeterlidir: 1 $uyeler = Uye::on('bağlantı-adı')->find(1); 284 Eloquent ORM Toplu Atama Yeni bir model oluşturulurken model oluşturucuya niteliklerden oluşan bir dizi geçersiniz. Bu nitelikler bu durumda modele “toplu atama” aracılığıyla atanır. Bu gayet uygun bir yaklaşımdır, fakat bir kullanıcı girdisi bir modele körleme geçirildiği takdirde ciddi bir güvenlik sorunu olabilecektir. Kullanıcı girdisi bir modele körlemesine geçirilirse, bu kullanıcı modelin niteliklerinin birisini (any) ve hepsini (all) değiştirebilecektir. Bu sebepler yüzünden, tüm Eloquent modelleri ön tanımlı olarak toplu atamaya karşı koyar. Başlamak için modelinizde fillable veya guarded özelliğini ayarlayınız. Bir Modelde Fillable Niteliklerin Tanımlanması Bunlardan fillable özelliği hangi niteliklerin toplu atanacaklarını belirler. Bu işlem sınıf ya da olgu düzeyinde ayarlanabilir. 1 class Uye extends Eloquent { 2 protected $fillable = array('ismi', 'soy_ismi', 'email\ 3 4 '); 5 6 } Bu örnekte, sadece belirttiğimiz üç nitelik toplu atanabilecektir. Bir Modelde Guarded Niteliklerin Tanımlanması fillable‘in tersi guarded‘dır ve bir “beyaz-liste” yerine bir “kara- liste” olarak iş görür: 285 Eloquent ORM 1 class Uye extends Eloquent { 2 protected $guarded = array('id', 'parola'); 3 4 5 } Not: guarded kullanıyorken de, yine bir save veya update metoduna Input::get() veya kullanıcının kontrolündeki herhangi bir ham diziyi hiçbir zaman için geçmemelisiniz, çünkü öyle yaptığınızda guarded olmayan herhangi bir sütun güncellenebilir. Toplu Atamanın Tüm Nitelikler İçin Engellenmesi Yukardaki örneğe göre id ve parola nitelikleri toplu atana mayacaktır. Diğer tüm nitelikler toplu atanabilecektir. Toplu atamayı niteliklerin hepsi için bloke etmeyi de seçebilirsiniz: 1 protected $guarded = array('*'); Ekleme, Güncelleme, Silme Veritabanında bir modelden yeni bir kayıt oluşturmak için, yeni bir model olgusu oluşturun ve save metodunu çağırın. Yeni Bir Modelin Kaydedilmesi Eloquent ORM 1 286 $uye = new Uye; 2 3 $uye->isim = 'Can'; 4 5 $uye->save(); Not: Tipik olarak, Eloquent modellerinizde otomatik artan anahtarlar olacaktır. Ama siz kendi keylerinizi belirlemek isterseniz, modelinizdeki incrementing özelliğini false olarak ayarlayın. Yeni bir modeli tek satırda kaydetmek için create metodunu kullanabilirsiniz. Eklenen model olgusu bu metoddan döndürülecektir. Ancak, tüm Elequent modelleri toplu atamaya karşı korunumlu oldukları için, bunu yapmadan önce modelinizde bir fillable veya guarded özelliği belirlemeniz gerekecektir. Otomatik artan IDler kullanan yeni bir modelin kaydedilmesi (olgu oluşturup, değer atanıp, “save” kullanılması) veya oluşturulması (üç işlemin hepsini birden yapan “create” metodunun kullanılması) sonrasında, nesnenin id niteliğine erişerek bu ID’i öğrenebilirsiniz: 1 $insertedId = $user->id; Modeldeki Korunumlu Niteliklerin Ayarlanması 1 class Uye extends Eloquent { 2 protected $guarded = array('id', 'hesap_no'); 3 4 5 } Model Create Metodunun Kullanımı Eloquent ORM 1 2 287 // Veritabanında yeni bir üye oluştur... $uye = Uye::create(array('isim' => 'Can')); 3 4 5 6 // Bazı alanlarına göre üyeyi getir ya da öyle bir üye \ yoksa oluştur... $user = User::firstOrCreate(array('name' => 'John')); 7 8 9 10 // Bazı alanlarına göre üyeyi getir ya da yeni bir üye \ olgusu başlat... $user = User::firstOrNew(array('name' => 'John')); Getirilen Bir Modelin Güncellenmesi Bir modeli güncellemek için onu getirir, bir niteliğini değiştirir, sonra da save metodunu kullanabilirsiniz: 1 $uye = Uye::find(1); 2 3 $uye->email = 'can@filan.com'; 4 5 $uye->save(); Bir Model ve İlişkilerinin Kaydedilmesi Bazen sadece bir modeli değil, onun bütün ilişkilerini de kaydetmek isteyebilirsiniz. Bunu yapmak için push metodunu kullanın: 1 $uye->push(); Ayrıca, bir modeller kümesinde güncelleme sorguları da çalıştırabilirsiniz: 288 Eloquent ORM 1 2 $satirSayisi = Uye::where('puan', '>', 100)->update(arr\ ay('durum' => 2)); Not: Eloquent sorgu oluşturucu aracılığıyla bir modeller kümesi güncellendiği zaman herhangi bir model olayı ateşlenmez. Mevcut Bir Modelin Silinmesi Bir modeli silmek için olgu üzerinde delete metodunu çağırın: 1 $uye = Uye::find(1); 2 3 $uye->delete(); Mevcut Bir Modelin Key Aracılığıyla Silinmesi 1 Uye::destroy(1); 2 3 Uye::destroy(array(1, 2, 3)); 4 5 Uye::destroy(1, 2, 3); Elbette, bir modeller kümesinde bir silme sorgusu da çalıştırabilirsiniz: 1 $satirSayisi = Uye::where('puan', '>', 100)->delete(); Bir Modelin Sadece Zaman Damgalarının Güncellenmesi Eğer bir modelde sadece zaman damgalarını güncellemek istiyorsanız, touch metodunu kullanabilirsiniz: 289 Eloquent ORM 1 $uye->touch(); Belirsiz Silme Bir model belirsiz silindiğinde, aslında veritabanınızdan çıkartılmaz. Onun yerinde kayıttaki bir deleted_at zaman damgası ayarlanır. Bir model için belirsiz silmeler yapılabilmesi için modelinize ‘SoftDeletingTrait’ uygulamanız gerekir: 1 use Illuminate\Database\Eloquent\SoftDeletingTrait; 2 3 class Uye extends Eloquent { 4 use SoftDeletingTrait; 5 6 protected $dates = ['deleted_at']; 7 8 9 } Tablonuza bir deleted_at sütunu eklemek için ise, bir migrasyondan softDeletes metodunu kullanabilirsiniz: 1 $table->softDeletes(); Şimdi, artık modelinizde delete metodunu çağırdığınız zaman, bu deleted_at sütunu güncel zaman damgasına ayarlanacaktır. Belirsiz silme kullanılan bir model sorgulandığında, “silinmiş olan” modeller sorgu sonuçlarına dahil edilmeyecektir. Belirsiz Silinmiş Modelleri Sonuçlara Girmeye Zorlama Bir sonuç kümesinde belirsiz silinmiş modellerin gözükmesini zorlamak için sorgunuzda withTrashed metodunu kullanınız: Eloquent ORM 1 2 290 $uyeler = Uye::withTrashed()->where('hesap_no', 1)->get\ (); Bu withTrashed metodu tanımlanmış bir ilişki üzerinde kullanılabilir: 1 $user->posts()->withTrashed()->get(); Sonuç kümenizde sadece belirsiz silinmiş modellerin olmasını istiyorsanız, onlyTrashed metodunu kullanabilirsiniz: 1 2 $uyeler = Uye::onlyTrashed()->where('hesap_no', 1)->get\ (); Belirsiz silinmiş bir modeli tekrar etkin hale getirmek için, restore metodunu kullanın: 1 $uye->restore(); restore metodunu bir sorguda da kullanabilirsiniz: 1 Uye::withTrashed()->where('hesap_no', 1)->restore(); restore metodu ilişkilerde de kullanılabilir: 1 $uye->postalar()->restore(); Bir modeli veritabanından gerçekten çıkartmak istediğinizde, forceDelete metodunu kullanabilirsiniz: 291 Eloquent ORM 1 $uye->forceDelete(); forceDelete metodu ilişkilerde de çalışır: 1 $uye->postalar()->forceDelete(); Belli bir model olgusunun belirsiz silme özelliğine sahip olup olmadığını öğrenmek için, trashed metodunu kullanabilirsiniz: 1 2 3 4 if ($uye->trashed()) { // } Zaman Damgaları Ön tanımlı olarak, veritabanı tablonuzdaki created_at ve updated_at sütunlarının idamesini otomatik olarak Eloquent yapacaktır. Size tek düşen datetime tipindeki bu iki alanı tablonuza eklemektir, geri kalan işleri Eloquent üstlenecektir. Şayet siz bu sütunların idamesini Eloquent’in yapmasını istemiyorsanız, modelinize şu özelliği eklemeniz gerekir: Otomatik Zaman Damgalarının Devre Dışı Bırakılması 292 Eloquent ORM 1 class Uye extends Eloquent { 2 protected $table = 'uyeler'; 3 4 public $timestamps = false; 5 6 7 } Özel Bir Zaman Damgası Biçiminin Şart Koşulması Zaman damgalarınızın biçimini özelleştirmek isterseniz, modelinizdeki freshTimestamp metodunu ezebilirsiniz (override): 1 class Uye extends Eloquent { 2 public function freshTimestamp() { return time(); } 3 4 5 6 7 8 } Sorgu Kapsamları Bir Sorgu Kapsamının Tanımlanması Kapsamlar size sorgu mantığınızı modellerinizde tekrar tekrar kullanma imkanı verir. Bir kapsam tanımlamak için bir model metodunun başına scope getirmeniz yeterlidir: 293 Eloquent ORM 1 class Uye extends Eloquent { 2 public function scopePopular($query) { return $query->where('puan', '>', 100); } 3 4 5 6 7 public function scopeKadin($query) { return $query->whereGender('W'); } 8 9 10 11 12 13 } Bir Sorgu Kapsamının Kullanılması 1 2 $uyeler = Uye::popular()->kadin()->orderBy('created_at'\ )->get(); Dinamik Kapsamlar Bazen parametreler kabul eden kapsam tanımlamak isteyebilirsiniz. Yapmanız gereken kapsam metoduna parametrelerinizi eklemek: 1 class Uye extends Eloquent { 2 public function scopeOfType($query, $type) { return $query->whereType($type); } 3 4 5 6 7 8 } Parametreyi kapsamın çağrısına geçin: 294 Eloquent ORM 1 $uyeler = Uye::ofType('moderator')->get(); Küresel Kapsamlar Bazen, bir model üzerinde yapılan tüm sorgular için uygulanan bir scope tanımlamak isteyebilirsiniz. Aslında, Eloquent’in kendi “belirsiz silme” özelliği bu şekilde çalışmaktadır. Global scope’lar PHP trait’leri ve bir Illuminate\Database\Eloquent\ScopeInterface implementasyonu birlikte kullanılarak tanımlanırlar. İlk olarak, bir trait tanımlayalım. Bu örnek için Laravel’le birlikte gelen SoftDeletingTrait kullanacağız: 1 trait SoftDeletingTrait { 2 /** * Boot the soft deleting trait for a model. * * @return void */ public static function bootSoftDeletingTrait() { static::addGlobalScope(new SoftDeletingScope); } 3 4 5 6 7 8 9 10 11 12 13 } Eğer bir Eloquent modeli bir bootTraitIsmi isimlendirme kuralına uyan bir metoda sahip olan bir trait kullanırsa, bu Elequent modeli boot edildiği zaman o trait metodu çağrılacaktır. Bu size küresel bir kapsamı kayda geçirme ya da istediğiniz başka bir şey yapma fırsatı vermektedir. Bir scope ScopeInterface interface’ini implemente etmelidir, bu interface iki metoda sahiptir: apply ve remove. Eloquent ORM 295 Bunlardan apply metodu bir Illuminate\Database\Eloquent\Builder sorgu oluşturucu nesnesi alır ve bu kapsama eklemek istediğiniz ilave where cümlelerinin eklenmesinden sorumludur. remove metodu da bir Builder nesnesi alır ve apply tarafından gerçekleştirilen eylemlerin geri döndürülmesinden sorumludur. Başka bir deyişle, remove metodu eklenmiş olan where cümlesini (veya herhangi bir başka cümleyi) çıkarmalıdır. Dolayısıyla, bizim SoftDeletingScope için, bu metodlar buna benzer gözükecektir: 1 2 3 4 5 6 7 8 9 10 11 /** * Verilen bir Eloquent sorgu oluşturucusuna scope uygu\ la. * * @param \Illuminate\Database\Eloquent\Builder $buil\ der * @return void */ public function apply(Builder $builder) { $model = $builder->getModel(); 12 $builder->whereNull($model->getQualifiedDeletedAtColum\ 13 14 15 n()); } 16 17 18 19 20 21 22 23 24 25 26 /** * Verilen Eloquent sorgu oluşturucusundan scope'u kald\ ır. * * @param \Illuminate\Database\Eloquent\Builder $buil\ der * @return void */ public function remove(Builder $builder) { 296 Eloquent ORM 27 28 $column = $builder->getModel()->getQualifiedDeletedAtC\ olumn(); 29 $query = $builder->getQuery(); 30 31 32 33 34 35 36 37 38 39 40 41 42 foreach ((array) $query->wheres as $key => $where) { // Eğer where cümlesi bir belirsiz silme date sınırla\ ması ise, onu sorgudan // kaldıracağız ve wheres'deki key'leri resetleyeceği\ z. Bu, bu geliştiriciye, // tembel yüklenen bir ilişki sonuç kümesinde silinmi\ ş modeli dahil etme imkanı verir. if ($this->isSoftDeleteConstraint($where, $column)) { unset($query->wheres[$key]); 43 $query->wheres = array_values($query->wheres); 44 } 45 } 46 47 } İlişkiler Pek tabii, veritabanı tablolarınız büyük ihtimalle bir diğeriyle ilişkilidir. Örneğin bir blog yazısında çok sayıda yorum olabilir veya bir sipariş onu ısmarlayan kullanıcı ile ilişkili olacaktır. Eloquent bu ilişkileri kolayca yönetmenizi ve rahat çalışmanızı sağlar. Laravel birçok ilişki tipini desteklemektedir: • Birden Bire • Birden Birçoğa • Birçoktan Birçoğa 297 Eloquent ORM • Aracılığıyla Birçoğa Sahip (Has Many Through) • Çokbiçimli İlişkiler • Birçoktan Birçoğa Çokbiçimli İlişkiler Birden Bire Birden Bire Tarzı İlişki Tanımlama Birden bire şeklindeki bir ilişki çok basit bir ilişkidir. Örneğin, bir Uye modelinin bir Telefon‘u olabilir. Eloquent’de bu ilişkiyi şöyle tanımlayabiliriz: 1 class Uye extends Eloquent { 2 public function tel() { return $this->hasOne('Telefon'); } 3 4 5 6 7 8 } hasOne metoduna geçirilen ilk parametre ilişkili modelin adıdır. İlişki tanımlandıktan sonra onu Eloquent’in dinamik özellikler‘ini kullanarak elde edebiliriz: 1 $tel = Uye::find(1)->tel; Bu cümlenin gerçekleştirdiği SQL şunlardır (tablo isimleri model tanımında özel olarak belirtilmedi ise tablo ismi olarak model isminin küçük harfli çoğul halinin kullanıldığını hatırlayınız): Eloquent ORM 1 298 select * from uyes where id = 1 2 3 select * from telefons where uye_id = 1 Eloquent’in ilişkideki yabancı key’in ne olduğuna model adına göre karar verdiğine dikkat ediniz. Şimdiki örnekte Telefon modelinin uye_id adlı bir yabancı key kullandığı varsayılmaktadır. Siz bu ön kuralı değiştirmek istiyorsanız hasOne metoduna ikinci bir parametre geçebilirsiniz. Dahası, ilişki için hangi local alanın kullanılması gerektiğini belirtmek için üçüncü bir parametre geçebilirsiniz: 1 return $this->hasOne('Telefon', 'foreign_key'); 2 3 4 return $this->hasOne('Telefon', 'foreign_key', 'local_k\ ey'); Bir İlişkinin Tersinin Tanımlanması Telefon modeli üzerinde ilişkinin tersini tanımlamak için, belongsTo metodunu kullanınız: 1 class Telefon extends Eloquent { 2 public function uye() { return $this->belongsTo('Uye'); } 3 4 5 6 7 8 } Yukarıdaki örnekte, Eloquent, telefons tablosunda bir user_id alanı arayacaktır. Eğer farklı bir yabancı anahtar sütunu tanımlamak isterseniz, onu belongsTo metoduna ikinci parametre olarak geçebilirsiniz: 299 Eloquent ORM 1 class Telefon extends Eloquent { 2 public function uye() { return $this->belongsTo('Uye', 'local_key'); } 3 4 5 6 7 8 } Ek olarak, ebeveyn tabloda ilişkilendirilen sütunun adını belirten üçüncü bir parametre geçebilirsiniz: 1 class Telefon extends Eloquent { 2 public function uye() { return $this->belongsTo('Uye', 'local_key', 'parent_k\ 3 4 5 6 ey'); } 7 8 9 } Birden Birçoğa Birden birçoğa ilişki örneği olarak birçok yorum yapılmış bir blog yazısı verilebilir. Bu ilişkiyi de şöyle modelleyebiliriz: Eloquent ORM 1 300 class Makale extends Eloquent { 2 public function yorumlar() { return $this->hasMany('Yorum'); } 3 4 5 6 7 8 } Şimdi artık bir makalenin yorumlarına dinamik özellik aracılığıyla ulaşabiliriz: 1 $yorumlar = Makale::find(1)->yorumlar; Hangi yorumların alınacağını daha da kısıtlamak için yorumlar metodunu çağırabilir ve şartlar koşmayı sürdürebilirsiniz: 1 2 $yorumlar = Makale::find(1)->yorumlar()->where('baslik'\ , '=', 'bu')->first(); Tıpkı hasOne’de olduğu gibi konvansiyonel yabancı key varsayımını hasMany metoduna ikinci bir parametre geçerek değiştirebilirsiniz. Ve, aynı şekilde local sütun da belirtilebilir: 1 return $this->hasMany('Yorum', 'foreign_key'); 2 3 4 return $this->hasMany('Yorum', 'foreign_key', 'local_ke\ y'); Bir İlişkinin Tersinin Tanımlanması İlişkinin tersini Yorum modelinde tanımlamak için, belongsTo metodu kullanılmaktadır: 301 Eloquent ORM 1 class Yorum extends Eloquent { 2 public function makale() { return $this->belongsTo('Makale'); } 3 4 5 6 7 8 } Birçoktan Birçoğa Birçoktan birçoğa ilişkiler daha karmaşık bir ilişki tipidir. Bu tarz bir ilişki örneği bir üyenin birçok rolü olması, aynı zamanda bu rollerin başka kullanıcılar tarafından da paylaşılmasıdır. Örneğin birçok üye “Müdür” rolünde olabilir. Bu ilişki için üç veritabanı tablosu gereklidir: uyeler, roller ve rol_uye. Bu rol_uye tablosu ilişkili model isimlerinin alfabetik sıralamasına göre adlandırılır ve uye_id ve rol_id sütunlarına sahip olmalıdır (model isimlerine alttire ve id eklenmiş iki alan). Birçoktan birçoğa ilişkileri belongsToMany metodunu kullanarak tanımlayabiliyoruz: 1 class Uye extends Eloquent { 2 public function roller() { return $this->belongsToMany('Rol'); } 3 4 5 6 7 8 } Artık rolleri Uye modeli aracılığıyla getirebiliriz: Eloquent ORM 1 302 $roller = Uye::find(1)->roller; Pivot tablo ismi olarak ön kabullü tablo ismi yerine başka bir isim kullanmak isterseniz, bunu belongsToMany metoduna ikinci bir parametre geçerek gerçekleştirebilirsiniz: 1 return $this->belongsToMany('Rol', 'uye_rolleri'); İlişkili keyler için konvansiyonel yaklaşımı da değiştirebilirsiniz: 1 2 return $this->belongsToMany('Rol', 'uye_rolleri', 'uye_\ id', 'foo_id'); Ve tabii ki ilişkinin tersini Rol modelinde de tanımlayabilirsiniz: 1 class Rol extends Eloquent { 2 public function uyeler() { return $this->belongsToMany('Uye'); } 3 4 5 6 7 8 } Aracılığıyla Birçoğa Sahip (Has Many Through) Bu “has many through” ilişkisi, aradaki bir ilişki aracılığıyla uzak ilişkilere erişim için uygun bir kestirme yol sağlar. Örneğin, bir Memleket modeli bir Uye modeli aracılığıyla bir çok Post sahibi olabilir. Bu ilişkinin tabloları şunun gibi gözükecektir: Eloquent ORM 1 2 3 303 memlekets id - integer isim - string 4 5 uyes id - integer memleket_id - integer isim - string 6 7 8 9 10 posts id - integer uye_id - integer baslik - string 11 12 13 Bu posts tablosunda bir memleket_id sütunu olmamasına rağmen, hasManyThrough ilişkisi bir memleketin post’larına $memleket->posts aracılığıyla erişebilmemize imkan verecektir. Önce bu ilişkiyi tanımlayalım: 1 class Memleket extends Eloquent { 2 public function posts() { return $this->hasManyThrough('Post', 'Uye'); } 3 4 5 6 7 8 } Eğer ilişkinin keylerini elle belirtmek isterseniz, metoda üçüncü ve dördüncü parametreler geçebilirsiniz: 304 Eloquent ORM 1 class Memleket extends Eloquent { 2 3 4 5 6 7 public function posts() { return $this->hasManyThrough('Post', 'Uye', 'memleket\ _id', 'uye_id'); } 8 9 } Çokbiçimli İlişkiler Çokbiçimli (Polimorfik) İlişkiler bir modelin tek bir ilişkilendirme ile birden çok modele ait olmasına imkan verir. Örneğin, kendisi ya bir personel modeline ya da bir siparis modeline ait olan bir foto modeliniz olduğunu düşünün. Bu ilişkiyi şu şekilde tanımlayacağız: 1 class Foto extends Eloquent { 2 public function resim() { return $this->morphTo(); } 3 4 5 6 7 8 } 9 10 class Personel extends Eloquent { 11 public function fotolar() { return $this->morphMany('Foto', 'resim'); } 12 13 14 15 16 17 } Eloquent ORM 305 18 19 class Siparis extends Eloquent { 20 public function fotolar() { return $this->morphMany('Foto', 'resim'); } 21 22 23 24 25 26 } Çokbiçimli Bir İlişkinin Getirilmesi Artık bir personel ya da siparişe ait fotoları elde edebiliriz: 1 $personel = Personel::find(1); 2 3 4 5 6 foreach ($personel->fotolar as $foto) { // } Çokbiçimli Bir İlişkinin Sahibinin Getirilmesi Ancak, “çokbiçimli” ilişkinin gerçek farkını bir personel veya siparişe Foto modelinden erişebilmekle görürsünüz: 1 $foto = Foto::find(1); 2 3 $resim = $foto->resim; Foto modelindeki resim ilişkisi, fotonun sahibi olan modele bağlı olarak ya bir Personel ya da bir Siparis olgusu döndürecektir. 306 Eloquent ORM Çokbiçimli İlişki Tablo Yapısı Bunun nasıl çalıştığını anlamanıza yardımcı olmak için bir polimorfik ilişkinin veritabanı yapısını keşfedelim: 1 2 3 personel id - integer isim - string 4 5 6 7 siparisler id - integer fiyat - integer 8 9 10 11 12 13 fotolar id - integer dosyayolu - string resim_id - integer resim_type - string Buradaki anahtar alanların fotolar tablosundaki resim_id and resim_type olduğuna dikkat ediniz. Buradaki ID, fotonun sahibi olan personel veya siparişin ID’ini, TYPE ise sahip olan modelin sınıf adını tutacaktır. Böylece ORM, resim ilişkisiyle erişildiğinde döndürülecek sahip modelin hangisi olduğunu tespit edebilecektir. Birçoktan Birçoğa Çokbiçimli İlişkiler Çokbiçimli Birçoktan Birçoğa İlişkilerin Tablo Yapısı Geleneksel çokbiçimli ilişkilere ek olarak, birçoktan birçoğa çokbiçimli ilişkiler de belirleyebilirsiniz. Örneğin, bir blog Post ve Video modeli bir Tag modeline polimorfik bir ilişki paylaşabilirler. Önce, tablo yapısını inceleyelim: Eloquent ORM 1 307 posts id - integer name - string 2 3 4 5 videos id - integer name - string 6 7 8 9 tags id - integer name - string 10 11 12 13 14 15 16 taggables tag_id - integer taggable_id - integer taggable_type - string Sonra da, model üzerinde ilişkileri kurmaya geçelim. Post ve Video modellerinin her ikisi de bir tags metodu aracılığıyla bir morphToMany ilişkisine sahip olacaktır: 1 class Post extends Eloquent { 2 public function tags() { return $this->morphToMany('Tag', 'taggable'); } 3 4 5 6 7 8 } Tag modeli ise ilişkilerinin her biri için bir metod tanımlayabilir: 308 Eloquent ORM 1 class Tag extends Eloquent { 2 public function posts() { return $this->morphedByMany('Post', 'taggable'); } 3 4 5 6 7 public function videos() { return $this->morphedByMany('Video', 'taggable'); } 8 9 10 11 12 13 } İlişkilerin Sorgulanması Seçerken İlişkilerin Yoklanması Bir modelin kayıtlarına erişirken, sonuçları bir ilişki varlığına göre sınırlamak isteyebilirsiniz. Diyelim ki, en az bir yorum yapılmış tüm blog makalelerini çekmek istediniz. Bunu yapmak için has metodunu kullanabilirsiniz: 1 $makaleler = Makale::has('yorumlar')->get(); Ayrıca, bir işlemci ve bir sayı da belirleyebilirsiniz, örneğin üç ve daha çok yorum almış makaleleri getirmek için: 1 $makaleler = Makale::has('yorumlar', '>=', 3)->get(); Hatta daha fazla güce ihtiyacınız varsa, has sorgularınıza “where” şartları koymak için whereHas ve orWhereHas metodlarını kullanabilirsiniz: 309 Eloquent ORM 1 2 3 $makaleler = Makale::whereHas('yorumlar', function($q) { $q->where('content', 'like', 'filan%'); 4 5 })->get(); Dinamik Özellikler Eloquent, ilişkilerinize dinamik özellikler yoluyla erişme imkanı verir. Eloquent ilişkiyi sizin için otomatik olarak yükleyecektir. Hatta, get (birden birçoğa ilişkiler için) metodunun mu yoksa first (birden bire ilişkiler için) metodunun mu çağırılacağını bilecek kadar akılllıdır. İlişkiyle aynı isimli dinamik bir özellik aracılığı ile erişilebilir olacaktır. Örneğin, şu $telefon modelinde: 1 class Telefon extends Eloquent { 2 public function uye() { return $this->belongsTo('Uye'); } 3 4 5 6 7 8 } 9 10 $telefon= Telefon::find(1); Bu üyenin email’ini şu şekilde göstermek yerine: 1 echo $telefon->uye()->first()->email; Buradaki gibi basit bir hale kısaltılabilir: 310 Eloquent ORM 1 echo $telefon->uye->email; Not: Çoklu sonuç döndüren ilişkiler bir Illuminate\Database\Eloquent\Coll sınıf olgusu döndürecektir. Ateşli (Eager) Yüklemeler Ateşli yükleme N + 1 sorgu problemini gidermek içindir. Örnek olarak, Yazar ile ilişkilendirilmiş bir Kitap modelini düşünün. İlişki de şöyle tanımlanmış olsun: 1 class Kitap extends Eloquent { 2 public function yazar() { return $this->belongsTo('Yazar'); } 3 4 5 6 7 8 } Şimdi, şu kodu ele alalım: 1 2 3 4 foreach (Kitap::all() as $kitap) { echo $kitap->yazar->isim; } Bu döngü tablodaki kitapların hepsini almak için 1 sorgu çalıştıracak, sonra da yazarını elde etmek için her bir kitabı sorgulayacaktır. Yani, eğer 25 kitabımız varsa bu döngü 26 sorgu çalıştıracaktır. Neyseki, sorgu sayısını büyük ölçüde azaltan ateşli yükleme kullanabiliriz. Ateşli yüklenecek ilişkiler with metodu aracılığıyla belirlenebilmektedir: 311 Eloquent ORM 1 2 3 4 foreach (Kitap::with('yazar')->get() as $kitap) { echo $kitap->yazar->isim; } Yukardaki döngüde sadece iki sorgu çalıştırılacaktır (model tanımında tablo isimleri açıkça belirtilmediyse ingilizce küçük harf çoğul kabulünü hatırlayınız): 1 select * from kitaps 2 3 select * from yazars where id in (1, 2, 3, 4, 5, ...) Ateşli yüklemenin akıllıca kullanımı uygulamanızın performansını önemli ölçüde artırabilir. Tabii ki, bir defada birden çok ilişkiyi ateşli yükleyebilirsiniz: 1 $kitaplar = Kitap::with('yazar', 'kitabevi')->get(); Hatta içi içe ilişkileri de ateşleyebilirsiniz: 1 $kitaplar = Kitap::with('yazar.kisiler')->get(); Yukarıdaki örnekte yazar ilişkisi ateşli yüklenecektir ve yazarın kisiler ilişkisi de ateşli yüklenecektir. Ateşli Yükleme Sınırlamaları Bazen bir ilişkiyi ateşli yüklemek, ama ateşli yükleme için de bir şart belirlemek isteyebiliriz. İşte bir örnek: 312 Eloquent ORM 1 2 3 4 $uyeler = Uye::with(array('makaleler' => function($quer\ y) { $query->where('baslik', 'like', '%birinci%'); 5 6 }))->get(); Bu örnekte üyenin makalelerinden sadece baslik alanında “birinci” kelimesi geçen makalelerini ateşli yüklüyoruz. Tabii ki, ateşli yükleme Closure’ları “sınırlamalara” sınırlı değildir. Sıralama da yapabilirsiniz: 1 2 3 4 $uyeler = Uye::with(array('makaleler' => function($quer\ y) { $query->orderBy('created_at', 'desc'); 5 6 }))->get(); Tembel Ateşli Yükleme İlişkili modelleri, direkt olarak önceden mevcut model koleksiyonundan ateşli yüklemek de mümkündür. Bu özellikle ilişkili modeli önbellekleme ile birlikte yükleyip yüklememeye dinamik karar vereceğiniz zaman işe yarayabilir. 1 $kitaplar= Kitap::all(); 2 3 $kitaplar->load('yazar', 'kitabevi'); 313 Eloquent ORM İlişkili Modelleri Ekleme İlişkili Bir Modelin Eklenmesi Yeni ilişkili model ekleme ihtiyacınız çok olacaktır. Örneğin, bir makale için yeni bir yorum eklemek isteyebilirsiniz. Model üzerinde makale_id yabancı key alanını elle ayarlamak yerine, doğrudan ebeveyn Makale modelinden yeni yorum ekleyebilirsiniz: 1 $yorum = new Yorum(array('mesaj' => 'Yeni bir yorum.')); 2 3 $makale = Makale::find(1); 4 5 $yorum = $makale->yorumlar()->save($yorum); Bu örnekte eklenen yorumdaki makale_id alanı otomatik olarak ayarlanmaktadır. Eğer birden çok sayıda ilişkili model kaydetmeniz gerekirse: 1 2 3 4 5 $yorumlar = new new new ); array( Yorum(array('mesaj' => 'Yeni bir yorum.')), Yorum(array('mesaj' => 'Bir başka yorum.')), Yorum(array('mesaj' => 'Son bir yorum.')) 6 7 $makale = Makale::find(1); 8 9 $yorum = $makale->yorumlar()->saveMany($yorumlar); Modellerin Üye Yapılması (Belongs To) Bir belongsTo ilişkisi güncellenirken, associate metodunu kullanabilirsiniz. Bu metod çocuk modeldeki yabancı anahtarı ayarlayacaktır: Eloquent ORM 1 314 $hesap = Hesap::find(10); 2 3 $uye->hesap()->associate($hesap); 4 5 $uye->save(); İlişkili Model Ekleme (Birçoktan Birçoğa) Birçoktan birçoğa ilişkilerle çalışırken de ilişkili model ekleyebilirsiniz. Daha önceki örneğimiz Uye ve Rol modellerini kullanmaya devam edelim. Bir üyeye yeni roller eklemeyi attach metodu ile yapabiliriz: Birçoktan Birçoğa Modellerinin Eklenmesi 1 $uye = Uye::find(1); 2 3 $uye->roller()->attach(1); İlişkiler için pivot tabloda tutulan nitelikleri bir dizi olarak da geçebilirsiniz: 1 2 $uye->roller()->attach(1, array('sonaerme' => $sonaerme\ )); Tabii, attach‘in ters işlemi detach‘tir: 1 $uye->roller()->detach(1); Birçoktan Birçoğa Model Bağlamak İçin Sync Kullanımı İlişkili modelleri bağlamak için sync metodunu da kullanabilirsiniz. Bu sync metodu parametre olarak pivot tablodaki yerlerin Eloquent ORM 315 id’lerinden oluşan bir dizi geçirilmesini ister. Bu işlem tamamlandıktan sonra, model için kullanılacak ara tabloda sadece bu id’ler olacaktır: 1 $uye->roller()->sync(array(1, 2, 3)); Sync Yaparken Pivot Veri Eklenmesi Belli id değerleri olan başka pivot tabloyu da ilişkilendirebilirsiniz: 1 2 $uye->roller()->sync(array(1 => array('sonaerme' => tru\ e))); Bazen yeni bir ilişkili model oluşturmak ve tek bir komutla bunu eklemek isteyebilirsiniz. Bu işlem için, save metodunu kullanabilirsiniz: 1 $rol = new Rol(array('isim' => 'Editor')); 2 3 Uye::find(1)->roller()->save($rol); Bu örnekte, yeni bir Rol modeli kaydedilecek ve uye modeline eklenecektir. Bu işlem için bağlı tablolardaki niteliklerden oluşan bir dizi de geçebilirsiniz: 1 2 Uye::find(1)->roller()->save($rol, array('sonaerme' => \ $sonaerme)); Ebeveyn Zaman Damgalarına Dokunma Bir Yorum‘un bir Makale‘ye ait olması örneğimizdeki gibi, bir model başka bir modele ait (belongsTo) olduğu takdirde, çocuk modeli 316 Eloquent ORM güncellediğiniz zaman ebeveyn zaman damgasını da güncellemek iyidir. Örneğin, bir Yorum güncellendiğinde, bunun sahibi olan Makale‘nin updated_at zaman damgasını otomatikman güncellemek isteyebilirsiniz. Bunu gerçekleştirmek için tek yapacağınız şey, çocuk modele ilişkilerin isimlerini içeren bir touches özelliği eklemektir: 1 class Yorum extends Eloquent { 2 protected $touches = array('makale'); 3 4 public function makale() { return $this->belongsTo('Makale'); } 5 6 7 8 9 10 } Bunu yaptıktan sonra artık bir Yorum güncellediğinizde, sahibi olan Makale de güncellenmiş bir updated_at sütununa sahip olacaktır: 1 $yorum = Yorum::find(1); 2 3 $yorum->text = 'Bu yorumu düzelt!'; 4 5 $yorum->save(); Pivot Tablolarla Çalışmak Daha önce öğrendiğiniz gibi, birçoktan birçoğa ilişkilerle çalışmak bir ara tablonun olmasını gerektirir. Eloquent işte bu tablo ile etkileşim için çok yararlı bazı yollar sağlamaktadır. Örneğin bizim bir Uye nesnemiz, bir de onun bağlı olduğu birçok Rol nesnelerimiz olsun. Eloquent ORM 317 Bu ilişkiye eriştikten sonra, pivot tabloya modellerimiz üzerinden erişebiliriz: 1 $uye = Uye::find(1); 2 3 4 5 6 foreach ($uye->roller as $rol) { echo $rol->pivot->created_at; } Dikkat ederseniz, elde ettiğimiz her bir Rol modeline otomatikman bir pivot niteliği atanmıştır. Bu nitelik, ara tabloyu temsil eden bir modeli taşır ve herhangi bir Eloquent modeli gibi kullanılabilir. Ön tanımlı olarak, pivot nesnesinde sadece keyler olacaktır. Şayet pivot tablonuzda bunlardan başka nitelikler varsa, bunları ilişki tanımlama sırasında belirtmelisiniz: 1 2 return $this->belongsToMany('Rol')->withPivot('falan', \ 'filan'); Şimdi Rol modelinin pivot nesnesinde falan ve filan nitelikleri erişilebilir olacaktır. Eğer pivot tablonuzun created_at ve updated_at zaman damgalarını otomatik olarak halletmesini istiyorsanız, ilişki tanımlamasında withTimestamps metodunu kullanın: 1 return $this->belongsToMany('Rol')->withTimestamps(); Bir Pivot Tablodaki Kayıtların Silinmesi Bir modelin pivot tablosundaki tüm kayıtları silmek için, detach metodunu kullanabilirsiniz: 318 Eloquent ORM 1 Uye::find(1)->roller()->detach(); Bu operasyonun roller tablosundan kayıt silmediğine, sadece pivot tablodan sildiğine dikkat ediniz. Bir Pivot Tablodaki Bir Kaydın Güncellenmesi Bazen pivot tablonuzu güncellemeniz ama onu detach etmemeniz gerekebilir. Eğer pivot tablonuzu “yerinde” güncellemek istiyorsanız aşağıdakine benzer şekilde updateExistingPivot metodunu kullanabilirsiniz: 1 2 Uye::find(1)->roller()->updateExistingPivot($roleId, $a\ ttributes); Özel Bir Pivot Model Tanımlanması Laravel size özel bir Pivot model tanımlama imkanı da verir. Özel bir model tanımlamak için, öncelikle Eloquent‘i genişleten kendi “Taban” model sınıfınızı oluşturun. Diğer Eloquent modellerinizde, defaut Eloquent taban yerine bu özel taban modeli genişletin. Taban modelinize, sizin özel Pivot modelinizin bir olgusunu döndüren aşağıdaki fonksiyonu ekleyin: 1 2 3 4 5 6 public function newPivot(Model $parent, array $attribut\ es, $table, $exists) { return new YourCustomPivot($parent, $attributes, $tabl\ e, $exists); } Koleksiyonlar Eloquent tarafından get metodu veya bir relationship (ilişki) aracılığıyla döndürülen tüm çoklu sonuç kümeleri bir Eloquent 319 Eloquent ORM Collection nesnesi döndürecektir. Bu nesne PHP’nin IteratorAggregate arayüzünün bir uygulama biçimidir ve tıpkı bir dizide dolaşır gibi dolaşılabilinmektedir. Bunun yanında, bu nesne sonuç kümeleriyle çalışırken işe yarayan başka bir takım metodlara da sahiptir. Bir Koleksiyonun Bir Key Taşıyıp Taşımadığının Yoklanması Örneğin biz contains metodunu kullanarak bir sonuç kümesinin belli bir primer key içerip içermediğini tespit edebiliriz: 1 $roller = Uye::find(1)->roller; 2 3 4 5 6 if ($roller->contains(2)) { // } Koleksiyonlar aynı zamanda bir dizi ya da JSON’a dünüştürülebilmektedir: 1 $roller = Uye::find(1)->roller->toArray(); 2 3 $roller = Uye::find(1)->roller->toJson(); Eğer bir koleksiyon bir string kalıbına çevrilirse JSON olarak döndürülecektir: 1 $roller = (string) Uye::find(1)->roller; Koleksiyonlarda Tekrarlı İşlemler Eloquent koleksiyonları içerdikleri elemanları dolaşmak ve filtre etmekle ilgili bazı metodlara da sahiptir: 320 Eloquent ORM 1 2 $roller = $uye->roller->each(function($rol) { 3 4 }); Koleksiyonlarda Filtreleme Verilen Closure (callback) array_filter()¹⁹¹ için fonksiyon olarak kullanılacak. 1 2 3 4 $uyeler = $uyeler->filter(function($uye) { return $uye->isAdmin(); }); Not: Bir koleksiyonu filtreler ve onu JSON’a döndürürken, dizinin keylerini reset etmek için önce values fonksiyonunu çağırmayı deneyin. Her Bir Koleksiyon Nesnesine Bir Anonim Fonksiyon (Callback) Uygulamak 1 $roller = Uye::find(1)->roller; 2 3 4 5 6 $roller->each(function($rol) { // }); Bir Koleksiyonu Bir Değere Göre Sıralama ¹⁹¹http://php.net/manual/en/function.array-filter.php 321 Eloquent ORM 1 2 3 4 $roller = $roller->sortBy(function($rol) { return $rol->created_at; }); Bir Koleksiyonu Bir Değere Göre Sıralama 1 $roller = $roller->sortBy('created_at'); Özel Bir Koleksiyon Tipinin Döndürülmesi Bazen de, kendi eklediğiniz metodları olan özel bir koleksiyon nesnesi döndürmek isteyebilirsiniz. Bunu, Eloquent modeliniz üzerinde newCollection metodunu ezerek yapabilirsiniz: 1 class Uye extends Eloquent { 2 public function newCollection(array $models = array()) { return new CustomCollection($models); } 3 4 5 6 7 8 } Erişimciler & Değiştiriciler (Accessors & Mutators) Bir Erişimci Tanımlanması Eloquent model niteliklerini alıp getirirken veya onları ayarlarken dönüşüm yapmak için uygun bir yol sağlar. Bir erişimci beyan etmek için modeliniz üzerinde sadece bir getFilanAttribute metodu tanımlamak yeterlidir. Yalnız unutmamanız gereken şey, veritabanı 322 Eloquent ORM sütunlarınızın isimleri yılan tarzı (küçük harfli kelimelerin boşluk olmaksızın alt tire ile birbirine bağlanması) olsa dahi, metodlarınızın deve tarzı (birinci kelimenin tümü küçük harf olmak ve sonraki kelimelerin ilk harfi büyük diğer hafleri küçük olmak üzere boşluk olmaksızın kelimelerin yanyana dizilmesi) olması gerektiğidir: 1 class Uye extends Eloquent { 2 public function getSoyAdiAttribute($value) { return ucfirst($value); } 3 4 5 6 7 8 } Yukarıdaki örnekte soy_adi sütununun bir erişimcisi vardır. Niteliğin değerinin erişimciye geçildiğine dikkat ediniz. Bir Değiştirici Tanımlanması Değiştiriciler de benzer şekilde deklare edilir: 1 class Uye extends Eloquent { 2 public function setSoyAdiAttribute($value) { $this->attributes['soy_adi'] = strtolower($value); } 3 4 5 6 7 8 } 323 Eloquent ORM Tarih Değiştiricileri Ön tanımlı olarak, Eloquent created_at ve updated_at sütunlarını Carbon¹⁹², olgularına çevirecektir. Carbon çeşitli yardımcı metodlar sağlar ve PHP’nin DateTime sınıfını genişletir. Siz hangi alanların otomatik olarak değiştirileceğini isteğinize göre ayarlayabilirsiniz, hatta modeldeki getDates metodunu ezmek suretiyle bu davranışı tamamen devre dışı bırakabilirsiniz: 1 2 3 4 public function getDates() { return array('created_at'); } Bir sütun bir tarih olarak kabul edildiğinde, bunun değerini bir UNIX timetamp, date string (Y-m-d), date-time string ve tabii ki bir DateTime / Carbon olgusuna ayarlayabilirsiniz. Tarih değiştiricilerini tümden devre dışı bırakmak için getDates metodunda boş bir dizi döndürünüz: 1 2 3 4 public function getDates() { return array(); } Model Olayları Eloquent modelleri bazı olayları tetikleyerek, modelin yaşam döngüsündeki çeşitli noktalarda müdahale etmenize imkan verir. Bu amaçla şu metodlar kullanılmaktadır: creating, created, updating, updated, saving, saved, deleting, deleted, restoring, restored. ¹⁹²https://github.com/briannesbitt/Carbon 324 Eloquent ORM Yeni bir öğe ilk defa kaydedilir kaydedilmez creating ve created olayları ateşlenecektir. Eğer bir öğe yeni değilse ve save metodu çağrılırsa, updating / updated olayları ateşlenecektir. Her iki durumda da saving / saved olayları ateşlenecektir. Saklama Operasyonlarının Olaylar Aracığıyla İptal Edilmesi Eğer creating, updating, saving veya deleting olaylarından false döndürülürse, eylem iptal edilecektir: 1 2 3 4 Uye::creating(function($uye) { if ( ! $uye->isValid()) return false; }); Bir Model Boot Metodunun Ayarlanması Eloquent modelleri bunun dışında static bir boot metodu içermekte olup, olay bağlamanızı kayıt etmeniz için uygun bir yerdir. 1 class Uye extends Eloquent { 2 public static function boot() { parent::boot(); 3 4 5 6 // Olay bağlamayı ayarla... 7 } 8 9 10 } 325 Eloquent ORM Model Gözlemcileri Model olaylarının işlenmesini pekiştirmek için, bir model gözlemcisi kaydı yapabilirsiniz. Bir gözlemci sınıfında çeşitli model olaylarına tekabül eden metodlar bulunabilir. Örneğin bir gözlemcide, diğer model olay isimlerine ek olarak creating, updating, saving metodları olabilir. Yani, bir model gözlemcisi şöyle olabilir: 1 class UyeGozlemcisi { 2 public function saving($model) { // } 3 4 5 6 7 public function saved($model) { // } 8 9 10 11 12 13 } Modelinizde observe metodunu kullanarak bir gözlemci olgusu kaydı yapabilirsiniz: 1 Uye::observe(new UyeGozlemcisi); Diziye / JSON’a Çevirme Bir Modelin Bir Diziye Çevrilmesi JSON APIler oluşturulurken, çoğu defa modellerinizi ve ilişkilerini dizilere veya JSON’a çevirmeniz gerekecektir. Bu yüzden Eloqu- 326 Eloquent ORM ent bunları yapacak metodlar içermektedir. Bir modeli ve onun yüklenen ilişkilerini bir diziye çevirmek için toArray metodunu kullanabilirsiniz: 1 $uye = Uye::with('roller')->first(); 2 3 return $uye->toArray(); Modellerin koleksiyonlarının da bütün olarak dizilere dönüştürülebildiğini unutmayın: 1 return Uye::all()->toArray(); Bir Modelin JSON’a Çevrilmesi Bir Modeli JSON’a çevirmek için, toJson metodunu kullanabilirsiniz: 1 return Uye::find(1)->toJson(); Bir Modelin Bir Rotadan Döndürülmesi Bir model veya koleksiyon bir string kalıbına sokulduğu takdirde, JSON’a çevrileceğine dikkat ediniz. Yani Elequent nesnelerini direkt olarak uygulamanızın rotalarından döndürebilirsiniz! 1 2 3 4 Route::get('uyeler', function() { return Uye:all(); }); Niteliklerin Dizi veya JSON’a Çevrilmekten Saklanması Bazen bazı nitelikleri (örneğin şifreleri) modelinizin dizi veya JSON biçimlerinden hariç tutmak isteyebilirsiniz. Bunu yapmak için modelinize bir hidden özelliği ekleyiniz: Eloquent ORM 1 327 class Uye extends Eloquent { 2 protected $hidden = array('parola'); 3 4 5 } Not: İlişkileri gizlerken dinamik erişimci ismini değil ilişkinin metod ismini kullanın. Alternatif olarak, beyaz bir liste tanımlamak için visible özelliğini kullanabilirsiniz: 1 protected $visible = array('adi', 'soy_adi'); Kimi durumlarda, veritabanınızdaki bir sütuna tekabül etmeyen dizi nitelikleri eklemeniz gerekebilir. Bunu yapmak için, değer için bir erişimci tanımlamanız yeterlidir: 1 2 3 4 public function getIsAdminAttribute() { return $this->attributes['admin'] == 'yes'; } Erişimciyi oluşturduktan sonra, ilgili modeldeki appends özelliğine değeri ekleyin: 1 protected $appends = array('is_admin'); Nitelik appends listesine eklendikten sonra modelin hem dizi hem de JSON formlarına dahil edilecektir. Şema Oluşturucusu Giriş Laravel’in Schema sınıfı tablolara müdahale etmekte veritabanı bilinmesine gerek kalmaz bir yol sağlar. Laravel’in desteklediği tüm veritabanlarıyla sağlıklı çalışır ve bu sistemlerin tümünde aynı olan bir API’ye sahiptir. Tabloların Oluşturulması ve Yok Edilmesi Yeni bir veritabanı tablosu oluşturmak için Schema::create metodu kullanılır: 1 2 3 4 Schema::create('uyeler', function($table) { $table->increments('id'); }); Bu create metoduna geçilen ilk parametre tablonun adıdır ve ikincisi bu yeni tabloyu tanımlamakta kullanılabilecek bir proje (Blueprint) nesnesi alacak bir anonim fonksiyondur (Closure) . Mevcut bir veritabanı tablosunun adını değiştirmek için rename metodu kullanılabilir: 1 Schema::rename($eskisinden, $yeniye); Şema operasyonunun gerçekleştirileceği bağlantıyı belirlemek için Schema::connection metodunu kullanınız: Şema Oluşturucusu 1 2 3 4 5 329 Schema::connection('falan')->create('uyeler', function(\ $table) { $table->increments('id'); }); Bir tabloyu yok etmek için, Schema::drop metodunu kullanabilirsiniz: 1 Schema::drop('uyeler'); 2 3 Schema::dropIfExists('uyeler'); Sütunların Eklenmesi Mevcut bir tabloda sütun ekleme için Schema::table metodunu kullanıyoruz: 1 2 3 4 Schema::table('uyeler', function($table) { $table->string('email'); }); Tablo oluşturma zamanında ise tablo oluşturucusunda bulunan çeşitli sütun tiplerini kullanabilirsiniz: Komut | Açıklama ————- | ————- $table->bigIncrements('id'); | “big integer” eşdeğeri. $table->bigInteger('puan'); | BIGINT eşdeğeri sütun $table->binary('veri'); | BLOB eşdeğeri sütun $table->boolean('teyit'); | BOOLEAN eşdeğeri sütun $table->char('isim', 4); | bir uzunluğu olan CHAR eşdeğeri $table->date('created_at'); | DATE eşdeğeri sütun $table->dateTime('created_at'); | DATETIME eşdeğeri sütun $table->decimal('miktar', 5, 2); | Şema Oluşturucusu 330 basamak ve ondalık basamak sayısı belirlenmiş DECIMAL eşdeğeri sütun $table->double('column', 15, 8); | DOUBLE eşdeğeri sütun $table->enum('tercihler', array('falan', 'filan')); | ENUM eşdeğeri sütun $table->float('miktar'); | FLOAT eşdeğeri sütun $table->increments('id'); | Giderek artan ID alanı ekler (birincil anahtar). $table->integer('puan'); | INTEGER eşdeğeri sütun $table->longText('description'); | LONGTEXT eşdeğeri $table->mediumInteger('numbers'); | MEDIUMINT eşdeğeri $table->mediumText('description'); | MEDIUMTEXT eşdeğeri $table->morphs('taggable'); | INTEGER taggable_id ve STRING taggable_type alanlarını ekler $table->nullableTimestamps(); | NULLlara izin vermek dışında timestamps() ile aynı $table->smallInteger('puan | SMALLINT eşdeğeri sütun $table->tinyInteger('numbers'); | TINYINT eşdeğeri $table->softDeletes(); | Belirsiz silmeler için deleted_at sütunu ekler $table->string('email'); | VARCHAR eşdeğeri sütun $table->string('isim', 100); | belli uzunlukta VARCHAR eşdeğeri sütun $table->text('izahat'); | TEXT eşdeğeri sütun $table->time('ikindi'); | TIME eşdeğeri sütun $table->timestamp('eklenme_vakti'); | TIMESTAMP eşdeğeri sütun $table->timestamps(); | created_at ve updated_at sütunlarını ekler $table->rememberToken(); | VARCHAR(100) NULL olarak remember_token ekler ->nullable() | İlgili sütunun NULL değerleri olabilir demektir ->default($deger) | Bir sütun için ön tanımlı bir değer tanımlar ->unsigned() | INTEGER’i UNSIGNED olarak ayarlar MySQL Veritabanında After Kullanımı Şayet MySQL veritabanı kullanıyorsanız, sütunların sıralamasını belirlemek için after metodunu kullanabilirsiniz: 1 $table->string('isim')->after('email'); Şema Oluşturucusu 331 Sütun İsimlerinin Değiştirilmesi Bir sütun ismini değiştirmek için Şema Oluşturucusunda renameColumn metodunu kullanabilirsiniz: 1 2 3 4 Schema::table('uyeler', function($table) { $table->renameColumn('eski', 'yeni'); }); Not: enum sütun tipleri için isim değiştirme desteklenmemektedir. Sütunların Yok Edilmesi Bir Veritabanı Tablosundan Bir Sütunun Yok Edilmesi 1 2 3 4 Schema::table('uyeler', function($table) { $table->dropColumn('puan'); }); Bir Veritabanı Tablosundan Birden Çok Sütunun Yok Edilmesi 1 2 3 4 5 Schema::table('uyeler', function($table) { $table->dropColumn(array('puan', 'avatar', 'ikametgah'\ )); }); 332 Şema Oluşturucusu Mevcutluk Yoklanması Tablonun Var Olduğunun Yoklanması hasTable ve hasColumn metodlarını kullanarak bir tablo ya da sütunun var olup olmadığını kolayca yoklayabilirsiniz: 1 2 3 4 if (Schema::hasTable('uyeler')) { // } Sütunların Var Olduğunun Yoklanması 1 2 3 4 if (Schema::hasColumn('uyeler', 'email')) { // } İndeks Eklenmesi Şema oluşturucusu çeşitli indeks tiplerini desteklemektedir. Bunları iki şekilde ekleyebilirsiniz. Birinci yol bir sütun tanımı sırasında tanımlamak, ikinci yol ise ayrıca eklemektir: 1 $table->string('email')->unique(); Ya da, ayrı satırlarda indeks ekleme yolunu seçebilirsiniz. Aşağıda, kullanılabilecek tüm indeks tiplerinin bir listesi verilmiştir: Komut | Açıklama ————- | ————- $table->primary('id'); | Bir birincil anahtar eklenmesi $table->primary(array('ilk', 'son')); | Bileşik keylerin eklenmesi $table->unique('email'); | Benzersiz bir indeks eklenmesi $table->index('il'); | Basit bir indeks eklenmesi Şema Oluşturucusu 333 Yabancı Anahtar (Foreign Key) Laravel, tablolarınıza yabancı key sınırlaması eklemeniz için de destek verir: 1 2 $table->foreign('uye_id')->references('id')->on('uyeler\ '); Bu örnekte, uye_id sütununun uyeler tablosundaki id sütununu referans aldığını beyan ediyoruz. Ayrıca, güncelleme ve silme (“on delete” ve “on update”) eylemi sınırlamaları için seçenekler de belirleyebilirsiniz: 1 2 3 $table->foreign('uye_id') ->references('id')->on('uyeler') ->onDelete('cascade'); Bir yabancı keyi yok etmek için, dropForeign metodunu kullanabilirsiniz. Yabancı key için de diğer indeksler için kullanılan isimlendirme geleneği kullanılır: 1 $table->dropForeign('makaleler_uye_id_foreign'); Not: Otomatik artan bir tam sayıya başvuran bir foreign key oluşturulurken, foreign key sütununu her zaman için unsigned yapmayı unutmayın. İndekslerin Yok Edilmesi Bir indeksi yok etmek için indeksin adını belirtmelisiniz. Laravel, ön tanımlı olarak indekslere makul bir isim tahsis eder. Tablo adını, 334 Şema Oluşturucusu indekslenen alan adlarını ve indeks tipini art arda ekler. İşte bazı örnekler: Komut | Açıklama ————- | ————- $table->dropPrimary('uyeler_id_primary'); | “uyeler” tablosundan primer key’in yok edilmesi $table->dropUnique('uyeler_email_unique'); | “uyeler” tablosundan benzersiz bir indeksin yok edilmesi $table->dropIndex('geo_il_index'); | “geo” tablosundan basit bir indeksin yok edilmesi Zaman Damgaları ve Belirsiz Silmelerin Yok Edilmesi timestamps, nullableTimestamps veya softDeletes sütun türleri- nin yok edilmesi için aşağıdaki metodları kullanabilirsiniz: Komut | Açıklama ————- | ————- $table->dropTimestamps(); | Tablodan created_at ve updated_at sütunlarının düşürülmesi $table->dropSoftDeletes(); | Tablodan deleted_at sütununun düşürülmesi Depolama Motorları Bir tablo için depolama motoru ayarlamak için, şema oluşturucusunda engine özelliğini ayarlayınız: 1 2 3 Schema::create('uyeler', function($table) { $table->engine = 'InnoDB'; 4 $table->string('email'); 5 6 }); Migrasyon (Migration) ve Veri Ekme (Seeding) Giriş Migrasyonlar veritabanı için bir sürüm kontrol türüdür. Bir ekibin veritabanı şemasını değiştirmesine ve son şema durumuna güncel kalmalarına imkan verir. Migrasyonlar uygulama şemasını kolayca yönetmek amacıyla tipik olarak Şema (Schema) Kurucu¹⁹³ ile eşleştirilirler. Migrasyonların Oluşturulması Bir migrasyon oluşturmak için, Artisan KSA’da (Artisan Komut Satırı Arayüzü) migrate:make komutunu kullanabilirsiniz: 1 php artisan migrate:make kullanicilar_tablosunu_olustur Migrasyon app/database/migrations dizininize konumlandırılır ve Laravel’in migrasyonların sırasını belirlemesine imkan veren bir zaman damgası içerir. Migrasyonu oluştururken bir patika --path seçeneği de belirtebilirsiniz. Patika, kurulum kök dizinine göreceli olmalıdır: 1 2 php artisan migrate:make falancaMigrasyon --path=app/mi\ grations Tablo ismini ve yeni bir tablonun oluşturulacağını da, --table ve --create seçeneklerini kullanarak belirtebilirsiniz: ¹⁹³/docs/schema Migrasyon (Migration) ve Veri Ekme (Seeding) 1 2 336 php artisan migrate:make kullanicilar_tablosunu_olustur\ --table=users 3 4 5 php artisan migrate:make kullanicilar_tablosuna_oy_vere\ nler_ekle --create=users Migrasyonların Çalıştırılması Bekleyen Migrasyonların Hepsinin Birden Çalıştırılması 1 php artisan migrate Bir Patikadaki Migrasyonların Çalıştırılması 1 php artisan migrate --path=app/falancaDizin/migrations Bir Paketin Tüm Bekleyen Migrasyonlarının Çalıştırılması 1 php artisan migrate --package=vendor/package Not: Migrasyonlar çalıştırırken, “class not found” (sınıf bulunamadı) hatası alırsanız, composer dump-autoload komutunu çalıştırarak deneyiniz. Üretim Ortamında Migrasyonların Zorlanması Bazı migration işlemleri yıkıcıdır, yani verilerinizi kaybetmenize yol açabilir. Bu komutları üretim veritabanınızda çalıştırmanızdan korumak amacıyla, bu komutları çalıştırdığınızda sizden teyit etmeniz istenecektir. Bu komutların böyle bir istek olmadan çalışmasını zorlamak için --force flamasını kullanın: 337 Migrasyon (Migration) ve Veri Ekme (Seeding) 1 php artisan migrate --force Migrasyonların Geriye Döndürülmesi Son Migrasyon İşleminin Geriye Döndürülmesi 1 php artisan migrate:rollback Tüm Migrasyon İşlemlerinin Geriye Döndürülmesi 1 php artisan migrate:reset Tüm Migrasyon İşlemlerinin Geriye Döndürülmesi ve Hepsinin Tekrardan Çalıştırılması 1 2 php artisan migrate:refresh eden //Veri ekmeler dahil edilm\ 3 4 5 php artisan migrate:refresh --seed edilerek //Veri ekmeler dahil\ Veritabanına Veri Ekme Veri Ekme (seeding), migrasyon ile oluşturulacak veritabanı tablosunda gerekli olacak ilk veri kayıtlarının (seed data) oluşturulması işlemidir(:çevirenin notu). Laravel, veritabanınızın deneme verisi ile veri ekme için kolaylık sağlayacak olan veri ekme (seed) sınıflarını bulundurur. Bütün veri ekme sınıfları app/database/seeds dizininde konumlandırılır. Veri ekme sınıflarına istediğiniz isimleri verebilirsiniz. Fakat isimlendirirken anlaşılacak belli bir geleneğe uyulması lehinizedir, örneğin KullanicilarTablosunaVeriEkme, vb. Ön tanımlı olarak, sizin için bir DatabaseSeeder sınıfı tanımlanmıştır. Veri ekme sırasını denetlemenize imkan verecek olan, bu Migrasyon (Migration) ve Veri Ekme (Seeding) 338 sınıfın ‘çağır’ call metodunu kullanarak diğer veri ekme sınıflarınızı çalıştırabilirsiniz. Veritabanı Veri Ekme Sınıfı Örneği 1 class DatabaseSeeder extends Seeder { 2 public function run() { $this->call('KullanicilarTablosunaVeriEkme'); 3 4 5 6 $this->command->info('Kullanıcı tablosuna veri ekildi\ 7 8 !'); } 9 10 11 } 12 13 class KullanicilarTablosunaVeriEkme extends Seeder { 14 public function run() { DB::table('kullanicilar')->delete(); 15 16 17 18 User::create(array('email' => 'falanca@filanca.com')); 19 } 20 21 22 } Veritabanına veri ekmek için, Artisan KSA’da db:seed (veri ek) komutunu kullanabilirsiniz: 1 php artisan db:seed Ön tanımlı olarak, bu db:seed komutu DatabaseSeeder sınıfını çalıştırır (bu sınıf diğer ekme sınıflarını çağırmak için kullanılabil- Migrasyon (Migration) ve Veri Ekme (Seeding) 339 mektedir). Buna karşın bireysel olarak çalıştırılacak belirli bir seeder sınıfını belirtmek için --class seçeneğini kullanabilirsiniz: 1 2 php artisan db:seed --class=KullanicilarTablosunaVeriEk\ me Veritabanına migrate:refresh (yenile) komutunu kullanarak da veri ekebilirsiniz, bu komut aynı zamanda bütün migrasyonları geriye döndürüp, hepsini tekrardan çalıştıracaktır: 1 php artisan migrate:refresh --seed Redis Giriş Redis¹⁹⁴ açık kaynak, gelişmiş bir anahtar-değer deposudur. Anahtarlar stringler¹⁹⁵, hashler¹⁹⁶, listeler¹⁹⁷, kümeler¹⁹⁸ ve sıralı kümeler¹⁹⁹ taşıyabildikleri için sıklıkla bir veri yapısı sunucusu olarak da ifade edilmektedir. Not: Eğer PECL aracılığıyla yüklenmiş Redis PHP eklentiniz varsa, app/config/app.php dosyanızda Redis için kullanılan lakabın ismini değiştirmeniz gereklidir. Yapılandırma Uygulamanızdaki Redis yapılandırması app/config/database.php dosyasında saklanır. Bu dosya içerisinde, uygulamanız tarafından kullanılan Redis sunucularını içeren bir redis dizisi göreceksiniz: ¹⁹⁴http://redis.io ¹⁹⁵http://redis.io/topics/data-types#strings ¹⁹⁶http://redis.io/topics/data-types#hashes ¹⁹⁷http://redis.io/topics/data-types#lists ¹⁹⁸http://redis.io/topics/data-types#sets ¹⁹⁹http://redis.io/topics/data-types#sorted-sets 341 Redis 1 'redis' => array( 2 'cluster' => true, 3 4 'default' => array('host' => '127.0.0.1', 'port' => 63\ 5 6 79), 7 8 ), Geliştirme için bu “default” sunucu yapılandırması yeterlidir. Yine de siz ortamınıza göre bu diziyi değiştirmekte serbestsiniz. Sadece her Redis sunucusuna bir ad verin ve bu sunucu tarafından kullanılan ana bilgisayarı (host) ve bağlantı noktasını (port) belirtin. Buradaki cluster seçeneği Laravel Redis istemcisine Redis düğümleriniz arasında istemci taraflı bölümlendirme (sharding) yapmasını söylemektedir. Böylece siz düğüm havuzu ve büyük miktarda kullanılabilir RAM oluşturabilirsiniz. Bununla birlikte istemci taraflı bölümlendirmenin başarısızlık durumlarını halledemediğini unutmayın. Bu nedenle, istemci taraflı bölümlendirme, esasında başka bir asıl veri deposunda olup da önbelleğe alınmış veriler için uygundurlar. Şayet sizin Redis serveriniz authentication istiyorsa, Redis server yapılandırma dizinize bir password anahtar / değer çifti eklemek suretiyle bir şifre sağlayabilirsiniz. Kullanım Bir Redis olgusunu Redis::connection metodunu çağırarak getirebilirsiniz: 1 $redis = Redis::connection(); Redis 342 Bu size “default” Redis sunucusunun bir olgusunu verecektir. Eğer sunucu öbekleme (clustering) kullanmıyorsanız, Redis yapılandırmanızda tanımlanan belirli bir sunucuyu getirmek için connection metodunda parametre olarak o sunucunun adını geçersiniz: 1 $redis = Redis::connection('digerSunucu'); Redis istemci olgusu oluşturduktan sonra, artık bu olguya her türlü Redis komutu²⁰⁰ verebiliriz. Laravel Redis sunucusuna komut geçerken sihirli metodlar tekniğini kullanır: 1 $redis->set('isim', 'Tuana Şeyma'); 2 3 $isim = $redis->get('isim'); 4 5 $degerler = $redis->lrange('isimler', 5, 10); Görüldüğü gibi komut parametreleri basitçe sihirli metodlara geçilmektedir. Tabii ki siz sihirli metod tekniğini kullanmak zorunda değilsiniz, command metodunu kullanarak da sunucuya komut geçebilirsiniz: 1 $degerler = $redis->command('lrange', array(5, 10)); Komutlarınızı sadece “default” bağlantıda çalıştıracağınız zaman, direkt Redis sınıfındaki statik sihirli metodları kullanın: ²⁰⁰http://redis.io/commands 343 Redis 1 Redis::set('isim', 'Tuana Şeyma'); 2 3 $isim = Redis::get('isim'); 4 5 $degerler = Redis::lrange('isimler', 5, 10); Not: Redis Önbellekleme²⁰¹ ve Oturum²⁰² sürücüleri Laravel’de mevcuttur. Pipeline Kullanma Bir operasyonda sunucuya birçok komut göndermeniz gerektiğinde pipeline kullanılmalıdır. Bunu yapmak için pipeline komutunu kullanın: Sunucularınıza Birden Çok Komutun Döşenmesi 1 2 3 4 5 6 7 Redis::pipeline(function($pipe) { for ($i = 0; $i < 1000; $i++) { $pipe->set("key:$i", $i); } }); ²⁰¹/docs/cache ²⁰²/docs/session Artisan CLI Giriş Artisan, Laravel içerisinde gelen CLI’ın (Command-line Interface) adıdır. Artisan size uygulamanızı geliştirirken birçok yardımcı komut sağlar. Artisan, güçlü Symfony Console bileşeni üzerinden geliştirilmiştir. Kullanım Tüm Kullanılabilir Komutların Listelenmesi Tüm Artisan komutlarının bir listesini görmek için list komutunu kullanabilirsiniz: 1 php artisan list Bir Komut için Yardım Ekranının Görüntülenmesi Tüm komutların özel bir “yardım” ekranı vardır ve komut hakkındaki argüman sırası ile ayarlar gibi bilgilerin açıklanmasını sağlar. Bir yardım ekranını görüntülemek için komut adından önce help yazın: 1 php artisan help migrate Yapılandırma Ortamının Belirtilmesi --env anahtarını kullanarak bir komut çalıştırılırken kullanılacak olan yapılandırma ortamını belirtebilirsiniz: Artisan CLI 1 345 php artisan migrate --env=local Güncel Laravel Sürümünüzün Gösterilmesi Ayrıca Laravel yüklemenizin güncel sürümünü de --version seçeneğini kullanarak görebilirsiniz: 1 php artisan --version Artisan’ın Geliştirilmesi Giriş Artisan’da mevcut olan komutlara ilaveten, uygulamanız ile çalışacak olan kendi özel komutlarınızı inşa edebilirsiniz. Bu özel komutlarınızı app/commands dizininde depolayabilirsiniz. Komutlarınızı kendi istediğiniz başka bir dizinde de depolayabilirsiniz. Bunun için, bu komutlarınızın composer.json ayarlarınız bazında “autoload” edilebiliyor olması gerekmektedir. Komut Oluşturulması Sınıfının Oluşturulmması Yeni bir komut oluşturmak için, command:make Artisan komutunu kullanabilirsiniz. Bu komut, başlamanızda size yardımcı olmak için yeni bir komut taslağı oluşturacaktır. Yeni Bir Komut Sınıfının Oluşturulması 1 php artisan command:make FalancaKomut Ön tanımlı olarak, oluşturulan komutlar app/commands dizininde depolanırlar. Fakat, siz başka bir dizin veya bir ‘namespace’ de belirleyebilirsiniz. 1 2 php artisan command:make FalancaKomut --path=app/classe\ s --namespace=Siniflar 347 Artisan’ın Geliştirilmesi Bir komut oluşturulurken terminal komut adı atamak için --command seçeneği kullanılabilir: 1 2 php artisan command:make AssignUsers --command=users:as\ sign Komutun Yazılışı Komut oluşturulduktan sonra, komutu list ekranında görüntülerken kullanılacak olan, sınıf ismi name ve tanımı description özellikleri doldurulmalıdır. Komut çalıştırıldığında fire (ateşle) metodu çağırılmaktadır. Bu metoda, istenecek herhangi bir komut mantığı yerleştirebilinir. Argümanlar & Seçenekler Komutunuzun alacağı argüman veya seçenekleri tanımlayabileceğiniz yerler getArguments ve getOptions metodlarıdır. Bu metodların her ikisi de birer komut dizisi verirler. Bu komut dizileri, bir ‘dizi seçenekleri listesi’ ile tarif edilirler. Argümanları (arguments) belirlerlerken, dizi tanımı değerleri şunları belirler: (ismi, modu, tanımı, ön değeri) 1 array($name, $mode, $description, $defaultValue) Modu argümanı mode şunlardan herhangi biri olabilir: InputArgument::REQUIRED (mecburi) veya InputArgument::OPTIONAL (isteğe bağlı). Seçenekleri (options) belirlerken, dizi tanımı değerleri şunları belirler: (ismi, kısayolu, modu, tanımı, ön değeri) Artisan’ın Geliştirilmesi 1 2 348 array($name, $shortcut, $mode, $description, $defaultVa\ lue) Seçenekler için, modu argümanı mode şunlardan biri olabilir: InputOption::VALUE_REQUIRED (Girdi Seçeneği: mecburi), InputOption::VALUE_OPTIONAL (isteğe bağlı), InputOption::VALUE_IS_ARRAY (dizi), InputOption::VALUE_NONE (yok). VALUE_IS_ARRAY (Girdi Seçeneği: dizi) modu, komut çağırılırken, anahtarın birden çok kez kullanılabilir oldugunu belirtir: 1 php artisan falan --option=filan --option=fesmekan VALUE_NONE (Girdi Seçeneği: yok) modu, seçeneğin sadece bir “anah- tar” olarak kullanıldığını belirtir. 1 php artisan falan --option Girdilerin Çağırılması Komutunuz çalışırken, uygulamanızın kabul edeceği argüman ve seçenek değerlerine ulaşabilmeniz gerekecektir. Bunu yapabilmek için argüman argument ve seçenek option metodlarını kullanabilirsiniz: Bir Komut Argüman Değerinin Çağırılması 1 $value = $this->argument('ismi'); Tüm Argümanların Birden Çağırılması 349 Artisan’ın Geliştirilmesi 1 $arguments = $this->argument(); Bir Komut Seçeneği Değerinin Çağırılması 1 $value = $this->option('ismi'); Tüm Seçeneklerin Birden Çağırılması 1 $options = $this->option(); Çıktı Yazılışı Çıktının konsola gönderilmesi için, info (bilgi), comment (not), question (soru) ve error (hata) metodlarını kullanabilirsiniz. Bu metodların her biri, kendi amaçlarına uygun olan ANSI renklerini kullanacaktır. Konsola Bilgi Gönderilmesi 1 $this->info('Bunu ekranda göster'); Konsola Bir Hata Mesajı Gönderilmesi 1 $this->error('Bir hata oluştu!'); Soruların Soruluşu Kullanıcıdan bir girdi talep etmek için, ask (sor) ve confirm (onayla) metodlarını kullanabilirsiniz. Kullanıcıya Girdi Bilgisinin Soruluşu Artisan’ın Geliştirilmesi 1 350 $name = $this->ask('İsminiz nedir?'); Kullanıcıya Gizli Şifre Bilgisinin Soruluşu 1 $password = $this->secret('Lütfen şifrenizi giriniz!'); Kullanıcıya Onayının Soruluşu 1 2 3 4 5 if ($this->confirm('Devam etmek istiyor musunuz? [evet|\ hayır]')) { // } İsterseniz confirm (onayla) metoduna, true (evet) ve false (hayır) seçeneklerinden birini varsayılan ön değer olarak belirleyebilirsiniz : 1 $this->confirm($soru, true); Komutların Kayıt Ettirilmesi Bir Artisan Komutunun Kayıt Ettirilişi Komutunuzun inşa edilmesi tamamlandığında, kullanılmaya hazır olabilmesi için, Artisan’da kayıt ettirmeniz gerekir. Bu, genelde app/start/artisan.php dosyası içerisinde yapılır. Bu dosya içerisinde, kayıt ettirmek için Artisan::add metodunu kullanabilirsiniz. 1 Artisan::add(new FalancaKomut); Artisan’ın Geliştirilmesi 351 IoC Container’da Olan Bir Komutun Kayıt Ettirilişi Eğer komutunuz IoC container²⁰³ uygulamasında kayıtlı ise, Artisan’da da kullanılabilir olması için Artisan::resolve metodunu kullanabilirsiniz. 1 Artisan::resolve('binding.ismi'); Komutların Bir Hizmet Sağlayıcısında Kayda Geçirilmesi Eğer komutları bir hizmet sağlayıcısı içerisinden kayda geçirmeniz gerekirse, sağlayıcının boot metodundan commands metodunu çağırmalı ve çağırırken ilgili komutun IoC konteyneri²⁰⁴ bağlamasını geçmelisiniz: 1 2 3 4 public function boot() { $this->commands('command.binding'); } Diğer Komutların Çağırılması Bazı durumlarda, komutunuzun içerisinden başka bir komutu çağırmak isteyebilirsiniz. Bunu, call metodunu kullanarak yapabilirsiniz: 1 2 $this->call('command.ismi', array('argument' => 'falan'\ , '--option' => 'filan')); ²⁰³/docs/ioc ²⁰⁴/docs/ioc
© Copyright 2024 Paperzz