Laravel: Code Bright (TR) Türkçe Çevirisi

Ebat: px
Şu sayfadan göstermeyi başlat:

Download "Laravel: Code Bright (TR) Türkçe Çevirisi"

Transkript

1

2 Laravel: Code Bright (TR) Türkçe Çevirisi Yeni Başlayanlar İçin Laravel Framework Versiyon İle Web Uygulama Geliştirme Dayle Rees ve Sinan Eldem Bu kitap şu adreste satılmaktadır Bu versiyon şu tarihte yayımlandı 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. 013 Dayle Rees

3 Kitabı tweetleyin! Dayle Rees ve Sinan Eldem a kitabını şu adresten Twitter tanıtarak yardımcı olun! Kitap için önerilen tweet: Laravel: Code Bright kitabının Türkçe Çevirisi #codebright-tr Kitap için önerilen hashtag #codebright-tr. Kitap için diğerleri ne demiş merak ediyorsanız bağlantıya tıklayarak hashtagları arayabilirsiniz: =#codebright-tr

4 İçindekiler Teşekkürler Yazım Hataları i iii Geribildirim iv Çeviriler v Giriş vi Ön Bilgiler Aduzayları (Namespaces) JSON Composer Mimari Container (Konteyner) Facades Esneklik (Flexibility) Sağlamlık (Robustness) Başlarken Gereksinimler Yükleme Web Server Yapılandırması Proje Yapısı Basit Rotalama Basit Rotalama Rota Parametreleri Cevaplar (Responses) Görünümler Görünüm Verisi Redirekt Özel Cevaplar

5 İÇINDEKILER Cevap Kısayolları Filtreler Basit Filtreler Çoklu Filtreler Filtre Parametreleri Filtre Sınıfları Evrensel Filtreler Default Filtreler Desen Filtreleri Denetçiler (Controllers) Denetçilerin Oluşturulması Controller Rotaları RESTful Denetçiler Blade Şablonların Oluşturulması PHP Çıktısı Kontrol Yapıları Şablonlar Şablon Kalıtımı Yorumlar Gelişmiş Rotalama İsimli Rotalar Güvenli Rotalar Parametre Sınırlamaları Rota Grupları Rotalara Ön Ek Koyma Domain Rotalama URL Üretimi Şimdiki URL Framework URL leri Üretimi Varlık URL leri Üretim Kısayolları İstek Verisi Verileri Alma Önceki Input Gönderilmiş (Uploaded) Dosyalar Çerezler Formlar

6 İÇINDEKILER Formların Açılması Form Alanları Form Düğmeleri Form Makroları Form Güvenliği Geçerlilik Denetimi (Validation) Basit Geçerlilik Denetimi Geçerlilik Kuralları Hata Mesajları Özel Geçerlilik Kuralları Özel Geçerlilik Mesajları Veritabanları Soyutlama Yapılandırma Hazırlama Şema Oluşturucusu Tabloların Oluşturulması Sütun Türleri Özellikli Sütun Türleri Sütun Niteleyicileri Tabloların Güncellenmesi Tabloların Düşürülmesi Şema Püf Noktaları Migrasyonlar Temel Kavram Migrasyonların Oluşturulması Migrasyonların Çalıştırılması Geri Alma (Rolling Back) Migrasyon Püf Noktaları Eloquent ORM Yeni Modellerin Oluşturulması Mevcut Modellerin Okunması Mevcut Modellerin Güncellenmesi Mevcut Modellerin Silinmesi Eloquent Sorguları Hazırlık Eloquent ten String e Sorgu Yapısı

7 İÇINDEKILER Fetch Metodları Sorgu Sınırlamaları Sihirli Where Sorguları Sorgu Scope ları Eloquent Koleksiyonları Collection Sınıfı Collection Metodları En İyi Uygulamalar Eloquent İlişkileri (Relationships) İlişkilere Giriş İlişkilerin Uygulanması İlişkilendirme ve Sorgulama Bir Uygulama İnşa Edelim 1: Playstation Oyun Koleksiyonu Konu üzerinde düşünmeye başlayalım Şimdi hacking zamanı! Veritabanı Controller Rotalar Görünümler Uygulama Mantığı Rahatlayın Ev Ödevi Kimlik Doğrulama (Authentication) O nerede olacak? Prosedürel Kod Nesne Yönelimli Kod Pek Yakında

8 Teşekkürler Her şeyden önce kız arkadaşım Emma ya teşekkür etmek istiyorum, sadece benim tüm asosyal girişimlerime tahammül ettiği için değil, aynı zamanda her iki kitabım için müthiş kırmızı panda resimleri çektiği için! Seni seviyorum Emma! Taylor Otwell, geçen yıl inanılmaz oldu, bana ekibin bir parçası olma fırsatı verdiğin için ve dostluğun için teşekkür ederim. Kullanması gerçekten zevk veren bir framework yaptığın için, kodlarımızı şiir okunur gibi yaptığın için ve onun geliştirilmesine bu kadar zaman ve tutku koyduğun için teşekkür ederim. Laravel in bu yeni versiyonunda seninle çalışmaktan gerçekten zevk aldım ve gelecekteki projelerde tekrar seninle çalışmayı umuyorum! Eric Barnes, Phill Sparks, Shawn McCool, Jason Lewis, Ian Landsman, çatıyla ilgili tüm destekleriniz ve iyi dostlar olduğunuz için teşekkürler. Anne ve babama teşekkür ediyorum, yirmi sekiz yıldır benim asosyal çabalarımı destekliyorlar! Ve yine aile üyeleri için benim ilk kitabımdan bir milyar kopya kadar aldıkları için teşekkürler! İlk kitabım Code Happy almış olan herkese ve Laravel topluluğunun hepsine teşekkür ederim. Sizin desteğiniz olmadan ikinci kitabım asla gerçekleşemezdi. Çevirenin Notu Bu kitap, ilk çeviri tecrübem olarak bana son derece keyif verdi. Çeviriyi yaparken bir yandan da öğrendim, bu da işi daha zevkli hale getirdi. Dayle Rees in samimi anlatımı ve hemen her konuyu örneklendirmesi öğrenme sürecinde her bilgi seviyesindeki kullanıcıya son derece yardımcı olacak bir kaynağa dönüştürdü bu kitabı. Öncelikle sevgili eşim Bilge ve gözümün ışığı kızım Tuana Şeyma ya teşekkürler. İyi ki varsınız! Laravel Türkiye Forumları¹ nda oluşturduğumuz dokümantasyon çeviri ekibine, kısa zamanda belgelerin tamamlanmasını sağladığınız ve Laravel in kapılarını Türkçe dilini kullanan tüm kullanıcılara açtığınız için teşekkürler. Gerek dokümantasyon, gerekse bu kitabı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. Sen olmadan olmazdı! Çeviri sürecinde ince eleyip sık dokudum ancak yine de hatalar yapmış olabilirim, bu sebeple karşılaşmanız muhtemel hataları bana aşağıdaki kanallardan bildirirseniz sevinirim. E-posta: ¹

9 Teşekkürler ii Web: Twitter: twitter.com/sineld³ Diğer Laravel Türkçe Kitapları: leanpub.com/u/sineld⁴ ² ³ ⁴

10 Yazım Hataları Bu benim ikinci kitabım ve öncekinden bu yana yazılarımı iyileştirdim, ama sizi temin ederim, çok, pek çok hata olacak. Bulduğun hataları kesim başlığıyla birlikte bir e-posta olarak adresine göndermek suretiyle destek verebilirsiniz. Hatalar keşfedildikçe düzeltilecektir. Düzeltmeler kitabın sonraki baskılarında yer alacaktır.

11 Geribildirim Aynı şekilde, kitap içeriği konusunda veya başka nedenle adresine e-posta göndererek e bir tweet göndererek bir geribildirimde bulunabilirsiniz. Ben, aldığım tüm postaları cevaplamaya çalışacağım. ⁶mailto:me@daylerees.com

12 Çeviriler Code Bright ı kendi dilinize çevirmek isterseniz, lütfen planlarınızla birlikte adresine bir gönderin. Tercüme kopyadan gelecek kazancı 50/50 bölüşmeyi teklif ediyorum ve fiyatı İngilizce kopyasıyla aynı olacaktır. Lütfen kitabın markdown formatıyla yazılacağını unutmayın.

13 Giriş Evet, bir kitap bölümü yazmayalı çok zaman oldu. Code Happy 1 ay kadar önce yayınlandı ve üç bin satış rakamını aştı. Yazı nasıl yazılır hatırlayabilecek miyim bakalım. O kitabı okuduysanız benim öncelikle bir geliştirici, ikinci olarak bir yazar olduğumu zaten biliyorsunuzdur. Bu nedenle, bu kitapta uzun kelimeler göremeyeceksiniz. Shakespeare i hiçbir şey etkilemeyecektir nasıl olsa (yazım hataları dışında). Laravel çatısını öğrenmek için, basit, düz konuşmalar alacaksınız. Ayrıca tutku alacaksınız! Terli yatak çarşafları türünde bir tutku değil, rakipsiz Laravel framework coşkusu. Ben kitaplarımı karşınızda durmuş, sizinle karşılıklı konuşur gibi yazmayı seviyorum. Aslında, eğer gerçekten benimle konuşmak istiyorsanız, o zaman Laravel IRC kanalına gelin ve beni görün! Şimdi, Yazar hakkında bilgi paragrafına geldik. Burayı kimse okumak istemez, fakat bir miktar egonun kimseye zararı olmaz, öyle değil mi? Benim adım Dayle Rees (kapakta öyle diyor!) ve ben bir web geliştiricisi ve bir tasarım tutkunuyum. Galler kıyısında küçük bir kasaba olan Aberystwyth liyim. Son kitabım Code Happy yi yazdığım sırada Aberystwyth de Galler Milli Kütüphanesinde çalışıyordum, burası Birleşik Krallıktaki üç telif kütüphanesinden biridir. Galler başkenti Cardiff e taşındığımdan bu yana BoxUK ile çalışıyorum. BoxUK bir internet danışmanlık ve geliştirme örgütüdür, orada web geliştirme dünyasına meraklı bir geliştiriciler ekibi ile birlikteyim. Web geliştirme benim sadece işim değil, aynı zamanda hobim. Yararlı ve ilginç kod parçaları ya da güzel tasarımlar bulmak hoşuma gidiyor. Yeteneklerimizin harika şeyler üreteceğine inanıyorum ve hayata geçmiş fikirler görmeyi seviyorum. Bir yıldan biraz daha önce Laravel topluluğuna kod demetleri, web tasarımları ve yapabildiğim başka yollarla yardımcı olmaya başladım. O zamandan bu yana ilişkim arttı. Laravel artık benim esas açık kaynak projem ve ben şimdi çatının çekirdek geliştirme ekibinin bir üyesiyim. Laravel (kod adı Illuminate) ile birlikte benim katılımım çok yükseklere çıktı. Bu sürümü, şimdiye dek kullanılabilecek en iyi çatı yapmak için Taylor Otwell ile birlikte çalışıyorum. Laravel ile ilgili bir şey söylemeyin! Onu kullanmaya başlayın ve kod yazarken gülümsemelerinizi durduramadığınızda bize teşekkür edersiniz. Laravel bir geliştirme aracının ne kadar üretken olabileceğini gösteren bir örnektir. Laravel in güzelim sözdizimi Taylor Otwell in rakipsiz dehasından geliyor. O bize şiir gibi okunacak kodlar yazma imkanı vermektedir ve kodlama görevlerimizden zevk almamızı sağlayacaktır. Peki Dayle, çatının son sürümüyle ne değişti?

14 Giriş vii Basit ama kafa karıştırıcı cevap, her şey ve hiçbir şey! Laravel, bir milyar (tam rakam değil, saymadım) yeni özellikler ile birlikte esneklik ve test edilebilirliği artırmak üzere sıfırdan tekrar yazılmıştır. Laravel 3 te kodunuzu yapılandırmak için size bir miktar özgürlük verilmişti, Laravel hackerların vahşi doğaya çıkmalarına ve çatıyı kendi gereksinimlerine uygun şekilde değiştirmelerine olanak sağlayacaktır. Bir şeyin iyileştirildiğini duyduğumda her zaman bir bityeniği ararım fakat Laravel öyle değil. O hala sevdiğiniz güzel ve ifade edici sözdizimine sahip; belki de onu daha çok sevdiğinizi göreceksiniz! Dostum, niye yeni bir kitap yazdın? Code Happy 3.0 ile 3..x arasında dar bir sürümü kapsıyordu ve bir şeyleri doğru yapmış olmalıyım ki üç binden fazla kopya satıldı. Emin olun, Laravel ile çalışması için çok büyük ihtimalle bütün bir kitabı yeniden işleyecektim. Bununla birlikte, çatının bu versiyonu yeni bir frameworktür. Eğer kitabı güncellemiş olsaydım, hala büyük bir çatı olduğuna inandığım sürüm 3 hakkındaki tüm bilgileri kaybedecektiniz. Birçok insanın Laravel 3 e dayalı projeleri olacaktır ve bu kişiler ihtiyaç duyduklarında Code Happy deki bilgilere erişebilmelidir diye düşünüyorum. Ayrıca kendi tecrübelerim var. Code Happy yi bitirdikten sonra bir kitap yazma konusunda çok şeyler öğrendim. Şimdi kaçınabileceğim, sık yaptığım yanlışları öğrendim. Zaten yaptığım bir şeyi iyiye götürebilirim ve umarım öyle olur. Code Happy yi okumamıştım! Önce onu mu okumalıyım? İstiyorsanız okuyun, oraya bazı komik şakalar koymuştum. Ancak bu kitap da yeni başlayanlar içindir ve bu nedenle çok temel bilgilerden başlayacağız. Şayet zaten Laravel kullanıyorsanız devam edin ve ne değiştiğini görmek için ilginç parçalara geçin. Çatı için yeniyseniz, bana sadık kalmanızı ve sayfa sayfa okumanızı önereceğim. Merak etmeyin! İlginç tutmaya çalışacağım. Yakında, Laravel ile harika, etkileyici PHP uygulamaları oluşturmuş olacaksınız. Kitap ne zaman tamamlanacak? Önceki kitabımda olduğu gibi, bu kitap da ilerledikçe yayınlanacak. Yani siz her bölümü ben yazdıkça alacaksınız. Kitabın şimdiki durumu tam olmayabilir ancak ek bölümleri ekledikçe bir e-posta alacak, güncellemeleri ücretsiz indirebileceksiniz. Böyle yazma yönteminin büyük bir esneklik sağladığını düşünüyorum. Yanlışlarım varsa kolayca değiştirebileceğimi bilerek, yazdıklarım hakkında rahat olabiliyorum. Belli bir tarihe kadar yetiştirme telaşı olmadığında, yazacağım kitabın daha büyük kalitede olacağını hissediyorum. Gelecekteki sürümler için ya da ek bilgileri vurgulamak için bu kitabı güncelleyebilirim. Siz içeriğe daha hızlı erişebileceksiniz. Ayrıca, çatının yeni sürümünün piyasaya çıkmasıyla birlikte kitap yayınlayabilmemi de sağlamaktadır.

15 Giriş viii Sorulardan yoruldum.. İyi! Öyleyse, öğrenme sürecine başlamaya çok hevesli olmalısınız. Hemen atlayın ve Laravel in keyfini çıkarmaya başlayın. Benimle sohbet etmek isterseniz bir tweet veya IRC den mesaj göndermekten çekinmeyin!

16 Ön Bilgiler Hey! Code Happy de bu bölüm yoktu! Gerçek bir Code Happy hayranı olarak geçmişte böyle bir şey koyamadım! Aferin sadık okuyucu! Gördüğünüz gibi Laravel çok sayıda yeni teknoloji kullanıyor. Bu teknolojiler kendi konularında ve frameworke paralel olarak kolayca öğretilebilir. Bu düşünceyle, öğrenme deneyiminizi beslemek için bu yeni teknolojiler üzerine bir bölümle başlamanın iyi olabileceğini düşündüm. Deneyimli web geliştiricileri bu teknolojilerle zaten karşılaşmışlardır veya onları zaten kullanmaktadırlar. Eğer istiyorsanız bu ön bilgi bölümünü atlamanızı hoş karşılarım. Bu beni üzmez. Yoo, gerçekten devam edin. Artık bana ihtiyacınız yok. Şayet hala okuyorsanız sizi arkadaşım olarak kabul ediyorum. Doğrudan rotalama bölümüne atlayan hainlerden değilsiniz! Haydi ilk ön bilgimize geçelim ve PHP aduzaylarını (namespaces) konuşalım. Aduzayları (Namespaces) PHP 5.3 sürümünde dile namespace denen yeni bir özellik eklendi. Birçok modern dil bu özelliği bir süredir zaten kullanıyordu ancak PHP sahneye biraz geç çıktı. Az ya da çok, her yeni özelliğin bir maksadı vardır. Bakalım PHP namespace bizim uygulamalarımıza ne gibi faydalar sağlıyor. PHP de aynı adı paylaşan iki sınıfınız olamaz. Onlar benzersiz olmalıdır. Bu kısıtlamayla ilgili sorun, User adında bir sınıfı olan bir üçüncü parti kitaplık kullanıyorken, kendinize ait User adlı bir sınıf oluşturamayacak olmanızdır. Oldukça uygun bir sınıf adını veremiyor olmak gerçekten utanılacak bir durum, değil mi? PHP namespace leri bu sorunu aşmamızı mümkün kılar, gerçekten de istediğimiz kadar çok sayıda User adlı sınıfımız olabilir. Tek yararı bu değil, namespace leri benzer kodlarımızı düzgün küçük paketlere koymak, hatta sahipliği göstermek için de kullanabiliriz. Şimdi normal bir sınıfa bakalım. Evet Onları daha önce kullandığınızı biliyorum. Güvenin bana, tamam mı? Global Namespace İşte gerçekten basit bir sınıf.

17 Ön Bilgiler 3 // app/models/eddard.php 5 class Eddard 6 { 7 8 } Ona özel bir şey yok, kullanmak istediğimizde şöyle yapabiliriz. 3 // app/routes.php 5 $eddard = new Eddard(); Dayle, ben PHP biliyorum Tamam, tamam, pardon. Temel olarak, biz bu sınıfın global aduzayında olduğunu düşünebiliriz. Bu terimin onun için doğru olup olmadığını bilmiyorum ancak bana oldukça uygun geliyor. Bu aslında, bir namespace olmadan var olan bir sınıf anlamına gelir. Sadece normal bir sınıftır. Basit Namespace Şimdi orijinal, global Eddard yanında başka bir sınıf oluşturalım. 3 namespace Stark; 5 // app/models/another.php 6 7 class Eddard 8 { 9 10 } Burada küçük bir değişiklik, namespace direktifinin eklenmesiyle, başka bir Eddard sınıfımız var. Buradaki namespace Stark; satırı PHP ye yapacağımız her şeyin Stark aduzayına göreli olduğunu bildirir. Ayrıca, bu dosya içinde oluşturulan tüm sınıfların Stark aduzayı içerisinde yaşayacağı anlamına gelir. Şimdi, Eddard sınıfını bir kez daha kullanmayı denediğimizde.

18 Ön Bilgiler 3 3 // app/routes.php 5 $eddard = new Eddard(); Yine son kesimde oluşturduğumuz ilk sınıfın bir olgusunu elde ederiz, Stark namespace i içindekini değil. Hadi Stark aduzayı içindeki Eddard sınıfının bir olgusunu oluşturmaya çalışalım. 3 // app/routes.php 5 $eddard = new Stark\Eddard(); Bir namespace içindeki bir sınıfı, önüne namespace in adını getirerek ve ikisini bir ters bölü (\) ile ayırarak başlatabiliyoruz. Artık Stark aduzayı içindeki Eddard sınıfından bir olgumuz var. Büyü gibi değil mi? Namespace lerin gerektiği kadar çok hiyerarşi düzeyinde olabileceğini bilin. Örneğin: 1 Bu\Aduzay\Ve\Class\Kombinasyonu\Aptalca\Gibidir\Ama\Uygundur Rölativite Teorisi PHP nin her zaman için mevcut aduzayına göreli reaksiyon vereceğini söylediğimi hatırlayın. Bunun nasıl olduğunu görelim: 3 namespace Stark; 5 // app/routes.php 6 7 $eddard = new Eddard(); Başlatma örneğine namespace direktifi eklemekle, PHP skriptinin çalışmasını Stark aduzayına taşımış oluyoruz. Biz şimdi içine Eddard koyduğumuzla aynı namespace içinde olduğumuz için, bu sefer bu aduzayındaki Eddard sınıfını alacağız. Göreliliğin nasıl olduğunu gördünüz mü? Şimdi namespace değiştirince, küçük bir problem oluşturduk. Ne olduğunu tahmin edebilecek misiniz? Orijinal Eddard sınıfını nasıl başlatacağız şimdi? O bir namespace de değil ki. Neyse ki, PHP de global aduzayında bulunan sınıfları ifade etmek için bir püf noktası vardır, biz basitçe başına bir ters bölü (\) koyarız.

19 Ön Bilgiler 3 // app/routes.php 5 $eddard = new \Eddard(); Başında ters bölü (\) olunca, PHP global aduzayındaki Eddard ı söylediğimizi bilir ve onu başlatır. Biraz hayal gücünüzü kullanın ve Barney nin sizi nasıl gösterdiğini düşünün. Diyelim ki, Tully\Edmure adındaki başka bir aduzayı sınıfımız var. Stark çerçevesi içerisinde bu sınıfı kullanmak istiyoruz. Nasıl yapacağız? 3 namespace Stark; 5 // app/routes.php 6 7 $edmure = new \Tully\Edmure(); Tully namespace inden bir sınıfın başlatılabilmesi için, aynı şekilde başına ters bölü koyarak öncelikle global aduzayına geri getirmemiz gerekiyor. Diğer aduzaylarındaki sınıflara atıfta bulunurken her seferinde tam hiyerarşilerini kullanmak yorucu olabilir. Neyse ki kullanabileceğimiz güzel bir kısayol var: use. Bunu iş yaparken görelim. 3 namespace Stark; 5 use Tully\Edmure; 6 7 // app/routes.php 8 9 $edmure = new Edmure(); use cümleciğini kullanarak, başka bir aduzayındaki bir sınıfı mevcut aduzayına getirebiliyoruz. Bize onu sadece adıyla başlatma imkanı veriyor. Şimdi bana niçin ters bölü ön eki gerekmediğini sormayın, zira bilmiyorum. Bildiğim tek istisna bu değil. Bunun için üzgünüm. İsterseniz başına bölü getirebilirseniz de, buna gerek olmadığını bilin. O korkunç tutarsızlığı telafi etmek için, başka bir düzgün bir numara göstereyim. İthal ettiğimiz sınıflara, PHP de kullandığımıza benzer şekilde takma isimler verebiliyoruz. Göstereyim:

20 Ön Bilgiler 5 3 namespace Stark; 5 use Tully\Brynden as Blackfish; 6 7 // app/routes.php 8 9 $edmure = new Blackfish(); as anahtarını kullanmak suretiyle, Tully/Brynden sınıfımıza Blackfish takma adını verdik, bu bize onu mevcut namespace içerisinde tanımlamak için yeni takma adını kullanma imkanı sağlayacak. Düzgün bir numara değil mi? Aynı namespace içinde aynı isimli iki sınıf kullanmamız gerektiğinde bu gerçekten kullanışlıdır, örneğin: 3 namespace Targaryen; 5 use Dothraki\Daenerys as Khaleesi; 6 7 // app/routes.php 8 9 class Daenerys 10 { 11 1 } 13 1 // Targaryen\Daenerys 15 $daenerys = new Daenerys(); // Dothraki\Daenerys 18 $khaleesi = new Khaleesi(); Dothraki aduzayı içindeki Daenerys sınıfına Khaleesi takma adını vermekle, iki Daenerys sınıfını sadece isimleriyle kullanabiliyoruz. İşe yarıyor değil mi? İşin özü çatışmaları önlemek ve bir şeyleri amacına göre gruplamaktır. Ne kadar gerekiyorsa o kadar sınıfı use edebilirsiniz.

21 Ön Bilgiler 6 3 namespace Targaryen; 5 use Dothraki\Daenerys; 6 use Stark\Eddard; 7 use Lannister\Tyrion; 8 use Snow\Jon as Bastard; Yapı Aduzayları sadece çatışmaları önlemekle ilgili değildir, onları organizasyonlar için ve sahipliği belirtmek için de kullanabiliriz. Başka bir örnekle de bunu açıklayayım. Diyelim ki bir açık kaynak kitaplığı oluşturmak istiyorum. Başkalarının benim kodumu kullanmasını severim, bu harika bir şey! Sorun şu ki, benim kodumu kullanan kişinin herhangi bir sınıf adı çatışması problemine yol açmayı istemem. Bu son derece rahatsız edici olurdu. Burada, belirli bir açık kaynak için güçlüklere yol açmayı nasıl önleyeceğimizi gösteriyorum. 1 Dayle\Blog\Content\Post Dayle\Blog\Content\Page 3 Dayle\Blog\Tag Orijinal kodu benim oluşturduğumu göstermek ve benim kodumu benim kitaplığımı kullanan kişininkinden ayırmak için burada kendi adımı kullandım. Benim uygulamamı kendi iç yapısına göre organize etmek için de temel namespace içerisinde, birtakım alt aduzayları oluşturdum. Composer bölümünde, sınıf tanımlarını yükleme eylemini kolaylaştırmak için aduzaylarını nasıl kullanacağımızı öğreneceğiz. Bu yararlı mekanizmaya mutlaka göz atmanızı öneriyorum. Sınırlamalar Doğrusunu isterseniz, bu alt başlığa Sınırlamalar dediğim için bir miktar suçluluk hissediyorum. Hakkında konuşacağım şey aslında bir kusur değildir. Bildiğiniz gibi, diğer dillerde de aduzayları benzer bir yolla uygulanır ve bunlardan bir kısmı aduzaylarıyla etkileşimde ek özellikler sağlar. Mesela Java da, import cümleciğini bir jokerle birlikte kullanarak çok sayıda sınıfı mevcut namespace içine ithal edebiliyorsunuz. Java daki import bizim use ile eşdeğerdir ve iç içe aduzaylarını (veya paketleri) ayırmak için nokta kullanır. İşte bir örnek.

22 Ön Bilgiler 7 1 import dayle.blog.*; Bu satır dayle.blog paketi içinde bulunan sınıfların hepsini ithal edecektir. PHP de bunu yapamazsınız. Her sınıfı tek tek ithal etmek zorundasınız. Üzgünüm. Aslında, özrü niçin ben diliyorum ki? Git ve PHP iç ekibine şikayet edin. Sadece nazik olun. Onlar bize son zamanlarda bir sürü güzel şeyler verdiler. Bununla birlikte, ben size kullanabileceğiniz uygun bir numara vereyim. Önceki örnektekiyle aynı şu namespace ve sınıf yapımız olduğunu düşünün. 1 Dayle\Blog\Content\Post Dayle\Blog\Content\Page 3 Dayle\Blog\Tag Çocuk sınıflarını kullanmak için bir alt aduzayına bir takma ad verebiliriz. Örnek şöyle: 3 namespace Baratheon; 5 use Dayle\Blog as Cms; 6 7 // app/routes.php 8 9 $post = new Cms\Content\Post; 10 $page = new Cms\Content\Page; 11 $tag = new Cms\Tag; Eğer aynı namespace içindeki birçok sınıfı kullanmanız gerekirse, bu çok yararlıdır. Zevkini çıkarın! Sonraki konuda Jason öğreneceğiz. Hayır, Avustralyalı Jason Lewis değil, JSON stringleri. Sadece sayfayı çevirin ve ne demek istediğimi görün! JSON JSON Nedir? JSON JavaScript Nesne Gösterimi (Object Notation) anlamına gelir. Bu formatın avantajını ilk alan dil JavaScript olduğu için böyle adlandırılmıştır. Esasında, JSON dizileri ve nesneleri stringler halindeki değerleriyle birlikte insanların okuyabileceği şekilde depolama yöntemidir. Öncelikle veri transferi için kullanılmaktadır ve XML gibi diğer seçeneklerin bir kısmına göre gereksiz ayrıntılar çok daha azdır.

23 Ön Bilgiler 8 Çoğunlukla, uygulamanızın ön tarafında yeni bir sayfa yüklemesi olmadan arka taraftan bazı veriler gerektirdiğinde kullanılmaktadır. Bu normalde, JavaScriptle bir AJAX isteği kullanılarak elde edilir. Birçok yazılım API si içeriklerini bu dosya formatını kullanarak sunmaktadır. Bu tür API lerin güzel bir örneği Twitter dir. PHP 5..0 sürümünden itibaren nesneleri ve dizileri JSON a serileştirebilmeye başladı. Bu benim kişisel olarak bir milyar, belki daha fazla istismar ettiğim bir şeydir ve PHP diline büyük bir katkı olmuştur. Bir süredir PHP ile çalışıyorsanız, bir PHP nesnesini bir string olarak temsil etmek için onun serialize() metodunu zaten kullanmışsınızdır. Daha sonra bu stringi orijinal değeri içeren yeni bir olguya dönüştürmek için de unserialize() kullanabiliyorsunuz. JSON kullanarak ne olacağı kabaca budur. Ancak, avantajı JSON un birtakım farklı diller tarafından ayrıştırılabilmesi, oysa serialize() edilmiş stringlerin sadece PHP tarafından parse edilebilmesidir. Ek avantajı bizim (insanlar ve pandalar olarak) JSON stringlerini okuyabilmemiz, serileştirilmiş PHP stringlerinin ise çöp yığını gibi gözükmesidir. Bu kadar hikaye yeter, haydi içeri dalalım ve JSON a biraz göz atalım. JSON Sözdizimi 1 {"ismi":"lushui","cinsi":"panda","diyeti":"yeşil Şeyler","yas":7,"renkleri":["kır\ mızı","kahverengi","beyaz"]} Yaşasın JSON! Tamam, insanların onu okuyabildiğini söyledim ama bir şeyi söylemeyi unutmuş olabilirim. JSON ön tanımlı olarak, değerleri arasında hiçbir beyaz boşluk olmadan depolanır ve bu da okunmasını biraz zorlaştırır. Bu normalde veri transfer ederken bant genişliğinden tasarruf sağlar. Fazladan beyaz boşluklar olmadığında, JSON stringi çok daha kısa olacak ve böylece nakledilecek byte daha az olacaktır. İyi bir haber JSON un anahtarları ve değerleri arasındaki boşluk veya satır sonlarını umursamamasıdır. Haydi rastgele! Daha okunabilir yapmak için istediğiniz kadar beyaz boşluk koyun. Şüphesiz, biz bunu elimizle yapabiliriz (ancak yapmayalım), fakat web te JSON u güzelleştirmek için bol miktarda araç var. Ben sizin için birini seçmek istemiyorum. Kendiniz arayın, bulun! Web sunucularından gelen JSON cevabını daha kolay okumanıza imkan veren web tarayıcı uzantıları bile bulabilirsiniz. Bunlardan birini bulmanızı kuvvetle tavsiye ederim! Haydi okumasını daha kolay yapmak için, JSON a beyaz boşluklar ekleyelim. (Dürüst olmak gerekirse, bunu elle yaptım. Hey millet, bunu evde sakın denemeyin.)

24 Ön Bilgiler 9 1 { "ismi": "Lushui", 3 "cinsi": "Panda", "diyeti": "Yeşil Şeyler", 5 "yas": 7, 6 "renkleri": ["kırmızı", "kahverengi", "beyaz"] 7 } Aha! Başladık. Şimdi, kitaplarımın kapaklarında yaşayan kırmızı pandayı temsil eden bir JSON stringimiz oldu. Lushui sizin Laravel bilginizi meraklı gözlerden güvenle korur. Örnekten görebileceğiniz gibi, birkaç anahtar-değer çiftimiz var. Anahtar-değer çiftlerimizden birinin içinde bir dizi var. Açıkçası, daha önce JavaScript kullanmışsanız burada neyin değiştiğini merak edebilirsiniz. Gerçekten de, bu JavaScriptte nasıl temsil edilecekti bir görelim. 1 var lushui = { ismi: 'Lushui', 3 cinsi: 'Panda', diyeti: 'Yeşil Şeyler', 5 yas: 7, 6 renkleri: ['kırmızı', 'kahverengi', 'beyaz'] 7 }; Ümit ediyorum ki, JavaScript ile JSON kod parçacıkları arasındaki bazı benzerlikleri fark edeceksiniz. JavaScript kod parçası bir nesneyi bir değişkene atamaktadır, şöyle: 1 var lushui = {.. }; Tabii, JSON bir veri transfer biçimidir ve bir dil değildir. Değişken kavramına sahip değildir. İşte bu yüzden JSON kod parçasında atama yapmamıza gerek yoktur. Bir nesne değişmezini temsil etme yöntemi çok benzerdir. Bu bir rastlantı değil! Önce de söylediğim gibi, JSON orijinal olarak JavaScript ile kullanım için ortaya çıkarılmıştır. JSON ve JavaScript her ikisinde de, nesneler { iki küme parantezi } içinde barındırılır ve anahtardeğer veri çiftlerinden oluşur. JavaScript biçiminde anahtarlar değişkenleri temsil ettikleri için tırnak gerektirmezler ancak az önce JSON unda değişkenler olmadığını duydunuz. Bu gayet iyi, çünkü stringleri anahtar olarak kullanabiliyoruz ve JSON tam olarak bu problemle ilgileniyor. JavaScript değerleri etrafında tek tırnak kullandığım da dikkatinizi çekmiş olabilir. Bu bir tuzak! Bu davranış JavaScript te kusursuz olarak kabul edilir, JSON stringleri çift tırnaklar içinde olmak zorundadır. Bunu hiç unutmayın genç adam! JavaScript ve JSON, her ikisinde de anahtar-değer çiftleri iki nokta üst üste (:) ile ayrılmalıdır ve anahtar-değer takımları birbirinden virgülle (,) ayrılmış olmalıdır.

25 Ön Bilgiler 10 JSON stringleri ve sayısal tipleri destekleyecektir. Lushui nin yaş değerini yedi tam sayısı olarak ayarladığımızı görmüştünüz. 1 yas: 7, JSON aşağıdaki değer tiplerine izin verecektir. Double Float String Boolean Array Object Null Numerik değerler tırnak olmadan gösterilir. Bir değerin tırnaklı olup olmamasını seçerken dikkatli olun. Örnek olarak Türkiye posta kodları beş rakamdan oluşur. Bununla birlikte, eğer posta kodu için tırnak koymayı ihmal ederseniz, bu durumda bir tamsayı olarak davranacak ve 7700 ye budanmış olacaktır. Bu, bir web yolculuğuna çıkmış olanların başına çok gelmiş bir yanlıştır. Boolean lar true ve false kelimeleri ile temsil edilir ve her ikisi de PHP nin kendisindeki gibi tırnaksızdır. Daha önce söylediğim gibi, stringler tek tırnak içinde değil çift tırnak içine alınır. Null değer ise aynı PHP dekine benzer davranır ve tırnak olmaksızın null kelimesi ile temsil edilir. Bunu hatırlamak kolay olmalı! Nesneleri gördük. Ana JSON nesnesinin kendine çok benzer olarak, bunlar küme parantezi içine alınırlar ve tüm değer tiplerini içerebilirler. Diziler ise JavaScript dizilerine çok benzer. 1 // JavaScript ['kırmızı', 'kahverengi', 'beyaz'] 3 5 ["kırmızı", "kahverengi", "beyaz"] *Not Yukardaki örnekte JSON kod parçasında satır içi yorum eklemediğimi fark edeceksiniz. Bunun nedeni JSON un veri transferi için kullanılmasından dolayı yorumları desteklememesidir. Bunu aklınızda tutun! Görebileceğiniz gibi, her iki tipteki dizi [ köşeli parantez ] içine alınır ve anahtarlı olmayan, virgül (,) ile ayrılmış bir değerler listesi içerir. Tekrar hatırlatmakta fayda var, tek fark JSON içinde stringler için çift tırnak kullanımının şart olmasıdır. Söylediklerimden hala sıkılmadınız mı? Yukarıda bahsettiğim gibi, JSON içinde taşınabilen değerler hem nesne, hem de dizi içerebilirler. Okuyucularım arasındaki zeki adamlar (yani hepiniz) JSON un iç içe nesneler ve dizileri desteklediğini anlamıştır. İş üstünde bir görelim!

26 Ön Bilgiler 11 1 { "bir_nesne": { 3 "bir_nesneler_dizisi": [ { "Bizim": "sırrımız" }, 5 { "o": "ki" }, 6 { "ben": "hala" }, 7 { "ayakkabıları": "seviyorum!" } 8 ] 9 } 10 } Pekiyi. Derin bir nefes alın. Burada, bir nesneler dizisi içeren bir nesne içeren bir JSON nesnesi var. Bu gayet güzel bir şeydir ve JSON un karmaşık veri koleksiyonlarını ifade etmesine imkan vermektedir. JSON ve PHP Daha önce belirtildiği gibi PHP 5..0 sürümünden beri JSON formatına serileştirme ve JSON formatından veri çözme için destek vermiştir. Haydi gidip bu işe bir göz atalım. PHP dizisini JSON a serileştirme Bir PHP değerini serileştirmek için ihtiyacımız olan tek şey json_encode() metodunu kullanmak. Şöyle mesela: 3 $gercek = array('panda' => 'Müthiş!'); echo json_encode($gercek); Bu kod parçasının sonucu aşağıdaki değeri içeren bir JSON stringi olacaktır. 1 {"panda":"müthiş!"} Mükemmel! Daha fazlası da olabilir mi? Bu veriyi gerisin geriye, PHP nin anlayabileceği bir formata çevirebileceğimizden emin olalım. Bir JSON stringinden bir PHP dizisine seri çözme Bunun için de json_decode() metodunu kullanacağız. Ne geleceğini görmediğinizden eminim.

27 Ön Bilgiler 1 3 $gercek = json_decode('{"panda":"müthiş!"}'); echo $gercek['panda']; Müthiş! Gidiyoruz bekliyoruz, ne? 1 Fatal error: Cannot use object of type stdclass as array in... Gördünüz mü? json_decode() metodu bizim JSON u bir PHP dizisi olarak döndürmedi; verimizi temsil etmek için bir stdclass nesnesi kullanıyor. O zaman biz de nesne anahtarımıza bir nesne niteliği şeklinde erişeceğiz. 3 $gercek = json_decode('{"panda":"müthiş!"}'); echo $gercek->panda; 5 6 // Müthiş! Harika! İstediğimiz işte bu. Tabi bir dizi isteseydik PHP bu diziyi ona çevirecek çeşitli yollar sağlıyor, ama neyseki json_decode() kolunun altında başka bir hile taşıyor! Eğer biz bu fonksiyona ikinci bir parametre olarak true girersek, bizim PHP dizimizi tam beklediğimiz şekilde alabileceğiz. Teşekkürler json_decode()! 3 $gercek = json_decode('{"panda":"müthiş! }', true); echo $gercek['panda']; 5 6 // Müthiş! Yaşasın! Bir Laravel kitabı içinde sadece JSON üzerine neden dev bir bölüm yazdığımı merak ediyor olabilirsiniz. Üstelik, büyük ihtimalle bu soruya neden bölümün en sonunda cevap vermeyi tercih ettiğimi de sorguluyorsunuzdur! Sadece bu daha eğlenceli olduğu için. Sonraki kesimde PHP için yeni bir paket yöneticisi Composer a bakacağız. Composer ı incelemeye başladığımızda JSON bilgisinin ne kadar önemli olduğunu anlayacaksın.

28 Ön Bilgiler 13 Composer Composer PHP dünyasında özel bir şey. O bizim uygulama bağımlılıklarını yoluna koyma şeklimizi değiştirdi ve birçok PHP geliştiricisinin göz yaşlarını dindirdi. Bilirsiniz, eski günlerde, üçüncü parti bağımlılıklarına dayanan bir uygulama inşa etmek istediğimizde, onları PEAR veya PECL ile yüklemek zorundaydık. Bu iki bağımlılık yöneticisinde de günü geçmiş, çok sınırlı sayıda bağımlılık vardı ve uzun bir süredir PHP geliştiricileri açısından bir bela olmuşlardı. Bir paket, sonunda kullanılabilir olduğunda belirli bir versiyonunu indirebilir ve sisteminize yükleyebilirdiniz. Ancak, bağımlılık sizin uygulamanızın kendine değil, PHP ye bağlanırdı. Yani, aynı bağımlılıkların farklı versiyonlarını gerektiren iki uygulamanız olduğunda evet, kötü bir zaman yaşardınız. Composer geldi, paket yöneticilerinin kıralı. Öncelikle paketler hakkında konuşalım, onlar nedir? Her şeyden önce, şimdilik uygulamalar ve projeler kavramlarını unutalım. İnşa etmekte olduğunuz araç bir paket olarak adlandırılır. Uygulamanızın çalışması için gereken her şeyi taşıyan küçük bir kutu hayal edin ve onu tarif edin. Onu bir paket olarak kayda geçirmek için bu kutunun içinde sadece bir parça kağıt (dosya) bulunmasını gerektirir. Yapılandırma Önceki bölümde JSON öğrenmiştiniz, değil mi? Yani artık bunun için hazırsınız! Size JSON un web uygulamaları arasında veri transferi için kullanıldığını söylediğimi hatırlıyor musunuz? Tamam, yalan söyledim. Kötü birisi olduğumdan değil, sadece, konuyu onun yapabildiklerinin küçük bir kısmıyla öğretmek daha kolay olduğu için. Ben bunu çok yaparım, çok yalanlar bekleyin benden! Hatırlıyor musunuz, JSON karmaşık bir veri parçasını nasıl gösteriyordu? Peki, o zaman niçin biz onu yapılandırma sağlayacak düz dosyalar içinde kullanmayalım ki? İşte Composer adamlarının düşündüğü de tam olarak bu. Onlarla mı tartışacağız? JSON dosyaları.json uzantısı kullanır. Composer, paket yapılandırmasının paketinizin kök dizininde bulunan adı composer.json olan bir dosya olmasını bekler. Bunu unutmayın! Laravel bu dosyayı çok sık kullanacaktır. Haydi dosyayı açalım ve paketimiz hakkında bazı bilgiler girmeye başlayalım.

29 Ön Bilgiler 1 1 { "name": "marvel/xmen", 3 "description": "Mutants saving the world for people who hate them.", "keywords": ["mutant", "superhero", "bald", "guy"], 5 "homepage": " 6 "time": " ", 7 "license": "MIT", 8 "authors": [ 9 { 10 "name": "Stan Lee", 11 " ": "stan@marvel.com", 1 "homepage": " 13 "role": "Genius" 1 } 15 ] 16 } Tamam, X-Men paketinin kök dizininde bir composer.json dosyamız oldu. Neden X-Men? Onlar harika, o yüzden. Gerçeği söylemek gerekirse, bu dosyadaki opsiyonların (anahtarların) hepsi opsiyoneldir. Normalde yukarıdaki bilgileri paketi dağıtmayı veya vahşi doğaya salmayı düşünürseniz verirsiniz. Size karşı dürüst olacağım, ben normalde girerim ve bu bilgileri bir şekilde doldururum. Bu herhangi bir zarar vermez. Yukarıdaki yapılandırma, paketi tanımlamak için kullanılır. Bazı özel durumlar için ayrılmış olduğunu düşündüğüm birkaç anahtarı dahil etmedim. Ek yaplandırma maddelerini merak ediyorsanız, zengin bilgi ve belgeler içeren Composer websitesine⁸ bakmanızı öneririm. Ayrıca Composer a yeni gelenler için paket oluşturacakları zaman yararlı olabilecek bu yararlı cheat sayfasını⁹ da buldum. Yapılandırma maddelerini daha fazla keşfetmek için fareyi her satırın üstüne getirin. Her neyse, en iyisi biz X-Men paketi için oluşturduğunuz yapılandırmaya daha yakından bakalım.. 1 "name": "marvel/xmen", Bu paketin adıdır. Şayet Github¹⁰ kullanıyorsanız, isim formatı size tanıdık gelecektir, ama ben yine de açıklayacağım. Paket adı normal bölü (/) ile ayrılmış iki kelimeden ibarettir. Bölü işaretinden önceki kısım paketin sahibini temsil eder. Çoğu durumda geliştiriciler sahip olarak kendi Github kullanıcı adlarını ⁸ ⁹ ¹⁰

30 Ön Bilgiler 15 kullanırlar ve ben de bu görüşe tamamen katılıyorum. Ama siz istediğiniz ismi kullanabilirsiniz. Size ait tüm paketlerde bu tutarlı olsun. name stringinin ikinci kısmı paketin adıdır. Bunu basit ve açıklayıcı tutun. Aynı şekilde, birçok geliştirici paket için, Github ta barındırıldığındaki ambar ismini kullanmayı tercih eder ve ben yine aynı şekilde bu sisteme tam olarak katılıyorum. 1 "description": "Mutants saving the world for people who hate them.", Paketin işlevselliğinin kısa bir açıklamasıdır. Bunu da basit tutmayı unutmayın. Eğer paket açık kaynak için düşünülmüşse, ayrıntıları sizin ambardaki README dosyasında verebilirsiniz. Eğer bazı kişisel belgeleri tutmak istiyorsanız burası onun konacağı yer değildir. Sırtınıza dövme yaptırın ve bir ayna bulundurun. Bana en mantıklı geleni bu. Yapışkan notlar da aynı işi görecektir. 1 "keywords": ["mutant", "superhero", "bald", "guy"], Bu kelimeler paketinizi göstermekte kullanılan bir string dizisidir. Bunlar bloglardaki etiketlere benzer ve esasında aynı amaca hizmet eder. Paketiniz bir ambarda listelendiği zaman bu etiketler yararlı arama meta verileri olacaktır. 1 "homepage": " homepage yapılandırması açık kaynak olacak paketler için yararlıdır. Projeniz için homepage kullanabilirsiniz veya Github ambarının URL si olabilir. Daha bilgilendirici olacağını düşündüğünüz herhangi biri. Tekrar söylüyorum, bu yapılandırma seçeneklerinin tümü opsiyoneldir. Paketiniz için mantıklı değilse, atlamaktan çekinmeyin. 1 "time": " ", Bu çok sık görmediğim seçeneklerden biridir. Yukarıda sözünü ettiğim cheat sayfasına göre, uygulamanızın veya kitaplığın salınım tarihini temsil eder. Çoğu paket Github da veya diğer sürüm kontrol sitelerinde barındırıldığı için, çoğu durumda bunun gerekli olmadığını düşünüyorum. Bu siteler normalde her gönderi, her etiket ve diğer yararlı olaylarda tarih atmaktadırlar. time yapılandırması için kabul edilen biçimler YYYY-MM-DD ve YYYY-MM-DD HH:MM:SS dir. Hoşunuza gittiyse, gidin verin bu değerleri! 1 "license": "MIT",

31 Ön Bilgiler 16 Eğer paketiniz yeniden dağıtılabilir olacaksa, bu durumda ona bir lisans vermek isteyeceksiniz. Bir lisans olmadığında, birçok kullanıcı yasal sınırlamalar yüzünden paketinizi hiç kullanamayacaklardır. İhtiyaçlarınıza uygun ancak kodunuzu kullanmayı umanlar için çok kısıtlayıcı olmayan bir lisans seçiniz. Laravel projesi, büyük bir özgürlük sunan MIT lisansı kullanmaktadır. Çoğu lisans lisansın bir kopyasının kaynak ambarında tutulmasını gerektirir, fakat siz composer.json dosyasında bu yapılandırma girişini de verirseniz, bu durumda paket ambarı paketi kendi lisansı ile listeleyebilecektir. Yapılandırmanın authors bölümü paketi oluşturanlar hakkında bilgi verir ve iletişim kurmak isteyen paket kullanıcıları için yararlı olabilir. authors bölümünün, işbirliğiyle yapılan paketler için bir yazarlar dizisine izin verdiğine dikkat edin. Verilen seçenektekine bakalım tekrar. 1 "authors": [ { 3 "name": "Stan Lee", " ": "stan@marvel.com", 5 "homepage": " 6 "role": "Genius" 7 } 8 ] Her bir yazarı göstermek için bir nesne kullanın. Bizim örneğimizde sadece bir yazar var. Stan Lee ye bakalım. O sadece her Marvel filminde görünen biri değil, benim kitabımda da aynı şeyi yapıyor. Ne arsız eski sosis! 1 "name": "Stan Lee", Bu satırı nasıl basitleştireceğimi gerçekten bilemiyorum. Onu anlamakta sorun yaşıyorsanız, bu kitabı kapatmayı düşünebilirsiniz ve çorap kuklacılığı sanatına devam edebilirsiniz. 1 " ": "stan@marvel.com", Paket patlarsa sizinle irtibat kurulabilmesi için geçerli bir eposta adresi verdiğinizden emin olun. 1 "homepage": " Bu sefer kişisel web sayfası verilebilir, devam edin ve biraz hit alın!

32 Ön Bilgiler 17 1 "role": "Genius" role seçeneği yazarın proje içindeki rolünü tanımlar. Örneğin, geliştirici, tasarımcı, hatta çorap kuklası sanatçısı. Eğer doğru bir şey düşünemiyorsanız, o zaman komik bir şey koyun. Paketinizi tanımlamak için gereken şeylerin hepsi bu kadar. Şimdi daha ilginç bir şeye bakalım: Bağımlılık yönetimi! Bağımlılık Yönetimi X-Men i taşıyacak bir kutunuz oldu. Ancak bu kutuda henüz mutantlar yok. Büyük bir süper kahramanlar ekibi (uygulama) oluşturmak için diğer mutantların desteğinin alınması gerekiyor (3üncü parti bağımlılıkları). Composer in bunu gerçekleştirmemize nasıl yardımcı olacağını görelim. 1 { "name": "marvel/xmen", 3 "description": "Mutants saving the world for people who hate them." "keywords": ["mutant", "superhero", "bald", "guy"], 5 "homepage": " 6 "time": " ", 7 "license": "MIT", 8 "authors": [ 9 { 10 "name": "Stan Lee", 11 " ": "stan@marvel.com", 1 "homepage": " 13 "role": "Genius" 1 } 15 ], 16 "require": { } 19 } Şimdi bizim composer.json içinde require adında yeni bir kesimimiz oldu. Bu bizim bağıml mutantlarımızı listelemekte kullanılacak. Şimdi örnekleri kısaltmak için yapılanmanın geri kalanını bir tarafa bırakıp sadece require bloğunu göstereceğim. Orada olduğundan emin olalım! X-Men in bağımlı olduğu şeyleri biliyoruz: Wolverine Cyclops

33 Ön Bilgiler 18 Storm Gambit Başkaları da var ama bu adamlar oldukça uygun. Şimdilik onlara dayanacağız. Tabii şöyle yapabilirdik. Bunların kaynak dosyalarını doğrudan bizim uygulamamızın içine kopyalar, daha sonra her değişiklikte onları kendimiz güncellerdik. Bu gerçekten çok bunaltıcı olurdu. Biz onları require kesimine ekleyelim, ondan sonra Composer bunları bizim için yönetecektir. 1 "require": { "xmen/wolverine": "1.0.0", 3 "xmen/cyclops": "1.0.1", "xmen/storm": "1..0", 5 "xmen/gambit": "1.0.0" 6 } Biz burada, mutant bağımlılıklarımızı ve kullanmak istediğimiz sürümlerini listeliyoruz. Bu örnekte, onların hepsi aynı sahibe, X-Men paketine aittirler ancak başka bir kişiye ait de olabilirlerdi. Yeniden dağıtılabilir paketlerin çoğu bir sürüm kontrol web sitesinde, mesela Github¹¹ veya Bitbucket¹² sitesinde barındırılmaktadır. Versiyon kontrol ambarlarında, uygulamamızın stabil sürümlerini tanımlayabildiğimiz bir etiketleme sistemi vardır. Örneğin git te şu komutu kullanabiliriz: 1 git tag -a m 'İlk sürüm.' Bu komutla uygulamamızın sürümünü oluşturmuş oluyoruz. Bu, insanların bağımlı olabileceği stabil bir sürümdür. Şimdi Gambit bağımlılığına biraz yakından bakalım. 1 "xmen/gambit": "1.0.0" Artık Composer paket isimlerinin bir bölü (/) karakteri ile ayrılmış bir sahip ve bir paket takma adından oluştuğunu biliyorsunuz. Bu bilgiyle biliyoruz ki, bu gambit paketi xmen kullanıcısı tarafından yazılmıştır. require kesimi içindeki her maddenin key kısmı paketin adıdır ve değer kısmı gereken sürümü temsil eder. Gambit örneğimizde, sürüm numarası Github ta kodun o sürümünün olduğu etiketle karşılaştırılır. Bağımlılık sürümlerimizin nasıl tüm sisteme değil de uygulamamıza özgü olabildiğini gördünüz mü? ¹¹ ¹²

34 Ön Bilgiler 19 Projenize istediğiniz kadar çok bağımlılık ekleyebilirsiniz. Gidin, bir milyar ekleyin! Yanlışım varsa kanıtlayın. Dinleyin, size bir sır vereyim mi? Kimseye anlatmacağınıza söz veriyor musunuz? Vayy, hııı. Yaklaşın, kulağınıza fısıldayacağım. Duymak istediğiniz kelimeler Bağımlılıklarınızın da kendi bağımlılıkları olabilir. Bu doğru! Bağımlılıklarınız da Composer paketleridir. Onların da kendi composer.json dosyaları vardır. Bu demektir ki, onların da kendi bağımlılıklarını listeleyen kendi require bölümleri vardır ve hatta bu bağımlılıkların da bağımlılıkları olabilecektir. Daha iyisi ise, Composer in bu içi içe bağımlılıkları sizin için yönetecek ve yükleyecek olması. Ne kadar harika! Wolverine tools/claws, tools/yellow-mask ve power/regeneration gerektirebilir ama bu konuda endişelenmenize gerek yok. Siz kendi require kısmınıza xmen/wolverine paketini koyduğunuz sürece Composer gerisini halledecektir. Bağımlılık sürümlerine gelince, bunlar çeşitli biçimlerde olabilmektedir. Örneğin bir bileşen için minör güncellemeleri dikkate almayabilirsiniz. Bu durumda sürüm içinde joker kullanabilirsiniz, şöyle: 1 "xmen/gambit": "1.0.*" Bu durumda Composer 1.0 ile başlayan son sürümü yükleyecek. Örneğin Gambit ve sürümleri varsa, yüklenecektir. Paketinizde paket sürümleri için bir en alt veya en üst sınır olabilir. Bu tanımlama büyüktür ve küçüktür işaretleri kullanılarak yapılabilmektedir. 1 "xmen/gambit": ">1.0.0" Yukarıdaki örnek, den daha büyük bir sürüm numarasına sahip tüm xmen/gambit paket sürümleri ile karşılanabilecektir. 1 "xmen/gambit": "<1.0.0" Benzer şekilde, küçüktür işareti versiyon dan küçük paketlerle karşılanabilecektir. Paketinizin maksimum bir sürüm bağımlılığı belirlemesine imkan verecektir. 1 "xmen/gambit": "=>1.0.0" "xmen/gambit": "=<1.0.0" Karşılatırma operatörüne eşittir = işareti de eklemek, sürüm sınırlamasını karşılayan sürüm listesine karşılaştırılacak sürümün de eklenmesine yol açacaktır. Kimi zaman, birden çok sürüm girmek veya bir paket versiyon aralığı vermek isteyebilirsiniz. Birden çok sürüm sınırlaması, her sınırlamayı bir virgülle (,) ayırarak eklenebilmektedir. Örnek olarak:

35 Ön Bilgiler 0 1 "xmen/gambit": ">1.0.0,<1.0." Yukarıdaki örnek sürümü ile karşılanabilecektir. Eğer stabil bağımlılıkları yüklemek istemiyorsanız, mesela bungee jumping veya yamaç paraşütünden hoşlanan bir tip olabilirsiniz, dolayısıyla oranızı buranızı kanatacak sürümler kullanmak isteyebilirsiniz. Composer aşağıdaki sözdizimi kullanılarak bir ambarın dallarını (branches) nişanlayabilmektedir. 1 "xmen/gambit": "dev-dalismi" Örneğin, Github daki Gambit projesinin develop dalındaki güncel kodu kullanmak istiyorsanız, bu durumda dev-develop sürüm sınırlaması kullanacaksınız. 1 "xmen/gambit": "dev-develop" Paketiniz için doğru bir en düşük stabilite ayarınız olmadığı sürece bu geliştirme sürümü çalışmayacaktır. Ön tanımlı olarak, Composer stable minimum uyumluluk flag ını kullanır ki, bağımlılık sürümlerini stabil, etiketlenmiş sürümlere sınırlayacaktır. Bu seçeneği geçersiz kılmak isterseniz, tek yapacağınız composer.json dosyanızdaki minumum-stability yapılandırma seçeneğini değiştirin. 1 "require": { "xmen/gambit": "dev-master" 3 }, "minimum-stability": "dev" Minimum stabilite ayarı için kullanılabilecek başka değerler de var ancak bunların açıklanması sürüm stabilite etiketlerinin derinliklerine dalmak demek. Ben bunlara girip de bu bölümü daha da karıştırmak istemiyorum. Bu bölüme ileride geri dönüp konuyu anlatacağım ama konuyla ilgili ek bilgiler bulmak için şimdilik Paket sürümleri için Composer belgelerine¹³ bakmanızı önereceğim. Bazen, uygulamanızın sadece geliştirilmesiyle ilgili bağımlılıkları kullanma gereği duyabilirsiniz. Bu bağımlılıkların bir üretim ortamında uygulamanızın her günkü kullanımı için gerekli olmayabilir. Composer require-dev kesimi sayesinde bu yükü de sırtınızdan alır. Bir an için uygulamamızın kabul testleri sağlamak için Codeception test framework¹⁴ gerektirdiğini düşünelim. Bu testler bizim üretim ortamımızda hiç kullanılmayacaklardır, bu nedenle bunları composer.json dosyamızın require-dev kesimine ekleyeceğiz. ¹³ ¹⁴

36 Ön Bilgiler 1 1 "require": { "xmen/gambit": "dev-master" 3 }, "require-dev": { 5 "codeception/codeception": " " 6 } Bu codeception/codeception paketi yalnızca biz Composer i --dev anahtarıyla kullanırsak yüklenecektir. Yükleme ve kullanım kesimlerinde bu konuda daha fazla bilgi olacaktır. Yukarıda görmüş olduğunuz gibi, require-dev kesimi require kesimiyle tam aynı formatı kullanmaktadır. Aslında, aynı formatı kullanan başka kesimler de vardır. Neler varmış bir bakalım mı? 1 "conflict": { "marvel/spiderman": "1.0.0" 3 } conflict kesimi bizim paketimizle bir arada mutlu çalışamayacak paketlerin bir listesini taşır. Composer bu paketlerin yan yana yüklenmesine izin vermeyecektir. 1 "replace": { "xmen/gambit": "1.0.0" 3 } replace kesimi size bu paketin başka bir paket yerine kulllanılabileceğini bildirir. Bu, başka bir paketten dallandırılmış (forked) ama aynı işlevselliğe sahip paketler için işe yarar. 1 "provide": { "xmen/gambit": "1.0.0" 3 } Bu kesim paketlerin sizin paketinizin kod tabanı içerisinde sağlandığını gösterir. Şayet Gambit paketlerinin kaynağı sizin ana paketiniz içinde yer almışsa, bu durumda onu yeniden yüklemek anlamsız olacaktı. Bu kesimi Composer in sizin ana paketiniz içine gömülmüş hangi paketler olduğunu bilmesi için kullanın. Unutmayın, burada paket bağımlılıklarınızı listelemeniz gerekmiyor. require de bulunan bir şey sayılmayacaktır. 1 "suggest": { "xmen/gambit": "1.0.0" 3 }

37 Ön Bilgiler Paketinizde onun işlevselliğini artıran, ama kesin gereklilikte olmayan ekstra paketler olabilir. Neden onları suggest kesimine eklemiyorsunuz? Composer install komutu çalıştırıldığında, Composer bu kesimdeki paketleri yüklenmesi önerilenler olarak anacaktır. Bağımlılıklar üzerine söyleyeceklerim bu kadar. Şimdi Composer in başka bir sihirli parçasına gideceğiz. Otomatik yüklemeler! Otomatik Yüklemeler Şu ana kadar Composer in paket bağımlılıklarımızı bizim için alıp getirebildiğini öğrendik, fakat bunları nasıl kullanacağımızı biliyor muyuz? Biz kendimiz PHP içinde bu kaynak dosyalarını require() edebilirdik ancak bunu yapabilmek için onların tam olarak nerede olduklarını da bilmemiz gerekiyor. Bunu yapacak zamanı olan yoktur. Composer bunu bizim için halledecektir. Composer a sınıflarımızın oldukları yerleri ve onları yüklemek için kullanılabilecek metodların ne olduğunu söylersek, uygulamamız tarafından kullanılabilecek sınıf tariflerini yüklemek için otomatik yüklemesini üretecektir. Eylemler kelimelerden daha iyi anlaşılır, öyleyse hemen bir örnek verelim. 1 "autoload": { 3 } Burası bizim otomatik yükleme yapılandırmamızın tümünü kapsayacak olan kesimdir. Basit, değil mi? Süper! Sizin için çorap kuklacılığı değil. En basit yükleme mekanizması olan files yöntemine bakalım. 1 "autoload": { "files": [ 3 "path/to/my/firstfile.php", "path/to/my/secondfile.php" 5 ] 6 } Bu files yükleme mekanizması, uygulamanız içinde Composer otomatik yükleyicisi bileşeni yüklendiği zaman yüklenecek dosyaları bir dizi olarak verir. Dosya yolları uygulamanızın kök dizinine göreli kabul edilir. Bu yükleme yöntemi etkilidir ancak çok uygun değil. Büyük bir proje için her dosyayı elle tek tek eklemek istemezsiniz. Daha büyük miktarlarda dosya yüklemenin biraz daha iyi yöntemlerine bakalım şimdi de.

38 Ön Bilgiler 3 1 "autoload": { "classmap": [ 3 "src/models", "src/controllers" 5 ] 6 } classmap bir dizi alan başka bir yükleme mekanizmasıdır. Bu seferki dizi değişik sayıdaki dizinlerden ibarettir ve yine aynı şekilde projenin köküne görelidirler. Composer, otomatik yükleyicisinin kodunu üretirken, PHP sınıflarını içeren dosyaları bulmak için bu dizinleri dolaşacaktır. Bu dosyalar bir dosya yolunun bir sınıf adına eşleştirildiği bir koleksiyona eklenecektir. Bir uygulama Composer otomatik yükleyicisi kullandığı ve mevcut olmayan bir sınıf başlatmak istediği zaman, Composer devreye girecek ve bu eşleştirmede saklanan bilgiyi kullanarak, gerekli sınıf tarifini yükleyecektir. Ancak, bu yükleme mekanizmasını kullanmanın bir dezavantajı var. Yeni bir dosya eklediğiniz her zaman, sınıf eşleştirmesini yeniden inşa etmek için composer dump-autoload komutunu kullanmanız gerekecektir. Neyse ki, hepsinin en iyisi olan son bir yükleme mekanizması bulunmaktadır ve bir eşleştirme istemeyecek kadar zekidir. Öncelikle PSR-0 sınıf yükleme konusunda bilgi verelim. PSR-0 sınıf yüklemesi ilk kez PSR-0 PHP standardında tanımlanmıştır ve PHP aduzaylı sınıfları, içinde bulundukları dosyalara eşleştirmede basit bir yol sağlamaktadır. Sınıfınızı içeren dosyaya bir namespace deklarasyonu eklemeyi biliyor olmalısınız, bunun gibi: 3 namespace Xmen; 5 class Wolverine 6 { 7 //... 8 } Ondan sonra, bu sınıf Xmen\Wolverine haline gelir ve PHP artık Wolverine sınıfına tamamen farklı bir hayvan muamelesi yapacaktır. PSR-0 otomatik yüklemesi kullanılınca, Xmen\Wolverine sınıfı Xmen/Wolverine.php dosyası içinde olmalıdır. Namespace in sınıfın içinde olduğu dizin ile eşleştiğini görebildin mi? Xmen aduzayının Wolverine sınıfı Xmen dizininde yer almaktadır. Ayrıca, dosya adının da sınıf adıyla (büyük harfler de dahil) eşleştiğini farketmişsinizdir. PSR-0 otoyüklemenin düzgün çalışması için sınıf adıyla dosya adının aynı olması şarttır. Aduzayları birkaç seviyeli olabilir, örneğin, aşağıdaki sınıfı ele alalım.

39 Ön Bilgiler 3 namespace Super\Happy\Fun; 5 class Time 6 { 7 //... 8 } Time sınıfı Super\Happy\Fun aduzayı içinde bulunmaktadır. Dolayıyla PHP onu Time olarak değil Super\Happy\Fun\Time olarak tanıyacaktır. Bu sınıf aşağıdaki dosya yolunda yer alıyor olacaktır. 1 Super/Happy/Fun/Time.php Aduzayı ile dizin yapısının nasıl uyduğunu bir daha gördünüz mü? Ayrıca, dosya adının da sınıfla tam olarak aynı olduğu dikkatinizi çekmiştir. PSR-0 otoyüklemesi bu kadar. Gerçekten oldukça basit! Şimdi sınıf yüklememizi basitleştirmek için bunu Composer ile nasıl kullanabileceğimizi görelim. 1 "autoload": { "psr-0": { 3 "Super\\Happy\\Fun\\Time": "src/" } 5 } Bu sefer, bizim psr-0 otoyükleme bloğumuz bir dizi olmak yerine bir nesnedir. Bunun sebebi hem bir anahtar, hem de bir değer gerekmesidir. Bu nesnedeki her anahtar bir aduzayını temsil eder. Çift ters bölüler konusunda endişe etmeyin. Tek ters bölü JSON da escape karakterini temsil ettiği için bu şekilde kullanıyoruz. JSON dosyalarında aduzaylarını eşleştirirken bu kuralı unutmayın! İkinci değer aduzayının eşleşeceği dizindir. Ben sondaki bölünün aslında gerekli olmadığını keşfettim, ama birçok örnek bir dizini belirtmek için bölüyü de eklemeyi seviyor. Bundan sonrası çok önemlidir ve birçok insanın yakalandığı ciddi bir tuzaktır. Lütfen dikkatli okuyun. Bu ikinci parametre, aduzayı sınıflarının yerleşik olduğu dizin değildir. Onun yerine, aduzayının dizin eşleştirmeye başladığı dizindir. Bunu daha iyi açıklamak için önceki örneği inceleyelim. Super happy fun time sınıfını hatırlayın. Bir daha bakalım.

40 Ön Bilgiler 5 3 namespace Super\Happy\Fun; 5 class Time 6 { 7 //... 8 } Tamam, biz şimdi biliyoruz ki, bu sınıf Super/Happy/Fun/Time.php dosyasında yerleştirilmiş olacaktır. Bunu aklımızda tutarak, aşağıdaki otomatik yükleme kod parçacığını ele alalım. 1 "autoload": { "psr-0": { 3 "Super\\Happy\\Fun\\Time": "src/" } 5 } Sen Composer in sınıfı src/time.php içinde arayacağını bekleyebilirsin. Bu yanlış olacaktır ve sınıf bulunamayacaktır. Bunun yerine, dizin yapısı şu biçimde mevcut olmalıdır. 1 src/super/happy/fun/time.php Bu, birçok insanın Composer i ilk kullandığında yakalandığı bir şeydir. Bu gerçeği akılda tutmanın ne kadar önemli olduğunu yeterince vurguladığımı sanıyorum. Eğer biz Commposer ın bir yüklemesini şu anda çalıştırmış olsak ve daha sonra aynı aduzayına yeni bir sınıf, Life.php eklersek, otomatik yükleyiciyi yeniden üretmek zorunda olmayacağız. Composer, aduzayının sınıflarının olduğu yeri ve onları nasıl yükleyeceğini tam olarak bilir. Harika! Aduzayı dosyalarımı niçin bir src klasörüne koyduğumu merak etmiş olabilirsiniz. Composer tabanlı kitaplık yazarken bu sık kullanılan bir gelenektir. Aslında, bir Composer paketi için sık kullanılan bir dizin/dosya yapısı şöyledir. 1 src/ (Sınıflar.) tests/ (Unit/Kabul testleri.) 3 docs/ (Belgeler.) composer.json Bu standarda bağlı kalmakta ya da sizi ne mutlu edecekse onu yapmakta özgürsünüz. Laravel kendi sınıfları için kendi konumlarını vermektedir ve ilerideki bir bölümde bunları açıklayacağım. Otomatik yükleme mekanizmalarımızı nasıl tanımlayacağımızı artık öğrendik, Composeri nasıl yükleyeceğimizi ve kullanacağımızı öğrenmenin vakti geldi, otomatik yükleyicinin avantajını kullanmaya başlayabiliriz.

41 Ön Bilgiler 6 Yükleme Yükleme ve kullanım konusunu neden bu bölümün en sonuna bıraktığımı merak ediyorsunuzdur? Yapılandırma konusunu iyi bilmenin, Composer in biz onu kullanırken sahne arkasında neler yapıyor olduğunu anlamamıza yardım edeceğini düşündüm. Bırakın bileyim! Aşağıdaki yükleme yöntemleri Linux veya Mac OSX gibi unix tabanlı geliştirme çevrelerine özgüdür. Umarım Taylor bu bölüme düzenleme yapabilir de bir Windows ortamında Composer yükleme konusunda bilgi verir, çünkü ben belirli işletim sistemlerinden vebadan kaçar gibi kaçıyorum. Composer PHP tabanlı bir uygulamadır, dolayısıyla onu kullanabilmeniz için PHP CLI istemcisinin yüklü olması gerekiyor. Aşağıdaki komutu çalıştırarak bunu iki kez kontrol edin. 1 php -v Şayet PHP düzgünce yüklenmiş ise, şuna benzer bir şeyler göreceksiniz. 1 $ php -v PHP 5.. (cli) (built: Jul 01 17:8:56) 3 Copyright (c) The PHP Group Zend Engine v..0, Copyright (c) Zend Technologies 5 with XCache v.0.0, Copyright (c) , by moo Eğer çıktı sizin PHP sürüm 5.3. den daha küçüğünü kullandığınızı söylüyorsa, PHP sürümünüzü güncellemediğiniz sürece Composer kullanamayacaksınız demektir. Aslında, eğer PHP ten daha düşük bir sürüm kullanıyorsanız, bu durumda Laravel kullanmanız hiç mümkün olmayacaktır. Composer i indirmek için CURL kullanabilirsiniz. Mac OSX ön tanımlı olarak böyle gelir. Birçok Linux dağıtımları kendi yazılım ambarları içinde CURL bulundurur, tabii bir standart olarak zaten yüklenmiş değilse. Composer ın uygulamasını indirmek için CURL kullanalım. 1 curl -ss php Deneyimli linux kullanıcıları CURL un yükleme skriptini PHP ye bağlamasından endişe duyabilirler. Bu haklı bir endişedir, fakat Composer yüklemesi binlerce geliştirici tarafından kullanılmıştır ve güvenli olduğu kanıtlanmıştır. Bu güzelim yazılım parçasını kullanmaktan uzak durmayalım! Yükleme sürecinin başarıyla tamamlandığını (o size söyleyecektir) kabul ederek, şimdi uygulama dizininizde bir composer.phar dosyanız olacak. Composer i çalıştırmak için kullanacağınız dosya işte budur, örneğin 1 php composer.phar

42 Ön Bilgiler 7 mevcut komutların bir listesini size gösterecektir. Artık bu şekilde Composer kullanmaya devam edebilirsiniz ancak ben onu global olarak yüklemenizi önereceğim. Böyle yaptığınızda Composer projelerinizin tümünde kullanabileceksiniz ve onu çalıştırmak için daha kısa bir komut yeterli olacaktır. Composer i global tarzda yüklemek için, onu kendi PATH ortam değişkeninin içindeki bir konuma taşıyınız. Bu yerleşimleri aşağıdaki komutu kullanarak görebilirsiniz. 1 echo $PATH Bununla birlikte çoğu sistemde kabul edilebilir bir konum /usr/local/bin dir. Bu dosyayı taşıdığımız zaman, aynı zamanda onu daha kolay çalıştırmak için adını da composer olarak değiştirmiş oluyoruz. Bunun için gerekli komut şudur: 1 sudo mv composer.phar /usr/local/bin/composer Composer i global tarzda yüklemekle, artık aynı komutlar listesini görmek için aşağıdaki kısa sözdizimini kullanabileceğiz. Bu komut aynı zamanda sisteminizdeki her yerden çalıştırılabilecektir. 1 composer Hey, bu çok daha temiz, değil mi? Ee, kullanalım o zaman. Kullanım Paket dizinimizde aşağıdaki composer.json dosyasını oluşturmuş olduğumuzu varsayalım. 1 { "name": "marvel/xmen", 3 "description": "Mutants saving the world for people who hate them." "keywords": ["mutant", "superhero", "bald", "guy"], 5 "homepage": " 6 "time": " ", 7 "license": "MIT", 8 "authors": [ 9 { 10 "name": "Stan Lee", 11 " ": "stan@marvel.com", 1 "homepage": " 13 "role": "Genius" 1 }

43 Ön Bilgiler 8 15 ], 16 "require": { 17 "xmen/wolverine": "1.0.0", 18 "xmen/cyclops": "1.0.1", 19 "xmen/storm": "1..0", 0 "xmen/gambit": "1.0.0" 1 }, "autoload": { 3 "classmap": [ "src/xmen" 5 ] 6 } 7 } İlerleyelim ve paket bağımlılıklarımızı yüklemek ve otomatik yükleyicimizi kurmak için install komutunu kullanalım. 1 composer install Composer den alacağımız çıktı şöyle bir şey olacaktır: 1 Loading composer repositories with package information Installing dependencies 3 - Installing tools/claws (1.1.0) 5 Cloning bc0e1f0cc8517a38c afd53e Installing tools/yellow-mask (1.1.0) 8 Cloning bc0e1f0cc8517a38c6c13135dbafd53e Installing power/regeneration (1.0.0) 11 Cloning bc0e1f0cc ea88bc5dbafd53e Installing xmen/wolverine (1.0.0) 1 Cloning bc0e1f0cc8517a38c6c8ea88bc Installing xmen/cyclops (1.0.1) 17 Cloning bc0e1f0cc ea88bc5dbafd Installing xmen/storm (1..0) 0 Cloning bc0e1f0cc8517a38c6c8ea88bc5dbafd5333 1

44 Ön Bilgiler 9 - Installing xmen/gambit (1.0.0) 3 Cloning bc0e1f0cc8517a38c6c8ea88bc5dbafd566 5 Writing lock file 6 Generating autoload files Bunların bir örnek olarak kullanılan uyduruk paketler olduğunu unutmayın. Bunları indirmek işe yaramaz! Bununla birlikte, X-men olmaları nedeniyle daha eğlenceli olabilir! Yaa! Peki listede sadece dört tane varken neden yedi paket yüklendi? İyi de, Composer ın bağımlılıkların bağımlılıklarını otomatik olarak yönettiğini unutuyorsunuz! Fazladan gördüğünüz üç paket xmen/wolverine paketinin bağımlılıklarıdır. Ben sizin şimdi büyük bir ihtimalle bu paketlerin nereye yüklendiğini merak ettiğinizi düşünüyorum. Composer paketinizin kaynak dosyalarını içermek üzere projenizin kök dizininde bir vendor dizini oluşturur. xmen/wolverine paketi vendor/xmen/wolverine de bulunabilir, orada onun kaynak dosyalarını ve kendi composer.json dosyasını bulacaksınız. Composer ayrıca otomatik yükleme sistemiyle ilgili kendi dosyalarından bir kısmını da vendor/composer dizininde depolar. Dert etmeyin. Bunu hiç bir zaman doğrudan düzenlemek zorunda olmayacaksınız. Peki biz bu harika otomatik yükleme yetilerinin avantajını nasıl elde edeceğiz? Bunun cevabı otoyüklemenin kendisini kurmaktan bile basit. Sadece uygulamanız içinde vendor/autoload.php doyasını require() veya include() ediniz. Örneğin: 3 require 'vendor/autoload.php'; 5 // Harika uygulama bootstrap'ı işte burada! Müthiş! Artık, bağımlılıklarınızdan birine ait bir sınıfı başlatabilirsiniz, örneğin. 3 $gambit = new \Xmen\Gambit; Composer bütün sihri yapacak ve sınıf tarifini sizin için otomatik yükleyecektir. Ne kadar harika değil mi? Artık kaynak dosyalarınızı binlerce include() cümlesiyle karıştırmayacaksınız. Eğer bir sınıf-eşleştirme dizinine bir dosya eklemişseniz, Composer in onu yükleyebilmesi için öncelikle bir komut çalıştırmanız gerekecektir.

45 Ön Bilgiler 30 1 composer dump-autoload Yukarıdaki komut tüm eşleştirmeleri yeniden inşa edecek ve sizin için yeni bir autoload.php oluşturacaktır. Projemize yeni bir bağımlılık eklemek istersek ne yapacağız? Şimdi composer.json dosyamıza xmen/beast i ekleyelim. 1 { "name": "marvel/xmen", 3 "description": "Mutants saving the world for people who hate them.", "keywords": ["mutant", "superhero", "bald", "guy"], 5 "homepage": " 6 "time": " ", 7 "license": "MIT", 8 "authors": [ 9 { 10 "name": "Stan Lee", 11 " ": "stan@marvel.com", 1 "homepage": " 13 "role": "Genius" 1 } 15 ], 16 "require": { 17 "xmen/wolverine": "1.0.0", 18 "xmen/cyclops": "1.0.1", 19 "xmen/storm": "1..0", 0 "xmen/gambit": "1.0.0", 1 "xmen/beast": "1.0.0" }, 3 "autoload": { "classmap": [ 5 "src/xmen" 6 ] 7 } 8 } Şimdi, Composer in yeni eklediğimiz paketi yükleyebilmesi için composer install i tekrar çalıştırmamız gerekiyor.

46 Ön Bilgiler 31 1 Loading composer repositories with package information Installing dependencies 3 - Installing xmen/beast (1.1.0) 5 Cloning bc0e1f0c33337a38c afd53e9 6 7 Writing lock file 8 Generating autoload files Artık xmen/beast yüklendi ve onu hemen kullanabiliriz. Olağanüstü! composer install komutunun çıktısındaki aşağıdaki satır dikkatinizi çekmiş olabilir. 1 Writing lock file Aynı zamanda, Composer ın uygulamanızın kök dizininde composer.lock adlı bir dosya oluşturduğunu da fark etmiş olabilirsiniz. Ağladığınızı mı duyuyorum? Bu composer.lock dosyası paketiniz hakkında composer install veya composer update komutunun en son gerçekleştirilme zamanı hakkında bilgiler içerir. Ayrıca, yüklenmiş olan her bağımlılığın tam sürümünden oluşan bir liste de içerir. Neden ki? Çok basit. Dizin içinde bir composer.lock dosyası bulunduğunda, composer install komutunu kullandığınız zaman, her bağımlığın taze sürümlerini çekmek yerine bu dosya içinde bulunan sürümleri kullanacaktır. Bunun anlamı şudur: Eğer sürümünüz uygulama kaynağınızla birlikte composer.lock dosyasını içeriyorsa (bunu kuvvetle öneririm), üretim ortamını dağıttığınız zaman, lokal geliştirme ortamında denediğiniz ve test ettiğinizle tam aynı sürümler kullanılacaktır. Yani, Composer in uygulamanızı kırabilecek herhangi bir bağımlılık sürümünü yüklemeyeceğinden emin olabileceksiniz. composer.lock dosyasının hiç bir zaman elle düzenlenmemesi gerektiğini unutmayın. Bağımlılık sürümleri konusundayken, bunların güncellenmesi hususu niye yoktu? Örneğin composer.json dosyamızda aşağıdaki gereksinim olsaydı. 1 "xmen/gambit": "1.0.*" Composer bizim için sürümünü yükleyebilecektir. Ancak, birkaç gün sonra bu paket sürümüne güncellenmişse ne olacak? Peki o zaman, tüm bağımlılıklarımızı son sürümlerine güncellemek için composer update komutunu kullanabiliriz. Çıktıya bir bakalım.

47 Ön Bilgiler 3 1 $ composer update Loading composer repositories with package information 3 Updating dependencies (including require-dev) 5 - Installing xmen/gambit (1.0.1) 6 Cloning bc0e1f0cc8517a38c6c8ea88bc5dbafd Generating autoload files Harika! xmen/gambit paketi en son sürümüne güncellendi ve bizim composer.lock dosyası güncellendi. Tümünü değil de sadece bir bağımlılığı güncellemek istersek, update komutunu kullanırken paket adını belirtebiliriz. Örneğin: 1 composer update xmen/gambit Durun, oradaki (eklenen require-dev) ne demek oluyor? Hatırlarsanız composer.json dosyasındaki require-dev kesiminde biz sadece geliştirmeye özgü bağımlılıkları listeliyorduk. Composer, update komutunun sadece güvenli bir geliştirme veya test ortamında çalıştırılmasını bekler. Bu sebeple, geliştirme bağımlılıklarınızı isteyeceğinizi varsayacak ve onları indirecektir. Eğer geliştirme bağımlılıklarınızı yüklemek istemiyorsanız, aşağıdaki anahtarı kullanabilirsiniz. 1 composer update --no-dev Ayrıca, install komutunu kullanırken bağımlılıkları yüklemek istiyorsanız, basitçe şu anahtarı kullanın. 1 composer install --dev Bilmeniz gereken son şey, Composer binarisinin kendini güncellemek için composer self-update komutunu kullanabilecek olmanızdır. Global olarak yüklemek istiyorsanız, sudo kullanmayı unutmayın. 1 sudo composer self-update Tamam, Laravel le çalışırken ihtiyacınız olacak tüm Composer bilgisi bu kadar. Alınması gereken çok fazla bilgi ve bu yorgun parmaklar için uzun bir bölüm oldu. Umarım ondan bir şeyler kazanmışsınızdır. Belirli bir konunun genişletilmesi gerektiğini düşünüyorsanız, bana bildirmeyi unutmayın!

48 Mimari Code Bright ı daha kapsamlı bir öğrenme deneyimi yapmak istiyorum ve bu sebeple bu bölümü de dahil etmeye karar verdim. Kodlamaya bir an önce başlamak istiyorsanız, bu bölümü atlayabilirsiniz. Yine de ben, Laravel in nasıl inşa edildiğini öğrenmek için aşağıdaki satırların gerçekten yararlı olacağını düşünüyorum. Laravel 3 te, IoC konteyneri çoğu insanın kafasını karıştıran bir bileşen idi. Laravel te ise çatının her şeyi bir arada tutan kısmıdır. Bunun önemini ifade edemem. Evet, aslında anlamını kavrayabilmek için bu bölüme gerek duydum. Bir giriş yapalım bakalım. Container (Konteyner) Laravel te, konteyner bootstrap sürecinde erkenden oluşturulur. $app adı verilen bir nesnedir. Peki bir konteyner den söz ettiğimizde aklınıza ne geliyor? Hadi sözlük tanımına bakalım. Niçin? Çünkü emin değilim Diğer yazarların da böyle yaptıklarını gördüm. Beni küçük görmelerini istemem. İşte burada. İsim - Container. Özellikle nakliye veya depolama işlerinde, muhafaza için kullanılan veya muhafaza kapasitesindeki bir nesne, örneğin kutu, karton kutu vb. Ben bu tarifin Laravel container bileşenine tam uyduğunu düşünüyorum. Kesinlikle bir şeyler depolamakta kullanılıyor. Dürüst olalım Bir şeyleri depolamasaydı, o zaman Konteyner berbat bir isim olurdu. Taşımacılık bakımından da, diğer bileşenlere erişmemiz gerektiğinde onları çatı çevresinde taşımayı kolaylaştırıyor. Esasen bir karton ya da kutu gibi değildir. Daha ziyade, anahtarlı bir depolama sistemidir. Bu $app nesnesi oluşturulduktan sonra, app() helper metodunu kullanarak ona her yerden erişebilirsiniz. Tüm samimiyetimle söylüyorum, büyük ihtimalle bunu yapmak zorunda olmayacaksınız. Bu, bu bölümde daha ilerde açıklayacağım bir özellik nedeniyledir. app nesnesinin tuttuklarını alalım ve ne olduklarına bir bakalım. Bunu app/routes.php dosyanızda yapabilirsiniz.

49 Mimari 3 3 // app/routes.php 5 var_dump($app); 6 7 die(); app/routes.php dosyası içerisinde app() helperini kullanmak zorunda olmadığımız dikkatinizi çekmiştir. O, global kapsamdadır, dolayısıyla doğrudan erişebiliriz. Vuuaahh, bu ne büyük bir nesne böyle! Hııı, sanırım bu framework ün özü olmalı. Onun Illuminate\Foundation\Application sınıfının bir olgusu olduğunu göreceksiniz. Laravel bileşenlerinin tamamı Illuminate aduzayı içerisinde yaşar. Bu, çatının erken tasarım evrelerinde kullanılan bir kod adı idi ve henüz çıkarmaya yüreğimiz el vermedi. Laravel i PHP dünyasını illuminating (aydınlatan) olarak düşünün! Application sınıfının kaynaklarına bakarsak, Container i genişlettiğini göreceğiz. Buyrun, o kaynak şurada: Container sınıfı bütün sihrin gerçekleştiği yerdir. Ayrıca, ArrayAccess arayüzüne de bir uygulama getirir. ArrayAccess interface, bir nesnenin niteliklerine JavaScript nesne değişmezlerine benzer şekilde erişilebilmesine imkan veren özel bir arayüzdür. Örnek olarak, aşağıda verilen yöntemlerin her ikisiyle de nesne niteliklerine erişmek mümkün olacaktır: 3 $nesne->nitelik = 'falan'; $nesne['nitelik'] = 'falan'; Frameworkün bootstrapı sırasında çok sayıda hizmet sağlayıcı sınıfı çalışır. Bu sınıflar, çatının belirli bileşenlerinin uygulama konteyneri içinde kayıt edilmesi amacını yerine getirirler. Pekiyi, bileşen deyince ne anlayacağım? Şöyle ki, bir framework birçok farklı parçadan yapılmıştır. Örnek olarak, bizim bir rotalama katmanımız, bir geçerlilik denetimi sistemimiz, bir kimlik doğrulama katmanımız ve spesifik bir işlevi yerine getiren daha birçok paketimiz vardır. Biz bu framework bileşenlerimizi çağırırız ve onlar tam frameworkü oluşturmak üzere konteyner içerisinde bir araya gelirler. Laravel i ilk defa kullanıyorsanız, bir sonraki örnek size pek bir his vermeyecek. Üzerinde durmayın! O sadece Laravel 3 kullanıcılarının düşüneceği bir şey. Şuna bir göz atın. ¹⁵

50 Mimari 35 3 // app/routes.php 5 $app['router']->get('/', function() 6 { 7 return 'Code Bright\'ı satın aldığınız için teşekkürler!'; 8 }); Burada biz bir GET HTTP isteğine cevap verecek bir rota oluşturmak için konteyner içindeki rotalama katmanına erişiyoruz. Bu, Laravel 3 kullanıcılarına tanıdık gelecektir, gerçi sözdizimi biraz garip görünebilir. Gördüğünüz gibi, bir dizi sözdizimi kullanarak, konteynerimizdeki rotalama bileşenine erişebiliyoruz. Bu, ArrayAccess interface tarafından sağlanan bir sihirdir. İstersek, rotalama katmanına şu şekilde de erişebiliriz: 3 // app/routes.php 5 $app->router->get('/', function() 6 { 7 return 'Cidden, Code Bright\'ı satın aldığınız için teşekkürler!'; 8 }); İlgili bileşene konteynerimizin bir niteliği gibi erişilmesi de önceki metodla tam olarak aynı işi görür. Çok da güzel değilmiş, öyle değil mi? Yani framework te yeni iseniz, Laravel in güzel sözdizimini duymuşsundur. Daha önce Laravel 3 kullanmışsanız, onun zevkini zaten yaşıyorsunuzdur. Umarım bu şöhret berbat olmaz, değil mi? Tabiki olmayacak! Bak daha sihirli eylemler de var. Facades Sevgili dostum Kenny Meyers, ilk kitabım Code Happy için The Nerdary¹⁶ de güzel bir yorum yazmıştı. Bu iyiliğini ödemek isterim. Kendisi bize son Laravel konferansında belirli kelimeleri telaffuz etmekte zorlandığını söyledi ve bu kelimenin de telaffuzu zor bir kelime olduğundan eminim. Bu yüzden, Kenny ve ilk dil olarak ingilizce konuşmayanlar için Facade ın nasıl okunduğunu gösteriyorum. fah-sahd Laravel 3 te, çoğu bileşene statik bir metod kullanılarak erişilirdi. Örneğin, son bölümdeki rotalama örneği şu şekilde olabilirdi: ¹⁶

51 Mimari 36 3 // app/routes.php 5 Route::get('/', function() 6 { 7 return 'Sağol Kenny, seni seviyoruz!'; 8 }); Bu güzel görünüyor Bileşen için tanımlayıcı bir isme ve sıklıkla bu bileşende yapılan eylemi tarif eden bir fiile sahibiz. Ne yazık ki, deneyimli geliştiriciler statik bir metod görünce korkacaktır. Gördüğünüz gibi, statik metodları test etmek oldukça zor olabilir. Bunun neden böyle olduğunu açıklayarak daha kitabın başlarında bir şeyleri karıştırmak istemiyorum, o yüzden, bana güvenmek durumundasınız. Laravel tasarımı sırasında bu büyük bir problem oluşturdu. Biz güzel ve basit sözdizimimizi seviyorduk, ama aynı zamanda en iyi kodlama uygulamalarını benimsemek istiyorduk ve bu da kodumuzun sağlamlığından emin olmak için pek çok test yazmamızı da içerir. Neyseki, Taylor harika bir fikirle, adını Facade tasarım deseninden alan Facade sınıfı fikriyle geldi. Facade ları kullanarak her iki dünyanın en iyisine sahip olduk. Hoş statik metodlar, ama publik metodlarla başlatılan bileşenler. Bu, kodumuzun hem güzel, hem de son derece test edilebilir olduğu anlamına gelir. Nasıl çalıştığını bir görelim. Laravel te kök aduzayına takma ad verilmiş çok sayıda sınıf bulunmaktadır. Bunlar bizim Facade sınıflarımızdır ve bu sınıfların hepsi de Illuminate\Support\Facades\Facade sınıfını genişletirler. Bu sınıf çok zekidir. Onun zekasını bazı kod örnekleriyle açıklayacağım. Gördüğünüz gibi, tıpkı eski Laravel 3 teki gibi statik bir rotalama metodu kullanabiliyoruz, şöyle mesela: 3 // app/routes.php 5 Route::get('/', function() 6 { 7 return 'Facade\'lar için sağol Taylor!'; 8 }); Bu örnekteki Facade Route sınıfıdır. Her bir Facade konteynerde bir bileşenin bir olgusuna bağlanmıştır. Bir Facade ın statik metodları kısayollardır ve çağrıldıkları zaman, konteynerde temsil ettikleri nesnenin ilgili publik metodunu çağırırlar. Yani, buradaki Route::get() metodu aslında aşağıdaki metodu çağıracaktır:

52 Mimari 37 3 // app/routes.php 5 $app['router']->get('/', function() 6 { 7 return 'Facade\'lar için sağol Taylor!'; 8 }); Bu neden önemlidir? Şöyle ki, gördüğünüz gibi bu büyük bir esneklik sağlar. Esneklik (Flexibility) Esneklik ne demek? Bu sefer sözlüğe bakmayacağım. Değişebilirlik anlamına geldiğini biliyorum. Konteynerin faydalarını oldukça iyi açıklayan özelliklerden biridir. Göreceğiniz gibi, biz konteyner içinde kayda geçirilmiş nesne ve bileşenleri değiştirebiliriz veya yerine başkasını koyabiliriz. Bu bize büyük bir güç sunar. Bir an için rotalama katmanının çalışma şeklini gerçekten sevmediğimizi düşünelim (merak etmeyin, çok seveceksiniz, sadece hayal edin). Biz hepimiz epik kodlayıcılar olduğumuza göre, doğruca gidip, SuperRouter adında ana sınıfı olan kendi rotalama katmanımızı yazalım. Konteynerin esnekliğine bağlı olarak, rotalama katmanının yerine kendi yazdığımızı koyabiliriz. Tüm samimiyetimle söylüyorum, bu düşünebildiğiniz kadar kolaydır. Biz sadece mevcut rotanın indeksine kendi rotamızı atayacağız. Ooo, lütfen dikkat edin, özellikle acemiyseniz bunu şimdi yapmanızı önermiyorum. Sadece büyük bir örnek olduğu için gösteriyorum. 3 // app/routes.php 5 $app['router'] = new SuperRouter(); Şimdi, kendi rotamızı sadece konteyner içinde doğrudan erişmek suretiyle kullanmıyoruz, aynı zamanda, bizim Route Facade mız da bu bileşene erişmeye devam edecek. Aslında olanlar daha etkileyicidir. Laravel in bileşenlerini kendinizinkiyle değiştirdiğiniz zaman, çatı kendi görevleri için sizin koyduğunuz bileşeni kullanmaya çalışacaktır, tıpkı kendi bileşenleri gibi. Çekirdek çatı bileşenlerine bu şekilde erişilebilmesi, size büyük bir güç bahşetmektedir. Eminim şımardınız, değil mi!

53 Mimari 38 Sağlamlık (Robustness) Daha önce birkaç kez bahsettiğim gibi, Laravel tek tek bileşenler kümesinden meydana gelir. Her bileşen kendi küçük işlevselliğinden sorumludur. Bunun anlamı, bunların tek sorumluluk ilkesine çok saygılı olduklarıdır. Gerçekten de, Laravel bileşenlerinin birçoğu, çatıdan tamamen ayrılmış olarak, kendi başlarına hareket edebilirler. Bu sebeple, github taki Illuminate organizasyonu¹⁷ altında bileşenlerin kopyaları bulunabilir. Bu bileşenlerden bir takım aynı zamanda Packagist de¹⁸ bulunmaktadır, dolayısıyla Composeri kullanarak kendi projelerinizde bunların avantajından yararlanabilirsiniz. Peki buradaki Sağlamlık nedir? Çok iyi gördüğünüz gibi, Laravel tarafından kullanılan her bileşen iyi test edilir. Tüm framework 900 test ve 1700 iddianın üzerinde bir paket barındırır. Bu testler sayesinde, bir şey kırılacak mı ya da mevcut işlevsellik bozulacak mı gibi bir endişe duymadan çatı için verimli bir gelecek sağlayacak katkıları kabul edebilir ve değişiklik yapabiliriz. Tamam, mimari hakkında bu kadar yeter. Bence geliştirmeye geçmeye artık hazırsınız. Hadi başlayalım! ¹⁷ ¹⁸

54 Başlarken Laravel PHP programlama dili için bir çatıdır. PHP sözdizimi pek çekici değilken, kullanımı kolaydır, dağıtımı kolaydır ve her gün kullandığımız modern web sitelerinin bir çoğuna güç verdiği görülebilir. Laravel sizin web tabanlı projelerinizin tümünde başarı kazanmanıza yardımcı olmak için sadece yararlı kestirme yollar, aletler ve bileşenler sağlamakla kalmayıp, aynı zamanda bazı PHP kusurlarını düzeltmeyi de hedeflemektedir. Laravel çok sayıda PHP frameworkleri arasında kendini öne çıkarmasını sağlayan güzel, anlamlı ve üretken bir sözdizimine sahiptir. Güç ve verimlilikten ödün vermeden, PHP yi kullanımı keyifli bir hale getirir. Laravel hem amatör projeler hem de kurumsal çözümler için mükemmel bir seçimdir ve bu dilin tecrübeli bir profesyoneli de olsanız, yenisi de olsanız, Code Bright fikirlerinizi tam fonksiyonlu web uygulamaları haline çevirmenize yardım edecektir. Hem çatı hem de bu kitap için gereksinimlere hızlıca bir göz atalım. Gereksinimler Bir Bilgisayar Okumak harikadır ancak kitapta bulacağınız örneklerle oynamakla daha çok öğreneceksiniz. Bir Web Sunucu Laravel bir web sunucusu gerektirir. Hangisini kullandığınızın bir önemi yoktur ancak topluluğun büyük çoğunluğunun Apache ya da Nginx kullandığını gördüm ve aynısını yaparsak ihtiyacımız olduğunda daha kolay destek bulabiliriz. PHP: Hypertext Preprocessor 5.3 veya üstü Laravel bir PHP çatısıdır, PHP programlama dilini gerektirir. Bunun için bana güvenin. Laravel bu dilin bazı modern özelliklerini de kullandığı için, aynı zamanda veya üstü sürüm gerekecektir. Çoğu web sunucuda ya konsolda php -v yazarak ya da phpinfo() metodunu kullanarak kullanmakta olduğunuz PHP versiyonunu öğrenebilirsiniz. Bir Veritabanı Sürücüsü Çatının bir gereksinimi olmamakla birlikte, kitaptaki örneklerin birçoğu bir veritabanı ile etkileşmektedir. Bu sebeple, PDO bağlayıcıyla desteklenen bir veritabanı sunucusu kurmanızı önereceğim. Benim önerim Su.. Oracle ın esnek ve parasız MySQL ini kullanmanızdır. Diğer popüler veritabanı sunucuları arasında SQL Server, Postgres ve SQLite sayılabilir. Bir Metin Editörü Kitapta bulunan örneklerle oynamak için gereklidir. Ben Sublime Text kullanmanızı öneriyorum, parasız değildir ama son derece seksidir. Bununla birlikte piyasada milyonlarca editör ve IDE vardır, çalışma şeklinize uyan birini bulun. Laravel projelerimiz üzerinde çalışmaya başlamadan önce, frameworkün bir kopyasını indirmemiz gerekiyor.

55 Başlarken 0 Yükleme Yükleme kelimesinin bu kesim için doğru bir başlık olduğundan emin değilim. Ancak daha iyisini gerçekten düşünemiyorum. Görüyorsunuz, Laravel yeni Laravel uygulamanız için bir çeşit şablon gibi davranan bir Github ambarına sahiptir. Lokal makinemize bir kopya indirelim. Geliştirme web sunucumuzdaki bir klasöre indirilecek ambarı clone lamak için git kullanacağız. Komut şudur. 1 git clone git://github.com/laravel/laravel.git projem Şimdi projem klasörü içinde Laravel için bir şablon uygulamanız olacak. Diğerlerinin bu şablona app package dediğini duyabilirsiniz. Bu paket sizin bütün uygulamanızı taşıyacaktır ve tüm dizin muhtemelen versiyonlanacaktır. Bazı tecrübeli Laravel kullanııları çatıyı güçlendiren dosyaları taşımakta kullanılan laravel adındaki bir dizini hatırlayabilirler. Biz bazen bunu çatının çekirdek ( core ) dosyaları olarak ifade edeceğiz. Evet, bu dizin artık bulunmuyor. Composer ın gücünden yararlanarak, çatının çekirdek dosyaları artık ayrı bir paket olarak mevcuttur, yani bizim şablon paketimizin bir bağımlığıdır. Nelerin yeni olduğunu görmek için projem dizinimizin içindeki composer.json dosyasına bakalım. 1 { "require": { 3 "laravel/framework": ".0.*" }, 5 "autoload": { 6 "classmap": [ 7 "app/commands", 8 "app/controllers", 9 "app/models", 10 "app/database/migrations", 11 "app/database/seeds", 1 "app/tests/testcase.php" 13 ] 1 }, 15 "scripts": { 16 "post-update-cmd": "php artisan optimize" 17 }, 18 "minimum-stability": "dev" 19 }

56 Başlarken 1 Bu kesim son güncellendiğinden bu yana bağımlılık sürümlerinin değişmiş olabileceğini unutmayın. Ancak, sonuçlar yine de aynı kalacaktır. Bizim uygulama paketimiz sadece laravel/framework paketine bağımlıdır, bu paket sizin uygulamanızı güçlendirmek için gerekli tüm bileşenleri içermektedir. Bu composer.json dosyası bizimdir. Uygulamamız içindir ve istersek onu düzenleyebiliriz. Ancak, sizin için bazı makul ön tanımlı değerler verilmiştir. Ayrıca, laravel/framework paketini çıkarmanızı hiç önermem. Çok kötü şeyler olacaktır. Şu anda elimizde sadece bir şablon var. Çatının çekirdeğini yüklemek için composer komutunu çalıştıralım. install 1 Loading composer repositories with package information Installing dependencies 3 - Installing doctrine/lexer (dev-master bc0e1f0) Cloning bc0e1f0cc8517a38c6c8ea88bc5dbafd53e Installing doctrine/annotations (v1.1) 7 Loading from cache Burada daha birçok paket olacaktır Installing ircmaxell/password-compat (1.0.x-dev v1.0.0) 1 Cloning v Installing swiftmailer/swiftmailer (dev-master e77eb35) 15 Cloning e77eb358a1aa7157afb9f33eafcf6a7bef Installing laravel/framework (dev-master 7f5b8) 18 Cloning 7f5b85cc01b6330a8f7ea75f0093a311fe3b 19 0 predis/predis suggests installing ext-phpiredis (Allows faster serialization and \ 1 deserialization of the Redis protocol) symfony/translation suggests installing symfony/config (..*) 3 symfony/translation suggests installing symfony/yaml (..*) symfony/routing suggests installing symfony/config (..*) 5 symfony/routing suggests installing symfony/yaml (..*) 6 symfony/event-dispatcher suggests installing symfony/dependency-injection (..*) 7 symfony/http-kernel suggests installing symfony/class-loader (..*) 8 symfony/http-kernel suggests installing symfony/config (..*) 9 symfony/http-kernel suggests installing symfony/dependency-injection (..*) 30 symfony/debug suggests installing symfony/class-loader (~.1) 31 monolog/monolog suggests installing mlehner/gelf-php (Allow sending log messages \ 3 to a GrayLog server)

57 Başlarken 33 monolog/monolog suggests installing ext-amqp (Allow sending log messages to an AM\ 3 QP server (1.0+ required)) 35 monolog/monolog suggests installing ext-mongo (Allow sending log messages to a Mo\ 36 ngodb server) 37 monolog/monolog suggests installing doctrine/couchdb (Allow sending log messages \ 38 to a CouchDB server) 39 monolog/monolog suggests installing raven/raven (Allow sending log messages to a \ 0 Sentry server) 1 Writing lock file Generating autoload files Tekrar söylüyorum, paket sürümleri değişmiş olabilir ancak sonuçlar yine aynısı olacaktır. Bu paket listesi ne kadar uzun böyle! Onlar ne için? Peki şöyle ifade edeyim, Laravel açık kaynağın gücünü, Composer de bulunan zengin paketleri özümser. Bu paketler çatının kendi bağımlılıklarıdır. Laravel gibi yapıp, Packagist websitesinde¹⁹ listelenen paketlere bakabilirsiniz. Klişe kodlar geldikten sonra, tekerleği yeniden keşfetmenin alemi yok. Composer bölümünü okuduğunuz için, Laravel in çekirdek dosyalarının vendor klasörüne yüklenmiş olacağını biliyorsunuz. Kodunuzun yanında bağımlılıklarınızın versiyonlanmasını gerçekten istemiyorsanız, Laravel diğer birkaç makul ön tanımlar yanında vendorun klasörünü göz ardı edecek örnek bir.gitignore dosyası sağlamıştır. Laravel geliştirme ortamımızı hemen hemen kurmuş olduk. Sadece bir konu kaldı. Web sunucunun nasıl kurulacağı. Web Server Yapılandırması Bu kesim daima yazması zor olanlardan biri oluyor. Gördüğünüz gibi, her şey hafif farklı şekilde kuruluyor ve piyasada birçok farklı web sunucusu mevcut. Burada ne yapacağımı söyliyeyim. Web sunucusu için belirtilmesi gereken temellerden bahsedeceğim. Ayrıca, sık kullanılan web sunucuları için örnek bazı yapılandırmalar da vereceğim. Ancak, bunlar çok genel olacak ve her duruma uyması için biraz oynamak gerekecek. Yine de, benim çaba göstermediğimi söyleyemezsiniz! Burada amacımızın ne olduğuna bir göz atalım. Laravel de bootstrap (önceden yüklenecek) kodunu içeren public denen bir dizin vardır. Bu kod frameworkun başlatılması için ve uygulamanıza yapılan tüm istekleri işlemek için kullanılır. public klasörü aynı zamanda sizin kamuya açık varlıklarınızı, örneğin JavaScript, CSS ve resimleri de içerir. Esasında, doğrudan bir link ile erişilebilecek her şey public dizini içinde olmalıdır. ¹⁹

58 Başlarken 3 Bunlar web sunucu yapılandırması açısından ne anlama geliyor? Tabii ki bizim ilk görevimiz web sunucusunun doğru yere bakmasını temin etmek. Web sunucusunun yapılandırmasını, projemizin kök dizinine değil public dizinine bakacak şekilde düzenlememiz gerekiyor. Sonraki görev, web sunucusunun zarif URL leri nasıl işleyeceğini bilmesini sağlamak. Ben aslında uygun bir domain adı seçtim, benim zaten zarif bir URL em yok mu? Üzgünüm, çalışma şekli bu değil. Hayatın hepsi kek ve pasta değil, biliyorsunuz değil mi? Laravel in bootstrap ı (önceden yüklenmesi gereken kodları) public klasörü içindeki index.php denen bir dosyanın içinde bulunmaktadır. Framework e yapılan tüm istekler bu dosya üzerinden gidiyor. Yani, ön tanımlı durumda bizim ziyaretcidefteri sayfamızın URL si aşağıdaki gibi görünecektir: 1 Web sayfamızın ziyaretçilerinin her şeyin index.php aracılığıyla yönlendirildiğini bilmesine gerek yok. Ayrıca, arama motoru optimizasyonu için de harika bir özellik değildir. Bu sebeple, web sunucumuzu index.php yi URL den çıkartıp, sadece zarif bölümü kalacak şekilde yapılandırmalıyız. Bu normalde bir düzenli ifade sihirbazı tarafından hazırlanmış bir yapılandırma kodu ile elde edilir. Şimdi bizim yukarıda bahsedilen hedeflere varmamızı sağlayacak bazı örnek web sunucusu yapılandırmalarına geçelim. Tekrar belirtiyorum, bu yapılandırmalar sadece kaba kılavuz olarak kullanılabilir. Sunucu yapılandırması konusunda daha ayrıntılı bilgiler için, seçmiş olduğunuz web sunucusu belgelerini ziyaret etmenizi önereceğim. Önce nginx ile başlayalım. Nginx Nginx, encin-iks diye okunur, yakınlarda kullanmaya başladığım harika bir web sunucusudur. Benim için seçim basit oldu. Apache den çok daha hızlı çalışıyor ve XML(emsi) yapılandırması gerektirmiyor. Tam kafama göre. Ubuntu gibi Debian tabanlı bir linux dağıtımında, aşağıdaki komutu çalıştırarak nginx ve PHP yükleyebilirsiniz. 1 sudo apt-get install nginx php5-fpm İkinci paket PHP-FPM, nginx in PHP kodunu çalıştırmasına imkan verecek bir FastCGI modülüdür. Mac da bu paketler Macports da²⁰ bulunmaktadır. Gerekli paketler aşağıdaki komut kullanılarak yüklenebilir. ²⁰

59 Başlarken 1 sudo port install php5-fpm nginx Nginx site yapılandırmanız normalde /etc/nginx/sites-enabled de konumlandırılır. Burada yeni bir site kurmak için kullanabileceğiniz bir şablon verilmiştir. 1 server { 3 # Web sunucusunun dinleyeceği Port. listen # Bu projeyi sunacak Host. 7 server_name app.dev 8 9 # Debug için yararlı günlükler. 10 access_log /path/to/access.log; 11 error_log /path/to/error.log; 1 rewrite_log on; 13 1 # Projemizin publik dizininin konumu. 15 root /path/to/our/public; # Laravel ön kontrolöre index noktası. 18 index index.php; 19 0 location / { 1 # Denenecek URL'ler, zarif URL'ler dahil. 3 try_files $uri $uri/ /index.php?$query_string; 5 } 6 7 # Lütfen rota sistemi için son bölüyü çıkartınız. 8 if (!-d $request_filename) { 9 rewrite ^/(.+)/$ /$1 permanent; 30 } 31 3 # PHP FPM yapılandırması. 33 location ~* \.php$ { 3 fastcgi_pass unix:/var/run/php5-fpm.sock; 35 fastcgi_index index.php; 36 fastcgi_split_path_info ^(.+\.php)(.*)$; 37 include /etc/nginx/fastcgi_params;

60 Başlarken 5 38 fastcgi_param SCRIPT_FILENAME $document_root$fastcg\ 39 i_script_name; 0 } 1 # nginx'te.ht dosyalarına ihtiyacımız yok. 3 location ~ /\.ht { deny all; 5 } 6 7 } Tabii bütün web sunucuları aynı şekilde gitmiyor. Tüm durumlara uygun genel bir yapılandırma sağlamak imkansız bir görev olacaktır. Buna rağmen verdiğim örnek başlangıç için yeterlidir. Herkes katkıda bulunabilsin diye bu bölümde kullandığım yapılandırmaları Github ta paylaştım. Onları daylerees/laravel-website-configs²¹ ambarında bulabilirsiniz. Nginx harika bir web sunucu seçimi olsa da, Apache web sunucusu da yaygın kullanılmaktadır. Bir de onun nasıl yapılandırılacağına bakalım. Apache Apache web sunucusu Debian tabanlı sistemlerde aşağıdaki komut kullanılarak yüklenebilir. 1 sudo apt-get install apache php5 Burada verilen Apache VirtualHost yapılandırması birçok duruma uyacaktır, herhangi bir değişiklik gerekirse github daki ambara²² katkıda bulunabilirsiniz. 1 <VirtualHost *:80> 3 # Bu projeyi sunacak Host. ServerName app.dev 5 6 # Projelerin publik dizininin konumu. 7 DocumentRoot /path/to/our/public 8 9 # Debug için kullanılabilir günceler. 10 CustomLog /path/to/access.log common 11 ErrorLog /path/to/error.log ²¹ ²²

61 Başlarken # Zarif URL'ler için Rewrite yapar,.htaccess'e güvenmemek daha iyi. 1 <Directory /path/to/our/public> 15 <IfModule mod_rewrite.c> 16 Options -MultiViews 17 RewriteEngine On 18 RewriteCond %{REQUEST_FILENAME}!-f 19 RewriteRule ^ index.php [L] 0 </IfModule> 1 </Directory> 3 </VirtualHost> Proje Yapısı Önceki kitapta paketin dizin yapısını anlatan bir bölüm vardı ve oradaki herşey duruyor gibi. Bu bölümde çok fazla değer olduğunu düşünüyorum ve bu nedenle Laravel 3 ten bu yana oluşan dizin yapısı değişiklikleriyle birlikte tekrarlamak istiyorum. Başlarken in bu kesimi taze bir Laravel projesinde composer varsayacaktır. Proje Kök Dizini Kök klasör yapısına bir göz atarak başlayalım. install çalıştırmış olduğunuzu app/ bootstrap/ vendor/ public/.gitattributes.gitignore artisan composer.json composer.lock phpunit.xml server.php Bu kök öğeler hakkında sırayla geçemez miyiz? Bana harika bir fikir gibi geliyor! app

62 Başlarken 7 En başında app dizinimiz var. App, projenizin özel kodlarının tümü için ön tanımlı yer sağlamakta kullanılır. Burada uygulamanın işlevselliğini sağlayan sınıflar, yapılandırma dosyaları ve daha başka şeyler içerir. Bu app klasörü oldukça önemlidir, o yüzden tek bir paragrafta kötü bir özet vermek yerine bu kesimin sonunda ayrıntılı olarak değineceğim. Şimdilik burasının proje dosyalarınızın yaşadığı yer olduğunu bilmeniz yeterlidir. bootstrap autoload.php paths.php start.php Bootstrap dizini çatının başlangıç prosedürleriyle ilgili birkaç dosya içerir. Bu prosedürlerin çoğunu autoload.php dosyası içerir ve bu dosya sadece deneyimli Laravel kullanıcıları tarafından düzenlenmelidir. paths.php dosyası çatı tarafından kullanılan ortak dosya sistemi yollarından oluşan bir dizi meydana getirir. Eğer bir sebeple çatı paketlerinin dizin yapılarını değiştirmeye karar verirseniz, bu dosyanın içeriğini sizin yaptığınız değişiklikleri yansıtacak şekilde değiştirmeniz gerekebilecektir. start.php çatının diğer başlangıç prosedürlerini içerir. Gereksiz kafa karışıklığına yol açabileceği nedeniyle şimdilik bunun ayrıntılarına girmek istemiyorum. Bunun yerine çatının ortamlarının (environments) ayarlandığı yer olarak aklınızda bulunsun. Eğer ortamların ne için kullanıldığını bilmiyorsanız, endişelenmeyin. İleride onu da göreceğiz! Basitçe söyleyecek olursak, bootstrap dizininin içeriği sadece dosya sistemlerinde çatının biçimini değiştirmesi gereken deneyimli Laravel kullanıcıları tarafından düzenlenmelidir. Laravel de yeni iseniz, şimdilik onu görmezden gelin ancak silmeyin! Laravel in iş görmesi için bu dizin gereklidir. vendor vendor dizini uygulamanız tarafından kullanılan composer paketlerinin tümünü içermektedir. Tabii ki, Laravel framework paketini de içerir. Bu dizin hakkında daha fazla bilgi için lütfen Ön Bilgiler bölümündeki Composer kesimine bakınız. public packages/.htaccess favicon.ico index.php robots.txt public dizini bir Laravel uygulamasının webe dönük tek dizinidir. Normalde burası CSS, Javascript dosyaları ve resimler gibi varlıklarınızın yaşadığı yerdir. Bunun içeriğine biraz yakından bakalım.

63 Başlarken 8 packages dizini üçüncü parti paketleri tarafından yüklenmesi gerekecek varlıkları kapsamak için kullanılacaktır. Bunlar ayrı dizinlerde tutulurlar, dolayısıyla bizim uygulamamızın kendi varlıkları ile çatışmazlar. Laravel Apache web sunucusu için standart bir.htaccess dosyasıyla gelir. Bu dosya, çatı kullanıcılarının çoğu için uygun olacak bazı standart yapılanma direktiflerini içerir. Şayet alternatif bir web sunucu kullanıyorsanız, bu dosyayı ya görmezden gelebilir veya silebilirsiniz. Ön tanımlı olarak, web tarayıcıları bir sitenin dizin indeksinde bir favicon.ico dosyası bulmaya çalışır. Bu dosya küçük 16 x 16px bir görüntü olup, tarayıcı sekmesinde gösterilir. Sorun şu ki, web sunucusunda bu dosya bulunamadığı zaman bundan yakınmayı sever. Gereksiz günlük girişlerine yol açar. Bu problemi ortadan kaldırmak için Laravel ön tanımlı olarak boş bir favicon.ico dosyası sağlamış olup, sonradan istendiği şekilde değiştirilebilir. index.php dosyası Laravel framework ön denetleyicisidir. Bu dosya bir tarayıcıdan bir istek alındığında web sunucusunun ulaştığı ilk dosyadır. Çatının bootstrap ını başlatacak ve tabiri caizse topu çevirmeye başlayacak dosya budur. Bu dosyayı silmeyin, bu iyi bir fikir değildir! Laravel ön tanımlı olarak tüm ana bilgisayarlara izin veren standart robots.txt dosyası içerir. Bu size kolaylık sağlamak içindir, bu dosyayı gerektiği kadar değiştirebilirsiniz..gitattributes Laravel, kullanmanız için bazı ön tanımlı Git sürüm kontrol yapılandırması vermiştir. Git günümüzde en popüler sürüm kontrol seçimidir. Projenizi Git ile sürümlendirmek istemiyorsanız bu dosyaları çıkartmakta serbestsiniz..gitignore.gitignore dosyası Git sürüm kontrolünü hangi klasörlerin sürümlenmeyeceği konusunda bilgilendirdiği ön tanımlı bazı değerleri içerir. Bu dosyanın aynı zamanda hem vendor dizinini hem de uygulama storage dizinini de içerdiğine dikkat ediniz. Üçüncü parti paketlerinin versiyonlanmasını önlemek için vendor dizini dahil edilmiştir. composer.lock da dahil edilmiştir, ancak bu girişi çıkarmak ve kilit dosyanızı versiyonlamak isteyebilirsiniz, böylece üretim ortamınızın geliştirme ortamınızla tam aynı bağımlılık sürümlerini yükleyebilirsiniz. Ön Bilgiler bölümünün Composer kesiminde bu konuda daha fazla bilgi bulunmaktadır. artisan artisan dosyası Laravel için Artisan komut satırı arayüzünü çalıştırmak için kullanılan çalıştırılabilir bir dosyadır. Artisan, çatıya kısayollar ve ek işlevsellik sağlayan çok sayıda komutlar içermektedir. İlerdeki bir bölümde bu komutlar ayrıntılı olarak anlatılacaktır. composer.json ve composer.lock Hem composer.json hem de composer.lock dosyası bu proje tarafından kullanılan composer paketleri hakkında bilgi içerir. Tekrar ifade ediyorum, Ön Bilgiler bölümünün Composer kesiminde bu konularla ilgili daha fazla bilgi bulabilirsiniz.

64 Başlarken 9 phpunit.xml phpunit.xml dosyası PHP unit testi çatısı için varsayılan bir yapılandırma sağlar. Bu, composer bağımlılıklarının yüklenmesini halledecek ve klasöründe bulunan testleri çalıştıracaktır. Laravel de testlerle ilgili bilgiler ilerdeki bir bölümde karşımıza çıkacaktır, bizden ayrılmayın! Bu biraz daha araştırma yapmayı gerektirecek. Uygulama Dizini ( app ) Uygulamanızın şeklini alacağı yer burasıdır. Zamanınızın çoğunu alacak olan dizin bu dizindir. O zaman neden daha fazla bilgi sahibi olmuyoruz? commands/ config/ controllers/ database/ lang/ models/ start/ storage/ tests/ views/ filters.php routes.php commands Commands dizini uygulamanızın gerektirdiği özel artisan komut satırı arayüzü komutlarını içerir. Gördüğünüz gibi Artisan CLI sadece projenizi inşa etmenize yardım edecek varsayılan işlevselliği sağlamakla kalmayıp, aynı zamanda sizin yapmak istediğiniz özel komutları da oluşturabilmektedir. config Hem çatının hem de uygulamanızın yapılandırması bu dizinde tutulur. Laravel in konfigürasyonu anahtar-değer dizileri içeren bir takım PHP dosyaları şeklinde bulunmaktadır. Bu dizin aynı zamanda, farklı ortamlarda yüklenebilecek farklı yapılandırmalara imkan veren alt dizinler de içerecektir. controllers Adından da anlaşılacağı gibi, bu dizin controller larınızı (denetçilerinizi) barındırır. Denetçiler uygulama mantığı sağlamak ve uygulamanın ayrı parçalarını bir arada tutmak için kullanılabilir.

65 Başlarken 50 Size kolaylık olması bakımından bu dizin composer.json da ön tanımlı bir classmap otomatik yüklenen konumu olarak eklenmiştir. database Uzun vadeli bir depolama yöntemi olarak bir veritabanı kullanmayı seçerseniz, bu durumda bu dizin oluşturacağınız veritabanı şeması dosyalarını ve ona örnek veriler ekme (seeding) metodlarınızı barındırmak için kullanılacaktır. Bu dizinde, ön tanımlı SQLite veritabanı da bulunmaktadır. lang lang dizini uygulamanıza yerelleştirme desteği vermekte kullanılabilecek string dizileri olan PHP dosyalarını içerir. Bölgelere göre isimlendirilen alt klasörler birden çok dil için string dosyaları olmasına imkan verir. models Models dizini modellerinizi taşır. Şaşırdınız mı? Modeller iş modelinizi temsil etmek için veya depoyla (storage) etkileşim için kullanılırlar. Aklınız mı karıştı? Dert etmeyin. İlerideki bir bölümde modelleri ayrıntılarıyla göreceğiz. Uygulama kimlik doğrulaması için hazır olarak bir User modelinin sunulduğunu bilin. controllers dizini gibi bu dizin de ön tanımlı composer.json un classmap otomatik yüklenenler kesimine eklenmiştir. start bootstrap dizini çatıya ait başlangıç prosedürlerini içerirken, start dizini sizin uygulamanıza ait başlangıç prosedürlerini içerir. Her zaman olduğu gibi, sizin için bazı makul ön tanımlar sağlanmıştır. storage Laravel in diske bir şey yazması gerektiğinde, bunu storage dizini içinde yapar. Bu sebeple web sunucunuzun bu konuma yazabilir olması gereklidir. tests tests dizini uygulanızın tüm unit ve kabul testlerini içerecektir. Ön tanımlı olarak bu dizindeki testlere bakacak ön tanımlı bir PHP Unit yapılandırması Laravel e dahil edilmiştir. views Views dizini uygulamanızın görsel şablonlarını taşımak için kullanılır. Kolaylık olsun diye ön tanımlı bir hello görünümü sağlanmıştır. filters.php filters.php dosyası uygulamanızın rota filtrelerini içerir. İlerdeki bir bölümde filtreler hakkında daha fazla bilgi öğreneceksiniz. routes.php Routes dosyası uygulama rotalarınızın tümünü içerir. Rotaların ne olduğunu bilmiyor musunuz? O zaman, niye daha fazla vakit kaybedelim ki. Hemen sonraki bölüme geçelim!

66 Basit Rotalama Sen nin vahşi doğasında uzun, düz, çamurlu bir yoldasın. Hangi ülkede vahşi doğa var? Avustralya! Yapacağız. Heyecanlanmayın! Bu bölüm biraz hayal gücü gerektiriyor, bu yüzden öyle yapmaya çalışacağım. Ana karakterimizin adının kitaplardaki gibi olmasını öneriyorum. Hmm adı Browsy Mc Request olsun. Browsy Mc Request kanguru ülkesinde bir yerlerde düz, çamurlu bir yol boyunca yürüyor. Browsy buranın yerlisi değil ve kaybolduğunu düşünüyor, nereye gittiği konusunda hiçbir fikri yok. Ancak, nerede olmak istediğini biliyor. Daha önce bir arkadaşı ona Jason Lewis in Bıyıklı Keseliler Barınağından bahsetmişti. Movember in yaklaştığını ve Kanguru stilistlerinden yardım alması gerekeceğini biliyor. Aniden, Browsy uzaklarda yolun ikiye ayrıldığını fark etti. Eski bildik düz, çamurlu yoldan başka bir şey görünce heyecanladı, bir yön bulurum umuduyla yol ayrımına koşturdu. Yol ayrımına vardığında, barınağa götürebilecek bir gösterge aradı ancak hiçbir şey bulamadı. Browsy nin şansına, tam o anda bir vahşi web geliştiricisi ortaya çıktı. Bu güçlü ve yakışıklı web geliştiricisi göz açıp kapayıncaya kadarlık bir sürede bir tabelayı sert toprağa çarparak gözden kayboldu. Browsy web geliştiricisinin hızı ve yakışıklılığı karşısında şaşakaldı. Onun yakışıklı olduğunu söylemiş miydim? Browsy nin değil, web geliştiricisinin Browsy BU KİTAP tan gelmiş çok değerli ADAMLAR gibi görünüyor. En azından ben öyle görüyorum. Nefesini biraz tuttuktan sonra, Browsy tabelayı çalışmaya başlıyor. Sola dönüp Bob un Bobcat Binicilik Ahırlarını bulacaksınız ve sonra sağa ah! Devam edin. Sağ tarafta Jason Lewis in Bıyıklı Keseliler Barınağını bulacaksınız. Browsy sonunda Keseliler Barınağı yolunu buldu ve kangurulara seyislik etmeyi öğrenerek uzun ve mutlu bir yaşam sürdü. Gördüğünüz gibi bu öykünün ana fikri, ona yol gösteren (YAKIŞIKLI) bir geliştirici olmasaydı, Browsy Mc Request bizim uygulam.. pardon Keseliler Barınağının yolunu bulamayacaktı. Tıpkı bu öyküde olduğu gibi, bir web isteği de bir rotalama olmadan uygulamamız mantığına yönlenemeyecektir. Basit Rotalama Laravel framework e yapılan bir isteğe hep birlikte bakalım.

67 Basit Rotalama Bu örnekte domain.com da barındırılan Laravel uygulamanıza erişmek için http protokolu (çoğu web tarayıcısı tarafından kullanılan) kullanıyoruz. URL deki benim/sayfam kısmı web isteklerini uygun mantığa yönlendirmekte kullanacağımız şeydir. Devam edip, sizi en sona atayım. Rotalar app/routes.php dosyasında tanımlanmıştır, bu yüzden oraya gidelim ve yukarıda bahsettiğimiz isteği dinleyecek bir rota oluşturalım. 3 // app/routes.php 5 Route::get('benim/sayfam', function() { 6 return 'Merhaba dünya!'; 7 }); Şimdi web tarayıcısına girin, domain.com yerine Laravel uygulamanızın adresi yazılacak. Bu muhtemelen localhost dır. Eğer her şey düzgünce yapılandırılmış ise, harika Times New Roman fontuyla yazılmış Merhaba dünya! kelimelerini göreceksin! Bunun nasıl çalıştığını görmek için neden rota deklarasyonuna yakından bakmayalım. Rotalar her zaman için Route sınıfı kullanılarak deklare edilir. Yani başlangıçtaki :: öncesindeki kısımdır. get parçası ise, belirli bir URL ye HTTP GET fiili kullanılarak yapılmış olan istekleri yakalamak için kullanılan, rota sınıfındaki bir metodtur. Gördüğünüz gibi, bir web tarayıcısı tarafından yapılan bütün istekler bir fiil içerir. Çoğu defa bu fiil, bir web sayfası istemekte kullanılan GET olacaktır. Web tarayıcınıza yeni bir adres yazdığınız her seferinde bir GET isteği gönderilir. Tek istek bu değildir. Ayrıca, bir istek yapmak ve onunla birlikte bir parça veri de sağlamakta kullanılan POST da vardır. Bunlar normalde bir form göndermenin sonucudur, buradaki veriler URL de gösterilmeksizin web sunucusuna gönderilmesi gereken verilerdir. Başka HTTP fiilleri de vardır. Rotalama sınıfında kullanabileceğiniz metodların bazıları şunlardır:

68 Basit Rotalama 53 3 // app/routes.php 5 Route::get(); 6 Route::post(); 7 Route::put(); 8 Route::delete(); 9 Route::any(); Bu metodların hepsi de aynı parametreleri kabul eder, bu yüzden, verilen bir durumda hangi HTTP fiili kullanmanın doğru olacağı konusunda rahat olun. Bu, RESTful rotalama olarak bilinmektedir. İlerde bu konuya daha ayrıntılı değineceğiz. Şimdilik bilmeniz gerekenler GETin istek yapmak için kullanıldığı ve POSTun istekle birlikte ek bilgiler göndermeniz gerektiğinde kullanılacağıdır. Route::any() metodu herhangi bir HTTP filine eşleştirme için kullanılır. Yine de ben uygulamanızı daha transparan yapmak için, kullandığınız durum için doğru olan fiili kullanmanızı öneririm. Elimizdeki örneğe tekrar bakalım ve hafızamızı tazeleyelim: 3 // app/routes.php 5 Route::get('benim/sayfam', function() { 6 return 'Merhaba dünya!'; 7 }); Kod parçasının sonraki kısmı get() (veya başka bir fiil) metoduna ilk parametredir. Bu parametre, istediğimiz URL ile eşleşen URI yi tanımlar. Buradaki örnekte eşleştirilen benim/sayfam dir. Son parametre ise, isteği işleyecek uygulama mantığını vermektedir. Biz burada bir Closure kullanıyoruz (bu aynı zamanda anonim fonksiyon olarak da bilinmektedir). Closure lar diğer basit tiplerde olduğu gibi değişkenlere atanabilen bir ismi olmayan basit fonksiyonlardır. Örnek olarak, yukarıdaki kod parçacığı şöyle de yazılabilirdi:

69 Basit Rotalama 5 3 // app/routes.php 5 $mantik = function() { 6 return 'Merhaba dünya!'; 7 } 8 9 Route::get('benim/sayfam', $mantik); Burada Closureu $mantik değişkeninde saklıyoruz ve sonra da onu Route::get() metoduna geçiriyoruz. Bu örneğimizde, Laravel Closure fonksiyonunu sadece güncel istek HTTP GET fiilini kullandığı ve URI benim/sayfam olduğu zaman çalıştıracaktır. Bu şartlar altında return cümlesi işlenecek ve tarayıcıya Merhaba dünya! metni sunulacaktır. İstediğiniz kadar çok sayıda rota tanımlayabilirsiniz, örneğin: 3 // app/routes.php 5 Route::get('birinci/sayfa', function() { 6 return 'Birinci!'; 7 }); 8 9 Route::get('ikinci/sayfa', function() { 10 return 'İkinci!'; 11 }); 1 13 Route::get('ucuncu/sayfa', function() { 1 return 'Patates!'; 15 }); Uygulamanızın nasıl davrandığını görmek için aşağıdaki URL leri gezmeyi deneyin Web uygulamanızın kökünü eşleştirmek isteyebilirsiniz belki. Örneğin

70 Basit Rotalama Normalde bu, uygulamanızın ana sayfasını barındırmak için kullanılır. Ona uyan bir rota oluşturalım. 3 // app/routes.php 5 Route::get('/', function() { 6 return 'Sovyet Rusya\'da, fonksiyon sizi tanımlar.'; 7 }); Hey, bekle bir dakika! Bizim URI de bir bölü işareti olmayacaktı? SAKİN OL OKUYUCU! Giderek çıldırıyorsun. Görmüş olduğunuz gibi, sadece bir bölü işareti taşıyan bir rota, websitesinin URL si ile eşleşecektir, sonunda ister bölü olsun, ister olmasın. Yukarıdaki rota aşağıdaki URL lerin ikisine de cevap verecektir URL ler istediğiniz kadar çok segmentten (bölüler arasındaki parçalar) oluşabilir. Bunu bir site hiyerarşisi oluşturmak için kullanabilirsiniz. Şöyle bir site yapısını ele alalım: 1 / /kitaplar 3 /kurgu /bilim 5 /romantizm 6 /dergiler 7 /sohretler 8 /teknoloji Evet, bu oldukça küçük bir site, ama web de sıklıkla bulacağın bir yapı için büyük bir örnek. Şimdi Laravel rotalarını kullanarak bunu yeniden oluşturalım. Anlaşılır olması bakımından, her bir rotadaki Closure işleme kodları budanmıştır.

71 Basit Rotalama 56 3 // app/routes.php 5 // ana sayfa 6 Route::get('/', function() {}); // kitaplar kesimi için rotalar 10 Route::get('/kitaplar', function() {}); 11 Route::get('/kitaplar/kurgu', function() {}); 1 Route::get('/kitaplar/bilim', function() {}); 13 Route::get('/kitaplar/roman', function() {}); 1 15 // dergiler kesimi için rotalar 16 Route::get('/dergiler', function() {}); 17 Route::get('/dergiler/sohretler', function() {}); 18 Route::get('/dergiler/teknoloji', function() {}); Bu rota koleksiyonuyla kolaylıkla bir site hiyerarşisi oluşturduk. Ancak, belirli miktarda tekrar olduğunu fark etmiş olabilirsin. Bu tekrarlamaları en aza indirecek bir yol bulalım ve KTE (Kendinizi Tekrar Etmeyin) ilkelerine yapışalım. Rota Parametreleri Rota parametreleri rota tanımlarınıza yer tutucular eklemek için kullanılabilir. Bunlar hangi URI segmentlerinin toplanacağı ve uygulamanın mantık işleyicisine geçirilebileceğini tanımlayan bir deseni etkili bir şekilde oluşturacaklardır. Bu biraz kafanızı karıştırmış olabilir, ama işin yapılışını gördüğünüz zaman her şey yerine oturacak. İşte başlıyoruz 3 // app/routes.php 5 // kitaplar kesimi için rotalar 6 Route::get('/kitaplar', function() 7 { 8 return 'Kitaplar indeksi.'; 9 }); 10

72 Basit Rotalama Route::get('/kitaplar/{tarz}', function($tarz) 1 { 13 return "{$tarz} kategorisindeki kitaplar."; 1 }); Bu örnekte, bir rota yer tutucusu dahil etmekle kitap türlerinin hepsine rota yazma gereğini ortadan kaldırdık. {tarz} yer tutucusu /kitaplar/ URI den sonra gelen her şeyle eşleşecektir. Bu, onun değerini Closure un $tarz parametresine geçirecektir, böylece bu bilginin bizim mantık kısmımız içinde kullanılması mümkün olacaktır. Örneğin, şu URL yi ziyaret edecek olsaydınız: 1 Bu metin cevabı ile karşılaşacaktınız: 1 cinayet kategorisindeki kitaplar. Opsiyonel bir parametre kullanmak suretiyle kitapların index rotası için ihtiyacı da ortadan kaldırabiliriz. Adının sonuna bir soru işareti (?) eklemekle bir parametre opsiyonel yapılabilmektedir. Örneğin: 3 // app/routes.php 5 // kitaplar kesimi için rotalar 6 Route::get('/kitaplar/{tarz?}', function($tarz = null) 7 { 8 if ($tarz == null) return 'Kitaplar indeksi.'; 9 return "{$tarz} kategorisindeki kitaplar."; 10 }); Şayet URL de bir tarz verilmezse, bu durumda $tarz değişkeninin değeri null a eşit olacak ve Kitaplar indeksi. mesajı gösterilecektir. Eğer bir rota parametresi değerinin ön tanımlı olarak null olmasını istemiyorsak, atama kullanarak bir alternatif belirleyebiliriz. Örneğin:

73 Basit Rotalama 58 3 // app/routes.php 5 // kitaplar kesimi için rotalar 6 Route::get('/kitaplar/{tarz?}', function($tarz = 'Cinayet') 7 { 8 return "{$tarz} kategorisindeki kitaplar."; 9 }); Şimdi eğer aşağıdaki URL yi ziyaret edersek: 1 Bu cevabı alacağız: 1 Cinayet kategorisindeki kitaplar. Umarım, rotaların sitenize yapılan istekleri yönlendirmek için ve uygulamanızı birbirine bağlamakta kullanılan kod yapıştırıcısı olarak nasıl kullanıldığını görmeye başladınız. Rota konusunda daha çok şeyler var. Ona geri döneceğiz ama temeller üzerinde biraz daha kalalım. Sonraki bölümde Laravel in sunduğu cevap tiplerine bakacağız.

74 Cevaplar (Responses) Birisi bir şey sorduğunda, soru anlamsız değilse ve ruh haliniz yerindeyse büyük ihtimalle bir cevap verirsiniz. Ben diğer bir istisnanın soru benzeri karşılamalar olabileceğini düşünüyorum, birinin İyisin? demesi gibi. Böyle olduğunda bile, bir cevap çeşidi olarak en azından kafanızı sallarsınız. Bir web sunucusuna yapılan istekler İyisin? diyen birinden farklı değildir. Bir şeylerin geri gelmesini beklerler. Önceki bölümde bizim cevaplarımız rota closure larından döndürülen stringler biçimini alıyordu. Şöyle bir şey: 3 // app/routes.php 5 Route::get('/', function() 6 { 7 return 'İyi miyim be patron.'; 8 }); Yani burada web tarayıcısına İyi miyim be patron. stringini gönderdik. Bu string bizim cevabımızdır ve daima bir rota closure u veya daha sonra anlatacağımız bir Kontrolör eylemi tarafından döndürülür (return edilir). Cevap olarak bir miktar HTML göndermek isteyeceğinizi düşünmek yanlış olmasa gerek. Web uygulamaları geliştirirken genelde böyle yapılır. Cevap stringine HTML koyabileceğimizi sanıyorum? 3 // app/routes.php 5 Route::get('/', function() 6 { 7 return '<!doctype html> 8 <html lang ="en"> 9 <head> 10 <meta charset ="UTF-8"> 11 <title>pekala!</title> 1 </head>

75 Cevaplar (Responses) <body> 1 <p>bu mükemmel bir cevap!</p> 15 </body> 16 </html>'; 17 }); Müthiş! Laravel in gücünü ve zerafetini gördün mü şaka, şaka. Biz HTML i bu şekilde sunmak istemeyiz. Mantık gömme can sıkıcı olacaktır ve daha da önemlisi düz HTML olması da yanlış! Neyse ki, Laravel çok daha kolay anlamlı bir cevap döndürmemizi sağlayan çeşitli Response nesnelerine sahiptir. En heyecan verenlerden biri olan View (Görünüm) cevabına bakalım! Görünümler Görünümler uygulamanızın görsel kısmıdır. Model View Controller deseni içerisinde bunlar View kısmını oluştururlar. Bunlara onun için view deniyor. Bu roket bilimi değil sonuçta. Roket bilimi ilerideki bir bölümde anlatılacaktır. Bir görünüm web tarayıcısına döndürülebilecek düz bir metin şablonundan başka bir şey değildir, tabi HTML de içerebilir. Görünümler.php uzantısını kullanırlar ve normalde app/views dizinine konurlar. Demek ki, görünümleriniz içinde PHP kodu da parse edilebilecektir. Şimdilik çok basit bir görünüm oluşturarak işe başlayalım. 1 <!-- app/views/basit.php --> 3 <!doctype html> <html lang ="en"> 5 <head> 6 <meta charset ="UTF-8"> 7 <title>görünümler!</title> 8 </head> 9 <body> 10 <p>aa evet! GÖRÜNÜMLER!</p> 11 </body> 1 </html> Harika! app/views/basit.php dosyasında saklanan küçük bir HTML. Şimdi bir görünüm yapalım. Daha demin yaptığımız neydi? Haha! Evet önceki yaptığın görünümdü, ama ben Başka bir görünüm dosyası yapalım. demek istemedim. Oluşturduğumuz o görünüm dosyasına dayanan yeni bir view cevabı nesnesi yapalım (make()) demek istedim. Görünümleri temsil eden dosyalara şablon denilmektedir. Bu açıklama View nesneleri ile HTML şablonlarını ayırt etmenize yardımcı olabilir.

76 Cevaplar (Responses) 61 3 // app/routes.php 5 Route::get('/', function() 6 { 7 return View::make('basit'); 8 }); O, Görüyorum! make() metoduna gelmişsin. Biraz açıklayayım. View::make() metodunu kullanmakla yeni bir View cevap nesnesi olgusu oluşturabiliyoruz. make() metoduna verdiğimiz birinci parametre kullanmak istediğimiz görünüm şablonudur. Tam dosya yolu app/views/basit.php kullanmadığımıza dikkat edin. Bu Laravel in zeki olmasından geliyor. Çünkü o ön tanımlı olarak görünüm dosyalarının app/views dizininde olduğunu varsayacak ve uygun bir görünüm uzantısı olan bir dosya arayacaktır. Closure a daha yakından bakarsanız, oluşturduğumuz View nesnesini döndürdüğümüzü göreceksin. Bu çok önemlidir, çünkü Laravel web tarayıcına bizim Closure un sonucunu sunacaktır. İlerleyelim ve uygulamamızda / URI ye gitmeye çalışalım. Muhteşem, işte yazdığımız şablon! Bu kitabın ilerdeki bölümlerinde hayatınızı kolaylaştırmak için View cevabı ile çalışan farklı şablon tiplerinin nasıl oluşturulacağını öğreneceksiniz. Temel Laravel kavralarının iyice özümsenmesi adına şimdilik ben temellere bağlı kalacağım. Görünüm Verisi Şablonları gösterebiliyor olmak harika. Gerçekten. Peki, Closure umuzdan bazı veriler kullanmasını istersek ne olacak? Önceki bölümde Rota parametreleri kullanmayı öğrenmiştik. Görünüm içinde bu parametrelere başvurmak mümkün olabilir mi? Bunun nasıl yapılabileceğine bakalım. 3 // app/routes.php 5 Route::get('/{sincap}', function($sincap) 6 { 7 $veri['sincap'] = $sincap; 8 9 return View::make('basit', $veri); 10 });

77 Cevaplar (Responses) 6 Yukarıdaki örnekte $sincap parametresini aldık ve görünümümüzün veri dizisine ekledik. Gördüğünüz gibi, make() metodunun ikinci parametresi görünüm şablonuna geçilecek bir dizi kabul etmektedir. Onun görünümümüzün veri dizisi olduğunu işaret etmek için bu diziye normalde $veri dizisi diyorum, ama siz istediğiniz herhangi bir isim kullanabilirsiniz! Bu veriyi kullanmaya başlamadan önce, gelin görünüm veri dizisinden biraz daha söz edelim. Görünüme bu diziyi geçtiğiniz zaman, dizi anahtarları değişkenlere dönüştürülür; dizi anahtarları bu değişkenlerin adı, değeri de değeri olur. Basitleştirmek için bir örnek vermeden kafanız biraz karışabilir. View::make() e görünüm verisi olarak tutturulan dizi şöyle olsun. array('isim' => 'Taylor Otwell', 'durum' => 'Kod Gurusu') Görünüm şablonunun oluşturulmasında bu değerlere şu şekilde erişebileceğiz: echo $isim; // 'Taylor Otwell' verir?> 3 <?php echo $durum; // 'Kod Gurusu' verir?> Yani bizim isim dizi anahtarımız şablon içinde $isim değişkeni haline gelmiştir. Görünüm veri dizisinde istediğiniz derinlikte çok boyutlu diziler saklayabilirsiniz. Denemesi bedava! Daha önce oluşturduğumuz basit şablonundaki $sincap değişkenini kullanalım. 1 <!-- app/views/basit.php --> 3 <!doctype html> <html lang ="en"> 5 <head> 6 <meta charset ="UTF-8"> 7 <title>sincap</title> 8 </head> 9 <body> 10 <p><?php echo $sincap;?> bir sincap olmak isterdim!</p> 11 </body> 1 </html> Şimdi eğer /Gri URI yi ziyaret edersek Gri bir sincap olmak isterdim! diyen bir sayfa alırız. Çok basit değil mi? Görünümleri kullanmak sayesinde artık Closure den string döndürmek zorunda olmayacağız! Farklı tiplerde cevap nesneleri olduğunu daha önce söylemiştim. Bazı şartlarda uygulamanızın akışını başka bir rotaya veya mantık kısmına yön değiştirmek isteyebilirsiniz. Böylesi durumlarda Redirect cevap nesnesi işe yarayacaktır. Bak, Laravel arkanızda!

78 Cevaplar (Responses) 63 Redirekt Bir Redirect, uygulamanın akışını başka bir rotaya yönlendiren özel bir cevap nesnesi tipidir. Daha ayrıntılı açıklayabilmek için birkaç örnek rota oluşturalım. 3 // app/routes.php 5 Route::get('birinci', function() 6 { 7 return 'Birinci rota.'; 8 }); 9 10 Route::get('ikinci', function() 11 { 1 return 'İkinci rota.'; 13 }); Yukarıdaki rotaları eklediğimizde, /birinci URI ziyaretinde Birinci rota. ve /ikinci URI ziyaretinde İkinci rota. alacaksınız. Mükemmel, ne beklediysek o oldu. Şimdi ilk rotamızın Closure una bir redirekt ekleyerek uygulamamızın akışını tamamen kaydıralım. 3 // app/routes.php 5 Route::get('birinci', function() 6 { 7 return Redirect::to('ikinci'); 8 }); 9 10 Route::get('ikinci', function() 11 { 1 return 'İkinci rota.'; 13 }); İlk rotamızda şimdi Redirect::to() metodunun sonucunu döndürüyoruz ve hedef konum URI sini geçiyoruz. Şimdiki örneğimizde konum olarak ikinci rotanın URI si olan ikinci yi veriyoruz.

79 Cevaplar (Responses) 6 Eğer şimdi /birinci URI yi ziyaret ederseniz, İkinci rota. metni ile karşılaşacaksınız. Bunun sebebi döndürülen Redirect nesnesini almanızdır; Laravel, uygulamanızın akışını verilen hedefe gidecek şekilde kaydırmıştır. Bu durumda akış ikinci rotanın closure una kaydırılmıştır. Bu özellik, bir şey başarısız olduğunda kullanıcıyı daha yararlı bir yere yönlendirme gereği duyduğunuz zaman gerçekten yararlı olabilir. Başka bir kullanım alanı olan kimlik doğrulama sistemi (ilerde anlatılacaktır) örneğini gösterelim. 3 // app/routes.php 5 Route::get('kitaplar', function() 6 { 7 if (Auth::guest()) return Redirect::to('login'); 8 9 // Kitapları sadece giriş yapmış kullanıcılara göster. 10 }); Bu örnekte, sisteme henüz giriş yapmamış bir kullanıcı /kitaplar URI yi ziyaret ederse, misafir olarak kabul edilir ve login sayfasına yönlendirilecektir. İlerde rota filtrelerini tartışacağımız zaman, erişim sınırlamak için daha iyi bir yol bulacağız, bu yüzden yukarıdaki örneğe çok takılıp kalmayın. Sadece şunu anlamak yeterli, şartlarımız karşılanmazsa kullanıcıyı daha uygun bir yere yönlendirebiliyoruz. Özel Cevaplar View ve Redirect, her ikisi de Laravel in Response nesnesinden türemişlerdir. Cevap nesnesi, framework ün tarayıcıya doğru cevap türü sunabilmesini sağlamak için bir rota closure u veya bir kontrolör eyleminin bir sonucu olarak Laravel e geri sunulan bir sınıfın olgusudur. Response nesneleri genel olarak bir gövde (body), bir durum kodu (status code), HTTP başlıkları (header) ve diğer yararlı bilgiler taşır. Örnek olarak, Görünüm ün gövde kısmı HTML içeriği olacaktır. Bir Redirect için durum kodu 301 olacaktır. Laravel bu bilgiyi tarayıcıya döndürülebilecek makul bir sonuç oluşturmak için kullanır. Biz sadece View ve Redirect kullanmakla sınırlı değiliz. Kendi ihtiyaçlarımıza uygun cevap nesnelerimizi de oluşturabiliriz. Bunun nasıl yapılacağına bir göz atalım.

80 Cevaplar (Responses) 65 3 // app/routes.php 5 Route::get('ozel/cevap', function() 6 { 7 return Response::make('Merhaba dünya!', 00); 8 }); Yukarıdaki örnekte yeni bir cevap nesnesi oluşturmak için Response::make() metodunu kullanıyoruz. Birinci parametresi cevabın içeriği veya gövdesidir ve ikinci parametresi cevapla birlikte sunulacak HTTP durum kodudur. HTTP durum kodunu daha önce görmediyseniz, bunu sayfanızı alan web tarayıcısı için bir durum bildirimleri olarak düşünebilirsiniz. Örneğin, her şey yolunda giderse, standart bir cevap bir 00 durum kodunu içerebilir ki, web sunucusu A-OK demiş olmaktadır. Bir 30 durum kodu da bir redirekt yapıldığını gösterir. Aslında, meşhur 0 sayfa bulunamadı yı bildiğinizi sanıyorum. 0 kısmı istenen kaynak bulunamadığında tarayıcı tarafından alınan durum kodudur. Basitçe ifade edilecek olursa, yukarıdaki cevap tarayıcıya Merhaba dünya! içeriği yanında isteğin başarılı olduğunu bildiren bir HTTP 00 durum kodu da sunacaktır. HTTP başlıkları, cevabı alan web tarayıcısına yararlı bilgiler sunan bir anahtar-değer çifti koleksiyonudur. Normalde bunlar sonucun formatını veya içeriğin hangi uzunlukta önbelleklendiğini göstermek için kullanılır. Bununla birlikte, istediğiniz kadar özel başlık tanımlayabilirsiniz. Şimdi bazı header değerlerini nasıl ayarlayabileceğimizi görelim. 3 // app/routes.php 5 Route::get('ozel/cevap', function() 6 { 7 $cevap = Response::make('Merhaba dünya!', 00); 8 $cevap->headers->set('anahtar', 'değer'); 9 return $cevap; 10 }); Önceki örnekte yaptığımız gibi örnek bir cevap nesnesi oluşturduk. Ancak bu sefer özel bir başlık da ayarladık. HTTP başlıkları koleksiyonuna cevap nesnesinin headers özelliği ile erişebiliriz.

81 Cevaplar (Responses) 66 3 var_dump($cevap->headers); Koleksiyondaki set() metodunu kullanarak, koleksiyona kendi başlığımızı ekleyebiliyoruz, birinci parametresi bir anahtarı, ikinci parametresi de bunun değerini temsil ediyor. Başlığımızı ekledikten sonra cevap nesnesini daha önce yaptığımız gibi döndürüyoruz. Tarayıcı cevapla birlikte başlıkları da alacak, ancak bunu istediği gibi kullanacaktır. Daha yararlı olacak bir örnek düşünelim. Hrrm Şöyle yapalım, uygulamamızın HTML yerine markdown cevapları sunmasını istediğimizi hayal edelim. Bir web tarayıcısının bir markdown cevabını parse edemeyeceğini biliyoruz, fakat bunu yapabilen başka bir masaüstü uygulamamız olabilir. İçeriğin HTML değil de, markdown olduğunu göstermek için, Content-Type başlığını değiştireceğiz. Bu Content-Type web tarayıcıları tarafından kendilerine gönderilen çeşitli formatlardaki içerikleri ayırt etmekte kullandıkları yaygın bir başlık anahtarıdır. Kafanız karışmasın! Bakın bir örnek vereyim. 3 // app/routes.php 5 Route::get('markdown/cevap', function() 6 { 7 $cevap = Response::make('***Bu metin koyu yazılmış***', 00); 8 $cevap->headers->set('content-type', 'text/x-markdown'); 9 return $cevap; 10 }); Cevap nesnesinin gövde kısmını örnek bir markdown metnine (bu örnek için Bu metin koyu yazılmış) ve Content-Type başlığını Markdown düz metin formatının mime tipine ayarlayarak, Markdown olarak tanınacak bir cevap sunmuş olduk. Bizim masaüstü ugulamamız şimdi /markdown/cevap URI sine bir istek yapabilir, Content-Type başlığının ne olduğuna bakar ve text/x-markdown değerini elde edince, gövdeyi işlemek için bir markdown dönüştürücüsü kullanacağını bilir. Şimdi, biz hepimiz arkadaş olduğumuz için, sizinle bir sırrı paylaşacağım. Yaklaşın. Buraya gelin. Toplanalım. Cevap nesnesi aslında Laravel e ait değildir. İHANET? BU NE ÇILGINLIK?

82 Cevaplar (Responses) 67 Heyecan yapmayın. Gördüğünüz gibi, Laravel çok sayıda tekerleği yeniden keşfetmek ten kaçınmak için, Symfony projesine ait çok sağlam bileşenlerin bir kısmını kullanmaktadır. Laravel in response nesnesi içeriğinin çoğunu gerçekte Symfony HTTPFoundation bileşenine ait Response nesnesinden kalıtımla almıştır. Şunu demek istiyorum, eğer Symfony response nesnesinin API lerine bakarsanız, Laravel belgelerinde olmayan ekstra metodlara erişirsiniz! Kutsal duman! Bir sır daha vereyim, orada sizi bir Laravel ustası olmaktan alıkoyacak bir şey yok! Symfony Response nesnesi için API belgeleri burada bulunabilir²³ The Symfony Response Object. Eğer sayfaya bakarsanız bu sınıfın $headers adlı bir niteliğe sahip olduğunu fark edersiniz. Bu doğru! Yani sadece bir dakika önce kullanıyor olduğumuz headers koleksiyonu. Laravel response nesnesi bundan türetildiği için, Symfony API belgelerinde gördüğünüz her türlü metodu kullanabilirsiniz. Örnek olarak setttl() metoduna bakalım. API ne diyor? public Response setttl(**integer $seconds**) Sets the response s time-to-live for shared caches. This method adjusts the Cache-Control/s-maxage directive. Parameters: integer $seconds Number of seconds Return Value: Response Tamam, yani bu metod paylaşılan önbellek için yaşam süresini ayarlıyor. Ben bu konuda uzman değilim ancak bir bilgi parçasının atılmadan önce yararlı kabul edildiği süreyi ifade eder diyebilirim. Bu örnekte TTL, içerik önbellemesi ile ilgilidir. Eğlence olsun diye bir değer verelim. Metod imzasına baktığımızda, saniye cinsinden yaşam süresini temsil eden bir tam sayı kabul ettiğini görürüz. Bu cevabın 60 saniye yaşamasını bildirelim. Zalim James Bond un kötü bir örneği gibi. ²³

83 Cevaplar (Responses) 68 3 // app/routes.php 5 Route::get('bizim/cevap', function() 6 { 7 $cevap = Response::make('Bond, James Bond.', 00); 8 $cevap->setttl(60); 9 return $cevap; 10 }); Şimdi bizim cevap sunulduğu zaman, yaşamak için 60 saniyesi olacak. Gördüğünüz gibi, altta yatan Symfony bileşenini sorgulayarak uygulama cevaplarımızı ihtiyaçlarımıza göre değiştirebileceğimiz ileri seçeneklere sahip olabiliyoruz. Taban Response nesnesindeki karmaşıklık sizi bunaltmasın. Çoğu keresinde, basit HTTP cevapları sunmak için Laravel in View ve Response sınıflarını kullanmakla mutlu olacaksınız. Yukarıdaki örnek, yalnızca uygulamalarıyla özel senaryolar için oynamak isteyen ileri kullanıcılar için iyi bir başlangıç noktası olarak hizmet eder. Cevap Kısayolları Laravel arkadaşınızdır. Bu doğru Hayır aslında doğru değil. Laravel bir arkadaştan daha fazlasıdır. O sizi seviyor. Gerçekten seviyor. Bundan dolayı, hayatınızı kolaylaştırmak için birtakım cevap kısayolları sağlıyor. Kullanabileceğimiz neler var bir bakalım. JSON Cevapları Uygulamamız içinde çoğu kez JSON olarak sunmak isteyeceğimiz bazı veriler olacak. Bunlar basit bir nesne veya bir değerler dizisi olacaktır. Laravel, bir takım ayrıntılarıyla birlikte JSON sonuçlarına özgü cevap nesnesi yapılandıran bir Response::json() metodu sağlamaktadır. Örneğin uygun bir HTTP Content-Type başlığı. Bunları elle de ayarlayabilirdik ancak Laravel bunu bizim için yapacakken niçin zahmet edelim? Haydi bu metodu iş üstünde görelim.

84 Cevaplar (Responses) 69 3 // app/routes.php 5 Route::get('markdown/cevap', function() 6 { 7 $veri = array('demir', 'adam', 'harika'); 8 return Response::json($veri); 9 }); Bir diziyi Response::json() metoduna teslim edince o bir JSON stringine dönüştürülür ve bizim yeni Response nesnesinin gövdesi olarak ayarlanır. İlgili başlıklar, sağlanan verinin bir JSON stringi olduğunu açıklayacak şekilde ayarlanmıştır. Web tarayıcısı aşağıdaki gövdeyi alacaktır: 1 ["demir","adam","harika"] Hem özlü hem gerçek. Temiz ve fonksiyonel JSON API leri inşa etmek için bu kısayolun tadını çıkarın! İndirme Cevapları Dosyaların sunulması belirli başlıkların doğrudan ayarlanmasını gerektirir. Neyse ki Laravel Response::download() kısayolunu kullanarak bu işi sizin adınıza üstlenmektedir. Nasıl işlediğine bakalım. 3 // app/routes.php 5 Route::get('dosya/indir', function() 6 { 7 $dosya = 'dosya_yolu.pdf'; 8 return Response::download($dosya); 9 }); Şimdi eğer /dosya/indir URI sini gezinirsek, tarayıcı bir cevap göstermek yerine bir indirme başlatacaktır. Response::download() metodu, parametre olarak cevap döndüğü zaman sunulacak bir dosyanın dosya yolunu almaktadır. Özel bir HTTP durum kodu ve bir başlık dizisi yapılandırmak için opsiyonel ikinci ve üçüncü parametreler de verebilirsiniz. Örneğin:

85 Cevaplar (Responses) 70 3 // app/routes.php 5 Route::get('dosya/indir', function() 6 { 7 $dosya = 'dosya_yolu.pdf'; 8 return Response::download($dosya, 18, array('demir', 'adam')); 9 }); Burada dosyamızı 18 (Ben bir çaydanlığım) HTTP durum kodu ve demir =adam değerinde header ile birlikte sunacağız. Bu bölüm benim orijinal olarak düşündüğümden çok uzun oldu, ama uygun cevap nesneleri döndürmenin basit stringler döndürmekten çok daha değerli olacağını göreceğinizden eminim. Sonraki bölümde rota filtrelerini ele alacağız, bunlar rotalarımızı korumamıza ve onlar çalışmadan önce/çalıştıktan sonra eylemler uygulamamıza imkan verecekler.

86 Filtreler Birkaç yıl öncesinde Jesse O brien ve arkadaşlarının yerel hokey takımlarının Laravel Pandalarına karşı oynadıkları son maçlarını seyretmek için özel bir etkinlik planladıkları zamanı hatırladım. Laravel Pandalarının Londra Şövalyeleri tarafından asla yenilgiye uğratılamayacağını hepimiz biliyoruz, fakat Jesse dinlemedi. Bunun Şövalyeler için zafere doğru giden yolun başlangıcı olacağında ısrar ediyordu. Etkinliğin Londra nın merkezindeki Hoser Hut ta gerçekleştirilmesi planlanmıştı. Çok kuzey Amerika da (Maple şurubu ülkesi) doğmuş biri için dostça konuksever bir yer. Ne yazık ki, Hoser Hut sınırdan gelenlere karşı öyle konuksever olmamakla bilinen bir üne sahipti. Amerikalıların düzenli olarak Hoser Hut pencerelerinin dışına atıldığı bilinen bir gerçekti. Kötü Amerikalıları dışarda tutmak için bir çeşit kapı filtresine ihtiyacı olduğu hükmüne varması bu yüzdendi. Tabii ki, iyi ingiliz adamı Dayle Rees Hoser Hut ta her zaman iyi karşılanırdı. O her yerde iyi karşılanır. Jesse, Hoser Hut un önünde durup, gelen misafirlerin Kanada lı olup olmadığını teyit etmek için kimliklerini göstermelerini istemek üzere bir fedai tuttu. Görüyorsunuz ki, Jesse nin yaptığı bir filtre uygulamaktı. Filtrenin gereksinimlerini geçenler Laravel Pandalarının Londra Şövalyelerini mahvettiğini görmek için sıcak ve rahat Hoser Hut a giriş elde edecekti. Buna karşın bara girmeye çalışan Amerikalılar filtreyi karşılayamayacak ve kendilerine çizmenin parlak tarafı gösterilecekti. Jesse yi oyununa bırakalım ve uygulama rotalarımızı korumak için filtreleri nasıl kullanacağımızı görelim. Basit Filtreler Filtreler bir rotaya tatbik edilebilecek belirli kurallar veya eylemler kümesidir. Bunlar bir rota mantığının çalıştırılmasından önce veya sonra yapılabilirler ancak before filtrelerini daha yararlı bulacaksınız. Before filtrelerini kullanarak, eğer belirli kurallar veya kriterler karşılanmazsa, uygulamanın akışını değiştirebiliriz. Bu filtreler rotalarımızı korumanın mükemmel bir yoludur. Her zaman olduğu gibi, bir örnek bin kelime konuşmaktan iyidir. Bir filtreyi inceleyelim ancak önce başka bir şeye ihtiyacımız var. Görelim:

87 Filtreler 7 1 <!-- app/views/dogumgunu.php --> 3 <h1>mutlu yıllar!</h1> <p>mutlu yıllar Dayle, yaşa, varol!</p> Süper! Artık doğum günü kutlama görünümümüz olduğuna göre, ilk filtremizi oluşturabiliriz. İşte başlıyoruz: 3 // app/filters.php 5 Route::filter('dogumgunu', function() 6 { 7 if (date('d/m/y') == '1/1/8') { 8 return View::make('dogumgunu'); 9 } 10 }); Bu ilk filtremiz oldu. Laravel, filtrelerimiz için genel bir yer olarak app/filters.php dosyasını sağlar ancak aslında bunu istediğiniz yere koyabilirsiniz. Yeni bir filtre oluşturmak için Route::filter() metodunu kullanıyoruz. Birinci parametresi dostça bir isim olup, biraz sonra onu bir rota için filtre olarak atamak için kullanacağız. Bu örnekte ben dogumgunu filtresi adını verdim. Rotaya ikinci parametre bir geriçağrı (callback) fonksiyonudur ve örneğimizde bu bir anonim fonksiyondur (Closure). Callback filtre çalıştığı zaman çağrılan bir fonksiyondur. Bu fonksiyon tıpkı bizim rota mantığımızda kullandığımız gibi cevap tipinde bir nesne döndürürse, bu cevap döndürülecek ve rota mantığının sonucunun yerine bu sunulacaktır. Şayet filtre geriçağrı fonksiyonundan hiçbir cevap döndürülmezse, o zaman rota mantığı normal şekilde devam edecektir. Bu bize büyük bir güç verir, öyleyse ilerleyin ve kötü kahkahanızı atın. Ciddiyim, bu önemli bir iş. Muahahahah! Güzel, yapacağınız her şeyi ben söyleyeceğim. Gördüğünüz gibi ya uygulamanın akışını değiştirebiliriz veya bir eylem yapıp rota mantığının çalışmaya devam etmesine izin verebiliriz. Örneğin, biz web sitemizde belirli tipteki bir kullanıcıya sadece belirli tipte bir içerik göstermek isteyebiliriz. Bu başka bir sayfaya bir yönlendirme cevabı döndürmek yoluyla olabilir. Alternatif olarak, hangi sayfaların ziyaret edildiğini görmek için filtre her çalıştığında bir günlük tutabiliriz. Belki de kendimi öne alıyorum, örnek filtremize bir daha bakalım.

88 Filtreler 73 3 // app/filters.php 5 Route::filter('dogumgunu', function() 6 { 7 if (date('d/m') == '1/1') { 8 return View::make('dogumgunu'); 9 } 10 }); Closure fonksiyonuna yakından baktığımızda, bir şart ve bir cevabımız olduğunu görüyoruz. Filtremizde, eğer şu andaki tarih 1/1/8 e, yani evrendeki en önemli kişinin doğduğu tarihe eşitse, closure o zaman bir cevap döndürecektir. Şayet Closure den cevap dönerse mutlu yıllar görünümüne yönlendirileceğiz. Aksi takdirde rota mantığımız normal şekilde devam edecektir. Tabii bir filtrenin işe yaraması için bir rotaya bağlamamız gerekiyor. Ancak, bunu yapmadan önce rotanın yapısını biraz değiştirmemiz gerekiyor. Rotalama metodlarının ikinci parametre olarak bir closure aldığını söylediğimi hatırlıyor musunuz? Pekala, ben yine beyaz bir yalan söyledim. Kusura bakmayın. Gördüğünüz gibi, rota metodları ikinci parametre olarak bir dizi de kabul edebilmektedir. Rotaya ek parametreler atamak için bu diziyi kullanabiliriz. İkinci parametre olarak bir dizi verildiğinde bir rotanın nasıl göründüğüne bir bakalım. 3 // app/routes.php 5 Route::get('/', array(function() 6 { 7 return View::make('hello'); 8 })); Görüyorsunuz, oldukça benzer. Yaptığımız Closure ı diziye çevirmek. O aynen önceki yaptığı işi görür. Aslında, closure ı dizide tuttuğumuz sürece, başka değerler dahil edebiliriz. (Çevirenin notu: hello görünümünün Laravel ilk kurulduğunda ön tanımlı olarak açılış sayfası göstermek için oluşturulan görünüm olduğunu biliyorsunuz.) Şimdi filtreyi nasıl bağlayacağımıza geçiyoruz. before filtre seçeneğine bakarak başlayalım.

89 Filtreler 7 3 // app/routes.php 5 Route::get('/', array( 6 'before' => 'dogumgunu:1/1', 7 function() 8 { 9 return View::make('hello'); 10 } 11 )); Görebileceğiniz gibi, dizimizin içinde başka bir seçenek oluşturduk. Dizideki before anahtarı framework e rota mantığı çalıştırılmadan önce dogumgunu filtresini çalıştırmak istediğimizi söyler. dogumgunu değeri filtremize verdiğimiz takma ad ile eşleşmektedir. İlerleyelim ve / yi ziyaret ederek rotamızı çalıştıralım. Şimdi, bu günün Aralık ın 1 si olmadığını varsayarsak, bu durumda Laravel karşılama sayfasını göreceksiniz. Çünkü filtrenin şartlı mantığından kalınmış ve bir cevap döndürülmemiştir. Pekiyi, filtre şartı geçip de cevap döndürdüğü zaman ne olacağını görmek için 1 Aralık olana kadar bekleyelim. Şaka yapıyorum, en iyisi filtreyi geçmeye zorlayacak şekilde değiştirelim. Şartı, boolean değer true olarak değiştirebiliriz. 3 // app/filters.php 5 Route::filter('dogumgunu', function() 6 { 7 if (true) { 8 return View::make('dogumgunu'); 9 } 10 }); Başlayalım, bir şeylerin değişip değişmediğini görmek için / i ziyaret edelim. Yaşasın, bu benim doğum günüm! Benim için mutlu yıllar şarkısı söyleyelim. Aslında, Aralık a kadar beklemek lazım. O zaman doğumgünü filtre mantığının geçtiğini ve mutlu yıllar görünümü döndürüldüğünü görebileceğiz. Bir rota dizisinin after seçeneğini kullanarak bir filtre bağlayabiliriz, bu tür filtre rota mantığınızdan sonra çalıştırılacaktır. İşte bir örnek:

90 Filtreler 75 3 // app/routes.php 5 Route::get('/', array( 6 'after' => 'dogumgunu', 7 function() 8 { 9 return View::make('hello'); 10 } 11 )); Ancak, aklınızda tutmanız gereken bir şey var, after filtresi cevabın yerine ikame edilemez. Dolayısıyla, after kullanıldığı zaman bizim dogumgunu filtresi anlamsız olacaktır. Yine de bazı günlüğe yazma işleri veya temizleme operasyonları yapabilirsiniz. İhtiyacınız olduğunda onun orada olduğunu unutmayın yeter! Çoklu Filtreler Bilmeniz gereken başka bir şey de, bir rotaya istediğiniz sayıda filtre uygulayabileceğinizdir. Bu eylemin bir örneğini görelim. İlk olarak, çoklu before filtreleri bağlayalım: 3 // app/routes.php 5 Route::get('/', array( 6 'before' => 'dogumgunu yilbasi', 7 function() 8 { 9 return View::make('hello'); 10 } 11 )); Burada rotaya hem dogumgunu hem de yilbasi before filtreleri bağladık. Yeni yilbasi filtresinin ne yapacağının mantığını senin hayal gücüne bırakıyorum ancak marifetli bir şey yapacağından eminim. Boru karakteri bir filtre listesini ayırmakta kullanılır. Liste soldan sağa doğru çalıştırılır ve bir cevap döndüren ilk filtre, isteği sonlandıracak ve o cevap sonuç olarak sunulacaktır. İsterseniz çoklu filtre vermek yerine bir dizi de kullanabilirsiniz. Bu size belki daha phpemsi gelebilir.

91 Filtreler 76 3 // app/routes.php 5 Route::get('/', array( 6 'before' => array('dogumgunu', 'yilbasi'), 7 function() 8 { 9 return View::make('hello'); 10 } 11 )); Size hangisi uygunsa onu kullanın, ben şahsen dizileri seviyorum. İsterseniz bir before ve after filtresini aynı anda da ekleyebilirsiniz, bunun gibi: 3 // app/routes.php 5 Route::get('/', array( 6 'before' => 'dogumgunu', 7 'after' => 'yilbasi', 8 function() 9 { 10 return View::make('hello'); 11 } 1 )); Doğal olarak, ilk önce before filtresi çalışacak, sonra rota mantığı ve son olarak da after filtresi çalışacaktır. İyi, filtreler tamam mı diyorsunuz? Bırakıp gitmek yok! Filtre Parametreleri Tıpkı PHP fonksiyonları gibi, filtreler de parametre kabul edebilirler. Bu, tekrarlardan kaçınmak için harika bir yoldur ve esneklik artışı imkanı verir. Her zaman olduğu gibi, bir örnekle gidelim.

92 Filtreler 77 3 // app/filters.php 5 // before 6 7 Route::filter('test', function($route, $request) 8 { 9 10 }); 11 1 // after 13 1 Route::filter('test', function($route, $request, $response) 15 { }); Bir dakika, neden orada iki filtre var? İyi fark ettiniz! Aslında onlar aynı filtre, ama yine de sizin sorunuz geçerli. Gördüğünüz gibi Laravel before ve after filtreleri için farklı parametre setleri sunmaktadır. Her iki filtrenin de $route ve $request değişkenleri aldığını unutmayın. Aslında bunlara istediğiniz ismi verebilirsiniz ancak bu şekilde isim vermemin bir nedeni var. Eğer ilk parametreye var_dump() yaparsanız onun bir Illuminate\Routing\Route olgusu olduğunu göreceksiniz. Hatırlayacaksınız, Illuminate Laravel bileşenleri için kullanılan kod adıdır. Route sınıfı rotalama katmanı tarafından kullanılan bir rotayı temsil eder. Bu olgu, çalışmakta olan güncel rotayı temsil eder. Zekice değil mi? Route olgusu dev gibidir, bu Gallerli kurnaz adama inanmıyorsanız gidin onu var_dump() yapın. İçindeki bilgilerin ayrıntısını sorgulayabilir, hatta framework ü manipüle etmek için bazı değerleri değiştirebilirsiniz. Bununla birlikte, bu ileri bir konudur ve bu bölümün kapsamı içinde değildir, o yüzden en iyisi biz sonraki parametreye bakalım. Tahmin edebileceğiniz gibi, sonraki parametre güncel istek nesnesinin bir olgusudur. Web sunucunuza gönderilen isteğin durumunu Illuminate\Http\Request olgusu temsil eder. Bu olgu zengin ek bilgilerle birlikte URL yi ve istekle geçirilen veriyi taşır. After filtresi ek bir parametre alır, eylemi yapan rota filtresinden dönen bir cevap nesnesi olgusunu. Bu olgu güncel isteğin cevabı olarak sunulan neyse odur. Pekiyi, Laravel in bize verdiği bu parametreler frameworkun ileri kullanıcıları için yararlı olabilir ancak biz rota filtrelerimize kendi parametrelerimizi verebilsek harika olmaz mıydı? Bunu nasıl yapabileceğimizi bir görelim. İlk olarak bizim filtre Closure una yer tutucu bir değişken eklememiz gerekiyor, bu değişken Laravel in kendi sağladığından daha sonra gelmelidir, bunun gibi:

93 Filtreler 78 3 // app/filters.php 5 Route::filter('dogumgunu', function($route, $request, $tarih) 6 { 7 if (date('d/m') == $tarih) { 8 return View::make('dogumgunu'); 9 } 10 }); Bizim dogumgunu filtremiz bir $tarih parametresi kabul edecek şekilde değişmiş oldu. Eğer güncel tarih verilen tarihe uyarsa bu durumda dogumgunu filtresi çalışacaktır. Şimdi de rota filtrelerine parametrelerin nasıl verileceğini öğrenmemiz gerekiyor. Bir bakalım. 3 // app/routes.php 5 Route::get('/', array( 6 'before' => 'dogumgunu:1/1', 7 function() 8 { 9 return View::make('hello'); 10 } 11 )); Rotaya atadığımızda iki nokta üst üste : karakterinden sonra gelen parametre filtremize geçirilir. Şimdi bunu test edelim, tarihi bu günkü tarihe değiştirelim ve filtrenin ateşlendiğini izleyelim. Eğer ek parametreler vermek istersek, Closure de fazladan yer tutucu değişkenler vermemiz gerekiyor. Bu şöyle bir şey olacaktır. 3 // app/filters.php 5 Route::filter('dogumgunu', function($route, $request, $birinci, $ikinci, $ucuncu) 6 { 7 return "{$birinci} - {$ikinci} - {$ucuncu}"; 8 });

94 Filtreler 79 İstediğimiz kadar parametre alabiliriz. Birden çok parametre vermek için öncelikle filtre adı ile filtrenin parametreleri arasına iki nokta üst üste : eklemeliyiz. Parametrelerin kendileri de virgül ile, ayrılmalıdır. İşte bir örnek: 3 // app/routes.php 5 Route::get('/', array( 6 'before' => 'dogumgunu:falan,filan,gibi', 7 function() 8 { 9 return View::make('hello'); 10 } 11 )); falan, filan ve gibi değerleri filtreye eklediğimiz yer tutuculara geçirilecektir. Tıpkı fonksiyonlarda olduğu gibi filtre parametrelerine ön tanımlı değerler atayabiliriz, böylece onları opsiyonel yapmış oluruz. İşte bir örnek: 3 // app/filter.php 5 Route::filter('ornek', function($route, $request, $opsiyonel = 'Aynen!') 6 { 7 return $opsiyonel; 8 }); Opsiyonel parametreyi vermek veya vermemek. Bu size kalmış, O sizin frameworkünüz! Filtrenizi daha verimli yapmak için istediğiniz kadar parametre kullanmakta serbestsiniz. Bu harika özelliğin avantajını kullanın. Filtre Sınıfları Closure ler harika. Bunlar gerçekten kullanışlıdır ve örneklerimde iyi iş yapar. Bununla birlikte, bunlar yazdığımız mantığa sarılı kalırlar. Onları başlatamayız, bu da onların test edilmesini zorlaştırır. İşte bu sebeple, bir Closure gerektiren her Laravel özelliği bir alternatife de sahiptir. Bir PHP sınıfına. Filtrelerimizi temsil etmek üzere bir sınıfı nasıl kullanacağımızı görelim.

95 Filtreler 80 Sınıf yapmadan önce, onu koyacak bir yere ihtiyacımız var. Şimdi /app klasöründe filters denen yeni bir klasör oluşturalım ve bu yeni klasörü de içermesi için composer.json classmap ımızı güncelleyelim. 1 "autoload": { "classmap": [ 3 "app/commands", "app/controllers", 5 "app/models", 6 "app/filters", 7 "app/database/migrations", 8 "app/database/seeds", 9 "app/tests/testcase.php" 10 ] 11 } Şimdi bizim dogumgunu filtremiz için yeni bir sınıf oluşturalım. İşte yapıyoruz: 3 // app/filters/dogumgunu.php 5 class DogumgunuFilter 6 { 7 public function filter($route, $request, $tarih) 8 { 9 if (date('d/m') == $tarih) { 10 return View::make('dogumgunu'); 11 } 1 } 13 } Ben bu sınıfa DogumgunuFilter adını verdim, siz Filter son ekini kullanmak zorunda değilsiniz, fakat ben böyle yapmayı seviyorum, gerisi size kalmış. Fakat zorunda olduğunuz bir şey var, filter() metodu. Bu metod tıpkı bir Closure gibi çalışır. Aslında, tıpkı Closure gibi çalıştığı için onu tekrar açıklamaya gerek yok. Öyle yapmak yerine bir filtrenin bir rotaya nasıl takılacağını görebiliriz. Öncelikle bir filtre takma adı oluşturmamız gerekiyor, Bir kez daha biz Route::filter() metodunu kullanacağız. Bununla birlikte, bu sefer ikinci parametre olarak bir closure yerine bir string geçeceğiz. Bunun gibi:

96 Filtreler 81 3 // app/routes.php 5 Route::filter('dogumgunu', 'DogumgunuFilter'); Bu metodun ikinci parametresi kullanacağımız filtre sınıfını tanımlayan bir stringtir. Eğer filtre sınıfı bir aduzayı içinde ise, o zaman aduzayını da vermemiz gerekiyor. Artık filtre takma adı oluşturduğumuza göre, rotaya bunu aynen daha önce yaptığımız gibi ekleyebiliriz. 3 // app/routes.php 5 Route::get('/', array( 6 'before' => 'dogumgunu', 7 function() 8 { 9 return View::make('hello'); 10 } 11 )); Tabii ki, Composer ve Laravel in bizim filtre sınıfımızı bulabilmeleri için öncelikle composer dump-autoload komutunu çalıştırmamız gerektiğini unutmayın. Eğer kodunuzu tam olarak test etmek amacındaysanız, işiniz için en iyisi filtreleri sınıf olarak yazmaktır. İlerideki bir bölümde test konusunu daha ayrıntılı göreceğiz. Evrensel Filtreler Eğer /app/filters.php dosyasının içine bakarsanız garip görünen iki filtre göreceksiniz. Bunlar evrensel filtrelerdir ve uygulamanıza yapılan her istekten önce ve sonra çalışırlar.

97 Filtreler 8 3 // app/filters.php 5 App::before(function($request) 6 { 7 // 8 }); App::after(function($request, $response) 1 { 13 // 1 }); Bunlar ön tanımlı olarak tüm rotalara uygulanmaları dışında tam olarak normal filtreler gibi çalışırlar. Yani bizim rotalarımızın before ve after dizi indekslerine bunları eklememize gerek yoktur. Default Filtreler app/filters.phpde sizin için zaten oluşturulmuş bazı filtreler vardır. Bunlardan ilk üçüne bakalım. 3 // app/filters.php 5 Route::filter('auth', function() 6 { 7 if (Auth::guest()) return Redirect::guest('login'); 8 }); Route::filter('auth.basic', function() 1 { 13 return Auth::basic(); 1 }); Route::filter('guest', function() 17 { 18 if (Auth::check()) return Redirect::to('/'); 19 });

98 Filtreler 83 Bu filtrelerin hepsi de Laravel in kimlik doğrulama katmanı ile ilgilidir. Bunlar web uygulamamıza o anda giriş yapmış veya yapmamış kullanıcılara rota erişimini kısıtlamak için kullanılabilir. Sonraki bölümlerin birinde kimlik doğrulama katmanına daha yakından bakacağız ve bu filtrelerin içeriği daha anlaşılır olacaktır. Şimdilik, bunların sizi orada beklediğini bilmeniz yeterli! Dördüncü filtre siteler arası istek sahtekarlığı filtresidir ve şöyle görünmektedir: 3 // app/filters.php 5 Route::filter('csrf', function() 6 { 7 if (Session::token()!= Input::get('_token')) 8 { 9 throw new Illuminate\Session\TokenMismatchException; 10 } 11 }); Rotalarınızı sizin uygulamanızdan başka bir kaynaktan post edilen isteklerden korumak için bu filtreyi ilgili rotalarınıza bağlayabilirsiniz. Bu çok yararlı bir güvenlik önlemi olup, esas olarak formlar veya veri gönderimi rotalarını korumak için kullanılmaktadır. Laravel in sağladığı filtrelerin avantajını kullanmaktan çekinmeyin, onlar size zaman kazandırmak için oradalar. Desen Filtreleri Filtreyi tüm rotalarınıza elle bağlamak istemezsiniz değil mi? Hayır sizi suçlamıyorum. Parmaklar yorulur, bir kitap yazdığım için bunu biliyorum. Zavallı küçük parmaklarınızı korumanın bir yolunu bulmaya çalışayım. Burada bir desen filtresi var. Desen filtreleri jokerli bir rota deseni vererek bir before filtresini çok sayıda rotaya eşlemenize imkan verecektir. Bunu eylemde görelim. 3 // app/routes.php 5 Route::when('profile/*', 'dogumgunu'); Yukarıdaki Route::when() metodu, profile/ ile başlayan tüm rota URI lerinde dogumgunu filtresini çalıştıracaktır. İlk parametredeki yıldız bir joker olarak davranacaktır. Bu, bir before filtresini çok sayıda farklı rotaya bir seferde bağlamak için harika bir yoldur.

99 Denetçiler (Controllers) Denetçilerin Oluşturulması Basit rotalama bölümünde rotaların uygulamamızın yapısını oluşturan, küçük mantık ceplerinin, closure lara nasıl bağlandığını öğrenmiştik. Closure lar bir uygulama yazmanın hoş ve hızlı bir yoludur ve şahsen ben bu kitabın kod örnekleri içinde harika göründüklerine inanıyorum. Ancak, uygulama mantığını barındırmak için tercih edilen yol Controller dir. Controller, rotalama mantığı için kullanılan bir sınıftır. Normalde, bir Denetçi sınıfı eylem (action) olarak bilinen çok sayıda publik metod içerecektir. Eylemleri önceki bölümde kullanmış olduğumuz closure in direkt alternatifi olarak düşünebilirsiniz, bunlar hem görünüm olarak hem de işlevsel olarak çok benzerdir. Bir örnek göstermeden bir şey açıklamayı sevmiyorum. O yüzden gidip bir denetçiye bakalım. İşte benim daha önce yaptıklarımdan birisi! Cue Blue Peter teması. Gerçekte bu son referans sadece İngiliz halkı için mantıklı olabilir. Boşverin, yaptım artık ve onu silecek cesaretim yok! Peki, denetçiler 3 // app/controllers/makalecontroller.php 5 class MakaleController extends BaseController 6 { 7 public function tumgoster() 8 { 9 return View::make('liste'); 10 } 11 1 public function tekgoster($makaleid) 13 { 1 return View::make('tek'); 15 } 16 } İşte bizim denetçimiz! Güzel ve basit. Bu örnek bir blog veya diğer bazı CMS biçimleri için uygun olacaktır. İdeal olarak, bir blog tüm makalelerin bir listesini gösterecek bir sayfaya ve ayrıntılı olarak tek bir makaleyi gösterecek başka bir sayfaya sahip olacaktır. Bu aktivitelerin her ikisi de Makale

100 Denetçiler (Controllers) 85 kavramıyla ilgilidir, dolayısıyla bu mantığı bir arada gruplayabiliriz. Bu nedenle mantık tek bir MakaleController içine alınmıştır. Açıkçası, Denetçiye istediğiniz ismi verebilirsiniz. Sizin denetçiniz BaseController veya Controller den birisini genişlettiği sürece Laravel ne yapıyor olduğunuzu bilecektir. Yine de, bir denetçi ismine Controller son eki vermek, örneğin MakaleController demek web geliştiricilerinin kullandığı bir standarttır. Eğer başkalarıyla çalışmayı planlıyorsanız, bu durumda standartlar son derece yararlıdır. Denetçimiz, Laravel in bizim için oluşturmuş olduğu app/controllers dizininde oluşturulmuştur. Bu dizin, ön tanımlı olarak bizim composer.json dan yüklenen bir classmap dosyası oluyor. Şayet app/controllers sizin iş akışınıza uygun değilse, o zaman bu dosyayı istediğiniz yere koyabilirsiniz. Ancak, sınıfın Composer tarafından otomatik yüklenecek olmasını temin etmelisiniz. Bu konuda daha ayrıntılı bilgi için lütfen Ön Bilgiler bölümündeki Composer kesimine başvurunuz. Denetçimizin sınıf metodları gerçekte mantığımızı içeren şeylerdir. Tekrar ifade ediyorum, bunlara istediğiniz ismi verebilirsiniz ama ben şahsen eğer sonuç bir web sayfası göstermek olacaksa bir ön ek olarak show kullanmayı seviyorum. (Çeviri notu: Kitabın Türkçe çevirisinde ise dile daha uygun olması açısından son ek olarak goster kullanmayı tercih ettim) Bu metodlar Laravel in bunlara rotalama yapabilmesi için public olmalıdır. Soyutlamak için sınıfa private metodlar ekleyebilirsiniz ancak bunlar rotalanamaz. Aslında bu tür kodların konacağı daha iyi bir yer vardır, bunu modeller bölümünde öğreneceğiz. Birinci eylemimize yakından bakalım, bir blog makale listesini göstermek için kullanılacaktır. 1 public function tumgoster() { 3 return View::make('liste'); } Evet, ne kadar da tanıdık geliyor değil mi? Aynı etkiyi elde etmek için kullanabileceğimiz bir rota closure u ile karşılaştıralım. 1 Route::get('liste', function() { 3 return View::make('liste'); }); Görebileceğiniz gibi iç fonksiyon neredeyse aynı. Tek fark denetçi eyleminin bir adı vardır, closure ise anonimdir. Gerçekten de, denetçi eyleminde Closure de olabilecek her kod bulunabilir. Yani öğrendiğimiz her şey burada bile uygulanabilir durumdadır. Yazık, farklı olmuş olsaydı denetçiler üzerine başka bir kitap satabilirdim! Yine de, iki kod parçacığı arasında bir diğer fark var. Basit Rotalama bölümünde bir URI nin bir Closure içinde yer alan mantık parçasına nasıl rotalanacağını öğrenmiştik. Yukarıdaki rotalı closure örneğinde /liste URI si bizim uygulama mantığımıza yönlendirilecektir. Ancak bizim

101 Denetçiler (Controllers) 86 Denetçi eylemimizde bir URI den hiç bahsedilmemiş. Laravel onun rotasını bizim kontrollere yönlendireceğini nereden biliyor? Haydi denetçi rotalamasına bir göz atalım, umarım sorumuza bir cevap bulabiliriz. Controller Rotaları Controller lar derli topludur ve ortak mantıkları birlikte gruplamak için temiz bir yol sağlar. Ancak, kullanıcılarımız ilgili mantığa gerçekten ulaşamadığı sürece işe yarayamazlar. Neyse ki, bir URI yi bir denetçiye bağlama metodu da Closure ler için kullandıklarımıza benzerdir. Yakından bakalım. 3 // app/routes.php 5 Route::get('liste', 'MakaleController@tumGoster'); Bir URI yi bir denetçiye bağlayabilmek için /app/routes.php dosyasında yeni bir rota tanımlamalıyız. Closure rotalamasında kullandığımız aynı Route::get() metodunu kullanıyoruz. Ancak ikinci parametre tamamen farklıdır. Bu sefer bir string var. Bu string bir -de işareti (@) ile ayrılmış iki kesimden oluşuyor. Son kesimde oluşturduğumuz Denetçiye bir daha bakalım. 3 // app/controllers/makalecontroller.php 5 class MakaleController extends BaseController 6 { 7 public function tumgoster() 8 { 9 return View::make('liste'); 10 } 11 1 public function tekgoster($makaleid) 13 { 1 return View::make('tek'); 15 } 16 } Örnekte görüyoruz ki sınıf adımız MakaleControllerdır ve kendisine yönlendirmek istediğimiz eyleme tumgoster adını vermişiz. Aralarında bir -de işareti (@) olacak şekilde ikisini bir araya getirelim.

102 Denetçiler (Controllers) 87 1 MakaleController@tumGoster Bu kadar basit işte. Artık temel rota bölümünde keşfettiğimiz metodların hepsini kullanabiliriz ve onlara denetçileri gösterebiliriz. Örneğin bir POST HTTP istek fiiline cevap verecek bir denetçi şöyle olacaktır. 3 // app/routes.php 5 Route::post('makale/yeni', 'MakaleController@yeniMakale'); Siz oldukça akıllı dostlarsınız, bu kitabı satın almıştınız değil mi? İşte şimdi görüyorsunuz ki, yukarıdaki rota /makale/yeni URI sine yapılan POST isteklerine cevap verecektir ve MakaleController deki yenimakale() tarafından işlenecektir. Bilmeniz gereken zarif bir şey: Denetçiniz aduzayı olabilir ve Laravel gözünü kırpmaz. Önemli olan rota deklarasyonunuza aduzayını dahil ediniz, her şey mükemmel olacak! Bakın nasıl olduğunu göstereyim. 3 // app/controllers/makale.php 5 namespace Blog\Controller; 6 7 use View; 8 use BaseController; 9 10 class Makale extends BaseController 11 { 1 public function tumgoster() 13 { 1 return View::make('liste'); 15 } 16 } Burada diğer örnekte kullanılana benzer bir Controller var. Ancak bu sefer Blog\Controller aduzayı içinde yer alıyor. Onun konumu aduzayının Controller kesimi içinde olduğu için ben sınıf adına Controller son eki eklemedim. Bu benim kendi kişisel tercihim, bu eki koyup koymama kararını size bırakıyorum. Şimdi bu aduzaylı denetçiyi nasıl rotalayabileceğimizi görelim. Büyük ihtimalle zaten tahmin etmişsinizdir!

103 Denetçiler (Controllers) 88 3 // app/routes.php 5 Route::post('liste', 'Blog\Controller\Makale@tumGoster'); Tıpkı önceki gibi, sadece bu sefer denetçinin adının önüne onun aduzayı eklenmiştir. Bakın, aduzayının bir şeyleri karmaşıklaştırması gerekmiyor! Aduzaylı denetçinizi iç içe bir dizinde hatta bir PSR-0 yükleme şemasında başka bir yerde bile saklayabilirsiniz. Composer sizin sınıfınızı nerede bulacağını bildiği sürece Laravel bunu sorun yapmaz, onu kullanabilecektir. RESTful Denetçiler Laravel çözümler sunar, çoğunu biliyoruz. Seçenekler de verir, RESTful denetçileri bunun en önemli örneğidir. Rota metodlarını kullanarak eşleştirmek istediğimiz HTTP istek fiillerini tanımlayabildiğimizi biliyoruz, Closure lara rotalama yapıldığında bu gerçekten işimizi kolaylaştırıyor. Bununla birlikte, denetçilere rotalama yaptığınız zaman istek fiilinin tanımını uygulamanız mantığında tutmak isteyebilirsiniz. İyi bir haberim var, Laravel bu alternatif yapılandırmayı sağlamaktadır. Denetçimizde küçük bir değişiklik yapmaya ne dersiniz? 3 // app/controllers/makale.php 5 namespace Blog\Controller; 6 7 use View; 8 use BaseController; 9 10 class Makale extends BaseController 11 { 1 public function getform() 13 { 1 return View::make('form'); 15 } public function postform() 18 { 19 // Formu işleyen kod. 0 } 1 }

104 Denetçiler (Controllers) 89 Bir kere daha Makale denetçimiz var. Eylemlerin amacı yeni bir blog makalesi oluşturmak için bir form sağlamak ve yeni bir blog makalesi oluşturulmasını işlemektir. Eylemlerin adlarının başına get ve post getirilmiş olduğunu fark edeceksiniz. Bunlar bizim HTTP istek fiillerimizdir. Yani, yukarıdaki örnekte son noktaları aşağıdaki URL ler için ifade ettiğimizi düşünebilirsiniz: 1 GET /form POST /form RESTful denetçimize nasıl rotalama yapacağımızı da merak ediyor olabilirsiniz. Gördüğünüz gibi, burada Route sınıfında fiil metodlarını kullanmak pek mantıklı olmayacaktır. O zaman, bireysel eylemlere rota yapmaya elveda diyelim ve başka bir rotalama metoduna göz atalım. 3 // app/routes.php 5 Route::controller('makale', 'Blog\Controller\Makale'); Bu tek metod bizim RESTful denetçimizde sunulan tüm eylemleri rotalayacaktır. Metodun yazılışına yakından bakalım. İlk parametre taban URL dir. Normalde RESTful rotalama bir nesne sunmak için kullanılır, bu yüzden çoğu durumda taban URL o nesnenin adı olacaktır. Bunu, RESTful denetçimizin içinde oluşturduğumuz eylemlere bir ön ekmiş gibi düşünebilirsiniz. İkinci parametre zaten bildiğiniz bir şey. Kendisine rotalamak istediğimiz denetçidir. Tekrar ediyorum, Laravel aduzaylı bir denetçiyi bir rota hedefi olarak mutlulukla kabul edecektir, dolayısıyla denetçilerinizi kendi ihtiyaçlarınıza uyacak şekilde organize etmekte özgürsünüz. Görmüş olduğunuz gibi, denetçilerinize rotalama yapmak için bu metodun kullanılması orijinal rotalama yöntemlerine göre ayrı bir avantaj sağlar. Bu metod sayesinde, her eyleme bağımsız rotalama yapmak zorunda kalmak yerine bir denetçi için sadece tek bir rotalama girişi sağlayabileceğiz.

105 Blade Bu bölümde Kılıç Ustası (Blade) olmayı öğreneceğiz. Buna ihtiyacınız olacak. Bir PHP ustası olarak hak ettiğiniz yeri alabilmeniz için silahlı mücadelede Ulu Lord Otwell e maydan okumanız ve onu yenilgiye uğratmanız gerekiyor. Geçiş adetimiz böyledir. Ancak ondan sonra Laravel konseyi arasında hak ettiğiniz yeri alabilecek ve Phil Sturgeon ın masasında bir yer kazanabileceksiniz. Ayda bir kez de, Laravel in tepesindeki, pandalara binmiş korkunç konsey üyeleri diğer framework geliştiricileri ile savaşmak için PHP savaş alanına geçerler. Bizim yanımızda mücadeleye katılmak ve Laravel şerefine kavgaya tutuşmak isterseniz Kılıç kullanmayı öğrenmek zorundasınız. Evet, zorundasınız güçlü bir kelimedir. Demek istiyorum ki, aynı zamanda Blade şablonu ustası da olabilirsiniz. Abartıldığı kadar değildir ve kızgın pandalara binmek de yok. Buna rağmen oldukça kullanışlıdır ve belki de kodlayıcılar için sert mücadelelerden daha uygundur? Evet, tamamsa Blade şablonlarına bir göz atalım. Bu Blade (Kılıç/Bıçak) adının da nereden geldiğini merak edebilirsiniz? Bu bölümü yazmaya başladığımda Taylor a sormaya karar vermiştim. Dönen cevapta,.net web geliştirme platformunda Blade söz diziminin türetilmiş olduğu Ustura ( Razor ) adında bir şablonlama aracı olduğunu söyledi. Ustura bıçak tıraş bıçağı. Hepsi bu. Komik bir şey yok, özgünüm. :( Aslında, az önce söylediklerimi unutun. Öyküyü yeniden keşfedelim. Sadece bizim aramızda. Şablonlama dilinin adı Vampir avlama günlerinde Taylor Blade ile kendine güvenini değiştirmesinden geliyor. Gerçek öykü bu. Peki, şimdi bir şablon yapalım. Şablonların Oluşturulması Biliyorum, biliyorum, ben zaten görünüm oluşturmayı size öğrettim değil mi? Görünümler uygulamanızın görsel tarafını mantık tarafından ayırmakta gerçekten yararlıdır ancak bu onlar üzerine geliştirme yapılamaz anlamına gelmez. Standart PHP şablonlarıyla yaşadığımız problem, mantık kısımlarının sağladığı verileri kullanmak için onların içine çirkin php tagları eklemek zorunda olmamızdır. Bizim düzgün HTML şablonları içinde yersiz görünürler. Onları kirletir! Bu beni öyle kızdırıyor ki Ben Ben şimdi. Hayır, bir an için sakin olun. Erm

106 Blade 91 Tamam, öfkem dindi şimdi. Bu kötü PHP pisliğini yolumuzdan kaldırmak için bir Blade şablonu oluşturalım. Başlamak için yeni bir dosya oluşturmamız gerekiyor. Blade şablonları standart view dosyaları ile aynı konumda dururlar. Tek farklılık sadece.php yerine.blade.php uzantısını kullanmalarıdır. Şimdi basit bir şablon oluşturalım. 1 <!-- app/views/ornek.blade.php --> 3 <h1>değerli Lord Otwell</h1> <p>laravel'in onuru için seni bir düelloya davet ediyorum.</p> 5 6 <?php echo $sincap;?> Burada blade şablonumuz oldu ve daha önce gördüklerimize benziyor. Bunun nedeni Blade in dosyayı ilk önce PHP olarak parse etmesindendir. Bizim $sincap ı görüyor musunuz? Her view dosyasında bir sincap olmak zorundadır. Tamam, bu doğru değil, önce PHP parse edebileceğini göstermek için koydum. Biz bunu, normal bir view kullanımıyla aynı sözdizimi kullanarak gösterebiliriz. Bunun View::make() metoduna ornek.blade geçirilmesini gerektirdiğini düşünebilirsin, ama bu doğru olmayacaktır. 3 // app/routes.php 5 Route::get('ornek', function() 6 { 7 return View::make('ornek'); 8 }); Gördünüz mü? Laravel neyin bir Blade şablonu olduğunu bilir ve ona göre bakar. Bu sebeple, View::make() cümlesi hiç değişmemiştir. Ne kolaylık ama! Blade kullanımıyla ilgili bazı numaralar var. İlkini görelim mi? PHP Çıktısı Şablonlarınızın birçoğu uygulamanızın mantık kısmı tarafından sağlanan veriyi çıktılama (echo yaptırma) işlerini içerir. Normalde buna benzer bir şeyler görünür:

107 Blade 9 1 <!-- app/views/ornek.blade.php --> 3 <p><?php echo $vampiravcisitaylor;?></p> Tam ayrıntılı değil ama geliştirilebilir. Şimdi de Blade şablon kullanarak değerleri nasıl echo yaptıracağımızı görelim. 1 <!-- app/views/ornek.blade.php --> 3 <p>{{ $vampiravcisitaylor }}</p> Şablon işlendiği zaman {{ çifte küme parantezleri }} ile sarmalanmış her şey Blade tarafından bir echo ya dönüştürülür. Bu çok daha temiz bir sözdizimidir ve yazması da çok kolaydır. Blade şablon direktifleri doğrudan PHP ye çevrildiği için, bu parantezler içerisinde metodlar da dahil, her türlü PHP kodunu kullanabiliriz. 1 <!-- app/views/ornek.blade.php --> 3 <p>{{ date('d/m/y') }}</p> Kapatmak için noktalı virgül kullanmanıza da gerek yok, sizin yerinize bunu Laraval yapar. Bazen çıktınızdaki bir değeri escape ederek kendinizi korumak isteyebilirsiniz. Bu amaçla strip_- tags() ve htmlentities() gibi metodları kullanmayı biliyor olabilirsiniz. Niçin? Bu şablonun çıktısını ele alalım o zaman. 1 <!-- app/views/ornek.blade.php --> 3 <p>{{ '<script>alert( BİR KANGAL SUCUK! );</script>' }}</p> Çok kötü bir kod parçası! Bu, sayfamızın içine JavaScript kodları enjekte edilmesine sebep olacak ve BİR KANGAL SUCUK! metnini içeren bir tarayıcı popup ı gösterilecek. Neresi kötü ki! Pis ruby geliştiricileri daima websitelerimizi kırmaya çalışırlar. Şablonlarımızı çıktılardan koruyacak güce sahibiz. Eğer {{ iki }} yerine {{{ üç küme parantezi }}} kullanırsak bu durumda çıktımız escape edilecek, açılı parantezler (yani, < ve >) HTML antitelerine dönüştürülecek ve JavaScript sayfa içerisinde metin olarak gösterilecektir. Zararsız! Bunu eylemde görelim.

108 Blade 93 1 <!-- app/views/ornek.blade.php --> 3 <p>{{{ '<script>alert("bir KANGAL SUCUK!");</script>' }}}</p> Bu pis Javascript kodunun etrafındaki parantezlerin sayısını değiştirdik. Nasıl göründüğünü görmek için tarayıcıda sayfa kaynağına bakalım. 1 <!-- app/views/ornek.blade.php --> 3 <p><script>alert("bir KANGAL SUCUK!");</script></p> Gördüğünüz gibi, HTML tagları ve diğer bazı karakterler karşılıkları olan HTML antiteleri ile değiştirilmişlerdir. Sayfamız kurtuldu! Devam ediyoruz! Kontrol Yapıları PHP de çok sayıda kontrol yapısı vardır. If cümleleri, while, for ve foreach döngüleri. Bunları daha önce duymamışsanız, bu kitap gerçekten size göre değildir! Şablonlar içerisinde kontrol yapıları için iki nokta üst üste : kullanılan alternatif sözdizimi kullanımı size tanıdık gelecektir. if cümleleri böyle görünecektir: 1 <!-- app/views/ornek.blade.php --> 3 <? if ($birsey) :?> <p>bir şey doğrudur!</p> 5 <? else :?> 6 <p>bir şey yanlıştır!</p> 7 <? endif;?> Bu işe yarayacaktır ancak bunları yazmak çok eğlenceli değil. Bu sizi yavaşlatacaktır, neyse ki Blade sizi kurtarmaya gelecektir! Bir Blade şablonu içerisinde yukarıdaki kod parçası şöyle yazılır.

109 Blade 9 1 <!-- app/views/ornek.blade.php --> ($birsey) <p>bir şey doğrudur!</p> 6 <p>bir şey yanlıştır!</p> Bu daha temiz, değil mi? Neleri çıkarıp attığımıza bir göz atalım. En başta PHP açılma <? ve kapanma?> tagları gitmiş. Büyük ihtimalle yazması en karmaşık olanlar bunlardı. Ayrıca iki nokta üst üste : ve noktalı virgülü ; de çıkarabiliyoruz. Şablonlarımızda zaman kaybetmek zorunda değiliz! Son olarak, her zamanki sözdizimine bir ilave yapmışız. Kontrol cümlelerimizin olduğu satırların başına bir sembolu getiriyoruz. Aslında tüm blade kontrol yapıları ve helper metodları başına bu işaret getirilir, böylece şablon derleyicisi bunları nasıl işleyeceğini bilir. Daha ileri bir örnek için karışıma bir elseif ekleyelim. 1 <!-- app/views/ornek.blade.php --> ($birsey == 'Kırmızı Panda') <p>bir şey kırmızı, beyaz ve kahverengidir!</p> ($birsey == 'Dev Panda') 6 <p>bir şey siyah ve beyazdır!</p> 8 <p>bir şey bir sincap olabilir.</p> Karışıma başka bir cümle ekledik, bunu yaparken aynı şekilde PHP tagları, iki nokta üst üste ve noktalı virgülleri çıkardık ve işareti koyduk. Her şey mükemmel çalıştı. İşte bir meydan okuma. Blade sözdizimiyle temsil edilen bir foreach PHP döngüsünü hayal etmeye çalışın. Gözlerini kapat ve resmini hayal et. Odaklan odaklan! Buna benzedi mi?

110 Blade 95 1 <!-- app/views/ornek.blade.php --> 3 c~~p, ,---'oo ) \ 5 ( O O )/ 6 `=^=' / 7 \,. / 8 \\ -----' / 9 _ Hayır? İyi, çünkü bu bir su aygırı. Ancak, eğer biraz aşağıdaki kod parçasına benziyorsa bir kurabiye alabilirsin. 1 <!-- app/views/ornek.blade.php --> ($bircoksey as $sey) <p>{{ $sey }}</p> Kurabiyenin tadını çıkar! Görebileceğin gibi döngü değerini çıktılamak için Blade {{ echo }} sözdizimini kullandık. Bir for döngüsü tam düşündüğün gibi gözükür. Referans olması bakımından bir örnek vereyim. 1 <!-- app/views/ornek.blade.php --> ($i = 0; $i < 999; $i++) <p>{{ $i }} kırmızı panda bile yeterli değildir!</p> Basit ve tam olarak ne bekliyorsak o. While döngüsü de aynı kuralı izler ancak yararlı bir referans bölümü olmasını sağlamak için küçük bir örnek göstermek istiyorum. 1 <!-- app/views/ornek.blade.php --> (Guzelmi($keiraKnightly)) <p>büyük ihtimalle bu döngü asla bitmeyecek.</p> Tamam, artık koşullu durum ustasısınız. Kimse sizi aşamalardan geçiremez, değil mi dostum? PHP nin unless koşulu bile. Yanılıyor muyum Dayle, o Ruby de vardı. PHP de var mıydı bilmi.. Tamam, yakaladınız. PHP de unless diye bir koşul durumu yok. Ancak, Blade ona imkan veren bir helper sağlar. Haydi örneğimize bakalım.

111 Blade 96 1 <!-- app/views/ornek.blade.php --> (dunyasonaeriyor()) <p>hep gülümse.</p> Unless bir if cümlesinin tam karşıtıdır. Bir if cümlesi bir koşulun true bir değere eşit olup olmadığını yoklar ve ondan sonra bir mantığı çalıştırır. Buna karşın unless cümlesi, sadece koşul false e eşitse çalışacaktır. Bunu kötümserler için bir kontrol yapısı olarak düşünebilirsiniz. Şablonlar Blade, şablonlarınızı daha kolay oluşturmanız ve yönetmeniz için diğer bazı helper metodlar içermektedir. Ancak, bunlar görünümlerinizi sizin için yazmayacaklardır, belki de bunu Laravel 5 in görev listesine ekleyebiliriz? php artisan project:tamamla Görünüm kompozitörleri saç stillerini oluşturabilsin. Görünümler kendi kendine yazılabilsin. Artık başlıyoruz. Bu özellikler konana kadar biz kendi şablonlarımızı kendimiz yazmak zorundayız. Bu her şeyi bir dosyaya koymak zorundayız anlamına gelmez tabii ki. PHP de, güncel dosyanın içine bir dosya include() edebiliyor ve içeriğini çalıştırabiliyoruz. Organizasyon amaçlarıyla görünümlerimizi de bu şekilde ayrı dosyalar haline ayırabiliriz. Laravel bu amacı elde etmemize yardım Blade helper metodu sağlamaktadır. Bu metod sayesinde bir görünüm başka bir görünüme ithal edilip, içeriği bir Blade şablonu olarak parse edilir. Bunun nasıl gerçekleştiğini bir örnek üzerinde görelim. Sayfamızın ve belki de başka sayfaların başlığını taşıyan header.blade.php dosyası burası. 1 <!-- app/views/header.blade.php --> 3 <h1>atlar ne zaman sucuk oluyor?</h1> Bu da ilişkili footer şablonu. 1 <!-- app/views/footer.blade.php --> 3 <small>verilen bilgiler 3 Mayıs 013 tarihli araştırmalara dayalıdır.</small> Asıl şablonumuz ise şu. Bizim rota Closure umuz veya Controller eylemimiz tarafından gösterilecek olan şablon.

112 Blade 97 1 <!-- app/views/ornek.blade.php --> 3 <!doctype html> <html lang ="en"> 5 <head> 6 <meta charset ="UTF-8"> 7 <title>atlar</title> 8 </head> 9 <body> 11 <p>bu gece yarısından sonra efendim!</p> 13 </body> 1 </html> Görebileceğiniz gibi, ornek.blade.php şablonu içindeki helper helperini kullanarak header ve footer şablonlarımızı çekiyor. Bu helper fonksiyonu, daha önce kullandığımız View::make() metodundaki kısa formatla aynı şekilde bir görünümün adını parametre olarak alır. Oluşan belgeye bir göz atalım. 1 <!doctype html> <html lang ="en"> 3 <head> <meta charset ="UTF-8"> 5 <title>atlar</title> 6 </head> 7 <body> 8 <h1>atlar ne zaman sucuk oluyor?</h1> 9 <p>bu gece yarısından sonra efendim!</p> 10 <small>verilen bilgiler 3 Mayıs 013 tarihli araştırmalara dayalıdır.</small> 11 </body> 1 </html> Dahil ettiğimiz şablonlar güzel, sayfaya dahil edilmiştir. Bu bizim header ve footer şablonlarımızı tekrarlı kullanılabilir ve KTE (Kendinizi Tekrar Etmeyin) yapar. Tekrar edilecek içerikten tasarruf etmek ve içeriğini tek bir yerden düzenlenebilir hale getirmek için diğer sayfalara include edebiliyoruz. Bunu yapmanın daha da iyi bir yolu var, bu yüzden, okumaya devam edin! Şablon Kalıtımı Laravel Blade, kalıtımdan yararlanabilen şablonlar oluşturmak için bir yol sağlar. Birçok insan bunu kafa karıştırıcı buluyor ancak aslında çok düzgün bir özelliktir. Yapabileceğim en iyi şekilde

113 Blade 98 basitleştirmeye çalışacağım ve umuyorum ki, şablon oluşturma sanatının keyifli bir deneyim olduğunu göreceksiniz. Herşeyden önce şablonlar hakkında düşünelim. Bir web sayfasının gerçekte her sayfada değişmeyen bazı kısımları vardır. Bunlar göreceğimiz herhangi bir web sayfası için bulunması gereken taglardır. İsterseniz buna demişbaş ya da klişe kodumuz diyelim. İşte bir örnek: 1 <!doctype html> <html lang ="en"> 3 <head> <meta charset ="UTF-8"> 5 <title></title> 6 </head> 7 <body> 8 </body> 9 </html> Tüm sayfalarımız için bu düzeni kullanmak istiyoruz. Neden Laravel e söylemiyoruz? Bunun bir Blade düzeni olduğunu söyleyelim. Bunun için yapmamız gereken tek şey içerik ekleyeceğimiz bazı yerleri tanımlamaktır. Laravel de bu bölgelere sections (kesimler) diyoruz. Bunları şöyle tanımlıyoruz: 1 <!-- app/views/layouts/base.blade.php --> 3 <!doctype html> <html lang ="en"> 5 <head> 6 <meta charset ="UTF-8"> 7 <title></title> 9 <link rel ="stylesheet" href ="style.css" /> 11 </head> 1 <body> 1 </body> 15 </html> Şimdi iki kesimi olan bir şablonumuz var. Önce body içindekine, yani en kolay olanına bakalım. Şöyle görünüyor:

114 Blade 99 Bu cümle Blade e burada içini sonradan doldurabileceğimiz bir kesim oluşturmasını söyler. İlerde onu tekrar ifade edebilmek için, biz ona body takma adını veriyoruz. Diğer kesim ise buna benziyor: <link rel="stylesheet" href="style.css" /> Bu yield kesimine çok benzer ancak bazı varsayılan içerikleri sağlayabiliyorsunuz. Yukarıdaki tagları arasındaki içerik, bir çocuk şablonu onu değiştirmeyi seçmediği takdirde gösterilecektir. Pekiyi bir çocuk şablondan ne anlıyoruz? Tamam, her zamanki gibi hemen bir örnek verelim. 1 <!-- app/views/home.blade.php --> 6 <h1>yaşasın!</h1> 7 <p>bir şablonumuz var!</p> Peki, ilerleyelim lütfen. İlk olarak extends blade fonksiyonu var: Bu Blade e içeriğimizi göstertmek için hangi düzeni kullanacağımızı söyler. Bu fonksiyona geçilecek isim View::make()e geçtiğiniz gibi görünmelidir, dolayısıyla bu örnekte app/views içindeki layouts dizinindeki base.blade.php dosyasını ifade etmiş oluyoruz. Görünümlerle iş yaparken nokta (.) karakterinin bir dizin ayıracını temsil ettiğini hatırlayınız. Laravel 3 te bu denirdi, fakat Symfony nin twig i gibi diğer şablon motorlarıyla daha uyumlu hale getirmek için olarak değiştirildi. Laravel 3 geliştiricilerinin dikkatine! Kullanacağımız düzeni artık biliyoruz, boşluklarını doldurmanın zamanı geldi. Ebeveyn şablon içindeki kesimlere içerik enjekte etmek blade fonksiyonunu kullanabiliriz. Buna benzer:

115 Blade 100 <h1>yaşasın!</h1> 3 <p>bir fonksiyonuna parametre olarak, ebeveyn şablondaki kesime verdiğimiz takma adı geçeriz. Hatırladınız mı? Ona body adını arasında yer alan her şey ebeveyn body ) kısmına enjekte edilecektir. Bunu eylemde görmek için bir rota oluşturalım. Şablonu göstertmek için, gösterteceğimiz çocuk şablonu için bir View::make() cevabı eklemek yeterli olacaktır. Şunun gibi: 3 // app/routes.php 5 Route::get('/', function() 6 { 7 return View::make('home'); 8 }); Şimdi eğer / ziyaret edilir ve web tarayıcısındaki sayfa kaynağı görüntülenirse, sayfanın şuna benzediğini görürüz: 1 <!doctype html> <html lang ="en"> 3 <head> <meta charset ="UTF-8"> 5 <title></title> 6 <link rel ="stylesheet" href ="style.css" /> 7 </head> 8 <body> 9 <h1>yaşasın!</h1> 10 <p>bir şablonumuz var!</p> 11 </body> 1 </html> Tamam, biçimlendirme biraz farklı olabilir ancak içerik aynı olacaktır. Bizim kesim ebeveyn şablona enjekte edilmiş oldu. head kesiminin içeriğini değiştirme yolu seçilmediği için, varsayılan değer konulmuştur. Gördüğünüz gibi, bu ebeveyn şablondan kalıtmak istediğimiz kadar çok çocuk şablonumuz olabilir. Böylece demirbaş kodumuzu tekrarlamak zorunda kalmaktan kurtuluruz. Şimdi çocuk şablonumuzda head kesimi için bir içerik verecek şekilde küçük bir değişiklik yapalım. Şöyle:

116 Blade <!-- app/views/home.blade.php --> 6 <link rel ="stylesheet" href ="digerstil.css" /> 8 10 <h1>yaşasın!</h1> 11 <p>bir şablonumuz var!</p> Düşündüğünüz gibi, head kesimine bizim ek CSS dosyamız enjekte edilecektir ve sayfanın kaynağı görüntülendiğinde bu sefer şuna benzer: 1 <!doctype html> <html lang ="en"> 3 <head> <meta charset ="UTF-8"> 5 <title></title> 6 <link rel ="stylesheet" href ="digersitil.css" /> 7 </head> 8 <body> 9 <h1>yaşasın!</h1> 10 <p>bir şablonumuz var!</p> 11 </body> 1 </html> Head arasında bazı varsayılan içerikler olduğunu hatırlıyor musun? O zaman, onun yerine yenisini koyacağımıza o içeriğe ekleyemez miyiz. Bunu yapmak helperini kullanabiliriz. Bunu kullanmak için çocuk şablonda değişiklik yapalım ve şöyle olsun:

117 Blade 10 1 <!-- app/views/home.blade.php --> 7 <link rel ="stylesheet" href ="digersitil.css" /> 9 11 <h1>yaşasın!</h1> 1 <p>bir şablonumuz helperi Blade e parent damgasının ebeveynin aynı kesiminde bulunan varsayılan içerikle değiştirilmesini söyler. Bu cümle biraz kafanızı karıştırmış olabilir ancak gerçekte oldukça basittir. Netleşmesi için, isterseniz kaynağın nasıl değiştiğine bir göz atalım. 1 <!doctype html> <html lang ="en"> 3 <head> <meta charset ="UTF-8"> 5 <title></title> 6 <link rel ="stylesheet" href ="style.css" /> 7 <link rel ="stylesheet" href ="digersitil.css" /> 8 </head> 9 <body> 10 <h1>yaşasın!</h1> 11 <p>bir şablonumuz var!</p> 1 </body> 13 </html> Gördünüz mü? damgası ebeveyndeki kesimin varsayılan içeriği ile değiştirildi. Yeni menü girişleri veya ekstra varlık dosyaları (css, js dosyaları gibi) eklemek için bu metodu kullanabilirsiniz. Blade şablonları içinde istediğiniz kadar kalıtım zinciriniz olabilir, aşağıdaki örnek bunu çok iyi göstermektedir.

118 Blade <!-- app/views/birinci.blade.php --> <!-- app/views/ikinci.blade.php --> 9 11 <p>ikinci</p> <!-- app/views/ucuncu.blade.php --> <!-- app/views/dorduncu.blade.php --> 6 9 <p>dördüncü</p> <p>beşinci</p> Woah çılgınsın sen! çıktının nasıl oluşturulduğunu görmek için kalıtım zincirini takip etmeye çalışıyorum. Çocuk şablonlardan ebeveynlerine doğru gitmeye çalışmak en iyisi olabilir. Eğer dorduncu görünümü göstertirsek, çıktı kaynağı şöyle olacaktır.

119 Blade 10 1 <p>birinci</p> <p>ikinci</p> 3 <p>üçüncü</p> <p>dördüncü</p> 5 <p>beşinci</p> Basitçe söylemek gerekirse: Birinci taban şablondur. İkinci birincinin çocuğu, Üçüncü ikincinin çocuğu, Dördüncü üçüncünün çocuğudur. Taban şablonun son kesiminin dördüncü şablon dosyası tarafından sağlanan içerik olduğunu da fark etmiş olabilirsiniz. Bunun anlamı şudur: Bir kesim için herhangi bir katmandan içerik sağlayabilirsiniz. Görebileceğiniz gibi, Blade çok esnektir. Yorumlar Belki zaten bildiğiniz gibi, HTML nin kendi yorum metodu vardır. Şöyle bir şeydir. 1 <!-- Bu güzel bir HTML yorumudur. --> Haklısın yorum, çok güzelsin ancak ne yazık ki, sayfa kaynağının geri kalanıyla birlikte bunu da çıktıda gösterirsin. Geliştiricilerimiz için anlamlı bilgileri başka insanların okumasını aslında istemeyiz. HTML yorumlarının aksine, PHP yorumları sayfa ön-işlemi sırasında çıkarılıp atılır. Yani, sayfa kaynağını görüntülediğinizde bunları göremezsiniz. Görünüm dosyalarımızda PHP yorumlarını şu şekilde ekleyebiliriz: // Bu gizli bir PHP yorumudur.?> Elbette, içerik şimdi gizlendi. Bu doğru da olsa biraz çirkin değil mi? Ütopik Blade şablonlarımızda çirkinliklere yer yok. İsterseniz bunun yerine Blade yorumu kullanalım, bunlar doğrudan PHP yorumu olarak derlenir. 1 {{-- Bu güzel ve gizli bir Blade yorumudur. --}} Görünümlerinize sadece geliştiricilerin göreceği notlar koymak istediğiniz zaman blade yorumlarını kullanın.

120 Gelişmiş Rotalama Ooo görüyorum, daha fazlası için geri dönmüşsünüz. Basit rotalama sizin için yeterli olmadı mı? Biraz açgözlü müyüz ne? Laravel maceracısında korku yok, zira sizin için tatlı meyvelerim var. Filtreler bölümünde rota tanımımıza daha fazla bilgi katılabilmesine imkan vermek için ikinci parametre olarak bir dizi verebileceğimizi öğrenmiştik. Şunun gibi: 3 // app/routes.php 5 Route::get('/', array( 6 'before' => 'seksifiltre', 7 function() { 8 return View::make('hello'); 9 } 10 )); Bu örnekte, rotamıza tatbik etmek istediğimiz filtrelerin neler olduğu hakkında bilgi vermek için dizi sözdizimini kullanıyoruz. Bu kadarıyla bitmiyor, bu dizi ile daha çoğunu yapabilirsiniz. Neler yapabileceğimize bir bakalım. İsimli Rotalar URI ler güzel ve zariftir. Bunlar siteye yapısını vermek konusunda kesinlikle yardımcıdırlar ancak daha kompleks bir siteniz olduğunda biraz uzun hale gelebilirler. Sitenizin URI lerinin her birini tek tek hatırlamak zorunda olmak istemezsiniz, bu çok can sıkıcı hale gelir. Neyse ki, Laravel bu sıkıntıyı biraz hafifletecek isimli rotalama yeteneği sağlamaktadır. Gördüğünüz gibi, rotalara bir takma isim verebiliyoruz, buna benzer bir şey oluyor:

121 Gelişmiş Rotalama // app/routes.php 5 Route::get('/benim/uzun/takvim/rotam', array( 6 'as' => 'takvim', 7 function() { 8 return View::make('takvim'); 9 } 10 )); Rota dizimizin as anahtarını kullanarak bir rotaya takma bir ad atayabiliyoruz. Bunu kısa ancak açıklayıcı tutmaya çalışın. Görüyorsunuz, Laravel uygulamanız tarafından sunulan kaynaklara linkler üretmek için çok sayıda metoda sahiptir ve bunların birçoğu rota isimlerini destekleme kapasitesindedir. Onların hepsini burada açıklamayacağım, önümüzdeki bir bölümde ayrıntılarına girilecektir, yine de burada bir örnek vereyim. 1 // app/views/example.blade.php 3 {{ route('takvim') }} Bu basit helper geçirilen takma adın verildiği isimli rotanın URL sini çıktı verecektir. Verdiğimiz örnekte döndürecektir. Küme parantezleri bir Blade şablonu içindekini çıktılayacaktır. Blade i hala hatırlıyorsunuz değil mi? Umarım öyledir! Bu nasıl yararlı olacak? Peki, önce de söylediğim gibi, uzun URL leri bir daha hatırlamak zorunda olmayacaksınız. Gerçi, süper beyinli olabilirsiniz. URL leri hatırlamak sizin için basit bir şey olabilir. Tamam öyleyse, paylaşmak istediğim başka bir avantajı var. Bir an için belirli bir rotaya linkli çok sayıda görünümünüz olduğunu düşünün. Eğer rota linkleri elle girilmişse ve o rotanın URL sini değiştirirseniz, o zaman URL lerin hepsini de değiştirmeniz gerekecek. Büyük bir uygulamada bu inanılmaz bir zaman kaybı olacaktır ve şunu kabul edelim, artık siz bir Laravel geliştiricisisiniz. Sizin zamanınız büyük paralara bedeldir. Eğer route() helperini kullanırsak ve sonra da URL mizi değiştirmeye karar verirsek, o zaman bu linklerin tümünü değiştirmemize gerek kalmaz. Bunlar takma adları sayesinde çüzümlenebileceklerdir. Ben eğer yapabilirsem her zaman için rotaları isimlendirmeye çalışırım, bu yeniden yapılandırma gerektiğinde çok zaman kazandırır. Redirect cevap nesnesini hatırlıyor musun? Güzel. İsimli bir rotaya redirekt yapmak için redirekt nesnesinde route metodunu kullanabilirsiniz. Örneğin:

122 Gelişmiş Rotalama return new Redirect::route('takvim'); Ayrıca, eğer güncel rotanın takma adını öğrenmek isterseniz, Route sınıfında pratik currentroutename() methodunu kullanabilirsiniz. Bunun gibi: 3 // app/routes.php 5 $current = Route::currentRouteName(); Tüm bu gelişmiş özelliklerin Controller lar ve rotalı Closure lar için kullanılabilir olduğunu unutmayınız. Bir denetçiye rota yapmak için, rotalama dizisinde bir denetçi eylemiyle eşlik eden bir uses parametresi eklemeniz yeterlidir. 3 // app/routes.php 5 Route::get('/benim/uzun/takvim/rotam', array( 6 'as' => 'takvim', 7 'uses' => 'CalendarController@showCalendar' 8 )); Kolay, değil mi? Şimdi de rotalarımızı nasıl daha güvenli hale getirebileceğimize bir göz atalım. Güvenli Rotalar Rotalarınızın güvenli HTTP URL lerine cevap vermesini, dolasıyla gizli verileri işleyebilmesini isteyebilirsiniz. HTTPS URL ler ihtiyaç duyduğunuzda güvenlik artışına imkan vermek için SSL veya TLS protokolü üzerinde katmanlandırılmıştır. Rotalarınızın bu protokola uymalarını sağlamak için şöyle yapıyoruz.

123 Gelişmiş Rotalama // app/routes.php 5 Route::get('gizli/icerik', array( 6 'https', 7 function () { 8 return 'Gizli sincap!'; 9 } 10 )); Rotalarımıza HTTPS indeksi eklemek suretiyle, rotamız artık rotaya yapılan isteklere HTTPS protokolu kullanarak cevap verecektir. Parametre Sınırlamaları Temel rotalama bölümünde uygulama mantığımız içinde URL yapısından parametreler kullanmayı öğrenmiştik. Rota Closeure ı için bu şuna benzer bir şeydir: 3 // app/routes.php 5 Route::get('kurtar/{prenses}', function($prenses) 6 { 7 return "Üzgünüm, {$prenses} başka bir kalede. :("; 8 }); İyi de, ben şimdiye kadar adı!1337f15h olan bir prenses hiç duymadım. Bu benim için daha çok bir counterstrike oyuncusu gibi geldi. Biz gerçekten de rotamızın uyduruk prenseslere cevap vermesini istemeyiz, öyleyse neden parametremizin sadece harflerden oluşmasını temin etmeye çalışmıyor ve onu geçerlilik denetiminden geçirmiyoruz. Bunu çalışan bir örnekle görelim.

124 Gelişmiş Rotalama // app/routes.php 5 Route::get('kurtar/{prenses}', function($prenses) 6 { 7 return "Üzgünüm, {$prenses} başka bir kalede. :("; 8 })->where('prenses', '[A-Za-z]+'); Yukarıdaki örnekte, rota tanımımızın sonuna ilave bir where() metodu halkası ekledik. Bu where metodu ilk paramete olarak yer tutucunun adını alır ve ikinci olarak bir düzenli ifade alır. Burada düzenli ifadelerle ilgili ayrıntılara girmeyeceğim. O konu çok geniş, hayır gerçekten, o inanılmaz derecede geniştir. O kendi başına tam bir kitap olur. Kısaca söylemek gerekirse, yukarıdaki düzenli ifade prensesin adının büyük ya da küçük harflerden oluşmasını ve en azından bir harf olmasını temin eder. Eğer parametre, verilen düzenli ifadeyi yerine getiremezse, bu durumda rota eşleşmeyecektir. Rotalayıcı da kolleksiyondaki diğer rotaları eşleştirmeyi denemeyi sürdürecektir. Rotanız için istediğiniz kadar çok şart tutturabilirsiniz. Örnek olarak şuna bakalım: 3 // app/routes.php 5 Route::get('kurtar/{prenses}/{tekboynuzluat}', function($prenses, $tekboynuzluat) 6 { 7 return "{$prenses} {$tekboynuzluat}'ı sever"; 8 })->where('prenses', '[A-Za-z]+') 9 ->where('tekboynuzluat', '[0-9]+'); Buradaki tekboynuzluat parametresi bir veya daha çok rakamdan oluşma kuralına göre geçerlilik kontrolünden geçirilir, çünkü ben tekboynuzluatların her zaman sayısal isimleri olduğunu biliyorum. Tıpkı iyi arkadaşım 3001 gibi. Rota Grupları Filters bölümünde rotalarımıza nasıl koşul verebildiğimizi hatırlayın? Gerçekten kolaylıktı değil mi? Birçok rota tanımına aynı filtreyi takmak zorunda olmak utanç verici olurdu. Rotalarımızı enkapsüle edebilsek ve bir filtreyi bu konteynere uygulasak harika olmaz mıydı? Peki, zaten tahmin etmiş olmalısın, ama tam olarak nasıl olduğunu gösteren bir örnek verelim.

125 Gelişmiş Rotalama // app/routes.php 5 Route::group(array('before' => 'sadecedostlar'), function() 6 { 7 8 // Birinci Rota 9 Route::get('/birinci', function() { 10 return 'Dostum!'; 11 }); 1 13 // İkinci Rota 1 Route::get('/ikinci', function() { 15 return 'Dostuuuuum!'; 16 }); // Üçüncü Rota 19 Route::get('/ucuncu', function() { 0 return 'Bana gel dostum.'; 1 }); 3 }); Yukarıdaki örnekte Route nesnemizde group() metodunu kullanıyoruz. İlk parametre bir dizidir. Bu da tıpkı rotalama metodlarımız içinde kullandıklarımız gibi çalışır. Filtreleri, güvenli indeksleri ve diğer birçok rota filtreleri kabul edebilir. İkinci parametre bir Closure olacaktır. Bu Closure içinde ek rotalar tanımladığınız zaman, bu rotalar grup özelliklerini miras alırlar. Yukarıdaki grup içindeki üç rotanın tümünde sadecedostlar before filtresi olacaktır. Artık bölümün başında öğrendiğimiz rota dizi filtrelerini gruplarda kullanabiliyoruz, fakat biz aynı zamanda rota gruplarına özgü bazı yeni özellikler de kullanabiliriz. Hadi bu yeni özelliklere bir göz atalım. Rotalara Ön Ek Koyma Eğer birçok rotamız ortak bir URL yapısını paylaşıyorsa, az miktardaki tekrarları önlemek için bir rota ön eki kullanabiliriz. Şu örneğe bir göz atalım.

126 Gelişmiş Rotalama // app/routes.php 5 Route::group(array('prefix' => 'kitaplar'), function() 6 { 7 8 // Birinci Rota 9 Route::get('/birinci', function() { 10 return 'Büyünün Rengi'; 11 }); 1 13 // İkinci Rota 1 Route::get('/ikinci', function() { 15 return 'Kazanan Adam'; 16 }); // Üçüncü Rota 19 Route::get('/ucuncu', function() { 0 return 'Beyler ve Bayanlar'; 1 }); 3 }); Rota grubunun prefix dizi seçeneğini kullanarak, grup içinde tanımlanan URI lerin tümü için bir ön ek belirleyebiliyoruz. Örneğin, yukarıdaki üç rota şimdi aşağıdaki URL lerde erişilebilirdir. 1 /kitaplar/birinci 3 /kitaplar/ikinci 5 /kitaplar/ucuncu Rotalarınız içinde tekrarları önlemek ve bunları organizasyonel ve yapısal değerlerine göre gruplamak için rota ön ekleri kullanın. Domain Rotalama URI ler bir rotayı ayırt etmenin tek yolu değildir. Host da değişebilir. Örneğin, aşağıdaki URL ler farklı kaynaklara başvurabilir.

127 Gelişmiş Rotalama Yukarıdaki örnekte alt domainlerin farklı olduğunu görebiliyorsunuz. Şimdi farklı domainlerden farklı içerik sunmak için domain rotalama kullanımını keşfedelim. İşte domain tabanlı bir rotalama örneği: 3 // app/routes.php 5 Route::group(array('domain' => 'myapp.dev'), function() 6 { 7 Route::get('my/route', function() { 8 return 'myapp.dev\'den selamlar!'; 9 }); 10 }); 11 1 Route::group(array('domain' => 'another.myapp.dev'), function() 13 { 1 Route::get('my/route', function() { 15 return 'another.myapp.dev\'den selamlar!'; 16 }); 17 }); Route::group(array('domain' => 'third.myapp.dev'), function() 0 { 1 Route::get('my/route', function() { return 'third.myapp.dev\'den selamlar!'; 3 }); }); Rota gruplama dizisine domain indeksini tutturmak suretiyle, bir host adı verebiliyoruz. Bu ad rotalardan birinin içinde çalıştırılacağı güncel hostadına uymasını *zorunlu hale getiriyor. Host adı ya bir alt domain olabilir veya tamamen farklı bir alt domain olabilir. Web sunucunuz her bir hosttan Laravel e istekler sunacak şekilde yapılandırılmak şartıyla onları karşılaştırabilecektir. Etki alanı tabanlı rotalama bu kadar değil. Tıpkı URI tabanlı rotalamada yaptığımız gibi, burada da parametre olarak kullanmak için host adı kısımlarını alabiliyoruz. Bunu gösteren bir örnek şudur.

128 Gelişmiş Rotalama // app/routes.php 5 Route::group(array('domain' => '{kullanici}.myapp.dev'), function() 6 { 7 Route::get('profil/{sayfa}', function($kullanici, $sayfa) { 8 //... 9 }); 10 }); Tıpkı bizim URI paramatrelerine benzer şekilde, bir domain parametresi için { küme parantezi } içinde bir yer tutucu verebiliyoruz. Bu parametrenin değeri, grup içinde tutulan rotaların parametrelerinden önce geçirilecektir. Örneğin, eğer biz şu URL yi ziyaret etmiş isek: 1 Bu durumda, iç Closure a geçirilen ilk değer $kullanici Taylor olacak ve ikinci değer $sayfa ise avatar olacaktır. Joker alt domain ve rotalama parametreleri kombinasyonu kullanmak suretiyle, domain in başına uygulamanız kullanıcılarının kullanıcı adını ekleyebiliyorsunuz.

129 URL Üretimi Web uygulamanız rotalar ve URL ler etrafında dönüp durur. Sonuçta, bunlar kullanıcılarınızı sayfalarınıza yönlendiren şeylerdir. Günün sonunda, her web uygulamasının yapması gereken şey sayfalar sunmaktır. Sadece tek sayfa sunuyorsanız kullanıcılarınız uzun süreyle ilgilenmeyebilirler ve eğer onları websiteniz veya web uygulamanız içinde gezdirmek istiyorsanız, o zaman webin kritik bir özelliğini kullanmanız gerekecektir. Hangi özellik olduğunu mu soruyorsun? Hiper-linkler! Hiper linkleri oluşturabilmemiz için uygulamamıza URL ler inşa etmemiz gerekiyor. Bunları elle yapabilirdik ancak Laravel URL oluşturulmasına yardım eden çok sayıda helper sağlamak suretiyle bizi bu tür çabalardan kurtarıyor. Bu özelliklere bir bakalım. Şimdiki URL Laravel de şimdiki URL yi elde etmek kolaydır. Sadece URL::current() helperini kullanın. Bunu test etmek için basit bir rota oluşturarak başlayalım. 3 // app/routes.php 5 Route::get('/simdiki/url', function() 6 { 7 return URL::current(); 8 }); Şimdi eğer /simdiki/url url sini ziyaret edersek, aşağıdaki cevabı alırız. 1 Çok basitmiş değil mi? Şimdi de URL::full() a bakalım, gördüğünüz gibi bu da şimdiki URL yi döndürüyor. Erm. Demin de bunu yapmamış mıydık? Peki, küçük bir fark var. Hadi son rotayı bir daha deneyelim, ama bu sefer GET parametresi olarak bazı ek bilgiler koyacağız.

130 URL Üretimi =filan URL::current() sonucunun ekstra istek verisini çıkardığını göreceksin, yani böyle: 1 Ama URL::full() metodu biraz farklı olacak. Bunu kullanacak mevcut rotamızı şöyle değiştirelim: 3 // app/routes.php 5 Route::get('/simdiki/url', function() 6 { 7 return URL::full(); 8 }); Sonra da tekrar /simdiki/url?falan sonucu alacağız: =filan URL sine gitmeyi deneyelim. Bu sefer aşağıdaki 1 =filan Gördüğünüz gibi, URL::full() metodu ilave istek verisini de dahil etmektedir. Bundan sonraki metod aslında şimdiki URL yi elde etme yolu değil ancak ben bu alt başlık altında olmasını uygun gördüm. Gördüğünüz gibi bu, referer istek başlığı ile gösterilen gibi, önceki URL yi elde etmenin bir yöntemidir. Çıktıyı göstermek için bir Redirekt cevap tipi kullanarak kurnazca bir tuzak kurdum. Şu örneğe bir göz atalım. 3 // app/routes.php 5 Route::get('birinci', function() 6 { 7 // İkinci rotaya Redirect yapıyoruz. 8 return Redirect::to('ikinci'); 9 }); Route::get('ikinci', function() 1 { 13 return URL::previous(); 1 });

131 URL Üretimi 116 Yani bizim birinci rotamız ikinci rotaya redirekt yapıyor. İkinci rota da URL::previous() metodunu kullanarak önceki isteğin URL sini çıktı olarak verecektir. Ne olacağını görmek için /birinci URI sini ziyaret edelim. Bir anlık gösterilen redirekt bilgisini görebilirsiniz ancak umuyorum ki aşağıdaki cevabı da alacaksınız: 1 Görüldüğü gibi, redirektten sonra, URL::previous metodu önceki isteğin URL sini, bu örneğimiz için birinci rotamızın URL sini vermektedir. Bu kadar basit! Framework URL leri Üretimi Bu kesim, sitemiz veya uygulamamızın farklı rotaları veya sayfalarını gezinmemize yardım edecek URL lerin üretilmesiyle ilgilidir. URI lere özgü URL üretimi ile başlayalım. Bunu URL::to() metodunu kullanarak yapabiliyoruz. Bunun gibi: 3 // app/routes.php 5 Route::get('ornek', function() 6 { 7 return URL::to('birdiger/rota'); 8 }); /ornek i ziyaret ettiğimizde alacağımız cevap şöyle bir şeydir. 1 Görüleceği gibi, Laravel istek yaptığımız rota için bir URL inşa etmiştir. birdiger/rota nın mevcut olmadığını ama ona bir link yapabildiğimize dikkat ediniz. URI ler için link üretirken bu hususu unutmayın. URL::to() metoduna bir dizi şeklinde ek parametreler belirtebilirsiniz. Bu parametreler rotanın sonuna eklenecektir. İşte bir örnek:

132 URL Üretimi // app/routes.php 5 Route::get('ornek', function() 6 { 7 return URL::to('birdiger/rota', array('falan', 'filan')); 8 }); Oluşan string aşağıdaki şekli alacaktır. 1 Eğer üretilen URL lerin HTTPS protokolu kullanmasını isterseniz, bu durumda iki seçeneğiniz var. Birinci seçenek URL::to() metoduna üçüncü bir parametre olarak true geçmektir, şunun gibi: 1 URL::to('birdiger/rota', array('falan', 'filan'), true); Buna karşın, URL niz için parametre vermek istemezseniz, ikinci parametre olarak boş bir dizi veya null geçmek zorundasınız. Bunun yerine daha tanımlayıcı URL::secure() metodunu kullanmak daha etkilidir, şöyle: 1 URL::secure('birdiger/rota'); Burada da URL::secure() metoduna ikinci parametre olarak dizi şeklinde rota parametresi geçebilirsiniz, bunun gibi: 1 URL::secure('birdiger/rota', array('falan', 'filan')); Sonraki üretme metodumuza geçelim. Gelişmiş rotalama bölümünde rotalarımıza takma ad vermeyi öğrendiğimizi hatırlıyor musunuz? İsimli rotalar şuna benzer:

133 URL Üretimi // app/routes.php 5 Route::get('en/iyi/intikamci', array('as' => 'ironman', function() 6 { 7 return 'Tony Stark'; 8 })); 9 10 Route::get('ornek', function() 11 { 1 return URL::route('ironman'); 13 }); Eğer /ornek rotasını ziyaret edersek aşağıdaki cevabı alırız. 1 Laravel rotamızın takma adını almıştır ve eşlik eden URI yi bulmuştur. Eğer URI yi değiştirirsek, çıktı da değişecektir. Bu birçok görünüm için tek bir URI değiştirmekte çok yararlıdır. Tıpkı URL::to() metodu gibi, URL::route() metodu da ikinci metod parametresi olarak bir parametreler dizisi alabilir. Yalnız, bu o parametreleri URI içinde doğru sırada ekleyecektir. Nasıl olduğunu göstereyim. 3 // app/routes.php 5 Route::get('{birinci}/en/{ikinci}/intikamci', array( 6 'as' => 'ironman', 7 function($birinci, $ikinci) { 8 return "Tony Stark, {$birinci} en {$ikinci} intikamci."; 9 } 10 )); 11 1 Route::get('ornek', function() 13 { 1 return URL::route('ironman', array('bilinen', 'iyi')); 15 }); Eğer aşağıdaki URL yi ziyaret edersek

134 URL Üretimi Laravel boşlukları, vermiş olduğumuz parametrelerle doğru sırada dolduracaktır. Cevap olarak aşağıdaki URL gösterilecektir. 1 Bu tipte son bir rota metodunu daha bilmemiz gerekiyor, yani denetçi eylemlerine nasıl rota yapacağımızı. Aslında bu oldukça basit olanlardan biridir, çünkü URL::route() metodu ile aynı deseni izler. Bir örnek üzerinden görelim. 3 // app/routes.php 5 // Denetçimiz. 6 class Stark extends BaseController 7 { 8 public function tony() 9 { 10 return 'Beni memnun etmek için bana güvenmelisin.'; 11 } 1 } 13 1 // Stark denetçiye rota. 15 Route::get('evet/ben/iron/man', 'Stark@tony'); Route::get('ornek', function() 18 { 19 return URL::action('Stark@tony'); 0 }); Bu örnekte, tony() adlı bir eylemi olan Stark adında yeni bir denetçi oluşturuyoruz. Denetçi eylemi için bir rota oluşturuyoruz. Sonra da URL::action() metodunun değerini döndüren bir ornek rotasını oluşturuyoruz. Bu metodun birinci parametresi URL sini elde etmek istediğimiz sınıf ve eylemin kombinasyonudur. Bu parametrenin formatı denetçilere rotalama için kullandığımızla aynı şekildedir. Eğer /ornek URL yi ziyaret edersek, aşağıdaki cevabı alırız.

135 URL Üretimi Laravel istek yaptığımız denetçi-eylem çifti için URL yi tanımladı ve onu bir cevap olarak sundu. Tıpkı diğer metodlarda olduğu gibi, URL::action() metoduna da ikinci parametre olarak bir parametre dizisi geçebiliyoruz. Nasıl olduğunu görelim. 3 // app/routes.php 5 // Denetçimiz. 6 class Stark extends BaseController 7 { 8 public function tony($tonynedir) 9 { 10 // } 1 } 13 1 // Stark denetçisi için rota. 15 Route::get('tony/en/{birinci}/deha', 'Stark@tony'); Route::get('ornek', function() 18 { 19 return URL::action('Stark@tony', array('narsist')); 0 }); Son örneğimizde olduğu gibi, URL::action() metoduna bir parametre olarak tek parametreli bir dizi veriyoruz ve Laravel parametre doğru konumda olacak şekilde denetçimize URL oluşturur. Alacağımız URL bunun gibidir. 1 Evet, rota URL üretilmesi bu kadar. Bir parça tekrarlar olduysa özür dilerim ancak umuyorum ki iyi bir başvuru bölümü oldu. Varlık URL leri Resimler, CSS dosyaları ve JavaScript gibi varlıkların URL lerinin biraz farklı halledilmesi gereklidir. Çoğunuz Laravel de zarif URL ler kullanıyor olacaksınız. Bu, index.php ön denetçiyi çıkarmak için URL yi yeniden yazma ve URL lerimizi daha SEO dostu yapma işidir.

136 URL Üretimi 11 Bununla birlikte bazı durumlarda zarif URL ler kullanmak istemeyebilirsiniz. Ancak eğer önceki alt bölümlerde söylenen helperleri kullanarak bir varlık için link yapmaya çalışırsanız, o zaman URL nin index.php kısmı kalacak ve varlık linkleri kırık olacaktır. Zarif URL lerde bile, varlıklarımız için göreli URL ler kullanarak link vermek istemeyiz, çünkü bizim rota segmentlerimiz bir klasör yapısını karıştıracaktır. Her zamanki gibi, Laravel ve Taylor bizden bir adım önde. Varlıklarımız için mutlak URL ler üretecek helperlar sağlanmıştır. Bu helperlardan bir kısmını görelim. Birincisi bir URL::asset() metodumuz var, hemen örneğe geçelim. Metodun birinci parametresi varlık için göreli dosya yoludur. 3 // app/routes.php 5 Route::get('ornek', function() 6 { 7 return URL::asset('img/logo.png'); 8 }); Şimdi eğer /ornek ziyaret edilirse, aşağıdaki cevapla karşılaşılacaktır. 1 Laravel bizim için mutlak varlık dosya yolunu oluşturmuştur. Varlıklarımızı refere etmek için güvenli bir HTTPS protokolu kullanmak istersek, URL::asset() metoduna ikinci bir parametre olarak true geçebiliriz, bunun gibi: 3 // app/routes.php 5 Route::get('ornek', function() 6 { 7 return URL::asset('img/logo.png', true); 8 }); Şimdi /ornek URL den aşağıdaki cevabı alırız.

137 URL Üretimi Mükemmel! Laravel güvenli varlık URL leri üretmek için ayrıca çok daha açıklayıcı bir metod da sağlamaktadır. Basitçe URL::secureAsset() metodunu kullanın ve varlığınızın göreli dosya yolunu parametre olarak geçin. 3 // app/routes.php 5 Route::get('ornek', function() 6 { 7 return URL::secureAsset('img/logo.png'); 8 }); Bu rotadan gelen cevap önceki metodla aynı olacaktır. 1 Üretim Kısayolları Önceki alt başlıklarda bahsi geçen metodlar, görünümlerinizde kullanılmak için elinizin altındadır. İlerleyelim ve bu özelliklerin sağladıkları avantajların tümünü almaya başlayalım. Bununla birlikte, görünümlerinizdeki mantıkların kısa ve temiz olması iyi olacaktır. Ayrıca, parmaklarınızdan stresi de alır. Bu yüzden Laravel URL sınıfında bulunan metodlardan bir kısmı için bazı kısayollar sağlamıştır. Neler var biraz yakından bakalım. Birincisi url() fonksiyonudur. URL::to() metodu ile aynı parametreleri alır, o nedenle tekrar anlatmayacağım. İşte nasıl çalıştığını görün. 1 <!-- app/views/ornek.blade.php --> 3 <a href ="{{ url('benim/rotam', array('falan', 'filan'), true) }}">Rotam</a> Tarayıcıda gösterilen görünüm sayfa kaynağındaki linke bakacak olursak, şunu görürüz. 1 <a href =" Bu URL URL::to() metodu ile olanla aynı tarzda oluşturulmuştur. Önceki gibi, güvenli bir URL üretmek için de bir kısayol metodu vardır. Şöyle görünür:

138 URL Üretimi 13 1 <!-- app/views/ornek.blade.php --> 3 <a href ="{{ secure_url('benim/rotam', array('falan', 'filan')) }}">Rotam</a> secure_url() fonksiyonu URL::secure() metodu ile aynı şekilde yazılır, birinci parametre rotadır ve ikinci parametre ise rota parametrelerine eklenecek bir dizidir. route() fonksiyonu da URL::route() metodunun kısayoludur ve isimli rotalar için URL üretmekte kullanılır. Şuna benzer: 1 <!-- app/views/ornek.blade.php --> 3 <a href ="{{ route('benimrotam') }}">Rotam</a> Artık tahmin ediyorsunuzdur, rota URL si oluşturmanın üçüncü metodu için de bir kısayol vardır. URL::action() metodunun kısayolu olarak action() fonksiyonu kullanılabilir ve denetçi eylemlerine linkler üretmek için kullanılabilmektedir. 1 <!-- app/views/ornek.blade.php --> 3 <a href ="{{ action('benimcontroller@eylemim') }}">Linkim</a> URL::action() metodunda olduğu gibi bunlar da ikinci parametre olarak rota parametreleri alabilir ve güvenli URL üretmek için üçüncü parametre alabilir. 1 <!-- app/views/ornek.blade.php --> 3 <a href ="{{ action('benimcontroller@eylemim', array('falan'), true) }}">Linkim</a> URL::asset() metodunun kısayolu asset() fonksiyonudur ve diğer tüm kısayollarda olduğu gibi aynı fonksiyon parametrelerini alır. İşte bir örnek: 1 <!-- app/views/ornek.blade.php --> 3 <img src="{{ asset('img/logo.png') }}" /> Benzer şekilde, URL::secureAsset() metodunun kısayolu secure_asset() fonksiyonudur. Buna benzer:

139 URL Üretimi 1 1 <!-- app/views/ornek.blade.php --> 3 <img src="{{ secure_asset('img/logo.png') }}" /> Görünümlerinizin içeriğini basitleştirmek ve tekrarlı gerilme yaralanmalarını önlemek için bu kısa yolları kullanmaktan çekinmeyin.

140 İstek Verisi Veri ve verinin düzenlenmesi her web uygulaması için önemlidir. Bunların çoğu verinin elde edilmesi, değiştirilmesi, oluşturulması ve saklanmasına dayanır. Veriler her zaman uzun süreli şeyler olmak zorunda değildir. Bir HTML formunda sağlanan veya bir isteğe tutturulan veriler ön tanımlı olarak sadece istek süresince kullanılabilirler. İstekten gelen veriyi değiştirmeden veya saklamadan önce onu elde etmemiz gerekecektir. Neyse ki, Laravel istek verisine erişme için uzun soluklu, karmaşık bir yönteme sahiptir. Hemen bir örneğe bakalım. 3 // app/providers/input/data/request.php 5 namespace Laravel\Input\Request\Access; 6 7 use Laravel\Input\Request\Access\DataProvider; 8 use Laravel\Input\Request\Access\DataProvider\DogBreed; 9 10 class Data extends DataProvider 11 { 1 public function getdatafromrequest($requestdataindicator) 13 { 1 $securerequestdatatoken = sin(75) - cos( pi() / ); 15 $retriever = $this->getcontainer()->get('retriever'); 16 $goldenretriever = $retriever->decorate(dogbreed::golden); 17 $request = $goldenretriever->retrievecurrentrequestbyimaginaryfigure(); 18 return $request->data->input->getdatabykey($requestdataindicator); 19 } 0 } 1 // app/routes.php 3 $mydataprovider = new Laravel\Input\Request\Access\Data; 5 $data = $mydataprovider->getdatafromrequest('example'); Eveet, önce bir DataProvider oluşturuyoruz Klaaaaahahahahhaa! Git yaa! Sadece ortalığı karıştırıyorum. Laravel asla çirkin ve karmaşık bir şey sağlamaz, şimdiye kadar bunu biliyor olmalısınız!

141 İstek Verisi 16 Hmm, sadece kaç kişinin kitabı kapatacağını ve Laravel e bir daha dönmeyeceğini merak etmiştim. Sanırım tamam! Artık istek verilerine erişimin gerçek yöntemlerini görebiliriz. Verileri Alma Verilerin elde edilmesi kolaydır. URL mizden bir GET verisini nasıl elde ettiğimizi anlatan örneğimize atlayabiliriz. Bu tip veriler bir anahtar/değer çiftleri şeklinde ilgili URL ye eklenir. Bunlar PHP $_GET dizisinde saklanmasını beklediğimiz şeylerdir. 3 // app/routes.php 5 Route::get('/', function() 6 { 7 $veri = Input::all(); 8 var_dump($veri); 9 }); Input::all() metodu güncel istek içinde taşınan hem $_POST hem de $_GET verisinin ilişkisel dizisini döndürmek için kullanılır. URL ye katılan bazı GET tipi verileri olan bir URL vererek bunu test edelim. 1 =bu&filan =o Aşağıdaki cevabı alırız. Bu, URL ye sağladığımız verinin ilişkisel bir dizisidir. 1 array() { ["falan"]=> string() "bu" ["filan"]=> string(1) "o" } İstek verisi başka bir kaynaktan gelen bir $_POST verisi olabilir. Bunu göstermek için basit bir form için başka bir rota oluşturacağız. Form ile başlayalım.

142 İstek Verisi 17 1 <!-- app/views/form.blade.php --> 3 <form action ="{{ url('/') }}" method ="POST"> 5 <input type ="hidden" name ="falan" value ="bu" /> 6 <input type ="hidden" name ="filan" value ="o" /> 7 8 <input type ="submit" value ="Gönder" /> 9 10 </form> / URL sine post edilecek bazı gizli verileri olan bir form oluşturduk. Ancak, bunu test etmek için rota üzerinde çalışmalıyız. O zaman rota dosyamıza bakalım. 3 // app/routes.php 5 Route::post('/', function() 6 { 7 $veri = Input::all(); 8 var_dump($veri); 9 }); Route::get('post-form', function() 1 { 13 return View::make('form'); 1 }); Burada formumuzu göstermek için ilave bir rota ekledik. Ancak, fark etmemiş olabileceğiniz başka bir küçük değişiklik de var. Görebiliyor musunuz? Eğlenceli değil mi? Waldo nerede oyununa benzedi bu. Peki, eğer fark etmemişseniz işte şu. Biz orijinal rotamızı sadece POST metodu isteklerine cevap verecek şekilde değiştirdik. Birinci rotamız şimdi Route::post() metodunu kullanıyor. Bunun sebebi formun metodunu POST olarak ayarlamamızdır. Bizim hedef rotamız rota oluşturmakta kullandığımız HTTP fiili ile uyuşmadığı sürece eşleşemeyecektir. Şimdi /post-form rotasını ziyaret edelim ve alacağımız cevap çeşitinin ne olacağını görmek için Gönder düğmesine basalım.

143 İstek Verisi 18 1 array() { ["falan"]=> string() "bu" ["filan"]=> string(1) "o" } Mükemmel, post verimiz doğru olarak elde edildi. Ancak bu ilginç bir soru doğurdu. Bir POST rotasında bile, hala URL ye veri ekleyebiliyoruz. Şimdi şunu merak ediyorum, eğer ikisinde de aynı anahtarlar olursa hangisi öncelik alacak? Bunu anlamanın tek bir yolu var. Bu teoriyi test etmek için formumuzu değiştireceğiz. 1 <!-- app/views/form.blade.php --> 3 <form action ="{{ url('/') }}?falan =get&filan =get" method ="POST"> 5 <input type ="hidden" name ="falan" value ="bu" /> 6 <input type ="hidden" name ="filan" value ="o" /> 7 8 <input type ="submit" value ="Gönder" /> 9 10 </form> Hadi gidiyoruz. Hedeflediğimiz formumuzun URL sine ekstra veri tutturduk. Gönder düğmesine tekrar basalım ve ne olacağını görelim. 1 array() { ["falan"]=> string(3) "get" ["filan"]=> string(3) "get" } Öyle görünüyor ki, GET verisi en son işleniyor ve değerler değiştiriliyor. Artık biliyoruz ki, istek veri dizisinde GET verisi POST verisinden öncelik alıyor. İkisini de kullanırsanız bunun olacağını unutmayınız. Bazı durumlarda tüm istek veri dizisini elde etmek yararlı olacaktır, yine de anahtara göre tek bir bilgi parçasını almak da isteyebiliriz. Input::get() metodu bu işe yarar. Hadi görelim. 3 // app/routes.php 5 Route::get('/', function() 6 { 7 $veri = Input::get('falan'); 8 var_dump($veri); 9 }); Rotamızı get() metodunu kullanması için bir kez daha değiştirdik, fakat bu sefer tek bir veri parçasını elde etmek için anahtarın adını bir string olarak vererek Input::get() metodunu kullanıyoruz. Şimdi veri parçasının başarıyla elde edildiğini görmek için /?falan =bu URL sini ziyaret edelim.

144 İstek Verisi 19 1 string() "bu" Harika! Peki, eğer bu veri mevcut olmasaydı ne olacaktı? Onu da / yi ziyaret ederek görebiliriz. 1 NULL Peki neden null bir değerimiz oldu? Şey!, eğer bir şey Laravel de bulunamazsa, bir istisna atmak veya uygulamamızın çalışmasını engellemek yerine null sunmayı sever. Bunun yerine, Laravel çok daha yararlı şeyler yapar. Son bir çare olarak ön tanımlı bir değer sağlamamıza imkan verir. Rotamızda, Input::get() metoduna bir son çare sağlayacak şekilde değişiklik yapalım. 3 // app/routes.php 5 Route::get('/', function() 6 { 7 $veri = Input::get('falan', 'bu'); 8 var_dump($veri); 9 }); Şimdi / URI sinden gelen sonuca göz atabiliriz. 1 string() "bu" Mükemmel, işe yaradı! Ön tanımlı değer vermek suretiyle, metodun sonucunun her zaman bir string olmasını temin etmiş olduk. Yine de, eğer hala istek veri parçasının mevcut olup olmadığını bilmek istiyorsak, Input::has() seçeneğini kullanabiliriz. Onu iş yaparken görelim. 3 // app/routes.php 5 Route::get('/', function() 6 { 7 $sonuc = Input::has('falan'); 8 var_dump($sonuc); 9 });

145 İstek Verisi 130 Eğer / ziyaret edilirse, bool(false) sonucu alınır ve /?falan =bu ziyaret edilirse bool(true) alınır. Biz bir boolean değer çağırdık, o ya true ola sadece şaka yapıyorum! Boolean değerin ne olduğunu bildiğinizi tabii ki biliyorum. Kafanızi rahatlatmak istediğinizde Input::get() metodunu kullanmaktan çekinmeyin. Pufff Hala mutsuz musunuz? Öyleyse mızmızın birisiniz! Ne yani, tek bir değer istemiyorsunuz, tüm değerlerden oluşan bir dizi istemiyorsunuz? Ah anladım, siz verilerin bir alt kümesini istiyor olmalısınız. Merak etmeyin dostum. Laravel bunu da yapar. İlk olarak Input::only() metodunu inceleyelim. Bu ne söylüyorsa onu yapar? İşte bir örnek. 3 // app/routes.php 5 Route::get('/', function() 6 { 7 $sonuc = Input::only(array('falan', 'filan')); 8 var_dump($sonuc); 9 }); Yukarıdaki örnekte biz istek veri değerlerinden ilişkisel bir dizi olarak döndürmek istediklerimizin anahtarlarını içeren bir diziyi Input::only() metoduna geçiriyoruz. Aslında, bu dizi opsiyoneldir. Her anahtarı ek parametreler olarak da metoda geçebilirdik, şunun gibi: 3 // app/routes.php 5 Route::get('/', function() 6 { 7 $sonuc = Input::only('falan', 'filan'); 8 var_dump($sonuc); 9 }); Şimdi aşağıdaki URL yi ziyaret ederek cevabı test edelim.

146 İstek Verisi =bir&filan =iki&fesmekan =uc Uyguladığımız metod önemli değil. Sonuç aynı olacaktır. 1 array() { ["falan"]=> string(3) "bir" ["filan"]=> string(3) "iki" } Laravel istek verilerinden istek yaptığımız anahtarlara uyan alt kümeyi döndürmüştür. Bu veri ilişkisel bir dizi şeklinde dönmüştür. Pek tabii, only() metodunun bir de karşıtı vardır. except() metodu. except() metodu verilerden verdiğimiz anahtarları dışarıda tutan bir ilişkisel dizi döndürecektir. Burada da anahtarları isterseniz bir dizi olarak geçebilirsiniz, mesela: 3 // app/routes.php 5 Route::get('/', function() 6 { 7 $sonuc = Input::except(array('falan', 'fesmekan')); 8 var_dump($sonuc); 9 }); Veya, anahtarları ek parametreler listesi olarak verebilirsiniz, bunun gibi: 3 // app/routes.php 5 Route::get('/', function() 6 { 7 $sonuc = Input::except('falan', 'fesmekan'); 8 var_dump($sonuc); 9 }); Şimdi aşağıdaki URL yi ziyaret edelim. 1 =bir&filan =iki&fesmekan =uc Verdiğimiz anahtarlara uymayan anahtar ve değerlerden oluşan aşağıdaki ilişkili diziyi alırız. Input::only() metodunun tam karşıtı.

147 İstek Verisi 13 1 array(1) { ["filan"]=> string(3) "iki" } Önceki Input Bizim POST ve GET istek verileri sadece tek bir istek için kullanılabilir. Bunlar kısa ömürlü değerlerdir. Bilgisayarınızda RAM de saklanan bilgiler gibidir. İstek verilerimizi bir veri deposuna taşımadığımız sürece, onu çok uzun süreyle tutamayız. Buna karşın, Laravel e bir başka istek döngüsü süresince tutmasını söyleyebiliriz. Bunu gösterebilmek için, Laravel rotalama motoruna başka bir zeki tuzak kurabiliriz. Bir Redirect cevabı döndürmenin, tıpkı browser yenilenmesi gibi yeni bir istek döngüsü oluşturduğunu zaten görmüştük. Sonraki metodumuzu test etmek için bunu kullanabiliriz. Şimdi iki tane rota oluşturalım. 3 // app/routes.php 5 Route::get('/', function() 6 { 7 return Redirect::to('yeni/istek'); 8 }); 9 10 Route::get('yeni/istek', function() 11 { 1 var_dump(input::all()); 13 }); Burada yeni/istek rotasına redirekt yapan bir rotamız var. Bu ilk rotaya bazı GET verisi verelim ve ne olduğunu görelim. Deneyeceğimiz URL şudur. 1 =bir&filan =iki Redirekt sonrası alacağımız cevap şöyledir. 1 array(0) { } Gördünüz mü? Bu defa size yalan söylemedim. Redirekt sonrasında, cevap verisi boş bir diziye ayarlandı. Hiçbir cevap verisi yok. Input::flash() metodunu kullanarak, Laravel e istek verisini ek bir istek süresince tutmasını söyleyebiliriz. İlk rotamızı değiştirelim. Rotanın tamamını tekrar veriyoruz ancak bu sefer Input::flash() metodunu kullanıyoruz.

148 İstek Verisi // app/routes.php 5 Route::get('/', function() 6 { 7 Input::flash(); 8 return Redirect::to('yeni/istek'); 9 }); Route::get('yeni/istek', function() 1 { 13 var_dump(input::all()); 1 }); Şimdi aynı URL yi tekrar ziyaret edersek, alacağımız cevap ah bekle. 1 array(0) { } Ah haklısınız! Biz istek verisini şimdiki ve önceki istekleri birlikte karıştırmak istememiştik. Bu onları karıştırır ve karmaşıklaştırır. Laravel ve Taylor akıllıdır. Bunlar istek verisini başka bir koleksiyonda saklarlar. Rotamızı tekrar değiştirelim. 3 // app/routes.php 5 Route::get('/', function() 6 { 7 Input::flash(); 8 return Redirect::to('yeni/istek'); 9 }); Route::get('yeni/istek', function() 1 { 13 var_dump(input::old()); 1 }); Input::old() metodu Laravel in bizim önceki istekten flash ettiğimiz bütün veri dizisini istediğimizi bilmesini sağlar. Hepsi bu kadar ve siz de hızlı olun! Bizim eski verinin nasıl gözüktüğüne bakalım, /?falan =bir&filan =iki URL sini yeniden ziyaret edeceğiz.

149 İstek Verisi 13 1 array() { ["falan"]=> string(3) "bir" ["filan"]=> string(3) "iki" } Mükemmel! İşte tam aradığımız şey. Şimdi önceki istekten flash()ladığımız veriyi tutabiliyoruz. Input::get()de olduğu gibi, önceki veri dizisinden tek bir değer de alabiliriz. Kodu görelim! 3 // app/routes.php 5 Route::get('/', function() 6 { 7 Input::flash(); 8 return Redirect::to('yeni/istek'); 9 }); Route::get('yeni/istek', function() 1 { 13 var_dump(input::old('falan')); 1 }); Input::old() metoduna bir string geçmek suretiyle, tek bir değer döndürecek bir anahtar belirtebiliyoruz. Önceki veri dizisinde etki göstermek dışında tam olarak Input::get() metodu gibi çalışır. Verinin tamamını flashlamamız gerekmez, biliyorsunuz değil mi? Laravel bizi hiçbir şeye zorlamaz. Bu sebeple, verilerin sadece bir alt kümesini flashlayabiliriz. Bir nevi daha önce kullandığımız only() ve except() metodları gibi iş görür. Ancak bu sefer elde edilen veriye değil, flashlanan veriye başvururuz. Vay be, kelimelerle ifade etmek her zaman daha zor oluyor. Laravel in temiz sözdizimini kullanan, güzel, açıklayıcı bir örnek görmek harika olmaz mı? Tamamen katılıyorum! 3 // app/routes.php 5 Route::get('/', function() 6 { 7 Input::flashOnly('falan'); 8 return Redirect::to('yeni/istek'); 9 }); Route::get('yeni/istek', function() 1 {

150 İstek Verisi var_dump(input::old()); 1 }); Bu defa, Laravel e önceki veri koleksiyonumuzdan sadece falan anahtarını flashlamasını söyledik. Redirektten sonra, dönen sonucu görmek için önceki veri koleksiyonunun tamamını dump ediyoruz. İlerleyelim ve /?falan =bir&filan =iki URL sinden ne döndüğüne bir bakalım. 1 array(1) { ["falan"]=> string(3) "bir" } Laravel sadece falan için bir değer vermiştir. Bu, redirekt edilen istek için saklanan tek değerdir ve tam olarak bizim istemiş olduğumuz şeydir! only() metodunda olduğu gibi, flashonly() metodunun da bir karşıtı vardır ve o da except()e benzer tarzda çalışır. O, sadece sonraki istek için verdiğimiz değerlere uymayan değerleri saklayacaktır. Hızla bir göz atalım. 3 // app/routes.php 5 Route::get('/', function() 6 { 7 Input::flashExcept('falan'); 8 return Redirect::to('yeni/istek'); 9 }); Route::get('yeni/istek', function() 1 { 13 var_dump(input::old()); 1 }); Laravel e sadece falan anahtarı olmayan istek değerlerini saklamasını istediğimizi söyledik. Tabii ki, Laravel iyi bir framework gibi davranarak aşağıdaki sonucu verir. -Gözde Laravel- Şimdi /?falan =bir&filan =iki URL sini bir kez daha ziyaret edelim. 1 array(1) { ["filan"]=> string(3) "iki" } Mükemmel! falan hariç hepsini aldık. Tıpkı get(), only() ve except() metodları gibi old(), flashonly() ve flashexcept() metodları da ya bir parametreler listesi, ya da bir dizi alabilirler. Mesela:

151 İstek Verisi Input::old('birinci', 'ikinci', 'ucuncu'); Input::flashOnly('birinci', 'ikinci', 'ucuncu'); 3 Input::flashExcept('birinci', 'ikinci', 'ucuncu'); 5 Input::old(array('birinci', 'ikinci', 'ucuncu')); 6 Input::flashOnly(array('birinci', 'ikinci', 'ucuncu')); 7 Input::flashExcept(array('birinci', 'ikinci', 'ucuncu')); Bu gerçekten size kalmış! İstek verilerinizi anahtarlar şeklinde mevcut bir dizi kullanarak sınırlandırmak istediğinizde ikinci seçenek gerçekten yararlı olabilir. Diğer durumlarda parametrelerin sıralandığı ilk yöntemin daha temiz bir kod olduğunu düşünüyorum. Önceki örneklerde, input verimizi flash ettik, ondan sonra da sonraki isteğe redirekt yaptık. Bunlar web uygulamalarında her zaman olan şeylerdir. Örneğin, kullanıcılarınızın bir form doldurduğunu ve gönder düğmesine bastığını düşünün. Formu işleyen mantık kısmı cevapta bir hata olup olmadığına karar verecek ve buna göre form verisini flash edecek veya formu gösteren rotaya redirekt yapacaktır. Böylece formu mevcut verilerle doldurabileceksiniz ve kullanıcılarınız bu bilgilerin tümünü tekrar girmek zorunda kalmayacaklardır. İşte Taylor bunun yaygın bir uygulama olduğunu tespit etmiş. Bu sebeple de withinput() metodu dahil edilmiş. Aşağıdaki örneğe bir göz atalım. 3 // app/routes.php 5 Route::get('/', function() 6 { 7 return Redirect::to('yeni/istek')->withInput(); 8 }); Eğer redirekt zincirine withinput() metod halkasını takarsanız, Laravel sizin için şimdiki istek verisinin tamamını sonraki isteğe flashlayacaktır. Ne kadar hoş değil mi? Laravel sizi seviyor. Gerçekten seviyor. Bazı gecelerde, yatağınıza kıvrılıp yatarken Laravel gizlice odanıza girer ve yatağınızın yanına oturur. Yanaklarınızı yumuşak yumuşak okşar ve size tatlı ninniler söyler. Anneniz bile sizi asla Laravel kadar çok sevmeyecektir. Afedersiniz, biraz konu dışına çıktım yine. Her neyse, withinput() zinciri aşağıdaki kod parçasına benzer bir tarzda çalışır.

152 İstek Verisi // app/routes.php 5 Route::get('/', function() 6 { 7 Input::flash(); 8 return Redirect::to('yeni/istek'); 9 }); Bir numara olarak, withinput() zincir metodu ile flashonly() ve flashexcept() de kullanabilirsiniz. İşte bir Input::flashOnly() alternatifi. 3 // app/routes.php 5 Route::get('/', function() 6 { 7 return Redirect::to('yeni/istek')->withInput(Input::only('falan')); 8 }); withinput() zincir metoduna Input::only() metodunun sonucunu geçmek suretiyle, istek verisini Input::only() metodu içinde tanımlanan anahtarlar kümesine sınırlayabiliyoruz. Benzer şekilde, istek verisini yukarıdaki örneğin tersine sınırlamak için withinput() metoduna Input::except() metodunu geçebiliyoruz. Şöyle mesela: 3 // app/routes.php 5 Route::get('/', function() 6 { 7 return Redirect::to('yeni/istek')->withInput(Input::except('falan')); 8 }); Artık standart istek verisine nasıl erişeceğimizi biliyoruz fakat dosyalar biraz daha karmaşıktır. İstek verisi olarak sunulan dosyalar hakkında nasıl bilgi alabileceğimizi görelim şimdi de.

153 İstek Verisi 138 Gönderilmiş (Uploaded) Dosyalar Uygulamamızın alabileceği tek istek verisi metin verileri değildir. Çok parçalı kodlanmış bir formun (multipart encoded form) bir parçası olarak gönderilmiş olan dosyaları da alabiliriz. Bu veriyi nasıl alacağımızı görmeden önce, bir test ortamı oluşturmamız gerekiyor. Bu özelliği GET verisini kullanarak gösteremem çünkü gerçekte şimdiki URL ye bir dosya ekleyemeyiz. Bunun yerine basit bir form yapalım. Bir görünümle başlayalım. 1 <!-- app/views/form.blade.php --> 3 <form action ="{{ url('form-isle') }}" method ="POST" 5 enctype ="multipart/form-data"> 6 7 <input type ="file" name ="kitap" /> 8 <input type ="submit"> 9 </form> Burada bir dosya yükleme alanı ve bir gönder düğmesi olan bir formumuz var. multipart/form-data kodlama tipi olmadıkça dosyaların yüklenmesi çalışmayacaktır. Güzel, devam edelim. Görünüm yanında başka şeyler de gerekmiyor mu? Tamam, doğru, formu göstermek için bir rotaya ihtiyacımız var. Bu nasıl sizce? 3 // app/routes.php 5 Route::get('/', function() 6 { 7 return View::make('form'); 8 }); Yeni bir şey yok orada, umarım şaşırmadınız! OMG, BU NE? Erm, belki de rotalama bölümüne geri dönseniz daha iyi olacak! Geri kalanlarımız için ikinci bir rota oluşturalım ve ne aldığımızı görmek için istek verisini dump edelim.

154 İstek Verisi // app/routes.php 5 Route::get('/', function() 6 { 7 return View::make('form'); 8 }); 9 10 Route::post('form-isle', function() 11 { 1 var_dump(input::all()); 13 }); Peki, formu görmek için şimdi / rotasını ziyaret edelim. Şimdi dump edilen istek verisinden ne aldığımızı görmek için bir dosya upload etmemiz gerekiyor. Tamam bir dosya gerekiyor hrm. Ooo, eveet, zeki bir dostumun Laravel hakkında harika bir kitap yazdığını hatırladım. Bu PDF yi upload edeyim! Bu kitabı genele açık bir siteye upload etmenizi teşvik etmediğime dikkat edin. Zaten bir hafta içinde çıkacak ve telif ihlali konusunda zaten 5 gönderdim! Sayıyı artırmanın alemi yok! Tamam, Code Bright PDF yi seçin ve gönder düğmesine basın! Ne cevap aldınız? 1 array(0) { } Hey, ne yapıyorsun Laravel? Bizim dosyamızı ne yaptın? Ah, tamam doğru, PHP de, dosyalar $_GET veya $_POST dizilerinde depolanmıyor. PHP bu değerleri $_FILES dizisinde saklar ama Laravel (tabi, aslında Symfony) bu dizi yerine güzel bir sarıcı sağlamaktadır. Bak nasıl yapılıyor. 3 // app/routes.php 5 Route::get('/', function() 6 { 7 return View::make('form'); 8 }); 9 10 Route::post('form-isle', function() 11 { 1 var_dump(input::file('kitap')); 13 });

155 İstek Verisi 10 İkinci rotamızı değiştirdik, bir string olarak elde etmek istediğimiz inputun name niteliğini (formdaki) vererek Input::file() metodunun değerini dump ettik. Bizim dosyamızı temsil eden bir nesneyi elde ettik. 1 object(symfony\component\httpfoundation\file\uploadedfile)#9 (7) { ["test":"symfony\component\httpfoundation\file\uploadedfile":private]=> 3 bool(false) ["originalname":"symfony\component\httpfoundation\file\uploadedfile":private]=> 5 string(1) "codebright.pdf" 6 ["mimetype":"symfony\component\httpfoundation\file\uploadedfile":private]=> 7 string(15) "application/pdf" 8 ["size":"symfony\component\httpfoundation\file\uploadedfile":private]=> 9 int(37013) 10 ["error":"symfony\component\httpfoundation\file\uploadedfile":private]=> 11 int(0) 1 ["pathname":"splfileinfo":private]=> 13 string(36) "/Applications/MAMP/tmp/php/phpPOb0vX" 1 ["filename":"splfileinfo":private]=> 15 string(9) "phppob0vx" 16 } Güzel! Tamam Evet çok güzel olmayabilir. Yaptık ama! Neyse ki, bu nesne kendisiyle etkileşim yapabileceğimiz bazı metodlara sahiptir. Bu nesnenin metodlarının Symfony projesine ait olduğunu ve bir kısmının PHP SplFileInfo sınıfından türetildiğini unutmayın. Açık kaynağın güzelliği budur, paylaşım önem vermektir! Symfony ve PHP nin isimlendirme gelenekleri Laravel inkinden bir parça daha uzun olma eğilimindedir ancak etkilidir. Şimdi birincisine bir göz atalım. 3 // app/routes.php 5 Route::get('/', function() 6 { 7 return View::make('form'); 8 }); 9 10 Route::post('form-isle', function() 11 { 1 return Input::file('kitap')->getFileName(); 13 });

156 İstek Verisi 11 Bizim file nesnemize getfilename() metodunu ekledik ve onun değerini form-isle rota Closure unun sonucu olarak atadık. Sonucu görmek için Code Bright PDF yi bir kez daha gönderelim. 1 phpal1ezs Bekle bir saniye, bu ne? Sizdeki sonuç bundan farklı da görünse yine kafa karıştırıcı bir isim olacaktır. Gördüğünüz gibi bu, yüklediğimiz dosyaya geçici konumunda verilen geçici dosya adıdır. Eğer isteğin sonunda onu başka bir yere taşımazsanız, oradan kaldırılacaktır. Geçici isim şu an için çok yararlı değildir. Upload edildiği zaman dosyanın gerçek adının ne olduğunu bulmaya çalışalım. Hmm, şu metodu deneyelim. 3 // app/routes.php 5 Route::get('/', function() 6 { 7 return View::make('form'); 8 }); 9 10 Route::post('form-isle', function() 11 { 1 return Input::file('kitap')->getClientOriginalName(); 13 }); Bu sefer getclientoriginalname() metodunu deneyeceğiz. Kitabı upload ettikten sonra alacağımız sonucu görelim. 1 codebright.pdf Şimdi ona daha benzedi! Dosyanın gerçek adını elde ettik. Metodun adı biraz hantal ama doğru bir şekilde iş görüyor. Pek tabii, dosya gönderilerini düşününce, dosya adından başka bilgiler de söz konusudur. Şimdi de dosya boyutunu nasıl bulacağımızı görelim.

157 İstek Verisi 1 3 // app/routes.php 5 Route::get('/', function() 6 { 7 return View::make('form'); 8 }); 9 10 Route::post('form-isle', function() 11 { 1 return Input::file('kitap')->getClientSize(); 13 }); Dosya yükledikten sonra alacağımız şey bir sayıdır Bu sayılar kazanan piyango numaralarıdır. Bilet almıştınız değil mi? Bu güzel olurdu ama üzgünüm, bu sadece gönderilen dosyanın boyutudur. Symfony API değerin formatının ne olduğunu söylemiyor ama zekice bazı matematik işlemleriyle bunun bayt cinsinden dosya boyutu olduğunu keşfettim. Üzerinde çalıştığımız dosyanın ne türde olduğunu bilmek işimize yarayabilir, o zaman bu amaca hizmet eden bir çift metodu görelim. Birincisi getmimetype() metodudur. Haydi uygulayalım. 3 // app/routes.php 5 Route::get('/', function() 6 { 7 return View::make('form'); 8 }); 9 10 Route::post('form-isle', function() 11 { 1 return Input::file('kitap')->getMimeType(); 13 }); Alacağımız sonuç bir mime tipidir. Bu, dosyaları tanımlamak için kullanılan bir gelenektir. Code Bright kitabının sonucu şudur.

158 İstek Verisi 13 1 application/pdf Bu sonuçla biz dosyanın bir PDF olduğunu açıkça görebiliyoruz. file sınıfı mime tipinden dosya uzantısını tahmin etmeyi deneyebileceğimiz bir metoda da sahiptir. Bu guessextension() metodunu eyleminde görelim. 3 // app/routes.php 5 Route::get('/', function() 6 { 7 return View::make('form'); 8 }); 9 10 Route::post('form-isle', function() 11 { 1 return Input::file('kitap')->guessExtension(); 13 }); Bir kez daha gönderdiğimizde aşağıdaki cevabı alırız. 1 pdf Mükemmel, dosyamız kesinlikle bir PDF. Pekiyi, bunu nasıl izleyeceğiz? Göndermiş olduğumuz dosya orada bekleyip durmuyor. Eğer dosyayı istek sona ermeden önce taşımazsak, onu kaybedeceğiz. Böyle olsun istemiyorum! O çok güzel bir kitap. Onu muhafaza etmeliyim. Öncelikle bu dosyanın şu anda nerede bulunduğunu bulmaya çalışalım. UploadedFile sınıfı bu görevde bize yardımcı olacak bir metoda sahiptir. Hadi görelim. 3 // app/routes.php 5 Route::get('/', function() 6 { 7 return View::make('form'); 8 }); 9

159 İstek Verisi 1 10 Route::post('form-isle', function() 11 { 1 return Input::file('kitap')->getRealPath(); 13 }); Göndermiş olduğumuz dosyanın şu andaki konumunu elde etmek için getrealpath() metodunu kullanabiliyoruz. Code Bright ı gönderince alacağımız cevabın ne olduğunu görelim. 1 /tmp/php/phplfbuaq Artık dosyamızın nerede olduğunu biliyoruz, ilerde onu kullanmak için dosyamızı bir yerlere kaydetmek için copy() veya rename() gibi şeyleri rahatlıkla kullanabiliriz. Daha iyi bir yolu var bunun. File nesnesi üzerinde move() metodunu kullanabiliriz. Bu metodun nasıl çalıştığını görelim. 3 // app/routes.php 5 Route::get('/', function() 6 { 7 return View::make('form'); 8 }); 9 10 Route::post('form-isle', function() 11 { 1 Input::file('kitap')->move('/storage/dizin'); 13 return 'Dosya taşındı.'; 1 }); Bu move() metodunun ilk parametresi dosyanın taşınacağı hedef konumdur. Web sunucunuzu çalıştıran kullanıcının bu hedef konuma yazma izni olduğundan emin olun, aksi takdirde bir istisna oluşacaktır. Kitabı bir kez daha upload edip ne olduğunu görelim. Eğer storage dizininize bakarsanız, dosyanın taşınmış olduğunu göreceksiniz ancak ismi hala PHP nin ona verdiği geçici isimdir. Belki biz geçici isim yerine dosyanın gerçek ismini tutmak isteyebiliriz. Neyse ki, move() metodu dosyaya bizim kendi seçeceğimiz bir isim vermemize imkan veren ilave, opsiyonel bir parametre de kabul eder. Eğer dosyanın gerçek adını elde eder ve onu move() metoduna ikinci parametre olarak geçersek, hedef konumuna daha mantıklı bir isimle varacaktır. Bir örnek üzerinden görelim.

160 İstek Verisi 15 3 // app/routes.php 5 Route::get('/', function() 6 { 7 return View::make('form'); 8 }); 9 10 Route::post('form-isle', function() 11 { 1 $isim = Input::file('kitap')->getClientOriginalName(); 13 Input::file('kitap')->move('/storage/dizin', $isim); 1 return 'Dosya taşındı.'; 15 }); İlk olarak gerçek dosya adını getclientoriginalname() metoduyla elde ediyoruz. Sonra bu değeri move() metoduna ikinci parametre olarak geçiyoruz. Şimdi storage dizinine bir daha bakalım. İşte orada! codebright.pdf adında bir dosyamız var. Bu bölümde dosyalar hakkında anlatacaklarım bu kadar, fakat ayıracak bir zamanınız varsa UploadedFile sınıfı için Symfony API belgelerine²⁴ ve bu sınıftan türetilen metodlara bakmanızı öneririm. Çerezler Çerezlere bakmak istemiyorum çünkü geçen yıldan beri düşük karbonhidrat diyetindeyim. Bu şeyler sadece şekerle dolu. Bunu yapmanın hiçbir yolu yok. Üzgünüm çocuklar. Düşük karbonhidratlı bademli kurabiyelere ne dersin? Oo bak hele. Düşük karbonhidrat püf noktalarının hepsini biliyorsunuz yoksa bilmiyor musunuz? Güzel, çerezler düşük karbonhidratlı ise anlatabilirim sanırım. Pekala, çerezler (cookies) nedir? Bunlar gerçekte besin değildir. Bunlar bazı verilerin istemci tarafında yani tarayıcıda depolanması için bir yöntemdir. Bunlar pek çok şey için gerçekten kullanışlı olabilir. Örneğin, kullanıcılara sitenizi ilk kez ziyaret ettikleri zaman bir mesaj göstermek isteyebilirsiniz. Bir çerez mevcut değilse bu iletiyi gösterebilirsiniz ve mesaj görüldüğü zaman, çerezi ayarlarsınız. Çerezlerde istediğiniz her şeyi saklayabilirsiniz. İstediğiniz kadar üretken olun! Dikkatinizi çekebildim mi? Güzel! Bir çerez nasıl oluşturuluyor bakabiliriz öyleyse. ²⁴

161 İstek Verisi 16 Çerezlerin Ayarlanması ve Elde Edilmesi 3 // app/routes.php 5 Route::get('/', function() 6 { 7 $cookie = Cookie::make('az-sekerli', 'bademli kurabiye', 30); 8 }); Yeni bir çerez oluşturmak için Cookie::make() metodunu kullanabiliyoruz. Çok açıklayıcı değil mi? Güzel iş Taylor! Metodun birinci parametresi çerezimizi tanımlamak için kullanacağımız bir anahtardır. İleride değeri elde etmek için bu anahtarı kullanmamız gerekecek. İkinci parametre ise çerezimizin değeridir. Verdiğimiz örnekte bademli kurabiye stringidir. Üçüncü ve son parametre Laravel in bu çerezi dakika cinsinden ne süreyle tutacağını bilmesini sağlar. Yukarıdaki örneğimizde, çerez 30 dakika boyunca var olacaktır. Bu zaman geçtikten sonra çerez sona erecek ve bir daha elde edilemeyecektir. Çerezin işlevselliğini test edebilmek için rotamızda küçük bir değişiklik yapalım. Yeni rota dosyamız bunun gibi gözükür: 3 // app/routes.php 5 Route::get('/', function() 6 { 7 $kurabiye = Cookie::make('az-sekerli', 'bademli kurabiye', 30); 8 return Response::make('Ham ham.')->withcookie($kurabiye); 9 }); Route::get('/ham-ham', function() 1 { 13 $kurabiye = Cookie::get('az-sekerli'); 1 var_dump($kurabiye); 15 }); URL /ya cevap veren ilk rotamızda, önceki örneğimizde yaptığımız aynı yolla bir çerez oluşturuyoruz. Ancak bu sefer, withcookie() metodunu kullanarak onu cevabımıza tutturuyoruz. Bu withcookie() metodu bir cevap nesnesine bir çerez bağlamak için kullanılabilmektedir. Cevap sunulduğu zaman, çerez oluşturulur. withcookie() metoduna geçilen tek parametre oluşturduğumuz çerezdir.

162 İstek Verisi 17 /ham-ham rotası Cookie::get() metodunu kullanarak çerezi elde edecektir. Birinci ve tek parametre elde edilecek çerezin ismidir. Bu örnekte bizim az-sekerli çerezimizi elde ediyor ve sonucu dump ediyoruz. Şimdi çıktıyı test edelim. Önce çerezimizi ayarlamak için / rotasını ziyaret edelim. 1 Ham ham. Harika, cevap sunulmuştur ve çerezimiz ayarlanmış olmalıdır. Emin olmak için /ham-ham rotasını ziyaret edelim. 1 string(16) "bademli kurabiye" Mükemmel! Çerezimizi başarıyla elde ettik. Eğer 30 dakika beklersek ve sonra çerezi bir kez daha elde etmeye çalışırsak null değerini alacağız. Input::get() metodu gibi, Cookie::get() metodu da ikinci parametre olarak ön tanımlı bir değer kabul edecektir, şöyle bir şey: 1 $kurabiye = Cookie::get('az-sekerli', 'tavuklu'); Güzel, şimdi eğer az şekerli çerez yoksa en azından tavuklu alacağız. Bir çerez ayarlanmış olup olmadığını yoklamak için Cookie::has() metodunu kullanabiliriz. Bu metod birinci parametre olarak çerezin adını alır ve boolean bir sonuç döndürür. Şuna benzer. 1 Route::get('/ham-ham', function() { 3 var_dump(cookie::has('az-sekerli')); }); Daha önceden bahsettiğim gibi, çerezlerinizin bir bitiş zamanı olacaktır. Belki çerezlerinizin sona ermesini istemezsiniz? Laravel in zihin okuma gücü sayesinde, asla sona ermeyecek bir çerez oluşturmak için Cookie::forever() metodunu kullanabiliriz. Metodun birinci ve ikinci parametreleri aynıdır: bir anahtar ve bir çerez değeri. İşte bir örnek:

163 İstek Verisi 18 3 // app/routes.php 5 Route::get('/', function() 6 { 7 $kurabiye = Cookie::forever('az-sekerli', 'bademli kurabiye'); 8 return Response::make('Ham ham.')->withcookie($kurabiye); 9 }); Mutfak dolabınızdaki çerezlerden farklı olarak, forever() metoduyla yapılanların bir son kullanma tarihi yoktur. Eğer bir çerezi silmek veya daha doğrusu sona ermeye zorlamak istersek Cookie::forget() metodunu kullanabiliriz. Bu metodun tek parametresi unutmak istediğimiz çerezin adıdır. İşte bir örnek. 3 // app/routes.php 5 Route::get('/', function() 6 { 7 Cookie::forget('az-sekerli'); 8 return 'Sanırım tavuklu yemek zorunda kalacağız.'; 9 }); Aynen öyle, az şekerli kurabiyemiz gitti. Çerez Güvenliği Laravel in zeki küçük bir maymun olduğunu gösteren başka bir örnek. Bir kullanıcı tarayıcıda saklanan çerezleri düzenleyebilir. Eğer çereziniz websiteniz için bir şekilde önemliyse, kullanıcın ona müdahale etmesini istemezsiniz. Bizim çerezlerimizin tahrif edilmediğinden emin olmalıyız. Neyse ki, Laravel bizim çerezlerimizi bir kimlik doğrulama kodu ile işaretler ve kriptolar, böylece kullanıcılarımız çerezleri okuyamazlar ve onları düzenleyemezler. Eğer bir çerez tahrif edilmiş ve kimlik doğrulama kodu Laravel in beklediği gibi değilse, bu durumda Laravel tarafından göz ardı edilecektir. Çok zekice değil mi?

164 Formlar Los Angeles ta soğuk, karanlık bir geceydi, fakat Dolby Tiyatrosunun ışıkları sokakları öyle aydınlatıyordu ki, gündüz zannedebilirdiniz. Bildiğiniz gibi mekan Şubat ayındaki Akademi Ödülleri için ayarlanmıştı, o gece sunulan Oscarların hepsini Iron Man kazanmıştı, kesinlikle, tamamen müthiş bir şeydi. Aslında, bu kitap iyi satarsa California da bir mansiyon alabilirim; belki onun altında süper bir laboratuvar oluşturabilirim. Orada kırmızı pandaya benzer bir dış iskelet modası üzerine çalışabilirim. Tony Stark tan farklı olarak süpermodelleri yalnız bırakırım. Emma nın bu komik işe aday olacağını hiç sanmıyorum. Ben kendime The Fire Fox adını verdim ve gücümü ve aletlerimi PHP toplumu içerisinde ortaya çıkan argümanları sekmeler ve boşluklara yerleştirmek için kullanıyorum. Ayrıca Mozilla davasını alma gücüne sahibim. Buna rağmen belki de hiç Audi süremeyeceğim. Ben onun yerine tamam. Afedersiniz, biraz konu dışına çıktım. Neredeydik? Ah evet, Dolby Tiyatrosu. Görüyorsunuz, Oscarlar sadece çok daha yüksek profilli bir olayın, Laravel dört galasının önünü açıyordu. Laravel 3 tarafından kurtarılmış PHP geliştiricileri yeni frameworkun lansmanını bekleyen milyonlarla bir araya gelmişti. Kalabalıklar sokakları dolduruyordu ve her yerde gazeteciler vardı! Hayal edin, gerçekten değil. Bunun çoğunu hayal edeceksiniz, ben sizin için kurgusal bir yazar değilim. Sadece bunun televizyonda nasıl görüneceğini hayal edin. Uzun, siyah bir limuzin kaldırıma yaklaşır. Kapı açılır ve uzun bir figür kırmızı halıda yürümeye başlar. Herkes çıldırır! Kadınlar üstlerini yırtar, erkekler birbirlerinin üstlerini yırtar, gazeteciler üstlerini yırtar, herkes üstsüzdür. Bunun nereye gideceğini bilmiyorum ancak bu benim öyküm, ben herkesin üstsüz olduğunu söylüyorum. Neyse, bu figür şüphesiz Laravel i yazan Taylor Otwell dan başkası değil. Taylor tiyatronun girişine adımını atmadan önce, gazeteciler Laravel dört konusunda bombardımana tuttular. O üstsüz gazetecileri itmeye çalıştı ancak onlardan çok vardı. Laravel dört üzerinde ne zamandır çalışıyorsunuz? Şu anda bir yıl kadar. diyor Taylor, devam edebilmek için tek şansının sorulardan bir kısmına cevap vermek olduğunu düşünerek. Üstsüz gazeteci sorusuna aldığı cevaptan tatmin olmuş görünüyor ve Taylor un geçmesine izin veriyor. Başka bir üstsüz gazeteci hızla Taylor un önüne geçiyor ve başka bir soru soruyor. Laravel dört üzerinde ne zamandır çalışıyorsunuz?

165 Formlar 150 Bekle bir saniye. Bu soru zaten sorulmamış mıydı? Tekrar değil. diye düşündü, kendini tekrar etmekten nefret ederdi. Bir yıl kadar. dedi sert bir sesle. Kalabalığın arasından kendini öne itmişti ki, yolu başka bir üstsüz gazeteci tarafından kesildi. Laravel oldukça uzun bir proje. Onu yazmak ne kadar zaman aldı? Taylor ani bir şey yaptı, cebine uzandı ve bir klavye çıkardı. Taylor gibi uzun cepler oh klavye oraya nasıl sığdı, ben bununla yapıyorum. Klavyeyle gazetecinin yüzüne vurdu ve üstsüz adamı yakındaki bir çöp bidonuna gönderdi. Belgeleri okumadınız mı!? Taylor yağlı çöp bidonundan çıkmaya çalışan gazeteciye bağırdı. Ben form oluşturucusu yaptım, bu sayede formlarınızı şablonlar içinde tanımlayabiliyorsunuz. Eğer önceden bir form yapmış olsaydınız, tüm bu tekrarları önleyebilirdik. BEN TEKRARDAN NEFRET EDERİM, diye hırladı Taylor. Etrafında döndü ve kuliste onu bekleyen Laravel ekibinin olduğu kapıya fırladı. Evet. Tüm bunlar form oluşturucu inşa etmek içindi. Hayal kırıklığına uğramış gibi bakmayın bana! Ben teknik bir yazarım, kurgusal yazar değil. Ne bekliyordunuz ki Bir Buz ve Ateş Şarkısı mı? Peki, onunla başlayalım! Bu bölüm gerçek bir ikilem arz ediyor. Tamam, sadece bu bölüm değil. Problemi benden daha iyi çözüp çözemeyeceğinizi görelim. Birbirine geçmiş konular işte burada. İstek Verisi Formlar Geçerlilik Denetimi Gördüğünüz gibi, bunların hepsi büyük konular ancak aynı zamanda birbirilerine dayanıyorlar. İstek verisini nasıl elde edeceğinizi bilmeden bir formdan gelen cevabı test edemezsiniz. Geçerlilik denetimini öğrenmeden önce formların yeniden doldurulmasını gösteremezsiniz. Gerçek bir kördüğüm. Peki, problemi nasıl çözeceğime geçiyorum. Formlar nasıl oluşturulur ve bunlar çatı rotalarına nasıl hedef gösterilir onu öğrenmekle başlıyoruz. Ancak, formlarımızın açıklamalarından bir kısmı sonraki bölümde yer alacaktır ve orada geçerlilik denetimi yaptıktan sonra formların tekrar nasıl doldurulacağını öğreneceğiz. Haydi başlayalım! Formların Açılması Veriyi göndermeden önce onu nereye göndereceğimize karar vermemiz gerekiyor. URL üretimi bölümünde çatı URL lerinin nasıl oluşturulduğunu görmüştük. O bölümden kaptığımız becerilerle bir form açma tagını kolaylıkla oluşturabiliriz, doğru mu? İsterseniz basit bir görünüm oluşturalım:

166 Formlar <!-- app/views/form.blade.php --> 3 <form action ="{{ url('bizim/hedef/rota') }}" method ="POST"> 5 </form> Burada bizim formun action niteliği için bir çatı URL si sağlamak amacıyla url() helper metodunu kullanıyoruz. form.blade.php blade şablonumuzu göstermek için bir rota closure ı da ekleyelim. 3 // app/routes.php 5 Route::get('/', function() 6 { 7 return View::make('form'); 8 }); Mükemmel! Gösterilecek kaynağı görmek için şimdi / url yi ziyaret edelim. Şuna benzer görünecektir. 1 <!-- app/views/form.blade.php --> 3 <form action =" method ="POST"> 5 </form> Formumuz şimdi toplayacağı veriler için bir hedef konuma sahiptir. Bu benim formları oluşturma eğilimim ancak Laravel bir seçenekler frameworküdür. Burada belki sizin tercih edeceğiniz başka bir form açma HTML si oluşturma yöntemini veriyorum. Bir bakalım. 1 <!-- app/views/form.blade.php --> 3 {{ Form::open(array('url' => 'bizim/hedef/rota')) }} 5 {{ Form::close() }} Form açılış tagı oluşturmak için Form::open() üretici metodunu kullanıyoruz. Bu metod birçok parametreli tek bir parametre kabul eder. Kafanız mı karıştı? Bir diziden bahsediyorum! Yukarıdaki örnekte formun hedefi olmasını istediğimiz bir rota değeri olan URL indeksini kullanıyoruz. Ayrıca formu kapatmak için Form::close() metodunu kullanıyoruz, gerçi bunu yapmamızı gerektiren bir sebep göremiyorum. Diğer kaynak üretme metodları yanında daha düzgün görünüyor değil mi? Bunu ya da bunun yerine </form> kullanmayı seçmek size kalmış. Gösterilen form görünümümüzün kaynağı şöyledir.

167 Formlar 15 1 <!-- app/views/form.blade.php --> 3 <form method ="POST" action =" accept-charset ="UTF\ -8"> 5 <input name ="_token" type ="hidden" value ="83KCsmJF1ZLMZfhb17ihvt9ks5NEcAwFoR\ 6 FTq6u"> 7 </form> Harika, formumuz aynı hedef için oluşturulmuş. Burada sizden gerçekten önemli bir şey isteyeceğim, buradaki gizli _token niteliğini lütfen göz ardı eder misiniz? Merak etmeyin, ilerde geri döneceğiz! Şimdilik o yokmuş gibi yapacağım. Bekleyin, biz sadece bir tek URL niteliğini verdik. Neden orada başka nitelikler var? Konuyu _token inputundan uzak bir yöne değiştirmek için yaptım. _token nedir? Harika! Tamam, sizin sorunuza geri dönelim. Gördüğünüz gibi, Laravel web uygulamaları yapılırken en popüler seçimin POST formlar olduğunu bilir. Bu sebeple, HTML nin kabul ettiği ön tanımlı GET metodunu geçersiz kılarak ön tanımlı olarak POST metodunu kullanacaktır. accept-charset niteliği ise Laravel in bize sağladığı bir diğer yararlı niteliktir. Formu gönderirken karakter kodlaması olarak UTF-8 kullanılmasını temin edecektir. Bu çoğu durum için mantıklı bir ön tanımdır. Belki de mantıklı ön tanımlar bizim durumumuza uygun değildir? Bunları kendimiz nasıl verebiliriz? 1 <!-- app/views/form.blade.php --> 3 {{ Form::open(array( 'url' => 'bizim/hedef/rota', 5 'method' => 'GET', 6 'accept-charset' => 'ISO ' 7 )) }} 8 9 {{ Form::close() }} Burada formumuzun metodu olarak GET kullanmak istediğimizi belirtmek için Form::open() dizimizin method anahtarını kullandık. Ayrıca, kodlama için farklı bir karakter seti sağlamak için accept-charset anahtarını kullandık. Yeni HTML kaynağımız şöyledir.

168 Formlar <!-- app/views/form.blade.php --> 3 <form method ="GET" action =" accept-charset ="ISO-\ "> 5 <input name ="_token" type ="hidden" value ="83KCsmJF1ZLMZfhb17ihvt9ks5NEcAwFoR\ 6 FTq6u"> 7 </form> Mükemmel! Biz uygun ön tanımlar için Laravel in görüşlerine değer verirken, onları geçersiz kılmak için tüm esnekliğe de sahibiz. Bu denli güçlü olduğumuza göre neden metod niteliği olarak DELETE HTTP fiilini kullanan bir form oluşturmayalım. Formun metodunu method dizi anahtarı ile değiştirebileceğimizi biliyoruz. Hadi yapalım. 1 <!-- app/views/form.blade.php --> 3 {{ Form::open(array( 'url' => 'bizim/hedef/rota', 5 'method' => 'DELETE' 6 )) }} 7 8 {{ Form::close() }} Bana mükemmel görünüyor, şimdi oluşturulan HTML kaynağını kontrol edelim. 1 <!-- app/views/form.blade.php --> 3 <form method ="POST" action =" accept-charset ="UTF\ -8"> 5 <input name ="_token" type ="hidden" value ="83KCsmJF1ZLMZfhb17ihvt9ks5NEcAwFoR\ 6 FTq6u"> 7 <input name ="_method" type ="hidden" value ="DELETE"> 8 </form> Bekleyin, orada neler oluyor? Biz bir POST metodu istememiştik. O ekstra input nedir? Aaa evet, şimdi hatırladım. HTML formları biraz aptaldır. Bildiğiniz gibi, HTML formlarda sadece POST ve GET metodlarını destekler. HTML5 ilave metodları da destekler ancak biz uygulamalarımızı HTML5 i tam destekleyen tarayıcılarla sınırlı tutmak istemeyiz. Merak etmeyin, Laravel in kolunun altında başka bir hile var. _method adında gizli bir input vermek suretiyle, HTML5 uyumlu olmayan HTTP fiillerini temsil edecek bir değer verebiliyoruz. Laravel in rotalaması bu POST isteğine bakacak, _method verisi dahil edildiğini görecek ve uygun eyleme rota yapacaktır. Bu hem HTML hem de HTML5 te çalışacaktır, ne kadar harika değil mi?

169 Formlar 15 Geçtiğimiz bölümde dosya göndermeyi ve onlar hakkında bilgi almayı öğrendiğimizi hatırlıyor musunuz? Dosyaların düzgün biçimde gönderilebilmesi için ilgili formun multipart/form-data değerinde bir enctype niteliği olması gerektiğini de hatırlıyor olabilirsiniz. İşte Laravel bu enctype niteliğini etkin hale getirmek için kolay bir yol sağlamıştır. Nasıl yaptığını görelim. 1 <!-- app/views/form.blade.php --> 3 {{ Form::open(array( 'url' => 'bizim/hedef/rota', 5 'files' => true 6 )) }} 7 8 {{ Form::close() }} Değeri boolean true olan files adlı yeni bir anahtar vermek suretiyle, Laravel dosya gönderimlerine imkan vermek için gerekli niteliği ekleyecektir. Yukarıdaki örnekle üretilen kaynak şöyledir. 1 <!-- app/views/form.blade.php --> 3 <form method ="POST" action =" 5 accept-charset ="UTF-8" 6 enctype ="multipart/form-data"> 7 <input name ="_token" type ="hidden" value ="83KCsmJF1ZLMZfhb17ihvt9ks5NEcAwFoR\ 8 FTq6u"> 9 </form> Ben okunması kolay olsun diye cevapta küçük bir biçimlendirme yaptım, fakat içeriği değiştirmedim. Görebileceğiniz gibi, Laravel bizim adımıza doğru kodlama tipini vermiştir. Tekrar teşekkürler Laravel! URL üretimi ve rotalama bölümlerinde isimli rotalar ve denetçi eylemlerine URL üretmenin özel metodlar kullanılarak yapılabildiğini öğrenmiştiniz. Şimdi Form::open() metodunda özel anahtarlar kullanarak bu rota ve eylemleri nasıl hedefleyebileceğimizi görelim. Önce isimli rotaları nasıl hedefleyebileceğimize bakalım. İşte bir örnek.

170 Formlar <!-- app/views/form.blade.php --> 3 {{ Form::open(array( 'route' => 'benim_rotam' 5 )) }} 6 7 {{ Form::close() }} url anahtarını kullanmak yerine, route anahtarını kullanıyoruz ve bir değer olarak rotanın adını veriyoruz. Bu kadar basit! Aslında, denetçi eylemlerini hedeflemek de bu kadar kolaydır. İsterseniz başka bir örneğe göz atalım. 1 <!-- app/views/form.blade.php --> 3 {{ Form::open(array( 'action' => 'BenimController@eylemim' 5 )) }} 6 7 {{ Form::close() }} Formumuzun hedefinin bir denetçi eylemi olması için, url ve route anahtarları yerine, action anahtarını kullanıyoruz ve değer olarak denetçi-eylem çiftini veriyoruz. Pekiyi, artık formların nasıl açılacağını biliyoruz, bazı alanlar eklemeye başlama zamanının geldiğini düşünüyorum. Haydi başlayalım! Form Alanları Formlar bir veri toplama yolu sağlamadıkları sürece çok işe yaramazlar. Laravel in form oluşturma kitaplığını kullanarak üretebileceğimiz form alanlarının bir kısmını görelim. Alan Etiketleri Durun, alanların kendileri dışında ihtiyacımız olan başka bir şey var. İnsanların ne değerler gireceğini bilmesi için etiketlere (label) ihtiyacımız var. Etiketler Form::label() metodu kullanılarak üretilebilirler. Haydi bir örneğe bakalım.

171 Formlar <!-- app/views/form.blade.php --> 3 {{ Form::open(array('url' => 'benim/rotam')) }} {{ Form::label('ilk_isim', 'Ad') }} 5 {{ Form::close() }} Form::label() metodunun ilk parametresi tarif ettikleri alanın name niteliğine tekabül eder. İkinci değer ise etikette görülecek metindir. Üretilen kaynağa bakalım. 1 <!-- app/views/form.blade.php --> 3 <form method ="POST" action =" 5 accept-charset ="UTF-8"> 6 <input name ="_token" type ="hidden" value ="83KCsmJF1ZLMZfhb17ihvt9ks5NEcAwFoR\ 7 FTq6u"> 8 <label for ="ilk_isim">ad</label> 9 </form> Süper! Alanlarımızı tarif etmek için hep label kullanabiliriz. Bölüm içindeki diğer alan örnekleri ile de bunları kullanacağım. label() metoduna üçüncü bir parametre vererek, üretilen label elementi içinde başka nitelik ve değer çiftleri verebileceğimizi unutmayın. Üçüncü parametre nitelik ve değer çiftlerinden oluşan bir dizidir. İşte bir örnek. 1 <!-- app/views/form.blade.php --> 3 {{ Form::open(array('url' => 'benim/rotam')) }} {{ Form::label('ilk_isim', 'Ad', 5 array('id' => 'ilk_isim')) }} 6 {{ Form::close() }} Yukarıdaki örnekte label elementine değeri ilk_isim olan bir id niteliği eklemiş olduk. Üretilen kod şöyledir.

172 Formlar <!-- app/views/form.blade.php --> 3 <form method ="POST" action =" 5 accept-charset ="UTF-8"> 6 <input name ="_token" type ="hidden" value ="83KCsmJF1ZLMZfhb17ihvt9ks5NEcAwFoR\ 7 FTq6u"> 8 <label for ="ilk_isim" id ="ilk_isim">ad</label> 9 </form> Harika! Tamam, şimdi alanlarımızı nasıl etiketleyeceğimizi öğrendik, artık biraz alan oluşturmaya geçebiliriz. Text Alanları Text alanları string veri değerleri toplamak için kullanılabilirler. Bu alan tipinin jeneratörü şöyledir. 1 <!-- app/views/form.blade.php --> 3 {{ Form::open(array('url' => 'benim/rotam')) }} {{ Form::label('ilk_isim', 'Ad') }} 5 {{ Form::text('ilk_isim', 'Taylor Otwell') }} 6 {{ Form::close() }} Form::text() metodunun ilk parametresi ilgili elementin name niteliğidir. Bu nitelik, istek veri koleksiyonumuzdaki alanın değerini saptamak için kullanacağımız şeydir. İkinci parametre opsiyoneldir. İnput elementi için bir ön tanım değeridir. Bu metodla üretilen kaynağa bir göz atalım. 1 <!-- app/views/form.blade.php --> 3 <form method ="POST" action =" 5 accept-charset ="UTF-8"> 6 <input name ="_token" type ="hidden" value ="83KCsmJF1ZLMZfhb17ihvt9ks5NEcAwFoR\ 7 FTq6u"> 8 <label for ="ilk_isim">ad</label> 9 <input name ="ilk_isim" type ="text" value ="Taylor Otwell" id ="ilk_isim"> 10 </form> İnput elementimiz oluşturulmuş ve name niteliği bir ön tanım değerine ayarlanmıştır. Tıpkı Form::label() metodunda olduğu gibi, Form::text() metodu da nitelik ve değer çiftlerinden oluşan bir dizi biçiminde üçüncü bir opsiyonel parametre daha alabilmektedir, mesela şöyle:

173 Formlar <!-- app/views/form.blade.php --> 3 {{ Form::open(array('url' => 'benim/rotam')) }} {{ Form::label('ilk_isim', 'Ad') }} 5 {{ Form::text('ilk_isim', 'Taylor Otwell', 6 array('id' => 'ilk_isim')) }} 7 {{ Form::close() }} Gerçek şu ki, input jeneratörlerinden her biri son bir parametre olarak opsiyonel bir nitelikler dizisi alabilmektedir. Bunların hepsi aynı şekilde iş görür, bu yüzden her kesimde bu özelliği açıklamayacağım. Ama bunu hep aklınızda tutun! Textarea Alanları Textarea alanı text inputuyla aynı şekilde iş görür ama textarea çok satırlı veriye izin vermektedir. Bunların nasıl üretildiğine göz atalım. 1 <!-- app/views/form.blade.php --> 3 {{ Form::open(array('url' => 'benim/rotam')) }} {{ Form::label('aciklama', 'Açıklama') }} 5 {{ Form::textarea('aciklama', 'Şimdiye kadarki en iyi alan!') }} 6 {{ Form::close() }} İlk parametre elementin name niteliğidir ve ikinci parametre yine varsayılan değerdir. Üretilen HTML kaynağında gözükecek form elementi şöyle olacaktır. 1 <!-- app/views/form.blade.php --> 3 <form method ="POST" action =" 5 accept-charset ="UTF-8"> 6 <input name ="_token" type ="hidden" value ="83KCsmJF1ZLMZfhb17ihvt9ks5NEcAwFoR\ 7 FTq6u"> 8 <label for ="aciklama">açıklama</label> 9 <textarea name ="aciklama" 10 cols ="50" 11 rows ="10" 1 id ="aciklama">şimdiye kadarki en iyi alan!</textarea> 13 </form> Üretilen kaynaktan görebileceğiniz gibi, Laravel bazı ön tanımlı değerler sağlamıştır, örneğin alandaki sütun ve satır miktarı gibi. Opsiyonel son parametre ile bu ön tanımlı değerleri geçersiz kılıp değiştirebiliyoruz. Umarım bu nitelikler dizisini unutmazsınız!

174 Formlar 159 Password Alanları Bazı şeyler sırdır. Aslında, isterseniz sırlarınızı bana açıklayabilirsiniz. Ben bunları daha fazla gülelim diye teknik bir kitapta şaka olarak yayınlayacak tiplerden değilim. Bununla birlikte, şayet kullanıcılarınızın en gizli sırlarını uygulamamıza güvenle yazabilmelerini isterseniz, bu durumda yazdıkları karakterlerin ekranda gözükmemesini temin etmemiz gerekiyor. password giriş tipi bunun için idealdir. Bunu nasıl üretebileceğimizi görelim. 1 <!-- app/views/form.blade.php --> 3 {{ Form::open(array('url' => 'benim/rotam')) }} {{ Form::label('gizli', 'Süper Gizli') }} 5 {{ Form::password('gizli') }} 6 {{ Form::close() }} Form::password() metodunun ilk parametresi name niteliğidir. Her zaman olduğu gibi, diğer element niteliklerinden oluşan bir dizi şeklinde son bir opsiyonel parametre de alabilir. Yukarıdaki örnekten üretilen kaynak şöyledir. 1 <!-- app/views/form.blade.php --> 3 <form method ="POST" action =" 5 accept-charset ="UTF-8"> 6 <input name ="_token" type ="hidden" value ="83KCsmJF1ZLMZfhb17ihvt9ks5NEcAwFoR\ 7 FTq6u"> 8 <label for ="gizli">süper Gizli</label> 9 <input name ="gizli" type ="password" value ="" id ="gizli"> 10 </form> Onay Kutuları Onay kutuları boolean değerleri almanıza imkan verir. Bir onay kutusu form elementinin nasıl oluşturulacağına bir göz atalım.

175 Formlar <!-- app/views/form.blade.php --> 3 {{ Form::open(array('url' => 'benim/rotam')) }} {{ Form::label('pandalar_sevimlidir', 'Pandalar sevimli midir?') }} 5 {{ Form::checkbox('pandalar_sevimlidir', '1', true) }} 6 {{ Form::close() }} Form::checkbox() metodunun ilk parametresi alanın name niteliğidir ve ikinci parametre alanın value niteliğidir. Üçüncü parametre ise onay kutusunun ön tanımlı olarak onaylı olup olmayacağını belirten opsiyonel bir parametredir. Onay kutusu için ön tanımlı değer onaysız olmasıdır. Yukarıdaki örnekle üretilen kaynak şudur. 1 <!-- app/views/form.blade.php --> 3 <form method ="POST" action =" 5 accept-charset ="UTF-8"> 6 <input name ="_token" type ="hidden" value ="83KCsmJF1ZLMZfhb17ihvt9ks5NEcAwFoR\ 7 FTq6u"> 8 <label for ="pandalar_sevimlidir">pandalar sevimli midir?</label> 9 <input checked ="checked" 10 name ="pandalar_sevimlidir" 11 type ="checkbox" 1 value ="1" 13 id ="pandalar_sevimlidir"> 1 </form> Seçenek Düğmeleri Radio buttonların yazım şekli onay kutularınınki gibidir. Farkı, küçük bir değerler grubu içinden bir seçim yapma yöntemi olarak birkaç radio giriş tipi kullanabilmenizdir. İşte bir örnek. 1 <!-- app/views/form.blade.php --> 3 {{ Form::open(array('url' => 'benim/rotam')) }} {{ Form::label('panda_rengi', 'Pandalar ne renktir?') }} 5 {{ Form::radio('panda_rengi', 'kirmizi', true) }} Kırmızı 6 {{ Form::radio('panda_rengi', 'siyah') }} Siyah 7 {{ Form::radio('panda_rengi', 'beyaz') }} Beyaz 8 {{ Form::close() }}

176 Formlar 161 Yukarıdaki örnekte aynı name niteliğine sahip birden çok seçenek düğmesi olduğu dikkatinizi çekecektir. Bir defada onların sadece birisini seçebiliyor olacağız. Bu şekilde, kullanıcılarımıza bir pandanın rengini seçme imkanı vereceğiz. Form gösterildiği zaman üretilmiş kaynak şöyle gözükür. 1 <!-- app/views/form.blade.php --> 3 <form method ="POST" action =" 5 accept-charset ="UTF-8"> 6 <input name ="_token" type ="hidden" value ="83KCsmJF1ZLMZfhb17ihvt9ks5NEcAwFoR\ 7 FTq6u"> 8 <label for ="panda_rengi">pandalar ne renktir?</label> 9 <input checked ="checked" 10 name ="panda_rengi" 11 type ="radio" 1 value ="kirmizi" 13 id ="panda_rengi"> Kırmızı 1 <input name ="panda_rengi" 15 type ="radio" 16 value ="siyah" 17 id ="panda_rengi"> Siyah 18 <input name ="panda_rengi" 19 type ="radio" 0 value ="beyaz" 1 id ="panda_rengi"> Beyaz </form> Seçim Kutuları Seçim kutuları veya açılır kutular uygulamamız kullanıcılarının değerler arasından seçim yapmasını sağlamanın bir başka yoludur. Bunların nasıl inşa edileceğini görelim.

177 Formlar 16 1 <!-- app/views/form.blade.php --> 3 {{ Form::open(array('url' => 'benim/rotam')) }} {{ Form::label('panda_rengi', 'Pandalar ne renktir?') }} 5 {{ Form::select('panda_rengi', array( 6 'kirmizi' => 'Kırmızı', 7 'siyah' => 'Siyah', 8 'beyaz' => 'Beyaz' 9 ), 'kirmizi') }} 10 {{ Form::close() }} Form::select() metodu birinci parametre olarak bir name niteliği kabul eder ve ikinci parametre olarak anahtar-değer çiftlerinden oluşan bir dizi alır. İstek verisi içinde döndürülecek olan seçilmiş seçeneğin anahtarıdır. Üçüncü ve opsiyonel parametre ise ön tanımlı olarak seçili gözükecek değerin anahtarıdır. Yukarıdaki örnekte, sayfa yüklendiği zaman Kırmızı seçeneği seçili vaziyette olacaktır. İşte üretilen kaynak. 1 <!-- app/views/form.blade.php --> 3 <form method ="POST" action =" 5 accept-charset ="UTF-8"> 6 <input name ="_token" type ="hidden" value ="83KCsmJF1ZLMZfhb17ihvt9ks5NEcAwFoR\ 7 FTq6u"> 8 <label for ="panda_rengi">pandalar ne renktir?</label> 9 <select id ="panda_rengi" name ="panda_rengi"> 10 <option value ="kirmizi" selected ="selected">kırmızı</option> 11 <option value ="siyah">siyah</option> 1 <option value ="beyaz">beyaz</option> 13 </select> 1 </form> Eğer istersek, seçim kutusu seçeneklerini kategorilere göre organize edebiliriz. Bunu yapabilmek için yapacağımız tek şey, ikinci parametre olarak çok boyutlu bir dizi vermektir. Dizinin ilk düzeyi kategori olacak ve ikinci düzeyi tıpkı önceki gibi değerler listesi olacaktır. Bir örnek verelim.

178 Formlar <!-- app/views/form.blade.php --> 3 {{ Form::open(array('url' => 'benim/rotam')) }} {{ Form::label('bear', 'Ayılar?') }} 5 {{ Form::select('bear', array( 6 'Panda' => array( 7 'kirmizi' => 'Kırmızı', 8 'siyah' => 'Siyah', 9 'beyaz' => 'Beyaz' 10 ), 11 'Karakter' => array( 1 'pooh' => 'Pooh', 13 'baloo' => 'Baloo' 1 ) 15 ), 'siyah') }} 16 {{ Form::close() }} Değerler dizimize yeni bir boyut ekledik. Dizinin üst düzeyi şimdi Panda ve Karakter olarak ayrıldı. Bu iki grup, açılır kutu içinde optgroup element tipleri olarak temsil edileceklerdir. Üretilen kaynak kodu şöyledir. 1 <!-- app/views/form.blade.php --> 3 <form method ="POST" action =" 5 accept-charset ="UTF-8"> 6 <input name ="_token" type ="hidden" value ="83KCsmJF1ZLMZfhb17ihvt9ks5NEcAwFoR\ 7 FTq6u"> 8 <label for ="bear">ayılar?</label> 9 <select id ="bear" name ="bear"> 10 <optgroup label ="Panda"> 11 <option value ="kirmizi">kırmızı</option> 1 <option value ="siyah" selected ="selected">siyah</option> 13 <option value ="beyaz">beyaz</option> 1 </optgroup> 15 <optgroup label ="Karakter"> 16 <option value ="pooh">pooh</option> 17 <option value ="baloo">baloo</option> 18 </optgroup> 19 </select> 0 </form>

179 Formlar 16 Alanı alanı Form::text() metodu ile aynı şekilde yazılır. Aralarındaki fark Form:: () metodunun, istemci tarafından girilen değerin geçerli bir adresi olmasını temin etmek için geçerlilik kontrolünden geçirileceği yeni bir HTML5 input elementi oluşturmasıdır. Başka bir örnek. 1 <!-- app/views/form.blade.php --> 3 {{ Form::open(array('url' => 'benim/rotam')) }} {{ Form::label(' ', ' Adresi') }} 5 {{ Form:: (' ', 'me@daylerees.com') }} 6 {{ Form::close() }} Form:: () metodunun birinci parametresi input elementimizin name niteliğidir. İkinci parametre ön tanımlı valuedir. Her zaman olduğu gibi ve umarım unutmamışsınızdır, ek element nitelikleri için, dizi biçiminde son bir opsiyonel parametre söz konusudur. Yukarıdaki örnek gösterildiğinde sayfa kaynağı şu şekildedir. 1 <!-- app/views/form.blade.php --> 3 <form method ="POST" action =" 5 accept-charset ="UTF-8"> 6 <input name ="_token" type ="hidden" value ="83KCsmJF1ZLMZfhb17ihvt9ks5NEcAwFoR\ 7 FTq6u"> 8 <label for =" "> Adresi</label> 9 <input name =" " 10 type =" " 11 value ="me@daylerees.com" 1 id =" "> 13 </form> Dosya Gönderme (File Upload) Alanı Önceki bölümde, gönderilen dosyaların nasıl işleneceğini öğrenmiştik. Şimdi de bir dosya gönderme alanının nasıl üretileceğini görelim.

180 Formlar <!-- app/views/form.blade.php --> 3 {{ Form::open(array( 'url' => 'benim/rotam', 5 'files' => true 6 )) }} 7 {{ Form::label('avatar', 'Avatar') }} 8 {{ Form::file('avatar') }} 9 {{ Form::close() }} Form::file() metodunun ilk parametresi file upload elementinin name niteliğidir, ancak, gönderme işinin çalışabilmesi bakımından formumuzun çok parçalı kodlama tipini içermesi için files seçeneğiyle açılmasını temin etmemiz de gerekmektedir. İşte üretilen sayfa kaynağı. 1 <!-- app/views/form.blade.php --> 3 <form method ="POST" action =" 5 accept-charset ="UTF-8" 6 enctype ="multipart/form-data"> 7 <input name ="_token" type ="hidden" value ="83KCsmJF1ZLMZfhb17ihvt9ks5NEcAwFoR\ 8 FTq6u"> 9 <label for ="avatar">avatar</label> 10 <input name ="avatar" type ="file" id ="avatar"> 11 </form> Gizli (Hidden) Alanlar Bazen, alanlarımız girdi elde etmek amacını taşımaz. Formlarımızla birlikte ekstra veri sağlamak için hidden alanları kullanabiliriz. Hidden alanların nasıl üretildiğine bir göz atalım. 1 <!-- app/views/form.blade.php --> 3 {{ Form::open(array('url' => 'benim/rotam')) }} {{ Form::hidden('panda', 'luishi') }} 5 {{ Form::close() }} Form::hidden() metodu için birinci parammetre name niteliğidir, Arkasından ne geleceğini görmediğinize bahse girerim! İkinci parametre tabii ki valuedir. Üretilen sayfa kaynağı böyle gözükür.

181 Formlar <!-- app/views/form.blade.php --> 3 <form method ="POST" action =" 5 accept-charset ="UTF-8"> 6 <input name ="_token" type ="hidden" value ="83KCsmJF1ZLMZfhb17ihvt9ks5NEcAwFoR\ 7 FTq6u"> 8 <input name ="panda" type ="hidden" value ="luishi"> 9 </form> Form Düğmeleri Onları gönderemediğimiz takdirde formlar işimize yaramayacaktır. Kullanabileceğimiz düğmelere biraz yakından bakalım. Submit Düğmesi Önce gönder düğmesi. Klasik dışı bir şey yok! Şöyle görünüyor. 1 <!-- app/views/form.blade.php --> 3 {{ Form::open(array('url' => 'benim/rotam')) }} {{ Form::submit('Kaydet') }} 5 {{ Form::close() }} Form::submit() birinci parametre valuedir, value bir düğme söz konusu olduğunda düğmeyi tanımlamak için kullanılan etikettir. İnput üretme metodlarının hepsinde olduğu gibi, button üretme metodları da son bir opsiyonel parametre olarak ek nitelikler dizisi kabul edebilecektir. Yukarıdaki örnekten üretilen HTML kaynak kodu şudur. 1 <!-- app/views/form.blade.php --> 3 <form method ="POST" action =" 5 accept-charset ="UTF-8"> 6 <input name ="_token" type ="hidden" value ="83KCsmJF1ZLMZfhb17ihvt9ks5NEcAwFoR\ 7 FTq6u"> 8 <input type ="submit" value ="Kaydet"> 9 </form> Harika! Artık formlarımızı gönderebiliyoruz. Alternatif düğme şekillerine de bir göz atalım.

182 Formlar 167 Normal Düğmeler Formumuzu göndermek için kullanmak istemediğimiz bir düğmeye ihtiyacımız olduğunda, Form::button() metodunu kullanabiliriz. Bir örnek verirsek: 1 <!-- app/views/form.blade.php --> 3 {{ Form::open(array('url' => 'benim/rotam')) }} {{ Form::button('Gülümse') }} 5 {{ Form::close() }} Form::button() metodunun parametreleri daha önce bahsettiğimiz Form::submit() metodunun tam aynısıdır. Örneğimizden üretilen kaynak şöyledir. 1 <!-- app/views/form.blade.php --> 3 <form method ="POST" action =" 5 accept-charset ="UTF-8"> 6 <input name ="_token" type ="hidden" value ="83KCsmJF1ZLMZfhb17ihvt9ks5NEcAwFoR\ 7 FTq6u"> 8 <button type ="button">gülümse</button> 9 </form> Resim (Image) Düğmeleri Formlarınızı göndermek için klasik düğme yerine, HTML5 image button tipini kullanabilirsiniz. İşte bir örnek. 1 <!-- app/views/form.blade.php --> 3 {{ Form::open(array('url' => 'benim/rotam')) }} {{ Form::image(asset('benim/image.gif', 'submit')) }} 5 {{ Form::close() }} Form::image() metodu için birinci parametre düğme için kullanacağımız bir imajın URL sidir. Ben URL üretmek için asset() helper metodunu kullandım. İkinci parametre buttonun değeridir. Üretilen kaynak kodu buradadır.

183 Formlar <!-- app/views/form.blade.php --> 3 <form method ="POST" action =" 5 accept-charset ="UTF-8"> 6 <input name ="_token" type ="hidden" value ="83KCsmJF1ZLMZfhb17ihvt9ks5NEcAwFoR\ 7 FTq6u"> 8 <input src =" type ="image"> 9 </form> Reset Düğmesi Reset düğmesi form içeriğini temizlemek için kullanılabilmektedir. Uygulamanız kullanıcıları tarafından, bir yanlışlık yaptıkları zaman kullanılırlar. Nasıl üretileceğine bir örnek üzerinden bakalım. 1 <!-- app/views/form.blade.php --> 3 {{ Form::open(array('url' => 'benim/rotam')) }} {{ Form::reset('Temizle') }} 5 {{ Form::close() }} Form::reset() metodu için birinci paramete düğme üzerinde gözükmesini istediğiniz etikettir. Yukarıdaki örnekten üretilen kaynak şöyledir. 1 <!-- app/views/form.blade.php --> 3 <form method ="POST" action =" 5 accept-charset ="UTF-8"> 6 <input name ="_token" type ="hidden" value ="83KCsmJF1ZLMZfhb17ihvt9ks5NEcAwFoR\ 7 FTq6u"> 8 <input type ="reset" value ="Temizle"> 9 </form> Form Makroları Önceki kesimlerde çeşitli form girişi üretim metodlarını keşfetmiştik. Bunlar büyük bir zaman kazandırabilmektedir ancak belki de kendi uygulamanıza özgü özel bir form input tipiniz olabilir. Şansımıza, Taylor bunu zaten düşünmüş. Laravel kendi form jeneratörlerinizi tanımlamanıza imkan veren bir metodla birlikte gelmektedir, isterseniz nasıl çalıştığına bir bakalım. Peki, form makrolarımızı nereye koyacağız? Ah anlıyorum, önce app/macros.php adında bir dosya oluşturalım, sonra da onu rotalar dosyamızda include edebiliriz. Bu dosya içeriği şöyle olsun:

184 Formlar // app/macros.php 5 Form::macro('adSoyad', function() 6 { 7 return '<p>ad Soyad: <input type ="text" name ="ad_soyad"></p>'; 8 }); Bir makro tanımlamak için Form::macro() metodunu kullanıyoruz. Birinci parametresi bizim form alanımızı oluşturacak metod tarafından kullanılacak isimdir. Bu sebeplerle bu ismin yazım biçimini camelcase yapmanızı öneririm. İkinci parametre bir Closure dur. Bu closure dan dönen değer alanımızı oluşturmak için gerekli kaynak kodu olmak zorundadır. Bu yeni makromuzdan gelen sonucu gösteren basit bir rota oluşturalım. İşte burada: 3 // app/routes.php 5 Route::get('/', function() 6 { 7 return Form::adSoyad(); 8 }); Bu rotamız Form sınıfındaki adsoyad() metodunun değerini döndürüyor. Bu sıradan bir statik metod değildir, Laravel in kendi form makrolarımızı çağırabilmemizi sağlayan bir sihre sahiptir. Metodun adı makromuza vermiş olduğumuz takma adla eşleşmektedir. Şimdi oluşturduğumuz rotadan ne döndüğüne bir göz atalım. 1 <p>ad Soyad: <input type ="text" name ="ad_soyad"></p> Görüldüğü gibi, Closure umuzun sonucu döndürülmüştür. Form makrolarımıza paremetre vermek istersek ne yapacağız? Elbette, problem değil! Önce makromuzu değiştirelim.

185 Formlar // app/macros.php 5 Form::macro('adSoyad', function($isim) 6 { 7 return '<p>ad Soyad: <input type ="text" name ="'.$isim.'"></p>'; 8 }); Makro closure u içinde yer tutucular vermek suretiyle, bu yer tutucularının değerlerini göstertilecek kaynakta kullanabiliyoruz. Yukarıdaki örnekte yeni input tipimiz için bir name niteliği sağlayan bir metod eklemiştik. Şimdi de bu yeni parametrenin nasıl verileceğini görelim. 3 // app/routes.php 5 Route::get('/', function() 6 { 7 return Form::adSoyad('yeni_alan'); 8 }); Evet, kolay oldu değil mi? Biz sadece Laravel in bize sağladığı sihirli metoda parametremizin değerini geçiyoruz. İsterseniz / rotamızın yeni sonucuna bir bakalım. 1 <p>ad Soyad: <input type ="text" name ="yeni_alan"></p> Müthiş, Yeni name değeri alanımıza yerleştirilmiş durumda! Tekrarları önlemenin bir başka harika yolu. Tadını çıkarın! Form Güvenliği Formlarımızdan veri alabilmek güzel şey. Orada olmalarının gerekçesi bu zaten. Sorun şu ki, bizim rotalarımız kendi formlarımızın bir hedefi olabiliyorsa, sitemize tehlikeli veri gönderen dış bir kaynağı nasıl durduruyor? Bize gönderilen verinin kendi websitemize ait olduğunu garanti altına almanın bir yoluna ihtiyacımız var. Problem değil. Sizin için bu işi Laravel yapar. Siteler Arası İstek Sahtekarlığı (Cross Site Request Forgery) veya kısaca CSRF denen bu form saldırılarını büyük ihtimalle biliyorsunuzdur. İşte şimdi, bunu şimdilik merak etmeyin dediğim _token hidden alanını hatırladınız mı? Tamam, artık onun hakkında konuşmaya başlamak istiyorum.

186 Formlar 171 ARGH. Meraktan ölecektik! Peki, tamam. İzin verin bu token in ne olduğunu anlatayım. Bu, Laravel in ne için olduğunu bildiği bir çeşit gizli paroladır. Application yapılandırma dosyamızdaki secret değeri kullanılarak üretilmektedir. Eğer Laravel e input verilerimiz içinde bu değeri kontrol etmesini söylersek, o zaman bir form tarafından sağlanan verilerin kendi uygulamamıza ait olduğundan emin olabiliriz. Bunun değerini Session::token() metodunun sonucuyla karşılaştırmak suretiyle token karşılaştırma işini kendimiz yapabilirdik fakat Laravel daha iyi bir seçenek sunmuştur. Filtreler bölümündeki ön tanımlı filtreleri hatırlıyor musunuz? Evet, Laravel ön tanımlı bir csrf filtresine sahiptir. Gelin bunu bir rotaya bağlayalım. 3 // app/routes.php 5 Route::post('/form-isle', array('before' => 'csrf', function() 6 { 7 // Gönderilen form verisini işle. 8 })); Form verilerimizi işleyecek rotaya bir before filtresi olarak csrf filtresi bağlamak suretiyle, bu _- token alanının mevcut ve doğru olmasını garantiye alabiliyoruz. Eğer bizim token yoksa veya onu kurcalamışlarsa, bu durumda bir Illuminate\Session\TokenMismatchException atılacak ve rota mantığımız çalıştırılmayacaktır. İlerideki bir bölümde, bu şartları uygun biçimde işleyebilmek için hata işleyicileri belirli istisna tiplerine nasıl bağlayacağımızı öğreneceğiz. Eğer formumuzun etrafını sarmak için Form::open() metodunu kullanmışsanız, güvenlik tokeni default olarak dahil edilecektir. Ancak, eğer bu tokeni elle yazılan formlara eklemek istiyorsanız, o zaman basitçe token üretme metodu eklemek zorundasınız. İşte bir örnek. 1 <!-- app/views/form.blade.php --> 3 <form action ="{{ url('form-isle') }}" method ="POST"> {{ Form::token() }} 5 </form> Bu Form::token() metodu formumuzun içine gizli token alanı ekleyecektir. Üretilecek olan kaynak şöyledir.

187 Formlar 17 1 <!-- app/views/form.blade.php --> 3 <form action =" method ="POST"> <input name ="_token" type ="hidden" value ="83KCsmJF1ZLMZfhb17ihvt9ks5NEcAwFoR\ 5 FTq6u"> 6 </form> Özetlemek gerekirse, dış uygulama ve kullanıcılarının formlarınıza veri gönderebilmesini istiyor olmadığınız sürece, rotalarınızın işleyeceği form verilerinizi korumak için CSRF filtresini kullanmalısınız.

188 Geçerlilik Denetimi (Validation) Birkaç ay önce gerçekten bir strese girmiştim. İş Laravel salımının montajlanmasıydı ki, her framework geliştiricisinin üstleneceği tipik rol yanında yeni sitenin tasarlanması ve inşa edilmesi, belge değişikliklerinin cevaplanması anlamına geliyordu. Zor zamanlardı. Bütün bunların üstüne bir de, Code Bright ı en az Code Happy kadar başarılı olacak şekilde inşa edebilme, böylece topluluğa yeni geliştiriciler katma baskısı altındaydım. Yapmam gereken şey Phill Parklarının birinde kısa bir mola almaktı. Bildiğiniz gibi, Phill Parkları dünyanın değişik yerlerinde geliştiricilerin tatil yaptığı parklardır. Bunlar orijinal olarak iki bin yılında Phill Parklarının CEO su Phill Sparks tarafından açılmıştı. Bu parklar günümüzde geliştiricilerin dinlenmek ve rahatlamak için gidebileceği tek yerdir. Phill Parkları zor bir çalışma yılının sonunda gevşemek isteyen geliştiriciler için çok çeşitli aktiviteler sunmaktadır. Bu etkinlikler arasında rekabetçi FizzBuzz turnuvaları, sekmeler ve boşluklar münazaraları ve ense sakalı yarışmaları yer almaktadır. Phill Parklarını biliyor olsaydım, Laravel dört çıkana kadar dinlenip, eğlenebilirdim. Oh tamam, en azından ne olduğunu öğrenmiş oldunuz? Şanslı bir Code Bright okuyucusu olarak, parklara giriş için % 90 indirim sağlayacak bir kupona erişebilirsiniz. Bu anlaşmadan yararlanmak için yapmanız gereken tek şey Phill Spark ı IRC, Twitter, ile veya bizzat izlemek ve CODE_BRIGHT_- TROLLS_YOU kupon kodunu aktarmaktır. Eğer hemen cevap vermezse, onu kupon kodu ile spama tutun. Er veya geç, tatil kodunuzu yakalayacaktır. Peki, bunun geçerlilik denetimiyle ne ilgisi var? Evet, bu bölümü yazmaya başladığımda, kafamda harika, büyük bir plan vardı. Ne yazık ki, tamamen Phill Parkları nın sunduğu eğlence ve oyunlara daldım ve artık bir fikrim yok. Sadece bir şey yaptım işte. Bu güne kadar ne doğru çıktı ki? Phill Parkları geliştiriciler için çok özel yerlerdir ve sadece geliştiriciler içindir. Geliştiricilerin problemi, dikkat etmedikleri takdirde, web geliştirme endüstrisindeki diğer rolleri tespit etmelerinin zor olmasıdır. Örneğin, tasarımcılar. Sinsi tasarımcıların geliştirici kılığında Phill Parklarına sızmasını istemeyiz. Onlar dekorasyon seçimlerimizi yargılamaya ve kafeterya menülerinde Comic Sans kullanmamızdan yakınmaya başlayacaklardır. Atmosfer tamamen berbat olacaktır! Hayır, parkta bunları hiç istemeyiz. Ziyaretçilerimizin geliştirici olduklarından emin olmamızı sağlayan bir geçerlilik kontrolü yöntemine ihtiyacımız var. Bakın, geri getirebileceğimi söylemiştim. Geçerliliğine bakacağımız şey bir nitelikler kümesidir. Bir park ziyaretçisinin bazı nitelikleri hakkında düşünelim. Oo, hoo, biliyorum. Önce bir liste yapabiliriz! Listeler eğlencelidir!

189 Geçerlilik Denetimi (Validation) 17 Favori içeceği. Web browser tercihi. Yüz kılı tipi. Kadınlarla konuşma yeteneği. Mükemmel, parka gelen ziyaretçileri tarif edebileceğimiz bazı niteliklerimiz var. Bazı geçerlilik sınırlamaları veya kurallarını kullanarak, ziyaretçimizin bir geliştirici olduğundan emin olabiliriz. Bu park için, bir park ziyaretçisinin niteliklerinin aşağıdaki gereksinimleri karşıladığını garanti altına almaya çalışacağız. Favori içeceği: Ayran. Web browser tercihi: Google Chrome. Yüz kılı tipi: Ense sakalı. Kadınlarla konuşma yeteneği: Yok. Uyarı: Bu değerler sadece eğlence içindir. Örneğin, yaptığı şeyler fantastik olan birçok kadın web geliştirici biliyorum ve bunların diğer kadınlarla konuşabilme yeteneğine sahip olduklarından oldukça eminim. Ayrıca, şu anda benim geleneksel ense sakalı değil de muhteşem van dayk sakalım var. Ayrana batırılmış bir şey olsa da Her neyse, bir park ziyaretçisinin niteliklerinin bir geliştiricininkine uyduğundan emin olduktan sonra geçip parka girmelerine izin verebiliriz. Ancak, eğer resepsiyona aşağıdaki niteliklere sahip sinsi bir adam gelirse Favori içeceği: Starbuck Frappechino. Web browser tercihi: Mobile Safari. Yüz kılı tipi: Yok. Kadınlarla konuşma yeteneği: Kadınlarla konuşur, kesinlikle. bu durumda, hayır olamaz, bu bir tasarımcı veya bir Ruby geliştiricisidir ve onu kapıdan içeri sokamayız. Bir kez daha ifade edeyim, bu sadece bir parça eğlence olsun diye. Lütfen bana nefret mektupları göndermeyin. İlerideki bir bölümde ana karakteri öldürene kadar bekleyin Erm, yani, unutun gitsin. Geçerlilik için yaptığımız uygulamayla, parka girecek insanların sahtekarlar değil geliştiriciler olduğundan emin olabiliyoruz. Phill Parkları artık güvenlidir, ya uygulamalarınız? Beklediğimiz neyse tam onu aldığımızdan emin olmak için Laravel de geçerlilik denetimini nasıl yapabileceğimizi görebiliriz.

190 Geçerlilik Denetimi (Validation) 175 Basit Geçerlilik Denetimi Kullanıcılarınıza güvenmeyin. IT sektöründe çalışırken öğrendiğim bir şey varsa, o da eğer uygulamanızda zayıf bir nokta varsa, kullanıcılarınızın onu bulacağıdır. Bunlar onu istismar edecek diyorsam bana güvenin. Onlara fırsat vermeyin. İyi girdi aldığınızdan emin olmak için geçerlilik denetimi kullanın. İyi girdi demekle neyi kastediyoruz? Peki, bir örnek üzerinden bakalım. Uygulamanız için kayıt bilgileri toplamakta kullanılan bir HTML formunuz olsun. Aslında, küçük bir gözden geçirme oturumu olması çok iyi olacak. Formu Blade şablon motoru ve form oluşturucu ile oluşturalım. İşte görünümümüz burada. 1 <!-- app/views/form.blade.php --> 3 <h1>phill Parkları için kayıt formu</h1> 5 {{ Form::open(array('url' => 'tescil')) }} 6 7 {{-- Kullanıcı Adı alanı }} 8 {{ Form::label('kullanici_adi', 'Kullanıcı Adı') }} 9 {{ Form::text('kullanici_adi') }} {{-- adresi alanı }} 1 {{ Form::label(' ', ' adresi') }} 13 {{ Form:: (' ') }} 1 15 {{-- Password alanı }} 16 {{ Form::label('password', 'Şifre') }} 17 {{ Form::password('password') }} {{-- Password teyit alanı }} 0 {{ Form::label('password_confirmation', 'Şifre tekrarı') }} 1 {{ Form::password('password_confirmation') }} 3 {{-- Form gönderme düğmesi }} {{ Form::submit('Kayıt Ol') }} 5 6 {{ Form::close() }} Voah, ne güzel bir görünüm?

191 Geçerlilik Denetimi (Validation) 176 Bu güzel bir görünüm. Mükemmel, zihinsel olarak hala Code Happy okuma şartlarında olmanıza sevindim. Görebileceğiniz gibi kayıt formumuz /tescil rotasını hedef alıyor ve ön tanımlı olarak POST istek fiilini kullanacak. Bir kullanıcı adı için bir text alanımız, kullanıcının adresi için bir alanımız ve bir şifre ve bir şifre teyidi almak için iki password alanımız var. Formun en altında da formu neşeli bir şekilde göndermek için kullanabileceğimiz bir submit buttonumuz var. Dikkat ederseniz, blade kaynağına eklediğim yorumlar var. Bu benim forma geri dönmek zorunda kalırsam, istediğim alanlara kolayca göz atabilmemi sağladığını düşündüğüm bir alışkanlıktır. Aynısını yapmakta serbestsiniz, ama eğer istemiyorsanız, bu konuyu dert etmeyin! Kendi bildiğiniz gibi kodlayın! Pekiyi, şimdi bu formu göstermek ve işlemek için bir çift rotaya ihtiyacımız olacak. Şimdi ilerleyelim ve bunları routes.php dosyamıza ekleyelim. 3 // app/routes.php 5 Route::get('/', function() 6 { 7 return View::make('form'); 8 }); 9 10 Route::post('/tescil', function() 11 { 1 $veri = Input::all(); 13 1 // formu işle }); Formumuzu göstermek için kullanacağımız bir GET / rotası, onun gönderdiklerini işlemek için de bir POST /tescil rotamız oldu. Form işleyen rotamızda formdan tüm verileri topladık ancak henüz onları kullanamayız. Niçin? Pekiyi, tamam, göstereyim. Devam edin ve / rotasını yükleyin, formu göreceksiniz. Pekala, formu doldurmayın, sadece Kayıt Ol düğmesine basın. İkinci rota tetiklendiği için ve formumuz boş bilgi gönderdiği için ekran boş gözükecek. Eğer biz boş bilgi kullanırsak uygulamamız için ciddi problemlere, hatta bir güvenlik açığına bile yol açabilir. Bu kötü bir veridir.

192 Geçerlilik Denetimi (Validation) 177 Bunun yerine verilerimizin iyi veri olmasını garanti altına almak için geçerlilik denetimini kullanarak bu sıkıntıyı önleyebiliriz. Geçerlilik denetimi yapabilmek için öncelikle bir geçerlilik sınırlamaları listesi vermemiz gerekir. Bunu bir dizi biçiminde yapabiliriz. Hazır mısınız? Güzel, görelim o zaman. 3 // app/routes.php 5 Route::get('/', function() 6 { 7 return View::make('form'); 8 }); 9 10 Route::post('/tescil', function() 11 { 1 $veri = Input::all(); 13 1 $kurallar = array( 15 'kullanici_adi' => 'alpha_num' 16 ); 17 }); Tamam, küçük bir şeyle başladık. Bir geçerlilik kural kümesi ilişkisel bir dizi biçimini alıyor. Bu dizinin anahtarı geçerlilik denetiminden geçirilecek alanı temsil eder. Dizinin değeri ise geçerlilik denetimi için kullanılacak bir veya birçok kuraldan ibaret olacaktır. Biz tek bir alanda tek bir geçerlilik sınırlamasına bakarak başlayacağız. 1 array( 'kullanici_adi' => 'alpha_num' 3 ) Yukarıdaki örnekte, kullanici_adi alanının alpha_num geçerlilik kuralına uyduğunu doğrulamak istiyoruz. Bu alpha_num kuralı bir değerin sadece alfanümerik karakterlerden oluştuğunu garantiye almak için kullanılabilmektedir. Kuralımızın doğru çalıştığından emin olmak için geçerlilik nesnesini ayarlayalım. Laravel içinde geçerlilik denetimi yapmak için, öncelikle bir Validation nesnesi olgusu oluşturmamız gerekiyor. İşte başlıyoruz.

193 Geçerlilik Denetimi (Validation) // app/routes.php 5 Route::get('/', function() 6 { 7 return View::make('form'); 8 }); 9 10 Route::post('/tescil', function() 11 { 1 // Tüm istek verilerini alalım. 13 $veri = Input::all(); 1 15 // Geçerlilik sınırlama kümesini oluşturalım. 16 $kurallar = array( 17 'kullanici_adi' => 'alpha_num' 18 ); 19 0 // Yeni bir validator olgusu oluşturalım. 1 $gecerlikci = Validator::make($veri, $kurallar); }); Yeni bir geçerlilik denetimcisi olgusu oluşturmak için Validator::make() metodunu kullanabiliyoruz. make() metodunun birinci parametresi geçerlilik denetiminden geçirilecek bir veri dizisidir. Bu örneğimizde istek verimizi denetimden geçirmek istiyoruz ancak başka bir veri dizisini de geçerlilik denetiminden geçirebilirdik. Metodun ikinci parametresi ise veriyi denetlemek için kullanılacak olan kurallar kümesidir. Artık geçerlilik denetçisi olgumuzu oluşturduğumuza göre, girilen verilerin koyduğumuz geçerlilik sınırlamalarına uyup uymadığını kontrol etmek için bu olguyu kullanabiliriz. İsterseniz bir örnekle gidelim. 3 // app/routes.php 5 Route::get('/', function() 6 { 7 return View::make('form'); 8 }); 9 10 Route::post('/tescil', function()

194 Geçerlilik Denetimi (Validation) { 1 // Tüm istek verilerini alalım. 13 $veri = Input::all(); 1 15 // Geçerlilik sınırlama kümesini oluşturalım. 16 $kurallar = array( 17 'kullanici_adi' => 'alpha_num' 18 ); 19 0 // Yeni bir validator olgusu oluşturalım. 1 $gecerlikci = Validator::make($veri, $kurallar); 3 if ($gecerlikci->passes()) { // Normalde veriyle bir şeyler yapacağız. 5 return 'Veri kaydedildi.'; 6 } 7 8 return Redirect::to('/'); 9 }); Geçerlilik denetiminin sonucunu test etmek için, validatör olgumuzda passes() metodunu kullanabiliyoruz. Bu metod geçerlilik denetiminden başarıyla geçilip geçilmediğini gösteren boolean bir cevap döndürecektir. Bir true cevabı verinin geçerlilik kurallarının tamamına uyduğunu gösterir. Bir false cevabı ise verinin geçerlilik gereksinimlerini karşılamadığını gösterir. Yukarıdaki örnekte, veriyi saklayacak mıyız, yoksa giriş formuna redirekt mi yapacağımıza karar vermek için bir if cümlesi kullanıyoruz. Şimdi / URI sini ziyaret ederek bunu test edelim. İlk olarak kullanici_adi alanına serginari değerini girip submit düğmesine basalım. serginari kullanıcı adının alfanümerik karakterlerden oluştuğunu biliyoruz, bu nedenle geçerlilik denetiminden başarıyla geçecektir. Bu itibarla aşağıdaki cümle ile karşılaşacağız. 1 Veri kaydedildi. Mükemmel, tam beklediğimiz gibi. Şimdi gelin bu denetimin sonucunu tersine çevirelim. Devam edelim ve / URI yi bir kez daha ziyaret edelim. Bu sefer!!! değerini girelim. Bir ünlem işaretinin ne bir alfabe harfi ne de bir rakam karakteri olmadığını biliyoruz, bu durumda denetimden kalacaktır. Submit düğmesine basalım, tekrar kayıt formuna redirekt olacağız. Ben bu passes() metodunu sevdim, gerçekten yararlı. Tek sorun biraz iyimser olması. Kendimize karşı dürüst olalım, dünya mükemmel bir yer değil. Biz hiçbirimiz Robert Downey Jr değiliz. Biraz daha kötümser olamaz mıyız? Mükemmel, bekleyin Tatmin edici. O zaman bunun yerine fails() metodunu deneyelim.

195 Geçerlilik Denetimi (Validation) // app/routes.php 5 Route::get('/', function() 6 { 7 return View::make('form'); 8 }); 9 10 Route::post('/tescil', function() 11 { 1 // Tüm istek verilerini alalım. 13 $veri = Input::all(); 1 15 // Geçerlilik sınırlama kümesini oluşturalım. 16 $kurallar = array( 17 'kullanici_adi' => 'alpha_num' 18 ); 19 0 // Yeni bir validator olgusu oluşturalım. 1 $gecerlikci = Validator::make($veri, $kurallar); 3 if ($gecerlikci->fails()) { return Redirect::to('/'); 5 } 6 7 // Normalde veriyle bir şeyler yapacağız. 8 return 'Veri kaydedildi.'; 9 }); Bu fails() metodu passes() metodunun tam aksi boolean döndürür. Nasıl olağanüstü kötümser ama! O anki ruh halinize hangisi uygunsa onu kullanabilirsiniz. İsterseniz, PHP yorumlarını kullanarak hislerinizi de yazabilirsiniz. Bazı geçerlilik kuralları parametre alabilmektedir. Şimdi alpha_num kuralımızı min ile değiştirelim. Kaynak şöyledir.

196 Geçerlilik Denetimi (Validation) // app/routes.php 5 Route::get('/', function() 6 { 7 return View::make('form'); 8 }); 9 10 Route::post('/tescil', function() 11 { 1 // Tüm istek verilerini alalım. 13 $veri = Input::all(); 1 15 // Geçerlilik sınırlama kümesini oluşturalım. 16 $kurallar = array( 17 'kullanici_adi' => 'min:3' 18 ); 19 0 // Yeni bir validator olgusu oluşturalım. 1 $gecerlikci = Validator::make($veri, $kurallar); 3 if ($gecerlikci->passes()) { // Normalde veriyle bir şeyler yapacağız. 5 return 'Veri kaydedildi.'; 6 } 7 8 return Redirect::to('/'); 9 }); min geçerlilik kuralı ilgili değerin verilen parametreye eşit veya ondan daha büyük olmasını garantiye alır. Parametresi iki nokta üst üsteden (:) sonra verilir. Bu validation kuralı biraz özeldir. Girilen veriye dayalı olarak farklı tepki verecektir. Örneğin, bir string değerde, parametremizin 3 olması değerin en azından 3 karakter uzunluğunda olmasını temin edecektir. Sayısal bir değerde ise değerin matematiksel olarak 3 e eşit veya daha büyük olmasını garanti edecektir. Son olarak, gönderilen bir dosya için min geçerlilik kuralı gönderilen dosyanın kilobayt olarak boyutunun verilen parametreye eşit veya daha büyük olmasını sağlama alacaktır. Yeni geçerlilik kuralımızı test etmeye geçelim. Önce / sayfasını ziyaret edelim ve kullanici_adi alanına Jo değerini girelim. Formu gönderdiğinizde, kayıt formuna geri yönlendirileceksiniz. Bunun sebebi değerimizin yeterince uzun olmamasıdır.

197 Geçerlilik Denetimi (Validation) 18 Yani, o diyor ki Oo hayır değil. Bu ciddi bir kitap, onu o dedi ki şakalarıyla kirletemeyiz. Tamam, şimdiye dek iki geçerlilik sınırlaması kullandık ancak ikisini birlikte kullanmak istersek ne yapacağız? Problem değil. Laravel alanlarımız üzerinde herhangi bir sayıda geçerlilik kuralı kullanmamıza imkan vermektedir. Bunu nasıl yapabileceğimize bir göz atalım. 3 // app/routes.php 5 Route::get('/', function() 6 { 7 return View::make('form'); 8 }); 9 10 Route::post('/tescil', function() 11 { 1 // Tüm istek verilerini alalım. 13 $veri = Input::all(); 1 15 // Geçerlilik sınırlama kümesini oluşturalım. 16 $kurallar = array( 17 'kullanici_adi' => 'alpha_num min:3' 18 ); 19 0 // Yeni bir validator olgusu oluşturalım. 1 $gecerlikci = Validator::make($veri, $kurallar); 3 if ($gecerlikci->passes()) { // Normalde veriyle bir şeyler yapacağız. 5 return 'Veri kaydedildi.'; 6 } 7 8 return Redirect::to('/'); 9 }); Görmüş olduğunuz gibi, kurallar dizimizin değer kısımları içinde pipe karakterleri ile ayrılmış birden çok geçerlilik sınırlaması geçebiliyoruz. Bu bölüme çok daha erken gelecektik ancak ben işte Linux, evde Mac kullanıyorum ve pipe tuşunu bulmak 30 saniyemi aldı.

198 Geçerlilik Denetimi (Validation) 183 Her neyse, birden çok geçerlilik kuralı vermenin alternatif bir yolu var. Altmışlarında bir büyükbaba değilseniz, pipoları anlamayabilirsiniz. İsterseniz, ek geçerlilik kurallarını belirtmek için çok boyutlu bir dizi kullanabilirsiniz. İşte bir örnek. 3 // app/routes.php 5 Route::get('/', function() 6 { 7 return View::make('form'); 8 }); 9 10 Route::post('/tescil', function() 11 { 1 // Tüm istek verilerini alalım. 13 $veri = Input::all(); 1 15 // Geçerlilik sınırlama kümesini oluşturalım. 16 $kurallar = array( 17 'kullanici_adi' => array('alpha_num', 'min:3') 18 ); 19 0 // Yeni bir validator olgusu oluşturalım. 1 $gecerlikci = Validator::make($veri, $kurallar); 3 if ($gecerlikci->passes()) { // Normalde veriyle bir şeyler yapacağız. 5 return 'Veri kaydedildi.'; 6 } 7 8 return Redirect::to('/'); 9 }); Laravel esnek bir framework tür ve kullanıcılarına seçenekler verir. Birden çok geçerlilik kuralı atamak için siz kendi tercih ettiğiniz yöntemi kullanın. Ben bir ingiliz beyefendisini taklit etmek için pipo kullanacağım.

199 Geçerlilik Denetimi (Validation) 18 Geçerlilik Kuralları Ey insanlar, dinleyin. Bir sürü doğrulama kuralı bulunmaktadır. Bu yüzden, bunları tek seferde göreceksek, tam dikkatli olmanız gerekecek. Eğer bunları okurken yatağınızda iseniz, kitabı kapatın ve uyuyun. Daha uyanık durumda olmanız gerekecek. Kullanabileceğimiz geçerlilik kuralları alfabetik sırada verilmiştir. accepted Bu kural olumlu bir teyit verildiğini sağlama bağlamak için kullanılabilir. Geçerlilik denetiminden geçirilen değer şu değerlerden biri ise geçecektir: yes, on veya sayısal 1. Bu kuralın amacı kullanıcının bir şeyi kabul ettiğini garantiye alma istediğinizi karşılamaktır, örneğin bir kullanım şartları onay kutusu. 1 array( 'alan' => 'accepted' 3 ); active_url active_url kuralı değerin geçerli bir URL olmasını kontrol edecektir. Bunu yapmak için PHP nin kendi checkdnsrr() metodunu kullanır, bu metod sadece URL yapısını kontrol etmez, aynı zamanda DNS kayıtlarınız içinde bu URL nin mevcut olduğunu da kesinleştirir. 1 array( 'alan' => 'active_url' 3 ); after after geçerlilik kuralı tekli bir parametre kabul eder: bir zamanı temsil eden bir string. Bu kural, ilgili alanın verilen parametredekinden sonraki bir tarihi taşımasını temin edecektir. Laravel karşılaştırma için gerek değeri gerek kural parametresini bir zaman damgasına çevirmek için PHP nin strtotime() metodunu kullanacaktır.

200 Geçerlilik Denetimi (Validation) array( 'alan' => 'after:1/1/13' 3 ); alpha alpha geçerlilik kuralı sağlanan değerin tamamıyla alfabe karakterlerinden oluşmasını garantiye alır. 1 array( 'alan' => 'alpha' 3 ); alpha_dash alpha_dash kuralı sağlanan değerin alfabe karakterleri yanında, tire - ve/veya alt tire _ karakterlerinden oluşmasını temin eder. Bu geçerlilik kuralı kimi URL parçalarını geçerlilik denetiminden geçirmekte çok yararlıdır. 1 array( 'alan' => 'alpha_dash' 3 ); alpha_num alpha_num kuralı sağlanan değerin alfabe ve sayı karakterlerinden oluşmasını garantiye alır. Kullanıcı adı alanlarını geçerlilik denetiminden geçirmek için bu kuralı kullanmayı seviyorum. 1 array( 'alan' => 'alpha_num' 3 ); before before kuralı tekli bir parametre alır. Sorgulanacak değer parametredekinden önce olmalıdır, karşılaştırma için her ikisi de PHP nin strtotime() metoduyla zaman damgasına dönüştürülürler. Bu kural after kuralının tam tersidir.

201 Geçerlilik Denetimi (Validation) array( 'alan' => 'before:1/1/13' 3 ); between between kuralı iki parametre alır. Geçerlilikten geçirilecek değer bu iki parametre arasında bulunan bir büyüklükte olmalıdır. Karşılaştırma şekli karşılaştırılacak verinin tipine bağlıdır. Örneğin sayısal alanlarda karşılaştırma matematiksel bir karşılaştırma olacaktır. Bir string için, karşılaştırma stringin karakter sayısına dayalı olarak yapılacaktır. Bir dosya için ise, karşılaştırma dosyanın kilobayt cinsinden boyutuna dayalı olacaktır. 1 array( 'alan' => 'between:5,7' 3 ); confirmed confirmed geçerlilik kuralı ilgili alanın adına _confirmation eklenmiş bir ada sahip başka bir alanın mevcut olmasını garantiye alır. Geçerlilikten geçirilecek değer, bu diğer alanın değeriyle aynı olmalıdır. Bu kuralın kullanım yerlerinden birisi password alan teyitleridir ve kullacının iki alandan birinde bir yazım hatası yapmamasını temin etme amacını güder. Aşağıdaki örnek alan ile alan_confirmation alanlarının değerlerinin aynı olmasını temin eder. 1 array( 'alan' => 'confirm' 3 ); date date geçerlilik kuralı değerimizin geçerli bir tarih olduğunun sağlamasını yapar. Değeri doğrulamak için PHP nin kendi strtotime() metodunu çalıştıracaktır.

202 Geçerlilik Denetimi (Validation) array( 'alan' => 'date' 3 ); date_format date_format geçerlilik kuralı değerimizin bir parametre olarak sağlanan formata uygun bir tarih stringi olmasını temin eder. Bir tarih format stringinin nasıl yapıldığını öğrenmek için PHP belgelerinde date() metoduna bakınız. 1 array( 'alan' => 'date_format:d/m/y' 3 ); different different geçerlilik kuralı ilgili değerin kural parametresinde belirtilen alandaki değerden farklı olduğunun sağlandığını grantiye alır. 1 array( 'alan' => 'different:bir_diger_alan' 3 ); geçerlilik kuralı geçerlilik denetiminden geçirilecek değerin geçerli bir adresi olmasını sağlama alacaktır. Kayıt formu oluşturulurken bu kural çok işe yarar. 1 array( 'alan' => ' ' 3 ); exists exists geçerlilik kuralı alan değerinin kural parametresi tarafından tanımlanan bir veritabanı tablosu içerisinde olmasını garanti edecektir. Araştırılacak olan sütun, geçerlilikten geçirilecek alanla aynı isimde olacaktır. Alternatif olarak, bir sütun ismi belirtmek için opsiyonel bir ikinci parametre verebilirsiniz. Bu kural, kayıt formlarında bir kullanici_adi nın başka bir kullanıcı tarafından daha önceden alınmış olup olmadığını yoklamak için çok yararlı olacaktır.

203 Geçerlilik Denetimi (Validation) array( 'alan' => 'exists:users,kullanici_adi' 3 ); Kurala geçirilen ek parametre çiftleri sorguya ek where cümlecikleri olarak eklenecektir. Bunun gibi: 1 array( 'alan' => 'exists:users,kullanici_adi,role,admin' 3 ); Yukarıdaki örnek, girilen değerin users tablosunun kullanici_adi sütununda mevcut olup olmadığını kontrol edecektir. Aynı zamanda, role sütunu da admin değerinde olmak zorundadır. image image geçerlilik kuralı upload edilen dosyanın geçerli bir imaj dosyası olmasını sağlama alır. Örneğin, dosyanın uzantısı şunlardan birisi olmalıdır:.bmp,.gif,.jpeg veya.png. 1 array( 'alan' => 'image' 3 ); in in geçerlilik kuralı alanın değerinin parametrede sağlanan değerlerden biriyle aynı olmasını temin eder. 1 array( 'alan' => 'in:siyah,kahverengi,beyaz' 3 ); integer En kolaylarından birisi! integer geçerlilik kuralı alanın değerinin bir tam sayı olmasını sağlama bağlar. Hepsi bu!

204 Geçerlilik Denetimi (Validation) array( 'alan' => 'integer' 3 ); ip ip geçerlilik kuralı alanın değerinin iyi biçimlendirilmiş bir IP adresi taşıdığından emin olmak için kontrol yapacaktır. 1 array( 'alan' => 'ip' 3 ); max max geçerlilik kuralı min kuralının tam tersidir. Alanın büyüklüğünün verilen parametreye eşit veya parametreden daha az olmasını garantiye alır. Eğer alan bir string ise parametre stringin karakter uzunluğu demek olacaktır. Sayısal değerler için karşılaştırma matematikle yapılacaktır. Dosya gönderme alanları için karşılaştırma dosyanın kilobayt cinsinden boyutuna dayalı olarak yapılacaktır. 1 array( 'alan' => 'max:3' 3 ); mimes mimes geçerlilik kuralı sağlanan stringin bir Fransız pandomimcisi ismi olmasını temin eder. Şaka, şaka. Bu kural bir upload dosyasının tipinin parametrede verilenlerden birine uymasını garantiye almak için kontrol yapacaktır. 1 array( 'alan' => 'mimes:pdf,doc,docx' 3 );

205 Geçerlilik Denetimi (Validation) 190 min min geçerlilik kuralı max kuralının tam karşıtıdır. Bir alan değerinin verilen parametreye eşit veya ondan daha büyük olmasını garantilemek için kullanılabilir. Eğer alan bir string ise parametre stringin karakter uzunluğu demek olacaktır. Sayısal değerler için karşılaştırma matematikle yapılacaktır. Dosya gönderme alanları için karşılaştırma dosyanın kilobayt cinsinden boyutuna dayalı olarak yapılacaktır. 1 array( 'alan' => 'min:5' 3 ); not_in Adının düşündürdüğü gibi, bu geçerlilik kuralı in kuralının tam tersidir. Alan değerinin sağlanan parametre listesi içinde mevcut olmamasını temin edecektir. 1 array( 'alan' => 'not_in:mavi,mor,pembe' 3 ); numeric numeric kuralı geçerlilikten geçirilecek alanın sayısal bir değer taşıdığından emin olmamızı sağlayan kontrolü yapacaktır. 1 array( 'alan' => 'numeric' 3 ); regex regex geçerlilik kuralı Laravel in Validation bileşeninde bulunan en esnek kuraldır. Bu kuralla, geçerlilikten geçirilecek alanın uyması gereken özel bir düzenli ifadeyi bir parametre olarak verebilirsiniz. Kendi başına bir kitap olmaya değer çok büyük bir konu olması nedeniyle bu kitapta düzenli ifadeler ayrıntılı olarak anlatılmayacaktır. Pipe karakterlerinin düzenli ifadeler içerisinde kullanılabilmesi nedeniyle, regex kuralını kullandığınız zaman birden çok geçerlilik kuralını birleştirmek için pipe kullanmak yerine içi içe dizi kullanmayı unutmayınız.

206 Geçerlilik Denetimi (Validation) array( 'alan' => 'regex:[a-z]' 3 ); required required geçerlilik kuralı ilgili alanın geçerlilik veri dizisinde mevcut olmasını garantilemek için kullanılabilir. 1 array( 'alan' => 'required' 3 ); required_if required_if geçerlilik kuralı ilgili alanın sadece kuralın ilk parametresinde belirtilen bir alanın değerinin, kuralın ikinci parametresiyle sağlanan değere eşit olması halinde mevcut olma zorunluğunu garanti eder. 1 array( 'alan' => 'required_if:kullanici_adi,serginari' 3 ); required_with required_with ilgili alanın sadece kural parametreleri ile tanımlanan bir veya daha fazla alanın da mevcut olması durumunda mevcut olmasını sağlama almak için kullanılır. 1 array( 'alan' => 'required_with:yas,boy' 3 ); required_without required_without kuralı required_with kuralının tam karşıtıdır. Alanımızın sadece kural parametreleri ile tanımlanan alanlar mevcut olmadığı zaman mevcut olmasını temin etmek için kullanılabilir.

207 Geçerlilik Denetimi (Validation) 19 1 array( 'alan' => 'required_without:yas,boy' 3 ); same same geçerlilik kuralı different kuralının tam tersidir. İlgili alanın değerinin kural parametresi ile tanımlanan başka bir alanınki ile aynı olmasını garantilemek için kullanılır. 1 array( 'alan' => 'same:yas' 3 ); size size kuralı alanın değerinin kural parametresi olarak sunulan belli bir büyüklükte olmasını sağlamak için kullanılabilir. Eğer alan bir string ise parametre stringin karakter uzunluğu demek olacaktır. Sayısal değerler için karşılaştırma matematikle yapılacaktır. Dosya gönderme alanları için karşılaştırma dosyanın kilobayt cinsinden boyutuna dayalı olarak yapılacaktır. 1 array( 'alan' => 'size:8' 3 ); unique unique kuralı mevcut alanın değerinin kural parametresi ile tanımlanan veritabanı tablosu içerisinde zaten bulunuyor olmamasını garantiye alır. Ön tanımlı olarak, kuralımız değerine bakılacak tablo sütunu olarak alanın adını kullanacaktır, ancak ikinci bir kural parametresi içinde alternatif bir sütun verebilirsiniz. Kayıt formları işleneceği zaman bir kullanıcının verdiği kullanıcı adının benzersiz olup olmadığını kontrol etmek için yararlı bir kuraldır. 1 array( 'alan' => 'unique:users,kullanici_adi' 3 ); Benzersizlik kuralı tarafından göz ardı edilecek bir takım satır ID lerini listelemek için fazladan opsiyonel parametreler kullanabilirsiniz.

208 Geçerlilik Denetimi (Validation) array( 'alan' => 'unique:users,kullanici_adi,,3,,1' 3 ); url url geçerlilik kuralı alanın geçerli bir URL taşıdığından emin olmak için kullanılabilir. active_- url geçerlilik kuralından farklı olarak, url kuralı DNS kayıtlarını kontrol etmez, sadece stringin formatını kontrol eder. 1 array( 'alan' => 'url' 3 ); Peki, onların hepsi bu kadar. O kadar da kötü değilmiş, değil mi? Gerçi henüz tam bitirmiş değiliz. Şimdi de hata mesajlarına bir bakalım. Hata Mesajları İlk bölümde geçerlilik denetiminin nasıl yapılacağını ve geçememe durumunda bir forma nasıl tekrar redirekt yapılacağını öğrendik. Buna karşın, bu yöntem kullanıcıya çok yapısal bir geri bildirim yolu sunmamaktadır. Neyse ki, Laravel geçerlilik denetiminin neden başarısız olduğunu açıklayan çok sayıda hata mesajı toplayabilmektedir. Bu bilgilere nasıl erişebileceğimize bir bakalım. 3 // app/routes.php 5 Route::get('/', function() 6 { 7 return View::make('form'); 8 }); 9 10 Route::post('/tescil', function() 11 {

209 Geçerlilik Denetimi (Validation) 19 1 // Tüm istek verilerini alalım. 13 $veri = Input::all(); 1 15 // Geçerlilik sınırlama kümesini oluşturalım. 16 $kurallar = array( 17 'kullanici_adi' => 'alpha_num' 18 ); 19 0 // Yeni bir validator olgusu oluşturalım. 1 $gecerlikci = Validator::make($veri, $kurallar); 3 if ($gecerlikci->passes()) { // Normalde veriyle bir şeyler yapacağız. 5 return 'Veri kaydedildi.'; 6 } 7 8 // Geçerlilik hata mesajları nesnesini toparla. 9 $errors = $gecerlikci->messages(); return Redirect::to('/'); 3 }); Yukarıdaki örnekte, validatör olgumuzun messages() metodunu kullanarak geçerlilik hata mesajları nesnesine erişebileceğimizi göreceksiniz. Şimdi, form rotamıza redirekt yaptığımıza göre, bu hata mesajlarına formumuz içinden nasıl erişebileceğiz? Peki, bu amaçla witherrors() metodunu kullanabileceğimizi düşünüyorum. Sana inanmıyorum, yalan söylemeye devam ediyorsun! Oo öyle mi? Kontrol et o zaman. 3 // app/routes.php 5 Route::get('/', function() 6 { 7 return View::make('form'); 8 }); 9 10 Route::post('/tescil', function()

210 Geçerlilik Denetimi (Validation) { 1 // Tüm istek verilerini alalım. 13 $veri = Input::all(); 1 15 // Geçerlilik sınırlama kümesini oluşturalım. 16 $kurallar = array( 17 'kullanici_adi' => 'alpha_num' 18 ); 19 0 // Yeni bir validator olgusu oluşturalım. 1 $gecerlikci = Validator::make($veri, $kurallar); 3 if ($gecerlikci->passes()) { // Normalde veriyle bir şeyler yapacağız. 5 return 'Veri kaydedildi.'; 6 } 7 8 return Redirect::to('/')->withErrors($gecerlikci); 9 }); Bu witherrors() zincir metoduna validatör olgusunu geçtiğimizi fark edeceksiniz. Bu metod, hataları formdan oturuma flash edecektir. Devam etmeden önce, örneğimize bazı geçerlilik kuralları ekleyelim. 3 // app/routes.php 5 Route::get('/', function() 6 { 7 return View::make('form'); 8 }); 9 10 Route::post('/tescil', function() 11 { 1 // Tüm istek verilerini alalım. 13 $veri = Input::all(); 1 15 // Geçerlilik sınırlama kümesini oluşturalım. 16 $kurallar = array( 17 'kullanici_adi' => 'required alpha_num min:3 max:3', 18 ' ' => 'required ',

211 Geçerlilik Denetimi (Validation) 'password' => 'required confirm min:3' 0 ); 1 // Yeni bir validator olgusu oluşturalım. 3 $gecerlikci = Validator::make($veri, $kurallar); 5 if ($gecerlikci->passes()) { 6 // Normalde veriyle bir şeyler yapacağız. 7 return 'Veri kaydedildi.'; 8 } 9 30 return Redirect::to('/')->withErrors($gecerlikci); 31 }); Şimdi, form görünümünden hata mesajlarına nasıl erişebildiğimizi görebiliriz. 1 <!-- app/views/form.blade.php --> 3 <h1>phill Parkları için kayıt formu</h1> 5 {{ Form::open(array('url' => 'tescil')) }} 6 7 <ul class="errors"> as $mesaj) 9 <li>{{ $mesaj }}</li> 11 </ul> 1 13 {{-- Kullanıcı Adı alanı }} 1 {{ Form::label('kullanici_adi', 'Kullanıcı Adı') }} 15 {{ Form::text('kullanici_adi') }} {{-- adresi alanı }} 18 {{ Form::label(' ', ' adresi') }} 19 {{ Form:: (' ') }} 0 1 {{-- Password alanı }} {{ Form::label('password', 'Şifre') }} 3 {{ Form::password('password') }} 5 {{-- Password teyit alanı }} 6 {{ Form::label('password_confirmation', 'Şifre tekrarı') }}

212 Geçerlilik Denetimi (Validation) {{ Form::password('password_confirmation') }} 8 9 {{-- Form gönderme düğmesi }} 30 {{ Form::submit('Kayıt Ol') }} 31 3 {{ Form::close() }} Görünümümüz yüklendiği zaman $errors değişkeni görünüm verisine eklenir. O her zaman oradadır ve her zaman için bir hata mesajı konteyneri olgusudur, dolayısıyla, onun varlığını veya içeriğini kontrol etme konusunda endişelenmenize gerek yoktur. Eğer önceki bir istekteki hata mesajlarımızı oturuma flash etmek için witherrors() kullanmışsak, bu durumda Laravel onları otomatik olarak errors nesnesine ekleyecektir. Ne kolaylık! $errors hata mesajları olgusu üzerinde all() metodunu kullanmak suretiyle tüm hata mesajlarına bir dizi şeklinde erişebiliyoruz. Yukarıdaki görünümde, bütün mesaj dizisini baştan sona dolaşarak, onların her birini bir liste elementi içinde çıktılıyoruz. Haklısınız, bu kadar gevezelik yeter. Bir deneyelim artık onu. Gidip / URL sini ziyaret edelim. Herhangi bir bilgi girmeden formu gönderelim ve ne olacağını görelim. Forma tekrar yönlendirildik. Ancak bu sefer bir takım hata mesajları görüntülendi. (Çevirenin notu: Burada hata mesajları Laravel yüklemesinin ön tanımlı dili ingilizce olarak gösterilmiştir. Türkçe dil dosyalarını yükleyip, ön tanımlı dili ayarlayarak hata mesajlarını Türkçe gösterebilirsiniz.) The kullanici_adi field is required. The field is required. The password field is required. Harika! artık uygulamamızın kullanıcıları kayıtla ilgili geçerlilik hatalarının farkında oluyorlar. Ancak, eğer hata mesajları açıkladıkları alanlara daha yakın olurlarsa kullanıcılarımız için daha uygun olacaktır. Görünümde küçük bir değişiklik yapalım öyleyse. 1 <!-- app/views/form.blade.php --> 3 <h1>phill Parkları için kayıt formu</h1> 5 {{ Form::open(array('url' => 'tescil')) }} 6 7 {{-- Kullanıcı Adı alanı }} 8 <ul class="errors"> as $mesaj) 10 <li>{{ $mesaj }}</li>

213 Geçerlilik Denetimi (Validation) </ul> 13 {{ Form::label('kullanici_adi', 'Kullanıcı Adı') }} 1 {{ Form::text('kullanici_adi') }} {{-- adresi alanı }} 17 <ul class="errors"> as $mesaj) 19 <li>{{ $mesaj }}</li> 1 </ul> {{ Form::label(' ', ' adresi') }} 3 {{ Form:: (' ') }} 5 {{-- Password alanı }} 6 <ul class="errors"> as $mesaj) 8 <li>{{ $mesaj }}</li> 30 </ul> 31 {{ Form::label('password', 'Şifre') }} 3 {{ Form::password('password') }} 33 3 {{-- Password teyit alanı }} 35 {{ Form::label('password_confirmation', 'Şifre tekrarı') }} 36 {{ Form::password('password_confirmation') }} {{-- Form gönderme düğmesi }} 39 {{ Form::submit('Kayıt Ol') }} 0 1 {{ Form::close() }} Tek bir alan için bir hatalar dizisini elde etmek için geçerlilik hataları nesnesinde get() metodunu kullanabiliyoruz. Bunun için sadece alanın adını get() metoduna ilk parametre olarak geçiniz. Şimdi formu tekrar submit edelim. Bu sefer kullanici_adi alanına tek bir ünlem! işareti koyun. Şimdi kullanici_adi alanının üstünde ortaya çıkan hatalara bir göz atalım. The kullanici_adi may only contain letters and numbers. The kullanici_adi must be at least 3 characters. Bu daha iyi. Evet Bir parça daha iyi. Pek çok form uygulamanın kullanıcılarını bunaltmamak için alan başına sadece tek bir geçerlilik hatası gösterir. Bunu Laravel geçerlilik hataları nesnesi ile nasıl yapabileceğimizi görelim.

214 Geçerlilik Denetimi (Validation) <!-- app/views/form.blade.php --> 3 <h1>phill Parkları için kayıt formu</h1> 5 {{ Form::open(array('url' => 'tescil')) }} 6 7 {{-- Kullanıcı Adı alanı }} 8 <span class ="error">{{ $errors->first('kullanici_adi') }}</span> 9 {{ Form::label('kullanici_adi', 'Kullanıcı Adı') }} 10 {{ Form::text('kullanici_adi') }} 11 1 {{-- adresi alanı }} 13 <span class ="error">{{ $errors->first(' ') }}</span> 1 {{ Form::label(' ', ' adresi') }} 15 {{ Form:: (' ') }} {{-- Password alanı }} 18 <span class ="error">{{ $errors->first('password') }}</span> 19 {{ Form::label('password', 'Şifre') }} 0 {{ Form::password('password') }} 1 {{-- Password teyit alanı }} 3 {{ Form::label('password_confirmation', 'Şifre tekrarı') }} {{ Form::password('password_confirmation') }} 5 6 {{-- Form gönderme düğmesi }} 7 {{ Form::submit('Kayıt Ol') }} 8 9 {{ Form::close() }} Geçerlilik hataları nesnesinde first() metodunu kullanmak ve parametre olarak alan ismini geçmek suretiyle, o alana ait ilk hata mesajını elde edebiliyoruz. Bir kez daha kullanici_adi alanına sadece bir ünlem! işareti koyarak formu submit edelim. Bu sefer ilk alanımız için sadece tek bir hata mesajı alacağız. The kullanici_adi may only contain letters and numbers. Ön tanımlı durumda geçerlilik mesajları olgusunun metodları, hata mesajları olmadığı takdirde boş bir dizi veya null döndürür. Bunun anlamı şudur: mesajların mevcut olup olmadığını kontrol etme zorunda kalmaksızın onu kullanabilirsiniz. Ancak bazı sebeplerle bir alan için bir hata mesajı mevcut olup olmadığını yoklamak isterseniz has() metodunu kullanabilirsiniz.

215 Geçerlilik Denetimi (Validation) 00 <p>hey, bir hata var!</p> all() ve first() metodlarıyla ilgili önceki örneklerimizde hata mesajlarımızı HTML elementleri ile sarmış olduğumuzu fark etmişsinizdir. Ancak, eğer bizim metodlarımızdan biri null döndürürse, HTML hala gösterilecektir. all() ve first() metodlarına ikinci parametre olarak kapsayıcı HTML yi string formatında geçmek suretiyle görünüm kaynak kodumuzda boş HTML elementlerinin gözükmesini engelleyebiliriz. Örneğin, ikinci bir parametre olarak sarıcı liste elementleri alan all() metodu şöyledir. 1 <!-- app/views/form.blade.php --> 3 <h1>phill Parkları için kayıt formu</h1> 5 {{ Form::open(array('url' => 'tescil')) }} 6 7 <ul class="errors"> as $mesaj) 9 {{ $mesaj }} 11 </ul> 1 13 {{-- Kullanıcı Adı alanı }} 1 {{ Form::label('kullanici_adi', 'Kullanıcı Adı') }} 15 {{ Form::text('kullanici_adi') }} {{-- adresi alanı }} 18 {{ Form::label(' ', ' adresi') }} 19 {{ Form:: (' ') }} 0 1 {{-- Password alanı }} {{ Form::label('password', 'Şifre') }} 3 {{ Form::password('password') }} 5 {{-- Password teyit alanı }} 6 {{ Form::label('password_confirmation', 'Şifre tekrarı') }} 7 {{ Form::password('password_confirmation') }} 8 9 {{-- Form gönderme düğmesi }} 30 {{ Form::submit('Kayıt Ol') }} 31 3 {{ Form::close() }}

216 Geçerlilik Denetimi (Validation) 01 all() metodunun ikinci parametresinin :message kısmı, dizi oluşturulduğunda gerçek hata mesajı ile değiştirilecektir. first() metodu da aynı opsiyonel parametreye sahiptir. 1 <!-- app/views/form.blade.php --> 3 <h1>phill Parkları için kayıt formu</h1> 5 {{ Form::open(array('url' => 'tescil')) }} 6 7 {{-- Kullanıcı Adı alanı }} 8 {{ $errors->first('kullanici_adi', '<span class ="error">:message</span>') }} 9 {{ Form::label('kullanici_adi', 'Kullanıcı Adı') }} 10 {{ Form::text('kullanici_adi') }} 11 1 {{-- adresi alanı }} 13 {{ $errors->first(' ', '<span class ="error">:message</span>') }} 1 {{ Form::label(' ', ' adresi') }} 15 {{ Form:: (' ') }} {{-- Password alanı }} 18 {{ $errors->first('password', '<span class ="error">:message</span>') }} 19 {{ Form::label('password', 'Şifre') }} 0 {{ Form::password('password') }} 1 {{-- Password teyit alanı }} 3 {{ Form::label('password_confirmation', 'Şifre tekrarı') }} {{ Form::password('password_confirmation') }} 5 6 {{-- Form gönderme düğmesi }} 7 {{ Form::submit('Kayıt Ol') }} 8 9 {{ Form::close() }} Özel Geçerlilik Kuralları Ah, anlıyorum, Laravel in size verdikleriyle mutlu olamadınız? Siz kendi yaptığınız geçerlilik metodlarınız olsun istiyorsunuz? Çok güzel, büyük silahları almanın zamanı geldi. Laravel size kendi kurallarınızı belirlemenize izin verecek kadar esnektir. Bunun nasıl yapılabileceğine bir göz atalım.

217 Geçerlilik Denetimi (Validation) 0 3 // app/routes.php 5 Validator::extend('harika', function($alan, $deger, $parametreler) 6 { 7 return $deger == 'harika'; 8 }); 9 10 Route::get('/', function() 11 { 1 return View::make('form'); 13 }); 1 15 Route::post('/tescil', function() 16 { 17 // Tüm istek verilerini alalım. 18 $veri = Input::all(); 19 0 // Geçerlilik sınırlama kümesini oluşturalım. 1 $kurallar = array( 'kullanici_adi' => 'harika', 3 ); 5 // Yeni bir validator olgusu oluşturalım. 6 $gecerlikci = Validator::make($veri, $kurallar); 7 8 if ($gecerlikci->passes()) { 9 // Normalde veriyle bir şeyler yapacağız. 30 return 'Veri kaydedildi.'; 31 } 3 33 return Redirect::to('/')->withErrors($gecerlikci); 3 }); Özel geçerlilik kuralları için ön tanımlı bir konum tanımlanmış değildir, bu nedenle ben örneği basitleştirmek amacıyla kuralı routes.php dosyasının içine koydum. Siz isterseniz bir validators.php dosyasını include edip, özel geçerlilik kurallarını orada verebilirsiniz. Kendi harika geçerlilik kuralımızı kullanici_adi alanımıza tutturduk. Bu geçerlilik kuralının nasıl oluşturulduğuna daha yakından bakalım.

218 Geçerlilik Denetimi (Validation) 03 3 // app/routes.php 5 Validator::extend('harika', function($alan, $deger, $parametreler) 6 { 7 return $deger == 'harika'; 8 }); Özel bir geçerlilik kuralı oluşturmak için Validator::extend() metodunu kullanıyoruz. Metoda geçilen ilk parametre geçerlilik kuralına verilecek olan takma addır. Bu isim, kuralı alana bağlamak için kullanılacaktır. Metodun ikinci parametresi bir closure dir. Closure true sonuçlu bir boolean değer döndürürse, geçerlilik denemesi denetimi geçmiş olacaktır. Closure dan eğer boolean false döndürülürse, geçerlilik girişimi denetimden kalmış olacaktır. Closure a koyulan parametreler şu şekildedir. Birinci parametre geçerlilikten geçirilecek alanın adını taşıyan bir stringtir. Yukarıdaki örnekte ilk parametre kullanici_adi stringini taşıyacaktır. Extent closure unun ikinci parametresi alanın değerini taşır. Üçüncü parametre ise geçerlilik kuralına geçilen bir parametreler dizisidir. Gerektiğinde geçerlilik kurallarını özelleştirmek için bunları kullanın. Eğer özel geçerlilik kurallarınızı bir closure yerine bir sınıf içerisinde tanımlamayı tercih ederseniz, bunu yapmanız mümkün olmayacaktır. Bir şeyler isteyip durmayın. Bekleyin azıcık, sadece şaka yapıyorum. Laravel bunu yapabilir. Bunu gerçekleştirecek bir sınıf oluşturalım. 3 // app/validators/ozelgecerlilik.php 5 class OzelGecerlilik 6 { 7 public function harika($alan, $deger, $parametreler) 8 { 9 return $deger == 'harika'; 10 } 11 } Görebileceğiniz gibi, geçerlilik sınıfımız geçerlilik closure unda olan aynı metod yazılımına sahip değişik sayıda metodlar içermektedir. Bu, özel bir geçerlilik sınıfının istediğimiz kadar çok sayıda geçerlilik kuralına sahip olabileceği anlamına gelmektedir.

219 Geçerlilik Denetimi (Validation) 0 Tekrar ifade edeyim, bu sınıflar için ideal bir yer yoktur, bu yüzden kendi proje yapınızı siz tanımlamak durumundasınız. Ben kendi geçerlilik sınıfımı app/validators klasörüne koymayı ve Composer ile bu klasörü classmap yapmayı tercih ediyorum. Evet, her şey açıklığa kavuştu. Bir saniye, geçerlilik sınıfı geçerlilik takma adı içermiyor. Ah evet, neredeyse unutuyordum. Çok iyisiniz dikkatli okuyucu! Gördüğünüz gibi, geçerlilik kuralının bulunabilmesi için yine Validator::extend() metodunu kullanmamız gerekiyor. En iyisi bir göz atalım. 3 // app/routes.php 5 Validator::extend('harika', 'OzelGecerlilik@harika'); Bu sefer Validator::extend() metoduna ikinci parametre olarak bir string verildi. Tıpkı bir kontrollere rota yaparken olduğu gibi bu string geçerlilik kural sınıfının sınıf adıyla, kuralı temsil eden eylemin sembolüyle birleştirilmesinden oluşuyor. İlerideki bir bölümde, özel geçerlilik kuralları sağlamanın daha gelişmiş, alternatif bir yöntemi olarak Validation sınıfının nasıl genişletileceğini öğreneceğiz. Özel Geçerlilik Mesajları Laravel yerleşik geçerlilik kurallarının tümü için ön tanımlı geçerlilik mesajları sağlamıştır, fakat siz ön tanımlı olan birilerini istemezseniz veya uygulamanızı ana dil olarak İngilizce kullanmayan bir bölge için yazmak isterseniz ne olacak? Tamam panik yapmayın! Laravel yerleşik geçerlilik mesajlarını geçersiz kılıp değiştirmenize izin verecektir. Bizim sadece ek bir dizi inşa etmemiz ve onu validator olgusunun make() metoduna geçmemiz gerekiyor. Hey, Validator::make() metodunu zaten görmüştük! Bu doğru, ama bir kez daha yalan söyledim. Neden bana işkence ediyorsun? Gerçekten emin değilim. Bu noktada sanırım onu bir hobi olarak düşünüyorum. Her neyse, örnek bir özel geçerlilik mesajları dizisi görmeye ne dersiniz?

220 Geçerlilik Denetimi (Validation) 05 3 // app/routes.php 5 Route::get('/', function() 6 { 7 return View::make('form'); 8 }); 9 10 Route::post('/tescil', function() 11 { 1 // Tüm istek verilerini alalım. 13 $veri = Input::all(); 1 15 // Geçerlilik sınırlama kümesini oluşturalım. 16 $kurallar = array( 17 'kullanici_adi' => 'min:3', 18 ); 19 0 // Özel mesajlar dizisini inşa edelim. 1 $mesajlar = array( 'min' => 'Hey dostum, bu alan yeterince uzun değil.' 3 ); 5 // Yeni bir validator olgusu oluşturalım. 6 $gecerlikci = Validator::make($veri, $kurallar, $mesajlar); 7 8 if ($gecerlikci->passes()) { 9 // Normalde veriyle bir şeyler yapacağız. 30 return 'Veri kaydedildi.'; 31 } 3 33 return Redirect::to('/')->withErrors($gecerlikci); 3 }); Ne büyük bir örnek, odak düğmesini tıklayalım. Klavyemde odak düğmesini bulamıyorum. Pekala, eğer bir Mac kullanıyorsan, sekme tuşunun bir üstündedir. Bunun ± gibi gözükür. Emin misin?

221 Geçerlilik Denetimi (Validation) 06 Peki, bu düğmenin ne anlama geldiği konusunda başka fikrin var mı? Ah, anlıyorum. Tamam, hadi örneğe odaklanalım. 3 // Özel mesajlar dizisini inşa edelim. $mesajlar = array( 5 'min' => 'Hey dostum, bu alan yeterince uzun değil.' 6 ); 7 8 // Yeni bir validator olgusu oluşturalım. 9 $gecerlikci = Validator::make($veri, $kurallar, $mesajlar); Mesajlar dizisi Validator::make() metodu için opsiyonel bir üçüncü parametredir. Bu dizi vermek istediğiniz ve aynı zamanda ön tanımlı geçerlilik mesajlarını geçersiz kılacak olan özel geçerlilik mesajlarını içerir. Geçerlilik mesaj dizisinin anahtar kısmı geçerlilik kuralının adını temsil eder ve değer kısmı geçerlilik kuralı başarısız olduğunda gösterilecek mesajı temsil eder. Yukarıdaki örnekte min geçerlilik kuralı için geçerlilik denetiminden kalma mesajını değiştirmiş oluyoruz. Bu metodu bizim özel geçerlilik kurallarımız için geçerlilik hataları sağlamak amacıyla da kullanabiliriz. Bizim özel kurallarımızda ön tanımlı geçerlilik hata mesajları olmaz, bu yüzden böyle yapmak normalde iyi bir fikirdir. 3 // Özel mesajlar dizisini inşa edelim. $mesajlar = array( 5 'harika' => 'Lütfen yeterince harika bir değer girin.' 6 ); 7 8 // Yeni bir validator olgusu oluşturalım. 9 $gecerlikci = Validator::make($veri, $kurallar, $mesajlar); Eğer belirli bir alan için özel bir hata mesajı vermek istersek, bunu dizi içindeki anahtar olarak alanın adını, bir nokta. karakterini ve geçerlilik tipini vererek yapabiliyoruz.

222 Geçerlilik Denetimi (Validation) 07 3 // Özel mesajlar dizisini inşa edelim. $mesajlar = array( 5 'kullanici_adi.min' => 'Hmm, bu biraz küçük görünüyor.' 6 ); 7 8 // Yeni bir validator olgusu oluşturalım. 9 $gecerlikci = Validator::make($veri, $kurallar, $mesajlar); Yukarıdaki örnekteki mesaj sadece kullanici_adi alanı için min geçerlilik kuralından kalındığı zaman gösterilecektir. Diğer tüm min kalmalarında ön tanımlı hata mesajı kullanılacaktır. Geçerlilik denetimi üzerine anlatacaklarım şimdilik bu kadar. Daha sonraki bir bölümde Laravel in validator sınıfının nasıl genişletileceğini ve tercüme edilebilir geçerlilik hata mesajlarının nasıl sağlanacağını öğreneceğiz, fakat şimdilik, veritabanları hakkında bilgi sahibi olmak için sonraki bölüme geçelim.

223 Veritabanları Şimdi bir itirafta bulunmak zorundayım. Ben büyük bir veritabanı hayranı değilim. Çocukken birisi tarafından ısırıldım. Isırıldım ve siz bunu gördünüz, çifte utanç. Tamam, tamam, yine şaka yapıyorum. Asıl sebebi bir veritabanının kardeşimi öldürmüş olması. Bir kez daha şaka yaptım, bir kardeşim yok benim. Onlardan neden hoşlanmadığımı aslında bilmiyorum, sanıyorum ben görsel şeyleri, zarif şeyleri, eğlenceli şeyleri seviyorum. Veritabanları ise sadece büyük veri ağlarıdır, şık değildirler ve eğlence karşıtıdırlar. Neyse ki, bu günlerde bizim veritabanı satırlarına nesne olguları olarak erişmemize imkan veren güzel ORM ler tarafından şımartıldık. İlerideki bir bölümde Laravel in kendine ait Eloquent adındaki ORM si hakkında daha çok duracağız. Eloquent güzeldir ve benim gibi acımasız bir veritabanı düşmanı için bile, veritabanlarıyla çalışmayı keyifli bir deneyim haline getirmektedir. Pekiyi, bir an için nefretimi bir tarafa bırakayım ve bir veritabanı kavramı üzerinde konuşayım. Ona neden ihtiyaç duyuyoruz? Tamam, gerek olmayabilir mi? Uygulamanızın, gelecekte yapılacak isteklerde kullanmak üzere veri saklaması gerekiyor mu? Ben sadece statik sayfalar göstermek istiyorum. Tamam, o zaman bir veritabanı gerekmez fakat çok sayıda istekler boyunca veri saklamanız ve onu uygulamanızın diğer rotalarında göstermeniz veya kullanmanız gerektiğinde ne olur? İşte o zaman bir veri depolama yöntemine ihtiyacınız var demektir ve bundan sonraki birkaç bölümü okumaktan memnun olacaksınız. Soyutlama Peki, Laravel dört ile kullanabileceğimiz veritabanları nelerdir? Bakalım aşağıdakilerden biri size hoş gelecek mi. MySQL Community / Standard / Enterprise Server²⁵ SQLite²⁶ PostgreSQL²⁷ SQL Server²⁸ Görebileceğiniz gibi, bir veritabanı platformu seçerken, bol miktarda seçeneğiniz var. Bu kitap için, ben MySQL Community Server Edition²⁹ kullanacağım. Bu mükemmel bir ücretsiz platformdur ve ²⁵ ²⁶ ²⁷ ²⁸ ²⁹

224 Veritabanları 09 geliştirme için kullanılanların en popülerlerinden biridir. Başka bir veritabanı kullanıyor olmaktan endişelenmek zorunda değilsiniz. Gördüğünüz gibi, Laravel bir soyutlama katmanı sağlamaktadır, bu katman frameworkün veritabanı bileşenlerini HAM SQL den farklı veritabanı tipleri için farklı sorgular sağlamaktadır. Basitçe ifade etmek gerekirse, SQL sözdizimi konusunu dert etmenize gerek yoktur, o işi Laravel e bırakın. Laravel in veritabanı soyutlama katmanını kullanmanın başka bir avantajı güvenliktir. Çoğu durumda, ben başka türlü göstermediğim sürece, Laravel den veritabanlarına gönderdiğiniz değerlerin escape edilmesini dert etmek zorunda değilsiniz. Çeşitli biçimlerdeki enjeksiyon saldırılarını önleme çabası olarak, Laravel bu değerleri sizin yerinize escape edecektir. Bir an için Laravel in veritabanı soyutlama katmanının esnekliğini tartabiliriz. Yani, istediğiniz zaman veritabanı sunucunuzu değiştirebilirsiniz ve bunu yaparken önceden yazmış olduğunuz veritabanı kodunuzda herhangi bir değişiklik yapmak zorunda kalmazsınız ve basit güvenlik konuları hakkında endişelenmenize gerek olmaz. Projelerimizden büyük bir iş yükünü kaldırmış oluyoruz gibi geliyor. Değerlerin escape edilmesi klişe işlerdendir, onu bizim yapmamız gerekmez. Bırakın o işi Laravel yapsın. Şimdi bir veritabanı kullanmak istediğimizi biliyoruz, bunlardan birini kullanmak için Laravel i nasıl ayarlayacağımızı görelim. Merak etmeyin, bu oldukça basit bir süreçtir! Öncelikle yapılandırma seçeneklerine bir göz atalım. Yapılandırma Laravel in veritabanı yapılandırmasının tümü app/config/database.php dosyasındadır. Hatırlaması kolay değil mi? Dosya boyunca bir gezi yapalım ve mevcut yapılandırma seçeneklerinden bir kısmına bakalım. 1 /* PDO Fetch Style By default, database results will be returned as instances of the PHP 7 stdclass object; however, you may desire to retrieve records in an 8 array format for simplicity. Here you can tweak the fetch style */ 11 1 'fetch' => PDO::FETCH_CLASS, Laravel in veritabanı bileşenlerinden birini çalıştıran bir sorgudan döndürülen satırlar ön tanımlı durumda PHP stdclass nesnesi biçiminde olacaktır. Bu, onun sütunlarındaki veriye şuna benzer bir formatta erişebileceğiniz anlamına gelir.

225 Veritabanları 10 3 echo $kitap->isim; echo $kitap->yazar; Bununla birlikte, satırların döndürüleceği formatı değiştirmek isterseniz, veritabanı yapılandırmasının fetch seçeneğini daha elverişli bir şeye değiştirebilirsiniz. Bu seçeneğin değerini PDO::FETCH_- ASSOC olarak değiştirirsek satırlarımızı tutmak için ilişkisel bir PHP dizisi kullanırız. Veritabanı satırlarımıza şimdi aşağıdaki tarzda erişebiliriz. 3 echo $kitap['isim']; echo $kitap['yazar']; PDO fetch yollarının tam bir listesi için, PHP PDO sabitleri belgeleri sayfasına³⁰ gidip, FETCH_ ile başlayan sabitlere bakınız. Sonraki bakacağımız yer connections dizisi. Ön tanımlı durumunda bu dizi şuna benzer. 3 'connections' => array( 5 'sqlite' => array( 6 'driver' => 'sqlite', 7 'database' => DIR.'/../database/production.sqlite', 8 'prefix' => '', 9 ), 'mysql' => array( 1 'driver' => 'mysql', 13 'host' => 'localhost', 1 'database' => 'database', 15 'username' => 'root', 16 'password' => '', 17 'charset' => 'utf8', 18 'collation' => 'utf8_unicode_ci', 19 'prefix' => '', 0 ), 1 ³⁰

226 Veritabanları 11 'pgsql' => array( 3 'driver' => 'pgsql', 'host' => 'localhost', 5 'database' => 'database', 6 'username' => 'root', 7 'password' => '', 8 'charset' => 'utf8', 9 'prefix' => '', 30 'schema' => 'public', 31 ), 3 33 'sqlsrv' => array( 3 'driver' => 'sqlsrv', 35 'host' => 'localhost', 36 'database' => 'database', 37 'username' => 'root', 38 'password' => '', 39 'prefix' => '', 0 ), 1 ), Woah, büyük bir varsayılan bağlantı listesi! Bu, başlamayı çok kolay hale getiriyor. Şimdi, yukarıdaki diziye bakarak, her veritabanı tipi için farklı bir anahtar olduğunu düşünebilirsiniz. Ancak eğer daha yakından bakacak olursanız, iç dizilerden her birinde, veritabanı tipini belirtmek için kullanılabilecek bir driver olduğunu fark edeceksiniz. Bunun anlamı, farklı MySQL veritabanı bağlantılarından oluşan bir diziniz olabilir demektir. Örneğin böyle: 3 'connections' => array( 5 'mysql' => array( 6 'driver' => 'mysql', 7 'host' => 'localhost', 8 'database' => 'database', 9 'username' => 'root', 10 'password' => '', 11 'charset' => 'utf8', 1 'collation' => 'utf8_unicode_ci', 13 'prefix' => '', 1 ),

227 Veritabanları 'mysql_' => array( 17 'driver' => 'mysql', 18 'host' => 'localhost', 19 'database' => 'database', 0 'username' => 'root', 1 'password' => '', 'charset' => 'utf8', 3 'collation' => 'utf8_unicode_ci', 'prefix' => '', 5 ), 6 7 'mysql_3' => array( 8 'driver' => 'mysql', 9 'host' => 'localhost', 30 'database' => 'database3', 31 'username' => 'root', 3 'password' => '', 33 'charset' => 'utf8', 3 'collation' => 'utf8_unicode_ci', 35 'prefix' => '', 36 ), ), Birtakım farklı veritabanı bağlantılarına sahip olmakla, bir veritabanından diğerine geçiş yapabiliriz. Dolayısıyla uygulamamız tek bir veritabanına sahip olmak zorunda kalmayacaktır. Çok esnek, sizin de aynı fikirde olduğunuzu sanıyorum. Connections dizisinin birinci anahtarı bağlantıya verilen bir takma isimdir, kodumuz içinden belirli bir veritabanında bir eylem yapma ihtiyacımız olduğunda bu ismi kullanabileceğiz. Veritabanlarınıza istediğiniz ismi verebilirsiniz! Şimdi köfte ve patateslere geçelim. Belirli bir bağlantı dizisindeki anahtarlara yakından bakacağız. Bir örnek daha verelim. 1 'my_connection' => array( 'driver' => 'mysql', 3 'host' => 'localhost', 'database' => 'database', 5 'username' => 'root', 6 'password' => '', 7 'charset' => 'utf8', 8 'collation' => 'utf8_unicode_ci', 9 'prefix' => '', 10 ),

228 Veritabanları 13 driver seçeneği bağlanmak istediğimiz veritabanı tipini belirtmek için kullanılabilir. 1 'driver' => 'mysql', Olabilecek değerler şunlardır. mysql - MySQL sqlite - SQLite pgsql - PostgreSQL sqlsrv - SQL Server Sonraki anahtar host anahtarı veritabanı sunucusunu barındıran makinenin ağ konumunu belirtmek için kullanılabilir. 1 'host' => 'localhost', Buraya bir IP adresi ( ) veya bir host adı (veritabani.ornek.com) da verebilirsiniz. Yerel geliştirme ortamında mevcut makinenizi ifade etmek için esas olarak veya localhost kullanacaksınız. SQLite Veritabanı SQLite veritabanları disk üzerindeki bir konumda depolanır ve bu nedenle bir host girişi yoktur. Bu sebeple, bir SQLite veritabanı bağlantı bloğundan bu anahtarı çıkartabilirsiniz. Bağlantı dizisinin sonraki indeksi database seçeneğidir. 1 'database' => 'veritabanı_adı', Bu bağlantıda üzerinde iş yapacağımız veritabanının adını tanımlamakta kullanılan bir string değerdir. Bir SQLite veritabanı olması durumunda, veritabanını saklamak için kullanılan dosyayı belirtmekte kullanılır, örneğin: 1 'database' => DIR.'/dosya/yolu/database.sqlite', username ve password anahtarları veritabanı bağlantınız için erişim kimlik bilgileri sağlamak amacıyla kullanılabilirler.

229 Veritabanları 1 1 'username' => 'dayle', 'password' => 'emma_wtson_is_hot', SQLite Veritabanı Bir kez daha, SQLite veritabanları burada bir parça farklıdır. Bunlarda erişim kimlik bilgileri olmaz. Bir SQLite bağlantı bloğundan bu anahtarları çıkartabilirsiniz. Sonraki yapılandırma anahtarı charset olup, bir veritabanı bağlantısı için varsayılan karakter kümesini belirtmekte kullanılabilir. 1 'charset' => 'utf8', SQLite Veritabanı Tahmin ettin onu sen! SQLite veritabanı bu seçeneği desteklemez. Bağlantı dizininden bu anahtarı dışarda tutmanız yeterlidir. Varsayılan veritabanı karşılaştırmasını collation anahtarını kullanarak ayarlayabilirsiniz. 1 'collation' => 'utf8_unicode_ci', SQLite Veritabanı Bir kez daha, SQLite benzersiz bir kar tanesi olmayı seçer. SQLite için karakter seti veya collation anahtarı sağlamanız gerekmez. Son olarak prefix seçeneğimiz var, veritabanı tablolarınıza ortak bir ön ek koymakta kullanılabilir. 1 'prefix' => '', Hazırlama Sonraki birkaç bölümdeki örnekleri çalışmak istiyorsanız, çalışan bir veritabanı bağlantısı kurmak isteyebilirsiniz. Bunun için bir veritabanı platformunu indirin ve yükleyin. Sonra bir bağlantı dizisi oluşturun ve gerekli tüm parametreleri doldurun. Neredeyse vardınız. Sadece Laravel e default olarak hangi veritabanı bağlantısını kullanacağınızı söylemeniz gerekiyor. Veritabanı yapılandırma dosyası app/config/database.php dosyasına tekrar bakalım.

230 Veritabanları 15 1 /* Default Database Connection Name Here you may specify which of the database connections below you wish 7 to use as your default connection for all database work. Of course 8 you may use many connections at once using the Database library */ 11 1 'default' => 'mysql', default dizi anahtarına, oluşturmuş olduğumuz yeni bağlantının tanımlayıcısını koyacağız. Bu sayede, veritabanını kullanmak istediğimiz her seferinde bir bağlantı belirtmek zorunda kalmayacağız. Peki, veritabanlarının seni heyecanlandırdığını biliyorum. Seni tuhaf, garip şahıs seni! Daha fazla zamanımı alma. Sayfayı çevir de şema oluşturucusunu inceleyelim.

231 Şema Oluşturucusu Evet, artık veritabanında bir şeyler saklamaya karar verdik. Veritabanı tam olarak basit anahtardeğer deposu değildir. Veritabanı içerisinde, verilerimizde farklı tiplerden oluşan yapılar olabilir ve ilişkiler olabilir. Seksi, harika ilişkiler. Yapılandırılmış verilerimizi saklayabilmemiz için, öncelikle yapıyı tanımlamamız gerekiyor. Bu kitap SQL üzerine yazılmamıştır, bu nedenle ben bir veritabanı tablosu ve onun sütunlarıyla ilgili kavramları biliyor olmanızı bekliyorum. Bu bölümde Schema sınıfına bakacağız, tablolarımızın yapısını tanımlamak için bu sınıfı kullanabiliriz. Bu bölümde herhangi bir veri saklaması olmayacaktır, bu nedenle zihninizde içerik değil hep yapı olsun. Sonraki bölümde, veritabanı yapınızı inşa etmeye başlamak için ideal konumu öğreneceksiniz, fakat her özelliği tek başına açıklamayı düşünüyorum. Şimdilik, şema oluşturma kodlarımızı rota closure ları içinde yazacağız. Daha fazla zaman kaybetmeden, sorgu oluşturucuna hızlı bir bakış yapalım. Tabloların Oluşturulması Bir tablo oluşturmak için Schema sınıfının create() metodunu kullanmamız gerekiyor. İşte bir örnek. 3 // app/routes.php 5 Route::get('/', function() 6 { 7 Schema::create('users', function($table) 8 { 9 // Henüz ayrıntıya girmiyoruz. 10 }); 11 }); Schema::create() metodu iki parametre alır. Birincisi oluşturmak istediğimiz tablonun adıdır. Bu örneğimizde users adında bir tablo oluşturuyoruz. Oluşturacağımız tablo şayet bir nesne tipini temsil eden verileri saklamak için kullanılacaksa tablonun adını o nesnenin ingilizce çoğulunun küçük harfleri olarak vereceğiz. (Çevirenin açıklaması: Aslında buna zorunlu değiliz. Örneğin tablo adına users yerine uyeler adını da verebilirdik. Ancak isimlendirmenin Laravel in bazı ön tanımlarına ve isimlendirme geleneklerine uygun olması bize birçok kolaylıklar sağlayacaktır.) Veritabanı sütunları

232 Şema Oluşturucusu 17 ve tabloları çoğu kez snake-casing kullanılarak isimlendirilir, yani tüm karakterler küçük harftir ve boşluklar alt tire ile (_) değiştirilmiştir. İkinci parametre anonim bir fonksiyon (Closure) olup kendisi de tek bir parametre alır. Yukarıdaki örnekte, ben bu parametreye $table adını verdim fakat siz ne isterseniz o ismi verebilirsiniz! Bu $table parametresi tablo yapısını inşa etmekte kullanılacaktır. Şimdi tablomuza otomatik artan birincil anahtar ekleyelim, bu sayede tablo satırlarımız benzersiz bir indeks ile tanımlanabilecektir. 3 // app/routes.php 5 Route::get('/', function() 6 { 7 Schema::create('users', function($table) 8 { 9 $table->increments('id'); 10 }); 11 }); increments() metodu bizim $table olgumuzda yeni bir otomatik artan sütun oluşturmak amacıyla bulunmaktadır. Otomatik artan bir sütun, her bir satır eklendikçe artan bir tam sayıyı otomatik olarak elde edebilecektir. Bu 1 ile başlayacaktır. Bu sütun aynı zamanda tablo için birincil anahtar olacaktır. increments metodunun birinci parametresi oluşturulacak sütunun adıdır. Ne kadar basit değil mi? Devam edelim ve bu tabloya daha başka sütunlar ekleyelim. 3 // app/routes.php 5 Route::get('/', function() 6 { 7 Schema::create('users', function($table) 8 { 9 $table->increments('id'); 10 $table->string('username', 3); 11 $table->string(' ', 30); 1 $table->string('password', 60); 13 $table->timestamps(); 1 }); 15 });

233 Şema Oluşturucusu 18 Mükemmel! Artık users tablomuzun yapısını oluşturmak için bir planımız oldu. Her bir sütun hakkında şimdilik endişe etmeyin, sonraki kesimde ayrıntılı olarak göreceğiz. Öncelikle, rota Closure umuzu ateşlemek için / URI sini ziyaret ederek bu tablomuzu inşa edelim. Şimdi bizim için oluşturulan veritabanı yapısına göz atabiliriz. Tabii ben kullanmak için hangi veritabanını seçtiğinizi bilmiyorum fakat bu kitap için ben mysql kullanıyorum, bu nedenle veritabanına mysql komut satırı arayüzünü kullanarak bakacağım. Siz elbette kendinize en uygun gelen yazılımı kullanabilirsiniz. 1 mysql> use myapp; Database changed 3 mysql> describe users; Field Type Key Extra id int(10) unsigned PRI auto_increment 9 username varchar(3) 10 varchar(30) 11 password varchar(60) 1 created_at timestamp 13 updated_at timestamp rows in set (0.00 sec) Evet, ben kitap biçimlendirme sınırlamalarına uyması için tablo açıklamasını biraz basitleştirdim ama anladığınızı umuyorum. Bizim users tablomuzun yapısı, $table nesnesiyle oluşturduğumuz plan kullanılarak inşa edilmiştir. $table nesnesinde kullanabileceğimiz metod ve sütunların ne olduğunu merak ediyor olmalısınız? Tamam, görelim! Sütun Türleri $table plan nesnesinde bulunan metodları incelemeye geçebiliriz. Bazı şeyleri basitleştirmek için rota Closure kısmını göstereceğim, o yüzden biraz hayal gücünüzü kullanmanız gerekecek! Haydi başlıyoruz. increments increments metodu tabloya bir otomatik artan tam sayı birincil anahtarı ekleyecektir. Bu metod, ilerideki bir bölümde öğreneceğimiz Eloquent ORM modelleri için yapı inşa ederken çok yararlı bir metodtur.

234 Şema Oluşturucusu 19 3 Schema::create('example', function($table) { 5 $table->increments('id'); 6 }); Bu increments() metodu için birinci ve tek parametre oluşturulacak sütunun adıdır. Oluşan tablo yapısı şöyledir: Field Type Key Extra id int(10) unsigned PRI auto_increment bigincrements Oo, demek increments metodu sizin için yeterince büyük olmadı? İyi işte, bigincrements() metodu olağan increments tan daha büyük bir tam sayı oluşturacaktır. 3 Schema::create('example', function($table) { 5 $table->bigincrements('id'); 6 }); Tıpkı increments() metodu gibi, bigincrements() metodu da tek bir string parametre olarak sütun adını alacaktır Field Type Key Extra id bigint(0) unsigned PRI auto_increment string string() metodu varchar sütunları oluşturmak için kullanılabilir, varchar sütunu kısa string değerleri saklamaya yarar.

235 Şema Oluşturucusu 0 3 Schema::create('example', function($table) { 5 $table->string('nickname', 18); 6 }); string() metodunun birinci parametresi oluşturulacak sütunun adıdır, bununla birlikte, stringin karakter cinsinden uzunluğunu tanımlamak için ikinci bir opsiyonel parametresi de olabilir. Bunun ön tanımlı değeri 55 tir Field Type nickname varchar(55) text text() metodu bir varchar sütun tipine sığmayacak kadar büyük miktarda metinleri depolamak için kullanılabilir. Örneğin, bir blog makalesinin gövde metnini taşımak için bu sütun tipi kullanılabilir. 3 Schema::create('example', function($table) { 5 $table->text('body'); 6 }); text() metodu tek parametre kabul eder. Oluşturulacak olan sütunun ismi Field Type body text

236 Şema Oluşturucusu 1 integer Integer sütun tipi tam sayı değerlerini saklamak için kullanılabilir, şaşırmadınız ya? Bunu daha ilginç hale getirecek başka bir şey bulamadım! Evet, Başka bir tablonun otomatik artan id değerine referans yaparken integer alanlarının yararlı olacağını düşünüyorum. Bu metodu tablolar arasında ilişkiler oluşturmak için kullanabiliriz. 3 Schema::create('example', function($table) { 5 $table->integer('role_id'); 6 }); integer() metodunun birinci parametresi sütunun adıdır. İkinci parametre sütunun otomatik artan olup olmadığını tanımlamak için kullanılan boolean bir değerdir. Üçüncü parametre tam sayının işaretsiz olup olmadığını tanımlamak için kullanılır. İşaretli bir tam sayı pozitif veya negatif olabilir, buna karşın eğer bir integeri işaretsiz olarak tanımlarsanız, bu durumda sadece pozitif olabilecektir. İşaretli tam sayılar,17,83,68 ile,17,83,67 aralığındaki tam sayıları taşıyabilir, işaretsiz bir integer ise 0 ile,9,967,95 arasındaki tam sayıları tutabilir Field Type role_id int(11) biginteger Big integer değerleri tam olarak normal tam sayılar gibi iş görür ancak daha büyük aralığa sahiptir. İşaretli bir integer 9,3,37,036,85,775,808 ile 9,3,37,036,85,775,807 arasındadır ve işaretsiz tam sayılar 0 ile 18,6,7,073,709,551,615 aralığındadır. Bu boyutlardaki tam sayılar normalde inç cinsinden bel ölçüsünü saklamak için kullanılır!

237 Şema Oluşturucusu 3 Schema::create('example', function($table) { 5 $table->biginteger('waist_size'); 6 }); Tam sayı çeşitlerinin hepsinde de yazım şekli integer() metodunun tam aynısıdır, bu yüzden bunu tekrarlamakla zaman kaybetmeyeceğim! Eğer çoktan unutmuşsanız, integer kesimine tekrar bakmanız gerekecektir? Field Type waist_size bigint(0) mediuminteger Başka bir tam sayı tipidir, Bu sütun türlerini biraz daha hızlı dolaşalım mı? Artık sadece sütun değer aralıklarını belirteceğim. İşaretli aralık ile arasıdır. İşaretsiz aralık 0 ile arasıdır. 3 Schema::create('example', function($table) { 5 $table->mediuminteger('size'); 6 }); Metodun yazım şekli integer() metodu ile aynıdır Field Type size mediumint(9) tinyinteger Bu başka bir integer türü sütundur. İşaretli aralık 18 ile 17. İşaretsiz aralık 0 ile 55 arasıdır.

238 Şema Oluşturucusu 3 3 Schema::create('example', function($table) { 5 $table->tinyinteger('size'); 6 }); Bu metodun yazım şekli integer() metodu ile aynıdır Field Type size tinyint(1) smallinteger Bu başka bir integer türü sütundur. İşaretli aralık 3768 ile 3767 arasıdır. İşaretsiz aralık 0 ile arasıdır. 3 Schema::create('example', function($table) { 5 $table->smallinteger('size'); 6 }); Metodun yazım şekli integer() metodu ile aynıdır Field Type size smallint(6) float Float sütun türleri kayan noktalı sayıları saklamak için kullanılır. Şu şekilde tanımlanabilirler.

239 Şema Oluşturucusu 3 Schema::create('example', function($table) { 5 $table->float('size'); 6 }); Birinci parametre sütunu tanımlamak için kullanılan isimdir. Opsiyonel ikinci ve üçüncü parametreler değerin uzunluğunu belirtmek ve değeri göstermekte kullanılacak ondalık sayısını belirtmek için kullanılabilir. Bu parametreler için ön tanımlı değerler sırasıyla 8 ve dir Field Type size float(8,) decimal decimal() metodu neydi, bir saniye desimal değerleri saklamak için kullanılır! float() metoduna çok benzer. 3 Schema::create('example', function($table) { 5 $table->decimal('size'); 6 }); Bu metod birinci parametre olarak bir sütun adı alır ve sütunu tanımlamak için uzunluk ve ondalık basamak sayısını temsil eden opsiyonel iki parametre daha alabilir. Bu opsiyonel parametreler için ön tanımlı değerler yine 8 ve dir Field Type size decimal(8,)

240 Şema Oluşturucusu 5 boolean Bütün değerler sayılar ve karakterlerden ibaret değildir. Bazıları sadece iki durumda olurlar, true veya false, 1 veya 0. Boolean sütun tipleri bu değerleri temsil etmek için kullanılır. 3 Schema::create('example', function($table) { 5 $table->boolean('hot'); 6 }); Boolean metodunun tek parametresi oluşturacağı alanın adıdır Field Type hot tinyint(1) Yukarıdaki örnekteki tinyint bir yazım hatası değildir. Tiny integerler 1 veya 0 gibi boolean değerleri göstermek için kullanılırlar. Bu kısmı yazmakla meşgulken mutfakta neredeyse yandığımı da belirtmek istiyorum. Teknik bir yazarın tehlikeli yaşamı hakkında bilgi sahibi olmak istersiniz diye düşündüm! Hayır? İyi, sütun tanımlamalarına devam edelim öyleyse. enum Numaralandırılmış tür bir izin verilenler listesinde yer alan stringleri saklamak için kullanılır. İşte bir örnek. 3 Schema::create('example', function($table) { 5 $izinliler = array('ali', 'Veli', 'Selami'); 6 $table->enum('who', $izinliler); 7 }); Birinci parametre oluşturulacak olan sütunun adıdır. İkinci parametre bu enum tipi için izin verilen değerlerden oluşan bir dizidir.

241 Şema Oluşturucusu Field Type Null who enum('ali','veli','selami') NO date Adından da anlaşılacağı gibi, date() metodu tarihleri depolayan sütunlar oluşturmak için kullanılır. 3 Schema::create('example', function($table) { 5 $table->date('when'); 6 }); Birinci ve tek parametre oluşturulacak olan sütunun adını belirtmek için kullanılır Field Type when date datetime datetime() metodu sadece bir tarihi saklamakla kalmayıp, aynı zamanda zamanı da saklayacaktır. Şaka yapmıyorum, gerçekten öyle yapar. Biliyorum, biliyorum, bu metodların birçoğu birbirine benziyor fakat bana güvenin, bu çok harika bir referans bölümü olacak!

242 Şema Oluşturucusu 7 3 Schema::create('example', function($table) { 5 $table->datetime('when'); 6 }); Bir kez daha, oluşturulacak sütunun adı tek parametredir Field Type when datetime time Zamanlarınızla birlikte tarih olsun istemiyor musunuz? Güzel! O zaman onun yerine time() metodunu kullanın. 3 Schema::create('example', function($table) { 5 $table->time('when'); 6 }); Bir kez daha, time() metodunun ilk ve tek parametresi oluşturulacak sütunun adıdır Field Type when time timestamp Tarih ve zamanı TIMESTAMP (zaman damgası) formatında saklamak için timestamp() metodu kullanılabilir. Şaşırtıcı mı? Hayır? Oo iyi, nasıl çalıştığına bakalım o zaman.

243 Şema Oluşturucusu 8 3 Schema::create('example', function($table) { 5 $table->timestamp('when'); 6 }); İlk ve tek değeri oluşturulacak olan veritabanı sütununun adıdır Field Type Default when timestamp :00: binary İkili verileri saklayacak sütunlar oluşturmak için binary() metodu kullanılabilir. Bu sütun tipleri, imajlar gibi ikili dosyaları saklamak için yararlı olacaklardır. 3 Schema::create('example', function($table) { 5 $table->binary('image'); 6 }); Binary metodu için tek parametre oluşturulacak sütunun adıdır Field Type image blob

244 Şema Oluşturucusu 9 Özellikli Sütun Türleri Laravel farklı kullanımları olan birkaç adet özel sütun tipi içermektedir. Onlara bir bakalım. Bunun için öncelikle timestamps() metodunu göreceğiz. Bu timestamps() metodu tabloya iki tane TIMESTAMP sütunu eklemek için kullanılabilmektedir. Bir satırın oluşturulduğu ve güncellendiği zamanı göstermek amacıyla created_at ve updated_- at sütunları kullanılabilmektedir. Daha sonraki bir bölümde bir ORM olgusu oluşturulduğu veya güncellendiği zaman Laravel in kendi Eloquent ORM sinin bu sütunları otomatik olarak nasıl güncel tutabileceğini öğreneceğiz. Şimdi timestamps() metodunun nasıl kullanılacağını görelim. 3 Schema::create('example', function($table) { 5 $table->timestamps(); 6 }); timestamps() metodu bir parametre almaz. Oluşturulan tablo yapısı şu şekildedir Field Type Default created_at timestamp :00:00 5 updated_at timestamp :00: Diğer metodumuz softdeletes() metodudur. Zaman zaman bir tablo satırını, içindeki veriyi gerçekte silmeksizin, silinmiş olarak işaretlemek isteyebilirsiniz. Eğer gelecek bir zamanda veriyi restore edebilmek istiyorsanız bu yararlı olacaktır. softdeletes() metoduyla satır üzerinde satırın silinmiş olduğunu gösteren bir gösterge sütunu koyabilirsiniz. Oluşan sütunun adı deleted_at ve tipi TIMESTAMP olacaktır. Aynı şekilde, Laravel in Eloquent ORM si bir ORM olgusunda delete metodu kullandığınız takdirde satırı gerçekten silmeksizin bu sütunu güncelleyebilmektedir. Tablomuza deleted_at sütununu şu şekilde ekleyebiliyoruz.

245 Şema Oluşturucusu 30 3 Schema::create('example', function($table) { 5 $table->softdeletes(); 6 }); Bu softdeletes() metodu herhangi bir parametre almaz. İşte oluşan tablo Field Type Null deleted_at timestamp YES Sütun Niteleyicileri Sütun niteleyicileri create() metodu ile oluşturduğumuz sütunlara ekstra sınırlamalar veya özellikler eklemek için kullanılabilirler. Örneğin, daha önce hem otomatik artan hem de birincil alan özelliğine sahip bir tablo indeks sütunu oluşturmak için increments() metodunu kullanmıştık. Bu yararlı bir kısa yoldur, fakat gelin bir başka sütunu birincil anahtara dönüştürmek için sütun niteleyicilerini nasıl kullanabileceğimizi görelim. Önce yeni bir sütun oluşturacağız ve onun benzersiz değerler taşıması gerektiğini bildireceğiz. 3 Schema::create('example', function($table) { 5 $table->string('username')->unique(); 6 }); Sütun oluşturma metodumuza unique() metodunu zincirlemek suretiyle, veritabanına bu sütun için kopya değerlere izin verilemeyeceğini söylemiş olduk. Birincil anahtarımız satırları tek tek tanımlamak için kullanılmalıdır, bu yüzden, kopya değerler içermesini istemeyiz, yapalım o zaman! Şimdi username sütununu tablonun birincil anahtarı yapıyoruz.

246 Şema Oluşturucusu 31 3 Schema::create('example', function($table) { 5 $table->string('username')->unique(); 6 $table->primary('username'); 7 }); Bu primary() metodunu kullanarak herhangi bir sütunu bir birincil anahtar olarak işaretleyebiliriz. Bu metodun tek parametresi anahtar olarak işaretlenecek olan sütunun adını temsil eden bir stringtir. Yeni oluşturduğumuz tablonun açıklamasını görelim Field Type Null Key Default Extra username varchar(55) NO PRI NULL Harika! Yeni bir birincil anahtarımız oldu. Burada güzel bir numara vereyim, gerek primary() key gerek unique() metodu bir diğerinde etki gösterebilir veya mevcut bir değere akıcı biçimde zincirlenebilirler. Yani yukarıdaki örneği şu şekilde de yazabiliriz: 3 Schema::create('example', function($table) { 5 $table->string('username')->unique()->primary(); 6 }); Yukarıdaki örnek, sütun niteleyicilerinin mevcut bir sütun tarifine zincirlenebileceğini gösteriyor. Alternatif olarak sütun niteleyicileri bir parametre olarak bir sütun adı sağlanmak suretiyle tek tek de kullanılabilmektedir.

247 Şema Oluşturucusu 3 3 Schema::create('example', function($table) { 5 $table->string('username'); 6 $table->unique('username'); 7 $table->primary('username'); 8 }); Tablonuz için tek bir birincil anahtar olmasından tatmin olmazsanız, önceki örnekte kullandığımız primary() metoduna sütun adlarından oluşan bir dizi sağlamak suretiyle çoklu birleşik anahtarlar kullanabilirsiniz. Haydi bakalım. 3 Schema::create('example', function($table) { 5 $table->integer('id'); 6 $table->string('username'); 7 $table->string(' '); 8 $anahtarlar = array('id', 'username', ' '); 9 $table->primary($anahtarlar); 10 }); Şimdi üç yeni sütunumuz birleşik bir anahtar olarak davranacaktır, böylece, bu sütunlarda yer alan değerlerin herhangi bir kombinasyonu belirli bir role benzersiz referans olacaktır. mysql describe ile elde edilen çıktıyı görelim şimdi Field Type Null Key Default Extra id int(11) NO PRI NULL 5 username varchar(55) NO PRI NULL 6 varchar(55) NO PRI NULL Bilgi aramak için indeksler olarak kullanılacak sütunları işaretleyerek sorgularımızı hızlandırabiliyoruz. Bir sütunu bir indeks olarak işaretlemek için index() metodunu kullanabiliyoruz. Aynı satırda kullanılabilir, örneğin şöyle:

248 Şema Oluşturucusu 33 3 Schema::create('example', function($table) { 5 $table->integer('age')->index(); 6 }); Veya tek başına da kullanılabilir, mesela böyle: 3 Schema::create('example', function($table) { 5 $table->integer('age'); 6 $table->index('age'); 7 }); Her iki şekilde de sonuç aynı olacaktır. İlgili sütun bir indeks olarak işaretlenecektir Field Type Null Key Default Extra age int(11) NO MUL NULL Ayrıca, birden çok sütunu indeksler olarak işaretlemek için sütun isimlerinden oluşan bir diziyi index() metoduna geçebiliyoruz. İşte bir örnek. 3 Schema::create('example', function($table) { 5 $table->integer('age'); 6 $table->integer('weight'); 7 $table->index(array('age', 'weight')); 8 }); Oluşan tablo yapısı şöyledir.

249 Şema Oluşturucusu Field Type Null Key Default Extra age int(11) NO MUL NULL 5 weight int(11) NO NULL Bazen bir sütunun null bir değer içerip içeremeyeceğini belirtmek için bir sınırlama ayarlamak isteyebilirsiniz. Bir sütunun null değerler alabilmesini nullable() metodunu kullanarak ayarlayabiliyoruz. Bu, zincir metodunun bir parçası olabilir, mesela böyle: 3 Schema::create('example', function($table) { 5 $table->string('name')->nullable(); 6 }); Oluşan tablo yapısı şöyledir Field Type Null name varchar(55) YES Görebileceğiniz gibi, bu sütun artık null bir değer taşıyabilecektir. Eğer bir sütunun null bir değeri olmasına izin vermek istemiyorsak nullable() zincirleme metoduna ilk parametre olarak boolean false geçebiliyoruz, bunun gibi: 3 Schema::create('example', function($table) { 5 $table->string('name')->nullable(false); 6 }); Oluşan tablo yapısına bir daha bakarsak.

250 Şema Oluşturucusu Field Type Null name varchar(55) NO Görebileceğiniz gibi, name sütunu artık null bir değer içeremez. Yeni bir satır oluşturulduğunda, bir sütunun ön tanımlı bir değer içermesini istersek, yeni sütun tanımında default() metodunu zincirlemek suretiyle ön tanımlı değer sağlayabiliriz. İşte bir örnek. 3 Schema::create('example', function($table) { 5 $table->string('name')->default('sergin Arı'); 6 }); default() metodunun birinci ve tek parametresi sütun için amaçlanan ön tanım değeridir. Oluşan tablo yapısının nasıl olduğuna bir göz atalım Field Type Null Key Default name varchar(55) NO Sergin Arı Yeni bir satır oluştururken name sütununa bir değer sağlamazsak, bu durumda onun değeri ön tanımlı Sergin Arı olacaktır. Göreceğimiz son bir sütun niteliyici var. Bu gerçekten gerekli değildir ancak güzel bir kısayoldur. Önceki kesimdeki integer sütun oluşturmayı hatırlıyor musunuz? Bir integerin işaretli olup olmadığını ve sütunun negatif bir değer içerip içeremeyeceğini belirtmek için boolean bir parametre kullanmıştık. Pekala, integer bir sütunun negatif değerler içeremeyeceğini belirtmek için unsigned() zincirleme metodunu kullanabiliriz. İşte bir örnek.

251 Şema Oluşturucusu 36 3 Schema::create('example', function($table) { 5 $table->integer('age')->unsigned(); 6 }); unsigned() zircirleme metodunu kullandıktan sonra oluşan tablo yapısı şöyledir Field Type age int(10) unsigned İster boolean anahtarını, ister unsigned() metodunu kullanabilirsiniz, tercih tamamen size kalmış. Tabloların Güncellenmesi Bir tablo oluşturulduktan sonra, onu değiştirmenin bir yolu yoktur. Emin misiniz, çünkü başlık diyor ki Eminim, Kesinlikle bir yolu yok. Hmm, ama başlık tabloların güncellenmesi diyor? Gitmeme izin vermiyor musun? Güzel, biraz şekerleme yapacaktım ama beni ikna ettin. Tabloların güncellenmesini öğrenmek istiyorsun, başlayalım öyleyse. Her şeyden önce, daha önce oluşturduğumuz bir tablonun adını Schema::rename() metodunu kullanarak kolaylıkla değiştirebiliriz. Bir örnek üzerinden görelim.

252 Şema Oluşturucusu 37 3 // users tablosunu oluştur. Schema::create('users', function($table) 5 { 6 $table->increments('id'); 7 }); 8 9 // users tablosunun adını idiots olarak değiştir. 10 Schema::rename('users', 'idiots'); Bu rename() metodunun birinci parametresi değiştirmek istediğimiz tablonun adıdır. Metodun ikinci parametresi ise tablonun yeni adıdır. Eğer mevcut bir tablonun sütunlarını değiştirmek istiyorsak, Schema::table() metodunu kullanmamız gerekir. Daha yakından görelim. 3 Schema::table('example', function($table) { 5 // $table'yu modifikasyon kodu... 6 }); table() metodu, daha önce bir tablo oluşturmak için kullandığımız create() metodunun neredeyse aynısıdır. Tek farkı, metodun birinci parametresi içinde belirtilen mevcut bir tablo üzerinde etki göstermesidir. Bu metodta da ikinci parametre bir tablo oluşturucusu olgusunu parametre olarak alan bir Closure dir. Mevcut bir tabloya yeni sütunlar eklemek için, önceki kesimlerde keşfettiğimiz sütun oluşturma metodlarının hepsini kullanabiliriz. İşte bir örnek. 3 Schema::create('example', function($table) { 5 $table->increments('id'); 6 }); 7 8 Schema::table('example', function($table) 9 { 10 $table->string('name'); 11 });

253 Şema Oluşturucusu 38 Yukarıdaki örnekte bir birincil anahtarı olan example tablosunu inşa etmek için Schema::create() metodunu kullanıyoruz. Daha sonra, mevcut tabloya bir string sütunu eklemek için Schema::table() metodunu kullanıyoruz. mysql komut satırı describe example; komutu ile elde edilen sonuç şöyledir: Field Type Key Extra id int(10) unsigned PRI auto_increment 5 name varchar(55) Şimdi bir tabloya ilave sütunlar eklemek için önceki kesimde öğrendiğimiz sütun oluşturma metodlarının herhangi birini kullanabiliyoruz. Her oluşturma metodunu tek tek anlatmak istemiyorum, yazılımlarında değişiklik yok. Eğer hızlı bir tazeleme dersi gerekirse, o zaman Sütun Türleri kesimine bir kez daha bakılabilir. Eğer bir sütunun tablomuzda artık olmamasına karar verirsek, onu çıkartmak için dropcolumn() metodunu kullanabiliriz. Bu eyleme bir göz atalım. 3 Schema::create('example', function($table) { 5 $table->increments('id'); 6 $table->string('name'); 7 }); 8 9 Schema::table('example', function($table) 10 { 11 $table->dropcolumn('name'); 1 }); Yukarıdaki örnekte, iki sütunu olan example tablosunu oluşturuyoruz. Daha sonra bu tablodan name sütununu çıkartmak için dropcolumn() metodunu kullanıyoruz. dropcolumn() metodu string bir parametre alacaktır ve bu parametre çıkartmak istediğimiz sütunun adı olacaktır. İşte yukarıdaki kod çalıştırıldıktan sonra example tablomuzun nasıl göründüğü.

254 Şema Oluşturucusu Field Type Null Key Extra id int(10) unsigned NO PRI auto_increment Görebileceğiniz gibi, name sütunu başarıyla çıkartılmıştır. Şayet bir defada birden çok sütunu çıkartmak istiyorsak, ya dropcolumn() metoduna ilk parametre olarak sütun adlarından oluşan bir dizi geçebiliriz 3 Schema::table('example', function($table) { 5 $table->dropcolumn(array('name', 'age')); 6 }); ya da sütun isimleri için birden çok string parametreler verebiliriz. 3 Schema::table('example', function($table) { 5 $table->dropcolumn('name', 'age'); 6 }); Hangi yöntem kodlama tarzınıza uygunsa onu kullanabilirsiniz. Sütunları o kadar da düşürmek zorunda değiliz. Eğer istersek sadece adını değiştirebiliriz. Bir örnek üzerinde görelim bunu. 3 Schema::create('example', function($table) { 5 $table->string('name'); 6 }); 7 8 Schema::table('example', function($table) 9 { 10 $table->renamecolumn('name', 'nickname'); 11 });

255 Şema Oluşturucusu 0 renamecolumn() metodu bir sütunun adını değiştirmek için kullanılır. Metodun birinci parametresi adını değiştirmek istediğimiz sütunun adıdır ve ikinci parametresi sütunun yeni adıdır. Yukarıdaki örnekten oluşan tablo yapısı şöyle olacaktır Field Type nickname varchar(55) Şimdi, önceki kesimde oluşturduğumuz birincil anahtarları hatırlayalım. Bazı sütunların artık birincil anahtarlar olmamasını istersek ne yapacağız? Problem değil, sadece anahtarı çıkartırız. İşte bir örnek. 3 Schema::create('example', function($table) { 5 $table->string('name')->primary(); 6 }); 7 8 Schema::table('example', function($table) 9 { 10 $table->dropprimary('name'); 11 }); Bu dropprimary() metodunu kullanırken bir parametre olarak bir sütun adını veriyoruz. Bu sütundan birincil anahtar niteliği çıkartılacaktır. Bu kod çalıştırıldıktan sonra tablonun nasıl göründüğüne bir göz atalım Field Type Null Key Default Extra name varchar(55) NO NULL Görebileceğiniz gibi, name sütunu artık birincil anahtar değildir. Bir tablodan değişik sayıda birleşik anahtarları çıkartmak için dropprimary() metodunun birinci parametresi olarak sütun adlarından oluşan bir dizi sunabiliriz. İşte bir örnek.

256 Şema Oluşturucusu 1 3 Schema::create('example', function($table) { 5 $table->string('name'); 6 $table->string(' '); 7 $table->primary(array('name', ' ')); 8 }); 9 10 Schema::table('example', function($table) 11 { 1 $table->dropprimary(array('name', ' ')); 13 }); Bir sütunun unique niteliğini dropunique() metodunu kullanarak çıkartabiliriz. Bu metod tek bir parametre alır: alt tire ile birleştirilmiş tablo adı, sütun adı ve unique kelimesi. Bir sütundan unique niteliğinin çıkartılması için bir örnek verelim. 3 Schema::create('example', function($table) { 5 $table->string('name')->unique(); 6 }); 7 8 Schema::table('example', function($table) 9 { 10 $table->dropunique('example_name_unique'); 11 }); Tekrar ifade edeyim, eğer istersek dropunique() metoduna aynı formatta yazılmış sütun isimlerinden oluşan bir dizi geçebiliriz. İşte bir örnek.

257 Şema Oluşturucusu 3 Schema::create('example', function($table) { 5 $table->string('name')->unique(); 6 $table->string(' ')->unique(); 7 }); 8 9 Schema::table('example', function($table) 10 { 11 $sutunlar = array('example_name_unique', 'example_ _unique'); 1 $table->dropunique($sutunlar); 13 }); Son olarak, bir tablo sütunundan index niteliğini düşürmek için bir saniye bekleyin evet, tahmin ettiğin gibi. dropindex() metodunu kullanabiliriz. Aynı dropunique() metodunda kullandığımız formatta, yani alt tire ile birleştirilmiş tablo adı, sütun adı ve index kelimesini vermemiz yeterlidir. Örneğin: 3 Schema::create('example', function($table) { 5 $table->string('name')->index(); 6 }); 7 8 Schema::table('example', function($table) 9 { 10 $table->dropindex('example_name_index'); 11 }); Nedense ben dropindex() metoduna sütun adlarından oluşan bir dizi geçemedim. Bunu Taylor a soracağım ve değişiklik olursa bölümü güncelleyeceğim. Şimdilik devam edelim. Tabloların Düşürülmesi Bir tabloyu düşürmek için bacaklarını kesmeniz yeterlidir. Şaka yapıyorum, bir tabloyu Schema::drop() metodunu kullanarak düşürebiliriz, bu metodu iş üstünde görelim.

258 Şema Oluşturucusu 3 3 Schema::create('example', function($table) { 5 $table->string('name'); 6 }); 7 8 Schema::drop('example'); Bir tabloyu düşürmek için sadece Schema::drop() metoduna ilk parametre olarak tablonun adını geçiyoruz. Varsa görmek için tabloyu açıklatmayı deneyelim. 1 mysql> describe example; ERROR 116 (S0): Table 'myapp.example' doesn't exist Güzel, çalıştı sanırım! Tablo gitmiş gibi görünüyor. Şayet mevcut olmayan bir tabloyu drop etmeye kalkarsak bir hata alırız. Bundan kaçınmak için bunun yerine dropifexists() metodunu kullanabiliriz. İsminden de anlaşılacağı gibi bu metod sadece bir tablo mevcut ise düşürecektir. İşte bir örnek. 3 Schema::create('example', function($table) { 5 $table->string('name'); 6 }); 7 8 Schema::dropIfExists('example'); Tıpkı drop() metodu gibi, dropifexists() metodu da tek bir parametre alır, düşürülecek tablonun adını. Şema Püf Noktaları Püf noktaları? Belki de değil. Bununla birlikte bu kesim, önceki kesimlere tam uymayan metodlar için kullanılmıştır. Daha fazla zaman kaybetmeden ilk metoda bir göz atalım. Şema değişikliklerimizi alternatif bir veritabanı veya bağlantıda yapmak için Schema::connection() metodunu kullanabiliriz. Bunu bir örnekle görelim.

259 Şema Oluşturucusu 3 Schema::connection('mysql')->create('example', function($table) { 5 $table->increments('id'); 6 }); 7 8 Schema::connection('mysql')->table('example', function($table) 9 { 10 $table->string('name'); 11 }); Bu connection() metodunun zircirlenecek herhangi bir Schema sınıfı metodundan önce gelmesi gerekir. Bu metodun ilk parametresi sonraki metodların dayanacağı veritabanı bağlantısının ismidir. Birden çok veritabanı kullanan bir uygulama yazmanız gerektiğinde connection() metodu çok yararlı olabilir. Bunun dışında, sütunların ve tabloların mevcut olup olmadığını kontrol etmekte kullanabileceğimiz bir çift metod var. En iyisi bir örnekle devam edelim. 3 if (Schema::hasTable('author')) { Schema::create('books', function($table) 5 { 6 $table->increments('id'); 7 }); 8 } Bir tablonun mevcut olup olmadığını yoklamak için hastable() metodunu kullanabiliyoruz. Bu metodun birinci parametresi kontrol etmek istediğimiz tablonun adıdır. Yukarıdaki örnekte, books tablosunu sadece author tablosu mevcutsa oluşturuyoruz. Zaten tahmin etmiş olabileceğiniz gibi, bir sütunun mevcut olup olmadığını kontrol etmek için benzer bir metodumuz var. Onu da başka bir örnekle görelim.

260 Şema Oluşturucusu 5 3 if (Schema::hasColumn('example', 'id')) { Schema::table('example', function($table) 5 { 6 $table->string('name'); 7 }); 8 } Bir tabloda bir sütun olup olmadığını kontrol etmek için Schema::hasColumn() metodunu kullanabiliyoruz. Bu metodun birinci parametresi ilgili tablodur ve ikinci parametresi bulmak istediğimiz sütunun adıdır. Yukarıdaki örnekte example tablosuna bir name sütunu eklenecektir. Eğer bir veritabanı dahisi olduysanız, tablo tarafından kullanılan depolama motorunu değiştirmek isteyebilirsiniz. İşte bir örnek. 3 Schema::create('example', function($table) { 5 $table->engine = 'InnoDB'; 6 $table->increments('id'); 7 }); Yapacağınız tek şey tablo planındaki engine niteliğinin değerini kullanmak istediğimiz depolama motorunun adına değiştirmektir. Burada mysql veritabanı için kullanılabilecek depolama motorlarının bir kısmı verilmiştir: MyISAM InnoDB IBMDMI MERGE MEMORY EXAMPLE FEDERATED ARCHIVE CSV BLACKHOLE Bu depolama motorlarıyla ilgili daha fazla bilgi için lütfen ilgili konudaki mysql belgelerine³¹ bakınız. mysql veritabanları için, after() metodunu kullanmak suretiyle bir tablonun sütunlarını yeniden sıralayabilirsiniz. İşte bir örnek. ³¹

261 Şema Oluşturucusu 6 3 Schema::create('example', function($table) { 5 $table->string('name')->after('id'); 6 $table->increments('id'); 7 }); Yapmanız gereken, sırasını değiştirmek istediğiniz sütuna after() metodunu zincirlemektir. Bu metodun tek parametresi kendisinden sonra gelmesini istediğiniz yeni sütunun adıdır. Bu metodu kullanmakta serbestsiniz, ancak ben tablolarınızı istediğiniz sırada basit yolla inşa etmenizi öneririm, bu çok daha temiz gözükecektir. Pekala, veritabanı inşa etme hususunda benden bu kadar. Neden şemalarımızı inşa etmek için daha uygun bir yer konusunu öğrenmiyoruz? Haydi öyleyse, migrasyonlar bölümüne geçelim.

262 Migrasyonlar Dayle malikanesinde oldukça etkili bir sistemimiz var. Günün tüm görevlerinin kırmızı pandalar görevli ordusu tarafından hiçbir karışıklık olmadan tamamlanmasını sağlayan bir sistem. Onu sizinle paylaşmak istiyorum. Elemanlarımın görev listesi şu şekilde. Onlara yardım edebilir misiniz? 09:00 AM - Dayle i yıka ve giydir. 10:00 AM - Kahvaltı için nadir ve egzotik et çeşitleri pişir ve ızgara yap. 1:00 PM - (Öğle Yemeği) Pandalar bir ağaca tırmanacak ve bir süre uyuyacaklar. 0:00 PM - Apple donanımlarını cilala. 0:00 PM - Bir sonraki Code Bright bölümü için yazı tahtasını hazırla. 09:00 PM - Uyuyan Dayle i yazı tahtasından sürükleyerek yatağına sok. Evet, kırmızı pandalarım için listem böyle. Oldukça yoğun bir günleri var ve onlar olmadan ne yapardım bilemiyorum. Problem listenin çok belirli bir sırada olması. Yazı tahtasına uğramamdan önce pandaların beni yatağa sokmalarını istemeyiz, aksi takdirde yeni bir bölüm yazamam. Ayrıca, bu görevlerin iki kez yapılması da olmaz. Pandaların bu görevleri sırasıyla ve bir kez yaptıklarından emin olmaları gerekir. Pandalar o kadar akıllı ki, tüm sorunlarına çözüm bulabiliyorlar. Ben onlara bir kalem ve orijinal listenin olduğu bir defter verdim, onlara hediye vermişim gibi heyecanlandılar. Yuvarlanıp durdular. Her neyse, sonunda kendi listelerini kendileri yapmaya karar verdiler, çifte eğlence? Pandalar ikinci bir liste yazmaya karar verdiler. Sıradaki ilk görevi tamamlar tamamlamaz ikinci listeye görevin zamanını ve adını yazacaklardı. Böylece, aynı görev asla tekrarlanmayacaktı. Kabul etmeliyim ki kötü bir fikir değildi. Neyse ki, bazı akıllı dostlarım veritabanları için de benzer bir fikir buldular. Şimdi migrasyonları görelim. Temel Kavram Veritabanlarınızı inşa ederken onun yapısını elle oluştururdunuz. Sütunlarınızı tanımlamak için bazı hoş SQL yazarsınız ama yanlışlıkla veritabanınızı drop yaparsanız ne olur? Bir ekip olarak çalışıyorsanız ne olur? Veritabanınızı senkronize tutmak için SQL dumplarınızı tüm ekibe göndermek zorunda kalmak istemezsiniz. İşte migrasyonların yararı burada kendini gösteriyor. Migrasyonlar veritabanınızın yapısını veya içeriğini değiştirmek için kullanılan birtakım PHP betikleridir. Migrasyonlar zaman damgalıdır, dolayısıyla her zaman düzgün sırada çalıştırılırlar.

263 Migrasyonlar 8 Laravel sizin ön tanımlı veritabanı bağlantınızdaki başka bir tablo içinde, daha önce hangi migrasyonların çalıştığının kaydını tutar. Bu yolla, sadece eklenmiş olan migrasyonları çalıştıracaktır. Migrasyonları kullanarak, siz ve ekibiniz her zaman tutarlı ve kararlı bir durumda aynı veritabanı yapısına sahip olacaksınız. Biliyor musunuz? Eylem yapmak konuşmaktan daha iyi ifade eder. Gelin bir migrasyon oluşturalım ve öğrenme sürecine başlayalım. Migrasyonların Oluşturulması Bir migrasyon oluşturmak için Artisan komut satırı arayüzünü kullanmamız gerekiyor. Gidin bir terminal penceresi açın ve proje klasörünüze geçin. Önceki bölümde şema inşa etmeyi öğrenmiştik ve orada şemaları kullanmak için daha iyi bir yer olduğunu söylemiştim. Tabii ki, migrasyonlardan söz ediyordum. Users tablomuzu oluşturmak için kullandığımız şema yapısını bir daha oluşturalım şimdi. Bir create_users migrasyonu inşa etmek için Artisan kullanmaya başlayacağız. 1 $ php artisan migrate:make create_users Created Migration: 013_06_30_186_create_users 3 Generating optimized class loader Compiling common classes Artisan migrate:make komutunu çağırdık ve yeni migrasyonumuzun adını geçtik. Laravel app/database/migration klasörü içinde yeni bir migrasyon şablonu üretmiş olacaktır. Bu şablon, migrate:make komutuna geçtiğiniz parametre ve bir zaman damgasıyla birlikte adlandırılan bir dosyanın içerisinde olacaktır. Bu örneğimiz için şablonumuz aşağıdaki dosyada yer alacaktır. 1 app/database/migrations/013_06_30_186_create_users.php Şimdi metin editörümüzde bu dosyayı açalım ve içinde ne olduğuna bakalım. 3 use Illuminate\Database\Migrations\Migration; 5 class CreateUsers extends Migration { 6 7 /** 8 * Run the migrations. 9 * 10 void 11 */ 1 public function up()

264 Migrasyonlar 9 13 { 1 // 15 } /** 18 * Reverse the migrations. 19 * 0 void 1 */ public function down() 3 { // 5 } 6 7 } Burada bizim migrasyon sınıfımız var. Migrasyonları oluşturmak için her zaman Artisan komutu kullanmanızın önemi burada, zaman damgalarını ve dolayısıyla veritabanı yapınızın geçmişini riske etmek istemezsiniz. İyi bir okuyucu olun, komut kullanın. Migrasyon sınıfının içinde iki adet publik metodumuz, up() ve down() bulunuyor. Bu iki metod arasında bir çizgi hayal edin veya dostumuz Barney nin hayal gücünü öğrenmediyseniz bir yorumunun içine bir şeyler yazın. Bu çizginin hangi tarafına bakarsanız, diğerinin tam tersi olacak. up() metodunda ne yaparsanız, down() metodunda geri almalısınız. Görüyorsunuz, migrasyonlar iki yönlüdür. Biz veritabanımızın yapısını veya içeriğini güncellemek için bir migrasyon kullanabiliriz ama aynı zamanda onu tekrar orijinal durumuna döndürmek için de migrasyon kullanabiliriz. Öncelikle up() metodunu dolduralım. 3 /** * Run the migrations. 5 * 6 void 7 */ 8 public function up() 9 { 10 Schema::create('users', function($table) 11 { 1 $table->increments('id'); 13 $table->string('name', 18);

265 Migrasyonlar 50 1 $table->string(' '); 15 $table->string('password', 60); 16 $table->timestamps(); 17 }); 18 } Umarım bu şema oluşturma kodunda kafanızı karıştıran bir şey yoktur. Eğer anlamadığınız bir şey varsa Şema Oluşturucusu bölümüne bir daha bakabilirsiniz. Peki, biliyoruz ki, up da ne varsa, down da da o gelecek. Bu sebeple, down() metodunu alalım ve up() metodundaki yapı değişikliğinin tersini oluşturalım. İşte yapıyoruz 3 /** * Reverse the migrations. 5 * 6 void 7 */ 8 public function down() 9 { 10 Schema::drop('users'); 11 } Tamam, tamam, sanırım tam tersi değil. Ben önce sütunları tek tek düşürüp, sonra da tabloyu düşüreceğini sanmıştım. İyi de, görüyorsun, ikisi de aynı sonucu verecektir. users tablosu düşürülmüş olacaktır. Öyleyse bunu niye tek satırda yapmayalım ki? Sonraki kesime geçmeden önce, migrasyon oluşturulmasıyla ilgili birkaç püf noktasını görelim. migrate:make komutunda --create ve --table anahtarlarını kullanarak, bir tablo oluşturma kodunu otomatik olarak oluşturabiliyoruz. Sadece çalıştıralım 1 php artisan migrate:make create_users --create --table=users ve aşağıdaki migrasyon kodunu alalım.

266 Migrasyonlar 51 3 use Illuminate\Database\Schema\Blueprint; use Illuminate\Database\Migrations\Migration; 5 6 class CreateUsers extends Migration { 7 8 /** 9 * Run the migrations. 10 * 11 void 1 */ 13 public function up() 1 { 15 Schema::create('users', function(blueprint $table) 16 { 17 $table->increments('id'); 18 $table->timestamps(); 19 }); 0 } 1 /** 3 * Reverse the migrations. * 5 void 6 */ 7 public function down() 8 { 9 Schema::drop('users'); 30 } 31 3 } Mükemmel! Bu kısayol bize büyük bir zaman kazandırdı. Yeni tablomuz için Schema::create() ve Schema::drop() metodlarının eklenmesi yanında, Laravel increments() ve timestamps() metodları da eklemiştir. Bu, Eloquent ORM uyumlu modellerin çok hızlı bir şekilde oluşturulmasını sağlamaktadır. Şimdilik Eloquent konusunu çok fazla dert etmeyin, yakın bir zamanda onu da keşfedeceğiz. Migrasyonların oluşturulmasında son bir püf noktası onların ön tanımlı app/database/migrations dizininden farklı bir konuma nasıl koyulabileceğidir. Migrasyon sınıfımız için yeni bir konum tanımlamak için --path anahtarını kullanabiliriz.

267 Migrasyonlar 5 1 $ php artisan migrate:make create_users --path=app/migs Created Migration: 013_06_30_15531_create_users 3 Generating optimized class loader Compiling common classes Şimdi migrasyonumuz projemizin köküne göre app/migs dizini içerisinde oluşturulacaktır. Bununla birlikte, migrasyonlarınızı çalıştırdığınızda Artisan ön tanımlı olarak bu yeni konuma bakmayacaktır, bu nedenle migrasyonlarınızı nerede bulacağını bilmesini sağlamalısınız. Bir sonraki kesimde bu konu üzerinde daha çok bilgi öğreneceğiz. Migrasyonların Çalıştırılması Tüm bu çabaları yeni migrasyonumuzu oluşturmak için verdik, onu çalıştıramadığımız takdirde büyük bir utanç olacaktır. Veritabanını migrasyonları kullanmaya hazırlayalım. Hatırlarsınız, Laravel in migrasyonların durumunu kayıt altına almak için bir veritabanı tablosu kullandığını söylemiştim? Tamam işte, öncelikle o tabloyu oluşturmamız gerekiyor. Migrasyonlar tablosuna istediğiniz ismi verebilirsiniz. Bu tablo adı için yapılandırma yeri app/config/database.php içerisindedir. 1 /* Migration Repository Table This table keeps track of all the migrations that have already run for 7 your application. Using this information, we can determine which of 8 the migrations on disk have not actually be run in the databases */ 11 1 'migrations' => 'migrations', Dizinin migrations anahtarında mantıklı bir ön tanım sağlanmıştır. Sizin migrations anahtarının değerini migrasyon durumunuzu izlemek için kullanmak istediğiniz tablonun adıyla değiştirmeniz yeterlidir. Başka bir Artisan komutunu çalıştırarak migrations tablomuzu yükleyebiliriz. Şimdi install komutunu çalıştıralım.

268 Migrasyonlar 53 1 $ php artisan migrate:install Migration table created successfully. Bakın şimdi veritabanımızı incelersek ve oluşturulmuş olanı görmek için migrations tablosuna bakarsak. 1 mysql> describe migrations; Field Type Null Key Default Extra migration varchar(55) NO NULL 6 batch int(11) NO NULL rows in set (0.01 sec) İki alanı olan yeni bir tablo oluşturulmuş. Migrasyonlar tablosunun işleriyle kendinizi yormayın, size düşen sadece onu oluşturmak ve migrasyon sisteminizi yüklemektir. Tamam, size bir yalan daha söyledim. Bu neden devam edip duruyor bilmiyorum? Belki de bir psikiyatriste falan gitmem lazım. Her neyse, migrasyonlar tablosunu yüklemeniz gerektiğini söylemiştim ya, yalan söyledim. Göreceğiniz gibi, migrasyonları çalıştırdığınızda bu tablo mevcut değilse Laravel onu bizim için otomatik olarak oluşturacaktır. Sizin için migrasyonlar sistemini yükleyecektir ama şimdi, en azından migrate:install komutunu öğrenmiş oldunuz, değil mi? Tüm bu aldatmacayı sanki ben planlamışım gibi Pekala, haydi başlayalım ve migrasyonumuzu ilk kez çalıştıralım. Bunun için migrate komutunu kullanabiliriz. 1 $ php artisan migrate Migrated: 013_06_30_186_create_users Komutun çıktısı çalıştırılmış olan migrasyonların bir listesidir. Bizim users tablomuz oluşturulmuş mu oluşturulmamış mı görmek için veritabanımıza bir bakalım.

269 Migrasyonlar 5 1 mysql> describe users; Field Type id int(10) unsigned 6 name varchar(18) 7 varchar(55) 8 password varchar(60) 9 created_at timestamp 10 updated_at timestamp rows in set (0.01 sec) Kitap biçimlendirmesine uygun olması için tabloyu bir miktar kısalttım fakat görüyoruz ki users tablomuz düzgün bir şekilde oluşturulmuş. Müthiş! Gelin şimdi users tablomuza bir title sütunu ekleyelim. Önceden yapmış olduğunuz migrasyonu açarak, ilgili şemayı bu yeni sütunu içerecek şekilde güncellemek size cazip gelmiş olabilir. Bunu yapmayın lütfen. Biliyorsunuz, eğer takım arkadaşlarınızdan birisi proje üzerinde çalışıyorsa ve bizim ilk migrasyonumuzu zaten çalıştırmış ise, bu durumda bizim değişikliğimizi alamayacak ve veritabanımız farklı durumlarda olacaktır. Bunun yerine, en iyisi biz veritabanımızı değiştirmek için yeni bir migrasyon oluşturalım. Haydi yapıyoruz. 1 $ php artisan migrate:make add_title_to_users Created Migration: 013_06_30_15167_add_title_to_users 3 Generating optimized class loader Compiling common classes Yeni migrasyona tanımlayıcı bir isim verdiğim dikkatinizi çekecektir, siz de bu deseni izlemelisiniz. Şimdi up() metodu içerisinde users tablomuzun şemasını title sütunu ekleyecek şekilde değiştirelim.

270 Migrasyonlar 55 3 use Illuminate\Database\Migrations\Migration; 5 class AddTitleToUsers extends Migration { 6 7 /** 8 * Run the migrations. 9 * 10 void 11 */ 1 public function up() 13 { 1 Schema::table('users', function($table) 15 { 16 $table->string('title'); 17 }); 18 } 19 0 /** 1 * Reverse the migrations. * 3 void */ 5 public function down() 6 { 7 // 8 } 9 30 } Harika, users tablomuza ihtiyacımız olan sütunu ekleyecek. Şimdi birlikte söyleyelim. up ta ne gelirse, down da o gidecektir. Haklısınız, bu migrasyon sınıfına down() metodu sağlamamız gerekiyor. Tablomuzu title sütununu çıkartacak şekilde değiştirelim şimdi.

271 Migrasyonlar 56 3 use Illuminate\Database\Migrations\Migration; 5 class AddTitleToUsers extends Migration { 6 7 /** 8 * Run the migrations. 9 * 10 void 11 */ 1 public function up() 13 { 1 Schema::table('users', function($table) 15 { 16 $table->string('title'); 17 }); 18 } 19 0 /** 1 * Reverse the migrations. * 3 void */ 5 public function down() 6 { 7 Schema::table('users', function($table) 8 { 9 $table->dropcolumn('title'); 30 }); 31 } 3 33 } Mükemmel, artık Laravel bizim migrasyonumuzu çalıştırabilecek ve gerekirse tüm değişiklikleri geri alabilecek durumda. Migrasyonlarımızı tekrar çalıştıralım. 1 $ php artisan migrate Migrated: 013_06_30_15167_add_title_to_users Laravel zaten çalıştırmış olduğumuz önceki migrasyonlarımızı bilir ve dolayısıyla sadece son migrasyon sınıfımızı çalıştırır. Şimdi tablomuzu bir kez daha inceleyelim.

272 Migrasyonlar 57 1 mysql> describe users; Field Type id int(10) unsigned 6 isim varchar(18) 7 varchar(55) 8 password varchar(60) 9 created_at timestamp 10 updated_at timestamp 11 title varchar(55) rows in set (0.00 sec) Görebileceğiniz gibi, yeni sütunumuz users tablosuna eklenmiştir. Eğer migrasyonumuz tamamlanır ve ekibin geri kalanı ile paylaşılırsa, onlar kendi veritabanlarını yeni yapıya uygun olarak almak için sadece migrate komutunu çalıştırabileceklerdir. Bir sebeple mevcut migrasyon dosyalarımızın birini değiştirmemiz gerekirse, tüm migrasyonları geri çevirmek, ondan sonra da onları bir kez daha çalıştırmak için migrate:refresh Artisan komutunu kullanabiliriz. Şimdi bunu users tablomuzda deneyelim. 1 $ php artisan migrate:refresh Rolled back: 013_06_30_15167_add_title_to_users 3 Rolled back: 013_06_30_186_create_users Nothing to rollback. 5 Migrated: 013_06_30_186_create_users 6 Migrated: 013_06_30_15167_add_title_to_users Migrasyonlarımız doğru bir sırada down() metodları kullanılarak geri alınmıştır ve sonra da kendi up() metodları kullanılarak tekrar çalıştırılmıştır. Veritabanımız bir kez daha ideal durumuna gelmiştir. Önceki kesimde, migrasyonlarımızı dosya sisteminde yeni bir konuma yazmak için --path anahtarı kullandığımızı hatırladınız mı? Evet, onları nasıl çalıştıracağınızı göstereceğime söz vermiştim. Arada bir yalan söyleyebilirim ama verdiğim sözden asla dönmem. Gelin şimdi bu standart dışı migrasyonlarımızı nasıl çalıştırabileceğimize bir bakalım. 1 $ php artisan migrate --path=app/migs Migrated: 013_06_30_15531_create_users Bakın, çok kolay? Migrasyonlarımızı depolayacağımız konumu uygulama köküne göreli belirtmek için yine sadece --path anahtarını kullanıyoruz. Migrasyonların iki yönlü olduklarını söyledim, dolayısıyla onları geri alabilmemiz gerekmez mi? Alalım öyleyse.

273 Migrasyonlar 58 Geri Alma (Rolling Back) Dönüyor, dönüyor, nehirde dönüyooor Bunun için özgünüm, biraz dağıldım galiba. Şimdi şeyleri ah evet! Migrasyonların geri alınmasını görelim. Migrasyonlarımızı çalıştırmak için migrate kullanabileceğimizi biliyoruz, ama onları nasıl geri alacağız? Peki, takım arkadaşlarımızın birinin migrasyonuna dayalı olarak veritabanımızı yeniden yapılandırmak için migrate komutunu kullanmış olduğumuzu varsayalım. Ne yazık ki, bizim arkadaşın şema değişikliği bizim kodumuzun bir kısmını göçürttü ve uygulamamızı da göçük bıraktı. Takım arkadaşımızın yapmış olduğu değişiklikleri geri almamız gerekiyor. Bunu yapmak için rollback komutunu kullanabiliriz. Bunu bir deneyelim mi? 1 $ php artisan migrate:rollback Rolled back: 013_06_30_15167_add_title_to_users rollback komutunu kullandığımızda, Laravel sadece bizim migrate kullanarak en son çalıştırmış olduğumuz migrasyonları geri alır. Son defa çalıştırdığımız migrate asla olmamış gibi olur. Eğer bütün migrasyonları geri almak istiyorsak, reset komutunu kullanabiliriz. 1 $ php artisan migrate:reset Rolled back: 013_06_30_15167_add_title_to_users 3 Rolled back: 013_06_30_186_create_users Nothing to rollback. Bu reset komutunun bizim migrations tablomuzu kaldırmayacağına dikkat ediniz. Migrasyon Püf Noktaları Aa, daha fazlasını yapmak ister misiniz? Anlıyorum. Tamam, merak etmeyin, geri almayla ilgili değil. Migrasyonlar sisteminin birkaç özelliğini daha öğrenmeye ne dersiniz? Veritabanı yapılandırma dosyası app/config/database.phpde keşfettiğimiz connections dizisini hatırlıyor musun? Herhangi bir migrasyon komutuna --database anahtarı eklemek suretiyle migrasyonlarımızı başka bir bağlantıda gerçekleştirebiliriz, mesela böyle:

PHP İle Paket Geliştirme

PHP İle Paket Geliştirme PHP İle Paket Geliştirme PHP için paket geliştirme ve yayınlama kılavuzu. Özgür Adem Işıklı PHP İle Paket Geliştirme PHP için paket geliştirme ve yayınlama kılavuzu. Özgür Adem Işıklı Bu kitap şu adreste

Detaylı

Laravel: Code Bright (TR) Türkçe

Laravel: Code Bright (TR) Türkçe Laravel: Code Bright (TR) Türkçe Yeni Başlayanlar İçin Laravel Framework Versiyon İle Web Uygulama Geliştirme Dayle Rees, Sinan Eldem ve Antonio Laguna Bu kitap http://leanpub.com/codebright-tr adresinde

Detaylı

Laravel: From Apprentice To Artisan (TR) Türkçe

Laravel: From Apprentice To Artisan (TR) Türkçe Laravel: From Apprentice To Artisan (TR) Türkçe Laravel 4 İle İleri Düzey Uygulama Mimarisi Taylor Otwell ve Sinan Eldem Bu kitap http://leanpub.com/laravel-4-tr adresinde satıştadır. Bu versiyon, 2015-08-29

Detaylı

Laravel 4 Türkçe Dokümantasyon (v. 4.2) (Ücretsiz)

Laravel 4 Türkçe Dokümantasyon (v. 4.2) (Ücretsiz) 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 http://leanpub.com/laravel42-tr adresinde satıştadır. Bu versiyon,

Detaylı

Laravel 4 Türkçe Dokümantasyon (v. 4.1) (Ücretsiz)

Laravel 4 Türkçe Dokümantasyon (v. 4.1) (Ücretsiz) Laravel 4 Türkçe Dokümantasyon (v. 4.1) (Ü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/laravel4-tr Bu

Detaylı

PHP, nesne-yönelimli (object-oriented) bir dil olduğu için, nesne oluşturma imkânına ve bunların kullanılmasını sağlayan metodlara da sahiptir.

PHP, nesne-yönelimli (object-oriented) bir dil olduğu için, nesne oluşturma imkânına ve bunların kullanılmasını sağlayan metodlara da sahiptir. PHP'nin Temelleri PHP Nedir? PHP, bir programlama dili olarak, değişkenler, değişkenlerin değerleriyle bir işlem yapmayı sağlayan işlemciler (operatörler), işlemcilerle oluşturulan deyimler ve nihayet

Detaylı

Bir dizinin boyutları sabittir ve kullanılmadan önce belirlenmelidir. Dizi boyutunu belirlemek için başka bir değişkende kullanabilirsiniz.

Bir dizinin boyutları sabittir ve kullanılmadan önce belirlenmelidir. Dizi boyutunu belirlemek için başka bir değişkende kullanabilirsiniz. C# da Diziler Diziler için aynı tipteki verilerin tutulduğu bir koleksiyon diyebiliriz. Örneğin integer verinin bir yığın şeklinde tutulması için dizileri kullanırız. C# da diziler referans tipinde değişkenlerdendir.

Detaylı

Basit Kılavuzu Eliberato bir Kitap Yayıncılık www.eliberato.com. Eylül 2010 50'den fazla dile çevrildi

Basit Kılavuzu Eliberato bir Kitap Yayıncılık www.eliberato.com. Eylül 2010 50'den fazla dile çevrildi Basit Kılavuzu Eliberato bir Kitap Yayıncılık www.eliberato.com Eylül 2010 50'den fazla dile çevrildi Içindekiler 1. Ne Eliberato olduğunu 2. Will Eliberato benim kitap yayınlayabilir miyim? 3. Ne malzeme

Detaylı

Adım Adım Windows 2000 Server Kurulumu 11 Cuma, 08 Eylül 2006 14:32 - Son Güncelleme Cumartesi, 12 Eylül 2009 03:45

Adım Adım Windows 2000 Server Kurulumu 11 Cuma, 08 Eylül 2006 14:32 - Son Güncelleme Cumartesi, 12 Eylül 2009 03:45 Nasıl bayaa yol kat ettik değil mi? Aslında bu noktada sistemimiz ciddi ciddi çalışmaya başladı. Bir süre sonra bir de baktık ki, kullanıcılar masaüstüne bazı "uygunsuz" duvar kağıtları koymaya başlamışlar.

Detaylı

Hızlı Başlangıç Kılavuzu

Hızlı Başlangıç Kılavuzu Hızlı Başlangıç Kılavuzu 1. Adım Windows Server 2012'yi Yükleme Bilgisayarınız Windows Server 2012 yüklenmiş olarak teslim edildiyse, 1. Adım'ı atlayabilirsiniz. Yükleme Yönergeleri Yükleme yönergeleri,

Detaylı

WebInstaller. 1. Kurulum Đçin Gereksinimler

WebInstaller. 1. Kurulum Đçin Gereksinimler WebInstaller Ürün Grubu [X] Fusion@6 [X] Fusion@6 Standard Kategori [X] Yeni Fonksiyon Versiyon Önkoşulu @6 Uygulama E-Netsis.Net uygulamasının kurulumu Netsis\ENetsis.Net\Kurulum dizininde bulunan NetsisWebInstall.exe

Detaylı

BİLGİSAYAR BİLİMİ DERSİ (KUR 1) PYTHON PROGRAMLAMA DİLİ ÇALIŞMA KÂĞIDI - 1

BİLGİSAYAR BİLİMİ DERSİ (KUR 1) PYTHON PROGRAMLAMA DİLİ ÇALIŞMA KÂĞIDI - 1 BİLGİSAYAR BİLİMİ DERSİ (KUR 1) PYTHON PROGRAMLAMA DİLİ ÇALIŞMA KÂĞIDI - 1 Ekrana Metin Yazdırmak Ekranda metin yazdırmak istendiğinde print komutu kullanılır. Kullanımı aşağıda verilmiştir. Parantez içinde

Detaylı

DAO İLE SQL KOMUTLARI. Sql komutlarını artık veri tabanında kullanmaktan başka çaremiz yok arkadaşlar. Şimdi bu sql derslerimize başlayalım.

DAO İLE SQL KOMUTLARI. Sql komutlarını artık veri tabanında kullanmaktan başka çaremiz yok arkadaşlar. Şimdi bu sql derslerimize başlayalım. DAO İLE SQL KOMUTLARI Sql komutlarını artık veri tabanında kullanmaktan başka çaremiz yok arkadaşlar. Şimdi bu sql derslerimize başlayalım. SQL-1 SELECT En basit SQL cümleciği oluşturmak için SELECT sözcüğü

Detaylı

Veritabanı Tasarımı. Düzenli İfadeler

Veritabanı Tasarımı. Düzenli İfadeler Veritabanı Tasarımı Düzenli İfadeler Konular Düzenli ifadeleri tanımlama SQL ifadelerinde düzenli ifadeleri arama, eşleme ve yer değiştirme katarlarında kullanma Düzenli ifadeleri ve kontrol kısıtlamalarını

Detaylı

Samsun Çocuk Hizmetleri İ l Koordinasyon Sekretarya Birimi

Samsun Çocuk Hizmetleri İ l Koordinasyon Sekretarya Birimi Samsun Çocuk Hizmetleri İ l Koordinasyon Sekretarya Birimi Veri Giriş Sistemi Klavuzu Amaç Veri Giriş Sistemi, koruyucu ve destekleyici tedbir kararlarının takibinde ve uygulamasında ilgili kurumları daha

Detaylı

Genel Programlama II

Genel Programlama II Genel Programlama II 22.03.2011 1 Yapılar ( Structures ) Yapılar ( structures ); tam sayı, karakter vb. veri tiplerini gruplayıp, tek bir çatı altında toplar. Bu gruplandırma içinde aynı ya da farklı veri

Detaylı

Hızlı Başlangıç Kılavuzu

Hızlı Başlangıç Kılavuzu Hızlı Başlangıç Kılavuzu Microsoft Access 2013 önceki sürümlerden farklı görünmektedir, dolayısıyla öğrenme eğrisini en aza indirmenize yardımcı olmak üzere bu kılavuzu hazırladık. Ekran boyutunu değiştirme

Detaylı

Hızlı Başlangıç Kılavuzu

Hızlı Başlangıç Kılavuzu Hızlı Başlangıç Kılavuzu Microsoft Publisher 2013 önceki sürümlerden farklı görünüyor, bu nedenle öğrenmenizi kolaylaştırmak için bu kılavuzu oluşturduk. Hızlı Erişim Araç Çubuğu En sevdiğiniz komutları

Detaylı

if (ad == "Sabri") Console.WriteLine("Merhaba Sabri. Ne zamandır gözükmüyodun...");

if (ad == Sabri) Console.WriteLine(Merhaba Sabri. Ne zamandır gözükmüyodun...); Koşul İfadeleri ve Akış Kontrolü Koşul ifadeleri ve akış kontrolleri programlama dillerinde her zaman en önemli yeri tutmaktadır. Yazdığımız uygulamanın hangi koşulda nasıl davranacağını belirterek bir

Detaylı

Bu makalede 2003 sunucu, Windows 2003 Server anlamına gelmektedir. Aşağıda yapılan işlemler 2003 R2 sunucu üzerinde denenmiş ve çalıştırılmıştır.

Bu makalede 2003 sunucu, Windows 2003 Server anlamına gelmektedir. Aşağıda yapılan işlemler 2003 R2 sunucu üzerinde denenmiş ve çalıştırılmıştır. WINDOWS 2003 SUNUCULARI ÜZERĐNE PHP YÜKLENMESĐ ERDAL YAZICIOĞLU erdal(at)gmail.com http://barbarossa41.wordpress.com Merhabalar, Çözümpark.com adresinde bir kullanıcı ASP ve PHP yi aynı sunucu üzerinde

Detaylı

Metin Editörleri YRD. DOÇ. DR. ENGİN CEMAL MENGÜÇ. ALINTI:

Metin Editörleri YRD. DOÇ. DR. ENGİN CEMAL MENGÜÇ. ALINTI: 1 Metin Editörleri YRD. DOÇ. DR. ENGİN CEMAL MENGÜÇ ALINTI: https://webmaster.kitchen Metin Editörleri 2 Bir web sitesi geliştirmek istiyorsanız, bir HTML düzenleyicisine ihtiyacınız olacaktır. Elbette

Detaylı

BOTAN SMS APİ DÖKÜMANI. www.botansms.com. Versiyon 1.0

BOTAN SMS APİ DÖKÜMANI. www.botansms.com. Versiyon 1.0 BOTAN SMS APİ DÖKÜMANI www.botansms.com Versiyon 1.0 BİLMENİZ GEREKENLER 1- Api ile sms göndermek için internet sayfasından giriş yaptıktan sonra Kullanıcı İşlemleri menüsünden Bilgilerim tıklayarak Api

Detaylı

Hızlı Başlangıç Kılavuzu

Hızlı Başlangıç Kılavuzu Hızlı Başlangıç Kılavuzu Güvenli erişim, paylaşım ve dosya depolama sayesinde her yerde daha fazlasını yapın. Office 365 aboneliğinizde oturum açın ve uygulama başlatıcıdan SharePoint'i seçin. Arama Siteler,

Detaylı

PHP 1. Hafta 2.Sunum

PHP 1. Hafta 2.Sunum PHP 1. Hafta 2.Sunum Hello World Bu derste görülecekler WAMP ve PHP Hosting kavramı ve bizi neden ilgilendirmediği Domain ve localhost kavramları www klasörü İlk PHP kodunun

Detaylı

Diziler İndisli Değişkenler

Diziler İndisli Değişkenler Diziler İndisli Değişkenler Aynı tür bilgileri (öğrenci isimleri, şehir isimleri, kapı numaraları, fakülteler vbg.) bellekte tutmak için kullanabileceğimiz listelere dizi adı verilir. Dizi kullanmanın

Detaylı

2. HTML Temel Etiketleri

2. HTML Temel Etiketleri 2. HTML Temel Etiketleri Bu bölümü bitirdiğinizde, HTML ve etiket kavramlarının ne olduğunu, HTML komut yapısını, Örnek bir HTML dosyasının nasıl oluşturulduğunu, Temel HTML etiketlerinin neler olduğunu,

Detaylı

Veritabanı Tasarımı. SQL Deyimi Anatomisi

Veritabanı Tasarımı. SQL Deyimi Anatomisi Veritabanı Tasarımı SQL Deyimi Anatomisi Amaç Bu ders aşağıdaki hedefleri kapsamaktadır: Projeksiyon (projection), seçim (selection) ve birleştirme (join) ifadelerini doğru fonksiyonları/yetenekleri ile

Detaylı

C#(Sharp) Programlama Dili

C#(Sharp) Programlama Dili Değişkenler C#(Sharp) Programlama Dili Program yazarken her zaman sabit verilerle çalışmayız, çoğu zaman programımızda bir verinin kullanıcının davranışına göre değişmesi gerekir. Kullanıcıdan bir metin

Detaylı

Uzaktan Eğitim Uygulama ve Araştırma Merkezi

Uzaktan Eğitim Uygulama ve Araştırma Merkezi JAVA PROGRAMLAMA Öğr. Gör. Utku SOBUTAY İÇERİK 2 Java Veri Tipleri ve Özelilkleri Değişken Tanımlama Kuralları Değişken Veri Tipi Değiştirme (Type Casting) Örnek Kodlar Java Veri Tipleri ve Özelilkleri

Detaylı

Lambda İfadeleri (Lambda Expressions)

Lambda İfadeleri (Lambda Expressions) Lambda İfadeleri (Lambda Expressions) Lambda İfadeleri, değişkenlere değer atamak için kullanılan sadeleştirilmiş anonim (isimsiz) fonksiyonlardır. Bu fonksiyonlar matematikteki ve bilgisayar bilimlerindeki

Detaylı

Aktarımı Çalıştırmak/Geri Almak 146 Alan Seçenekleri 148 Veri Tabanı Şeması 150 Veri Tabanı ile İlgili Bazı Rake Görevleri 162 Modeller 164

Aktarımı Çalıştırmak/Geri Almak 146 Alan Seçenekleri 148 Veri Tabanı Şeması 150 Veri Tabanı ile İlgili Bazı Rake Görevleri 162 Modeller 164 xi Ruby on Rails Nedir? 2 Rails Neden Farklıdır? 2 Başlamadan Önce Bilinmesi Gerekenler 4 İnternet Nasıl Çalışır? 4 İstemci-Web Sunucu İlişkisi 5 HTTP Protokolü 6 URL-Kaynak Konumlandırma Adresleri 7 HTTP

Detaylı

Android Ders Notları

Android Ders Notları Android Ders Notları 1. Yeni Bir Proje Başlatma Android Studio programında yeni bir proje başlatıyoruz. İlk olarak karşımıza resim 1 deki gibi bir pencere gelecek. Burada Application name kısmına proje

Detaylı

Hızlı Başlangıç Kılavuzu

Hızlı Başlangıç Kılavuzu Hızlı Başlangıç Kılavuzu Microsoft Excel 2013 önceki sürümlerden farklı görünüyor, bu nedenle öğrenmenizi kolaylaştırmak için bu kılavuzu oluşturduk. Hızlı Erişim Araç Çubuğu'na komutlar ekleme Şeridi

Detaylı

Araç Karşılaştırma Programı

Araç Karşılaştırma Programı 1 Araç Karşılaştırma Programı Sık Sorulan Sorular 01 Ocak 2015 2 Konu: Genel 1. Soru: Sistemdeki bilgiler nereden geliyor? Cevap: Görüntüleme ve karşılaştırma yapılan programda yer alan tüm bilgiler (sonuç

Detaylı

Global Haberleşme API Kullanıcı Notları

Global Haberleşme API Kullanıcı Notları Global Haberleşme API Kullanıcı Notları Yazar : Global Haberleşme Son Değiştirme Tarihi : 2015-02-14 Not: API Dökümanının en güncel halini kullanınız. En güncel halini http://uye.globalhaberlesme.com/uploads/api_user.pdf

Detaylı

ASP.NET CLASS KULLANARAK VERİTABANI İŞLEMLERİ

ASP.NET CLASS KULLANARAK VERİTABANI İŞLEMLERİ ASP.NET CLASS KULLANARAK VERİTABANI İŞLEMLERİ Asp.NET mimarisinin temelini oluşturan CLASS yapısını kullanarak veri tabanı işlemlerini nasıl daha az kodla ve daha stabil yapabiliriz bunu göreceğiz. Mevzu

Detaylı

Programın Adı: Eğitim ve Öğretim Yöntemleri Proje/Alan Çalışması. Diğer Toplam Kredi AKTS Kredisi

Programın Adı: Eğitim ve Öğretim Yöntemleri Proje/Alan Çalışması. Diğer Toplam Kredi AKTS Kredisi Dersin Adı Kodu: Bilgisayar II Yarıyıl Teori Uyg. Lab. Programın Adı: Eğitim ve Öğretim Yöntemleri Proje/Alan Çalışması Krediler Diğer Toplam Kredi AKTS Kredisi I (Güz) 28 28 56 3 6 Ders Dili Türkçe Zorunlu

Detaylı

Uzaktan Eğitim Uygulama ve Araştırma Merkezi

Uzaktan Eğitim Uygulama ve Araştırma Merkezi JAVA PROGRAMLAMA Öğr. Gör. Utku SOBUTAY İÇERİK 2 Java Kodlarına Yorum Satırı Eklemek Java Paket Kavramı Java Kütüphane Kavramı Konsoldan Veri Çıkışı ve JOPtionPane Kütüphanesi JOptionPane Kütüphanesi Kullanarak

Detaylı

e-imzatr Kurulum Klavuzu

e-imzatr Kurulum Klavuzu e-imzatr Kurulum Klavuzu Sürüm 0.0.1 1 İçindekiler İşletim Sistemi Sistem Türü Öğrenme Java yükleme Akis Kurulum Kart Okuyucu Sürücü Kurulum Kullanıcı Doğrulama 2 İşletim Sistemi Sistem Türü Öğrenme Bu

Detaylı

Dizi elemanları yukarıdaki gibi tek tek tanımlanabileceği gibi matematiksel ifadelerdeki diziler gibi de tanımlanabilir.

Dizi elemanları yukarıdaki gibi tek tek tanımlanabileceği gibi matematiksel ifadelerdeki diziler gibi de tanımlanabilir. DİZİLER/ARRAY: Dizi yi çeşitli şekillerde tanımlamak mümkün. Dizi içlerinde birden fazla değer saklayabilen veri kümeleridir diye tanımlarsak uygun olur sanırım. Diziler yan yana dizilmiş kutucuklar olarak

Detaylı

Veritabanı Yönetimi Bilgisayarların. Keşfi Hedefler. Veritabanı, Veri ve Bilgi. Veritabanı, Veri ve Bilgi. Veritabanı, Veri ve Bilgi

Veritabanı Yönetimi Bilgisayarların. Keşfi Hedefler. Veritabanı, Veri ve Bilgi. Veritabanı, Veri ve Bilgi. Veritabanı, Veri ve Bilgi Hedefler Veritabanı Yönetimi Bilgisayarların Discovering Keşfi 2010 Computers 2010 Living in a Digital World Dijital Dünyada Yaşamak Veritabanı terimini tanımlamak ve bir veritabanının veri ve bilgi ile

Detaylı

KULLANIM KILAVUZU. VSP Teknoloji ile sıfır hatada Dünya standartlarında web kalite politikasına uygun web sitesi oluşturabileceksiniz

KULLANIM KILAVUZU. VSP Teknoloji ile sıfır hatada Dünya standartlarında web kalite politikasına uygun web sitesi oluşturabileceksiniz KULLANIM KILAVUZU VSP Teknoloji ile sıfır hatada Dünya standartlarında web kalite politikasına uygun web sitesi oluşturabileceksiniz Kullanıcı dostu kontrol panelli dünya standartlarında web tasarım uygulaması.

Detaylı

MARTILAR A FORUM KULLANMA DERSLERİ

MARTILAR A FORUM KULLANMA DERSLERİ Bizde Hyde Park vardı da biz mi konuşmadık diyen Martılar ın yeri Ders 3. MARTILAR A FORUM KULLANMA DERSLERİ Kullanıcı adım var, şifreyi de biliyorum ama değiştirmek istiyorum Ne yapmalı? İşte Kullanıcı

Detaylı

Aşağıdaki programı inceleyip ekrana ne yazacağını söyleyebilir misiniz?

Aşağıdaki programı inceleyip ekrana ne yazacağını söyleyebilir misiniz? PYTHON DERS-8 LİSTELER-2 Geçen ders listeler oluşturmayı, listedeki her elemanın bir index numarası olduğu ve bu numaranın 0'dan başladığını, listenin tamamını veya index numarası sayesinde belirli bir

Detaylı

Hoş geldiniz. Twinspace Kılavuzu. Bu kılavuz, TwinSpace de yeni olan Öğretmen Yöneticiler tarafından kullanılmak üzere tasarlanmıştır.

Hoş geldiniz. Twinspace Kılavuzu. Bu kılavuz, TwinSpace de yeni olan Öğretmen Yöneticiler tarafından kullanılmak üzere tasarlanmıştır. Hoş geldiniz Twinspace Kılavuzu Bu kılavuz, TwinSpace de yeni olan Öğretmen Yöneticiler tarafından kullanılmak üzere tasarlanmıştır. Sizlere: - TwinSpace inize erişme - Profilinizi düzenleme - Proje aktiviteleri

Detaylı

Python Programlama Dili

Python Programlama Dili Python Programlama Dili 8. Hata Yakalama Hatalar programcılık deneyiminizin bir parçasıdır. Ancak bizim burada kastettiğimiz, programınızı çalıştıran kullanıcıların sebep olduğu ve programınızın çökmesine

Detaylı

Uzaktan Eğitim Uygulama ve Araştırma Merkezi

Uzaktan Eğitim Uygulama ve Araştırma Merkezi JAVA PROGRAMLAMA Öğr. Gör. Utku SOBUTAY İÇERİK 2 Java da Fonksiyon Tanımlamak Java da Döngüler Java da Şart İfadeleri Uygulamalar Java da Fonksiyon Tanımlamak JAVA DA FONKSİYON TANIMLAMAK 4 Fonksiyonlar;

Detaylı

Uludağ Projesi, İlk Adımlar (Kalite Takımı)

Uludağ Projesi, İlk Adımlar (Kalite Takımı) Uludağ Projesi, İlk Adımlar (Kalite Takımı) A. Murat Eren (meren@uludag.org.tr) 16 Mart 2005 Özet Bu belgede Uludağ Projesi Kalite Takımı nın amacından, nasıl bu takımın bir üyesi olunabileceğinden bahsedilmeye

Detaylı

COĞRAFİ BİLGİ SİSTEMLERİ İLERİ SEVİYE EĞİTİMLERİ BUILDING GEODATABASE EĞİTİMİ

COĞRAFİ BİLGİ SİSTEMLERİ İLERİ SEVİYE EĞİTİMLERİ BUILDING GEODATABASE EĞİTİMİ COĞRAFİ BİLGİ SİSTEMLERİ İLERİ SEVİYE EĞİTİMLERİ BUILDING GEODATABASE EĞİTİMİ http://facebook.com/esriturkey https://twitter.com/esriturkiye egitim@esriturkey.com.tr Kursun Süresi: 3 Gün 18 Saat COĞRAFİ

Detaylı

Burada a değişkeninin türü integer olarak verildi. Peki biz bu ifadeyi tırnak içerisinde yazarsak ne olur?

Burada a değişkeninin türü integer olarak verildi. Peki biz bu ifadeyi tırnak içerisinde yazarsak ne olur? STRİNG (KARAKTER) İŞLEMLERİ Python'da karakter dizilerini ifade etmek için yapmamız gereken tek şey, ifademizi tırnak ("") içinde belirtmektir. Python'da tırnak içerisinde belirtilen her şey karakter dizisi

Detaylı

Implementing Laravel (TR) Türkçe Çevirisi

Implementing Laravel (TR) Türkçe Çevirisi Implementing Laravel (TR) Türkçe Çevirisi Chris Fidao ve Sinan Eldem Bu kitap şu adreste satılmaktadır http://leanpub.com/implementinglaravel-tr Bu versiyon şu tarihte yayımlandı 2013-09-27 This is a Leanpub

Detaylı

C# Programlama Dili. İlk programımız Tür dönüşümü Yorum ekleme Operatörler

C# Programlama Dili. İlk programımız Tür dönüşümü Yorum ekleme Operatörler C# Programlama Dili İlk programımız Tür dönüşümü Yorum ekleme Operatörler 1 İlk Programımız Bu program konsol ekranına Merhaba dünya! yazıp kapanır. Programı geçen derste anlatıldığı gibi derleyin, sonra

Detaylı

Daha önce bu işlemin iki tane dosya oluşturduğunu gördük. GecDenTest.aspx dosyasının source kısmında içeriğini inceleyecek olursanız en başta

Daha önce bu işlemin iki tane dosya oluşturduğunu gördük. GecDenTest.aspx dosyasının source kısmında içeriğini inceleyecek olursanız en başta Bu gün dersimizde Validation Geçerlik Dentimi Kontrollerine değineceğiz. Önce adı GecerlikDeneme isimli bir yeni site oluşturalım. Burada programın otomatik olarak oluşturacağı Default.aspx dosyasını ve

Detaylı

BM-209 Nesne Yönelimli Programlama. Yrd. Doç. Dr. İbrahim Alper Doğru Gazi Üniversitesi Teknoloji Fakültesi Bilgisayar Mühendisliği Bölümü

BM-209 Nesne Yönelimli Programlama. Yrd. Doç. Dr. İbrahim Alper Doğru Gazi Üniversitesi Teknoloji Fakültesi Bilgisayar Mühendisliği Bölümü BM-209 Nesne Yönelimli Programlama Yrd. Doç. Dr. İbrahim Alper Doğru Gazi Üniversitesi Teknoloji Fakültesi Bilgisayar Mühendisliği Bölümü Java Programlama Dili Java bayt kodları Java Sanal Makineleri üzerinde

Detaylı

AFİLLİ EĞİTİM REHBERİ- Copyright By Alia RİOR

AFİLLİ EĞİTİM REHBERİ- Copyright By Alia RİOR syf. 1 2015 Alia RİOR. Tüm hakları saklıdır. Bu ekitap, Alia RİOR (yazar) tarafından publitory.com da yaratılmış ve yazarın kendisi tarafından Creative Commons Attribution-NonCommercial- NoDerivs CC BY-NC-ND

Detaylı

http://www.microsoft.com/visualstudio/eng/downloads

http://www.microsoft.com/visualstudio/eng/downloads Visual Studio 2012'nin kurulumunu, Visual Studio'nun kullanımını ve Windows Store'da basit bir proje hazırlanmasını anlatacağım. Hepsinden önce Visual Studio ortamından biraz bahsedelim. Visual Studio

Detaylı

Internet Programming II. Elbistan Meslek Yüksek Okulu Bahar Yarıyılı

Internet Programming II. Elbistan Meslek Yüksek Okulu Bahar Yarıyılı Internet Programming II Elbistan Meslek Yüksek Okulu 2015 2016 Bahar Yarıyılı Öğr.Gör. Murat KEÇECĠOĞLU 8 Mar. 2016 PHP de Değişken Tipleri Dizi (Array) Aynı değişken içerisinde birden fazla değer tutmak

Detaylı

Aşağıdaki şemaya dikkat edin. Sorgulamalarımızı genellikle bu şemaya göre yapacağız.

Aşağıdaki şemaya dikkat edin. Sorgulamalarımızı genellikle bu şemaya göre yapacağız. Bu Derste Öğrenecekleriniz: 1- Birden Fazla Tablodan Sorgulama 2- Tablo Birleştirme işlemleri (JOIN) a. INNER JOIN b. OUTER JOIN i. LEFT OUTER JOIN ii. RIGHT OUTER JOIN iii. FULL OUTER JOIN 3- Tablo Ekleme

Detaylı

SparkleShare. Çağrı Emer. Ekim, 2011

SparkleShare. Çağrı Emer. Ekim, 2011 SparkleShare Çağrı Emer Ekim, 2011 İçindekiler 1 Giriş.................................................... 2 2 GitHub ile Kurulum............................................ 5 3 Kendi Sunucumuza Kurulum.......................................

Detaylı

Klavyeden Basit Giriş/Çıkış İşlemleri

Klavyeden Basit Giriş/Çıkış İşlemleri Klavyeden Basit Giriş/Çıkış İşlemleri Klavyeden veri girilmesi, girilen verilere çeşitli işlemler uygulandıktan sonra ekrana yazdırılması ya da herhangi bir yazıcıdan çıktı alınması gibi işlemlerdir. Javada

Detaylı

LSI Keywords İle Sitenizin Sıralamasını Ve Trafiğini Arttırın

LSI Keywords İle Sitenizin Sıralamasını Ve Trafiğini Arttırın LSI Keywords İle Sitenizin Sıralamasını Ve Trafiğini Arttırın Giriş Her web sitesi sahibi, Seo açısından anahtar kelimelerin önemi çok iyi bilir. Fakat içeriğinizi optimize etmek için kullandığınız ana

Detaylı

UZAYLIYLA SOHBET. Kedi kuklasını silip bu kuklalardan birini seçin ve projenize başlayın.

UZAYLIYLA SOHBET. Kedi kuklasını silip bu kuklalardan birini seçin ve projenize başlayın. 1 Bugün bizimle konuşan bir uzaylı karakter, yaratacağız. Projeye başlamadan önce şunlara karar vermelisiniz. Karakterinizin adı ne? Nerede yaşıyor? Nası bir karakter? Mutlu mu? Ciddi mi? Komik mi? 2 Kedi

Detaylı

BİL-142 Bilgisayar Programlama II

BİL-142 Bilgisayar Programlama II BİL-142 Bilgisayar Programlama II (C/C++) Hazırlayan: M.Ali Akcayol Gazi Üniversitesi Bilgisayar Mühendisliği Bölümü Konular Giriş Sınıflar, Nesneler, Fonksiyon ve Veri Üyeleri Sınıf ve Fonksiyon Üyeleri

Detaylı

HSancak Nesne Tabanlı Programlama I Ders Notları

HSancak Nesne Tabanlı Programlama I Ders Notları Konsol Uygulaması Oluşturma Konsol uygulaması oluşturmak için program açıldıktan sonra Create: Project ya da New Project seçeneği tıklanabilir. New Project penceresini açmak için farklı yollar da vardır.

Detaylı

5S4 NESNELER KONUŞUYOR

5S4 NESNELER KONUŞUYOR GENEL BAKIŞ ÖĞRENME ÇIKTILARI Blok temelli programlama ortamında sunulan hedeflere ulaşmak için doğru algoritmayı oluşturur. Doğrusal mantık yapısını uygular. Döngü mantık yapısını uygular. MATERYALLER

Detaylı

API geliştiricileri. Web server ile yapılan entegrasyonun neticeleri. API Dokumantasyonu

API geliştiricileri. Web server ile yapılan entegrasyonun neticeleri. API Dokumantasyonu API geliştiricileri Open API serverınızın tüm kontrolünü, groupware erişim izini, kullanıcı ve domain yonetimi, server ayarları, tasarlanma, istatistikler ve daha fazlasına bu script programı ile erişebilirsiniz.

Detaylı

Kurulum ve Başlangıç Kılavuzu. DataPage+ 2013 için

Kurulum ve Başlangıç Kılavuzu. DataPage+ 2013 için DataPage+ 2013 için En Son Güncellenme Tarihi: 25 Temmuz 2013 İçindekiler Tablosu Önkoşul Olan Bileşenleri Yükleme... 1 Genel Bakış... 1 Adım 1: Setup.exe'yi Çalıştırın ve Sihirbazı Başlatın... 1 Adım

Detaylı

ARCHICAD in EĞİTİM SÜRÜMÜ İÇİN BAŞVURU YAPILMASI

ARCHICAD in EĞİTİM SÜRÜMÜ İÇİN BAŞVURU YAPILMASI ARCHICAD in EĞİTİM SÜRÜMÜ İÇİN BAŞVURU YAPILMASI Graphisoft ArchiCAD yazılımı ticari sürümü dışında aynı zamanda öğrenciler, öğretmenler ve üniversiteler* için ücretsiz bir sürüm içermektedir. Yazılımın

Detaylı

Birincil Yazı Başlığı

Birincil Yazı Başlığı Birincil Yazı Başlığı Kara delik, astrofizikte, çekim alanı her türlü maddesel oluşumun ve ışınımın kendisinden kaçmasına izin vermeyecek derecede güçlü olan, kütlesi büyük bir kozmik cisimdir. Kara delik,

Detaylı

Öğr. Gör. Serkan AKSU http://www.serkanaksu.net. http://www.serkanaksu.net/ 1

Öğr. Gör. Serkan AKSU http://www.serkanaksu.net. http://www.serkanaksu.net/ 1 Öğr. Gör. Serkan AKSU http://www.serkanaksu.net http://www.serkanaksu.net/ 1 JavaScript JavaScript Nedir? Nestcape firması tarafından C dilinden esinlenerek yazılmış, Netscape Navigator 2.0 ile birlikte

Detaylı

Kullanım Kılavuzu Milli Eğitim Bakanlığı 2010

Kullanım Kılavuzu Milli Eğitim Bakanlığı 2010 Kullanım Kılavuzu Milli Eğitim Bakanlığı 2010 Bu belge BT Sınıfı Etkinliklerinde Kullanılmak Üzere Hazırlanmıştır İÇİNDEKİLER GİRİŞ... 3 ÜYE (KAYIT) OLMA... 3 YÖNETİM PANELİ İŞLEMLERİ... 5 ŞABLON AYARLARI...

Detaylı

COĞRAFİ BİLGİ SİSTEMLERİ İLERİ SEVİYE EĞİTİMLERİ BUILDING GEODATABASE EĞİTİMİ

COĞRAFİ BİLGİ SİSTEMLERİ İLERİ SEVİYE EĞİTİMLERİ BUILDING GEODATABASE EĞİTİMİ COĞRAFİ BİLGİ SİSTEMLERİ İLERİ SEVİYE EĞİTİMLERİ BUILDING GEODATABASE EĞİTİMİ http://facebook.com/esriturkey https://twitter.com/esriturkiye egitim@esriturkey.com.tr Kursun Süresi: 3 Gün 18 Saat COĞRAFİ

Detaylı

08217 Internet Programcılığı II

08217 Internet Programcılığı II 08217 Internet Programcılığı II How to ASP and ASP variables Elbistan Meslek Yüksek Okulu 2015 2016 Güz Yarıyılı 29 Eyl. 2015 Öğr. Gör. Murat KEÇECĠOĞLU ASP Nedir? Microsoft un bizlere sunduğu karşılıklı

Detaylı

Tableau Yenilikler

Tableau Yenilikler Tableau 2018.2 Yenilikler İçindekiler Tableau Desktop... 2 1. Dashboard Eklentileri... 2 2. Coğrafi Verilerinizi Birleştirin... 3 3. Tableau Eklenti Galerisi... 4 4. Log ekseni üzerinde negatif değerler...

Detaylı

5S7 OYUN YAZIYORUM GENEL BAKIŞ A. PROJE - YILDIZ TOPLAYAN ÇOCUK

5S7 OYUN YAZIYORUM GENEL BAKIŞ A. PROJE - YILDIZ TOPLAYAN ÇOCUK GENEL BAKIŞ ÖĞRENME ÇIKTILARI Blok temelli programlama ortamında sunulan hedeflere ulaşmak için doğru algoritmayı oluşturur. Doğrusal mantık yapısını uygular. Döngü mantık yapısını uygular. Karar mantık

Detaylı

JSON Korsanlığı. Mesut Timur, Şubat 2010, WGT E-Dergi 4. Sayı

JSON Korsanlığı. Mesut Timur, Şubat 2010, WGT E-Dergi 4. Sayı JSON Korsanlığı Mesut Timur, Şubat 2010, WGT E-Dergi 4. Sayı İnternetin gün geçtikçe hayatımızdaki önemi arttı ve web siteleri milyonlarca insan tarafından girilen yerler haline geldi. Artık çevremizden

Detaylı

İnternet Programcılığı

İnternet Programcılığı 1 PHP le Ver tabanı İşlemler Yaptığımız web sitelerinin daha kullanışlı olması için veritabanı sistemleri ile bağlantı kurup ihtiyaca göre verileri okuyup yazmasını isteriz. 1.1 Veritabanı Nedir? Veritabanı

Detaylı

Fiery seçenekleri 1.3 yardımı (sunucu)

Fiery seçenekleri 1.3 yardımı (sunucu) 2015 Electronics For Imaging. Bu yayın içerisinde yer alan tüm bilgiler, bu ürüne ilişkin Yasal Bildirimler kapsamında korunmaktadır. 29 Ocak 2015 İçindekiler 3 İçindekiler...5 Bir Fiery seçeneğini etkinleştirme...5

Detaylı

Ecofont Yazılım Kullanıcı Rehberi

Ecofont Yazılım Kullanıcı Rehberi Ecofont Yazılım Kullanıcı Rehberi Ecofont Yazılım, baskılarınızı yaparken %50 ye, ve hatta resimsiz yazdırma seçeneğini kullandığınızda çok daha fazlasına varan tasarruf yapmanızı sağlar. Sadece tek bir

Detaylı

1.1 Web Kavramlar. 1.1.1.3 URL terimini tanımlayınız ve anlayınız.

1.1 Web Kavramlar. 1.1.1.3 URL terimini tanımlayınız ve anlayınız. 1.1 Web Kavramlar 117 Anahtar 7erim/er 1.1.1.1 Web ve Internet terimlerini tanımlayınız. Her birinin anahtar özelliklerini tanımlayınız. Web bir Internet hizmetidir. Web Internet üzerinde bağlantılı html

Detaylı

Windows Live ID ve parolanızı giriniz.

Windows Live ID ve parolanızı giriniz. Ücretsiz Deneme Hesabı Oluşturma ve Temel Özelliklerin Kullanım Kılavuzu Bilgi girilmesi gerekli alanlar Kişisel bilgi içeren alanlar http://www.windowsazure.com/tr-tr/pricing/free-trial/ adresine gidiniz

Detaylı

MongoDB. Doğan Aydın. Eylül, 2011

MongoDB. Doğan Aydın. Eylül, 2011 MongoDB Doğan Aydın Eylül, 2011 İçindekiler 1 Giriş.................................................... 2 2 Geleneksel Veri Tabanları Ve MongoDB................................. 3 3 Doküman Odaklı.............................................

Detaylı

E-postaya Tarama Hızlı Kurulum Kılavuzu

E-postaya Tarama Hızlı Kurulum Kılavuzu Xerox WorkCentre M118i E-postaya Tarama Hızlı Kurulum Kılavuzu 701P42712 Bu kılavuz, aygıtındaki E-postaya Tara özelliğini ayarlama hakkında hızlı başvuru sağlar. Aşağıdakiler için yordamlar içerir: E-postaya

Detaylı

Bolum 9. Konu Başlıkları

Bolum 9. Konu Başlıkları Bolum 9 Konu Başlıkları 1.Grafik Arayüz Tasarımı//Pencere Araçları(Widgets) Label Button Enrty Checkbutton Toplevel Listbox Menu Text Bitmap Herhangi bir pencere üzerinde bulunan düğmeler,etiketler,sağa-sola,yukarı-aşağı

Detaylı

Php İle Mysql Veritabanından Bilgi Çekme

Php İle Mysql Veritabanından Bilgi Çekme Mysql_fetch_assoc, mysql_fetch_row, mysql_fetch_object, mysql_fetch_array ve mysql_result metodları Uygulamada kullanacağımız veritabanı Veritabanı: kitaplik Tablo: kitaplar isbn adi yazari 944503382 Adım

Detaylı

1. Hafta MS SQL Server 2008 Kurulum ve Tanıtımı BPR255 Veritabanı. Bu Derste Öğrenecekleriniz: Kurulum:

1. Hafta MS SQL Server 2008 Kurulum ve Tanıtımı BPR255 Veritabanı. Bu Derste Öğrenecekleriniz: Kurulum: Bu Derste Öğrenecekleriniz: 1- MS SQL Server 2008 Kurulumu ve Tanıtımı 2- Komut Kullanarak Veritabanı Oluşturma ve Silme 3- SQL Yazım Kuralları Kurulum: Sistem gereksinimleri: Desteklenen işletim sistemleri:

Detaylı

Blogcu Kullanma Kılavuzu

Blogcu Kullanma Kılavuzu Blogcu Kullanma Kılavuzu İnternet tarayıcınıza www.blogcu.com adresini yazın ve görüntüleyin. 1 İki adımda basit olarak Web günlüğü oluşturabilirsiniz. Lütfen aşağıdaki adımları takip edin. Adım 1 : Sayfa

Detaylı

BLIND SQL INJECTION SALDIRILARI

BLIND SQL INJECTION SALDIRILARI SALDIRILARI Emre Karadeniz OSCP İçindekiler BTRisk Bilgi Güvenliği ve BT Yönetişim Hizmetleri I. Blind SQL Injection (Content Based)... 2 II. Blind SQL Injection (Content-Based) Örneği... 3 III. Blind

Detaylı

Üst Düzey Programlama

Üst Düzey Programlama Üst Düzey Programlama Struts Framework Üst Düzey Programlama-ders08/ 1 JSP MODEL 1 ve MODEL 2 Mimarileri Bu mimariler bir web uygulaması geliştirilirken kullanılan yöntemlerdir. Bu yöntemler arasındaki

Detaylı

MAT213 BİLGİSAYAR PROGRAMLAMA I DERSİ Ders 1: Programlamaya Giriş

MAT213 BİLGİSAYAR PROGRAMLAMA I DERSİ Ders 1: Programlamaya Giriş MAT213 BİLGİSAYAR PROGRAMLAMA I DERSİ Ders 1: Programlamaya Giriş Yard. Doç. Dr. Alper Kürşat Uysal Bilgisayar Mühendisliği Bölümü akuysal@anadolu.edu.tr Ders Web Sayfası: http://ceng.anadolu.edu.tr/ders.aspx?dersid=101

Detaylı

MVC. Görüldüğü üzere 2 adet cs. Dosyası oluşturdum. Birincisi çok satır kodu (20-25) içeren büyük işlerin yapılacağı class. İsmi buyuk_isler.

MVC. Görüldüğü üzere 2 adet cs. Dosyası oluşturdum. Birincisi çok satır kodu (20-25) içeren büyük işlerin yapılacağı class. İsmi buyuk_isler. MVC MVC Anlamakta zorluk çekiyorsanız bu yazımı dikkatle okumanızı tavsiye ediyorum. Derslerde öğrencilerimin en çok zorlandıkları konu MVC nin mantığıdır. Önce MVC anlamaya çalışmak yerine MVC den biraz

Detaylı

Web Uygulama Güvenliği Kontrol Listesi 2010

Web Uygulama Güvenliği Kontrol Listesi 2010 Web Uygulama Güvenliği Kontrol Listesi 2010 1 www.webguvenligi.org Web uygulama güvenliği kontrol listesi 2010, OWASP-Türkiye ve Web Güvenliği Topluluğu tarafından güvenli web uygulamalarında aktif olması

Detaylı

OKUL HABER EKLEME MODÜLÜ TANITIM DOSYASI. Okul haberlerinizi ilçemiz web sitesinde yayınlayabilmek için aşağıdaki adımları uygulamanız gerekmektedir.

OKUL HABER EKLEME MODÜLÜ TANITIM DOSYASI. Okul haberlerinizi ilçemiz web sitesinde yayınlayabilmek için aşağıdaki adımları uygulamanız gerekmektedir. OKUL HABER EKLEME MODÜLÜ TANITIM DOSYASI Okul haberlerinizi ilçemiz web sitesinde yayınlayabilmek için aşağıdaki adımları uygulamanız gerekmektedir. http://maltepe.meb.gov.tr/mebpanel adresine giriniz.

Detaylı

Arama motoru: kuş gribinin etkileri

Arama motoru: kuş gribinin etkileri Arama motoru: Bünyesinde milyonlarca internet sayfasına ve adresine (URL) dair ipuçları ve bu sayfaların barındırdığı anahtar kelimelere sahip olan, aradığımız konuda kolayca bilgi sahibi olmak için kullandığımız

Detaylı

DigiPara Liftdesigner Hidrolik Üniteleri Geliştirici Eğitimine Hoş Geldiniz

DigiPara Liftdesigner Hidrolik Üniteleri Geliştirici Eğitimine Hoş Geldiniz DigiPara Liftdesigner Hidrolik Üniteleri Geliştirici Eğitimine Hoş Geldiniz 12/19/2017 www.digipara.com Bir Bakışta DigiPara Profil Kuruluş Tarihi: 1989 Yer: Köln / Almanya Ürünler: 1996 DigiPara Liftdesigner

Detaylı

LDAP Administrator ile Active Directory Yonetimi

LDAP Administrator ile Active Directory Yonetimi LDAP Administrator ile Active Directory Yonetimi Active Directory; merkezi yonetim, esnek LDAP sorguları, group policy uygulamaları, replikasyon olanağı gibi özellikleri ile orta ölçekli ve büyük ölçekli

Detaylı

Veritabanı Tasarımı. NOT NULL ve UNIQUE Kısıtlamaları Tanımlama

Veritabanı Tasarımı. NOT NULL ve UNIQUE Kısıtlamaları Tanımlama Veritabanı Tasarımı NOT NULL ve UNIQUE Kısıtlamaları Tanımlama NOT NULL ve UNIQUE Kısıtlamaları Tanımlama Konular Kısıtlama terimini veri bütünlüğü ile ilişkilendirerek tanımlama Sütun seviyesinde ve tablo

Detaylı

E-Posta Hesabı Oluşturma

E-Posta Hesabı Oluşturma E-Posta Hesabı Oluşturma Elektronik Posta (E-posta) Nedir? Elektronik posta (e-posta) internet ortamından gönderilen dijital (elektronik) mektuptur. Bir başkasına e-posta gönderebilmemiz için öncelikle

Detaylı