PHP ile tekil anahtar oluşturmak

Türkçesini çok bulamadığım hash kelimesini anahtar olarak kullanacağım. Burada aslında bahsettiğim anahtar herhangi bir veri grubunuza atadığınız, sayısal olmayan kimliklerden bahsediyorum. Yani rasgele üretilmiş belirli bir uzunlukta olan kimlikleri her yerde kullanıyoruz.

Neden sayısal bir kimlik kullanmak yerine bu anahtarlara ihtiyaç duyacağınızı en açık şekilde şöyle anlatabilirim. Mesela tahmin ederek erişilmesini istemeyeceğiniz ama şifre veya kullanıcı girişi gibi herhangi bir sınırlama koyamayacağınız bir sayfanız var, örnek veriyorum yapılacak işler listesi veritabanı oluşturuyorsunuz ve her kayıt bir yapılacak iş listesi. Veritabanında sayısal bir kimliğe yani numaraya sahip bu kayıtlar. Hazırladığınız bir php sayfası da liste numarasına göre yapılacak iş listesinin detayını ekrana döküyor.

Eğer liste_detay.php?no=145 gibi basit bir şekilde tutarsanız url’i oynayarak başkalarının listelerine erişebilir, sadece erişmek değil sistemdeki tüm listeleri basit bir script ile tahmin edebilir veya tarayıp kaydedebiliriz. Böyle bir durumda listelerinizi sadece sayısal değil, tahmin edilemeyecek bir anahtar ile (örneğin: t34de6gx) tanımlamak istiyorsunuz.

Bu noktada rastgele bir anahtar üretebilirsiniz, bunu yapmak çok zor değil. PHP’deki rasgele sayı üretme fonksiyonunu kullanarak ve bir karakter dizisinden rastgele elemanlar çekerek bir kelime üretebilirsiniz.

Bunu daha pratik bir şekilde tek satırda bile yapabilirsiniz:

Bu satır size 6 karakterlik bir kelime üretecektir. Basitçe str_shuffle fonksiyonu ile özel karakter içermeyen ve rakamlarında dahil olduğu bir alfabeyi karıştırıyor ve başındaki ilk 6 karakteri alıyoruz.

Şimdi bu, işin basit kısmı. Eğer veritabanındaki bir veri set için bu anahtarı oluşturuyorsanız üretilen anahtarın veri setinde daha önce kullanılıp kullanılmadığını test etmek zorundasınız. Sonuçta tekil bir anahtar oluşturuyorsunuz. Bu arada veri setiniz mysql veya bir sql veritabanında olmak zorunda değil, bir xml, csv veya txt dosyasında saklı olan bir set için de benzer şeyi uygulayabilirsiniz.

Veritabanındaki veriyi test ederek bir anahtar oluşturmanın en kısa ve basit kodu şöyle:

Bu kod, veritabanında olmayan bir anahtar üretmenizi sağlayacaktır. Sonra verinizi hazırlayıp tablonuza yeni kayıdınızı ekleyebilirsiniz.

PHP’de tarih karşılaştırma

Bir web uygulaması/sitesi geliştiriyorsanız verilerinizin eklenme, güncellenme tarihleri genelde uygulamanın işleyişinde büyük rol oynar.

Örnek bir senaryo olarak, bir günlük sitesi hazırladınız ve günlükte görünen yazılarınızın son güncellenme tarihlerine göre son güncellenen yazıları listelemek isteyebilirsiniz. Veya bir e-ticaret sitesinde ürünleri belirli günlerde yayına çıkarmak istiyorsunuz ama bütün ürünleri her gün tek tek ekleyememeceğinize göre her ürünün yayına çıkış tarihini ayarlamak isteyebilirsiniz. Bunun gibi bir çok örnek bulabilirsiniz verilerin tarihleri üzerinden işlem yapmak isteyeceğiniz.

Yani aslında tarihlerle çalışmak bu ısın her noktasında. Dolayısıyla tarih eşleştirmeleri yapmak veya iki tarih/zaman arasındaki farkı bulmak gibi birçok is yapıyor olacaksınız yukarıdaki veya benzer senaryoları kodlarken. Size bu dökümanda php ile tarih eşlestirmesi yapmayı göstereceğim.

Benzer şekilde tarih karşılaştırmasını mysql’de yapmak için yakında başka bir yazı yayınlayacağım.

Tarih karşılaştırması denince akla çok basit örnekler gelebilir, örneğin X tarihi Y’den önce mi sonra mi? gibi, bunu string karşılaştırması yaparak da yapabilirsiniz. MySQL’de sürekli gördüğünüz “Y-m-d H:i:s” formatı aslında tam olarak bu ihtiyacı karşılayabılır, Yani o tarih formatları string’e de çevrilse string karşılaştırmasında tarihsel sırayı doğru yansıtacaktır.

Ama tarih karşılaştırmaları her zaman böyle once/sonra karşılaştırması değil, 1 haftadan önce mi? veya son 1 aylık veriler… gibi daha karışık örneklere dönebilir. Böyle karışık tarih karşılaştırmaları eğer sihirli fonksiyonlar kullanılmazsa baş ağrısı olabilecek bir konu, çünkü tarihler arasındaki farklar sadece saat dakika saniye gibi matematiksel hesaplarla hesaplanması kısa kodlarla yapılacak bir şey değil. Tabi ki yapılabilir fakat tek satırda ya da tek fonksiyon ile bunu yapmak varken anlamsız. 1 ay öncesi demek her zaman son 30 gün demek değildir mesela. Veya Geçen hafta Pazartesi’yi hesaplamak kolay değildir.

Bu tarz karışık karşılaştırmalar için php’de her zaman kullandığım bir fonksiyon olan strtotime() fonksiyonunu tarih karşılaştırması yapmak için de kullanırım. Örnegin X tarihinin 3 günden önce olup olmadigini:

veya “3 days ago” stringini matematiksel tarih değeri yani timestamp’e çevirerek karşılastırabiliriz. Farkettiyseniz $X değişkenini de strtotime fonksiyonundan geçiriyorum çünkü o da string değeri olduğunu varsayıyorum. Strtotime fonksiyonunun güzel yanı, herhangi bir tarih formatını timestamp’e çevirebiliyor olması. Yani amerikan tarih formatı da yazsanız, bizim kullandığımız formatta da yazsanız php’nin bunu çeviriyor olması. Bundan daha değerli olarak gördüğüm, söylem olarak kullandığımız tarihleri de (2 gün önce, 1 saat sonra, geçen cumartesi, önümüzdeki pazar saat 2) gibi stringleri de doğru olarak timestamp’e çevirebiliyor olması. Bunu kullanarak istediğiniz tarih karşılaştırmasını yapabilirsiniz.

Mesela daha karışık bir örnek olarak:

Bu ufak kontrolle, bütün hafta yazdığınız yazıları bir sonraki hafta pazartesi öğlen 1’de herkese görünür hale getirir. Kontrol’de su anki tarihe göre bir önceki haftanın pazartesi saat öğlen 1’in zaman değeri ile yazıların tarihlerini kıyaslıyoruz. Örnek veriyorum Bugün salı ve siz bi yazı yazdınız, o tarih değeri o haftanın pazartesisinden küçük olmadığı için yukarıdaki kodda if’in içindeki ilk tarih bir sonraki pazartesiye kadar değişmeyecektir. Bir sonraki pazartesi saat 1’de o anın tarihine dönüşeceği için bu salı günü yazdığınız yazı görünür hale gelecektir.

PHP ile basit HTTP authentication

Authentication, yani kimlik dogrulama, daha anlasilir ifade ile bir sayfayi kullanicilara sinirlamak veya tek bir kullanici olan yoneticiye sinirlamak icin genelde birkac yontem izlenir, hangi web altyapisini yaziyor olursaniz olun bununla her calistiginiz projede karsilasabilirsiniz. Kullanicilar icin hazirlanmasi gereken authentication icin yapacak birsey yok, kayit, giris, cikis vs gibi seyleri yazmak zorundasiniz. Fakat yonetici gibi tek kullanici icin sinirlandirilmak istenen sayfalar icin en pratik cozum ve genelde tercih edilen cozum htaccess ile basic auth yapilmasidir, yani statik bir sifre ve belirli bir kullanici adi ile yapilan http authentication. Sunucu konfigurasyonunuza gore (belki cpanel gibi paneller yardimi ile) bir dizini veya bir sayfayi sinirlandirir ve bunun icin hic kod yazmadan halledebilirsiniz.

Ancak her zaman bu imkan elinizde olmayabilir (mesela sadece ftp erisimine sahip oldugunuz ve htaccess desteklemeyen bir hosting konfigurasyonu). Ya da authentication’u bir sekilde kodunuzda saklamak istiyor olabilirsiniz.

PHP’de sayfa header’lari ile tarayicidan authentication bilgisi isteyebiliyoruz. Bunu kullanarak http authentication yaptirabiliriz, bunun avantaji kullanici girisi icin herhangi bir arayuz yazmak zorunda kalmamamizdir. Tabi bir diger avantaji ise bu bilgi giris ekranlarini tarayicilar yonettigi icin sifre hatirlama, belki 1password gibi uygulamalar ile kimlikleri saklama gibi secenekler sunuyor ve kullaniciniz bu seceneklerden faydalanmak istiyor olabilir. Her zaman sayfa icindeki elementlerle bunu saglayamayabilirsiniz.

Son birkac projemde daha duzenli kullandigim bir kodu paylasacagim. Bu kodu tek bir dosyaya (mesela auth.php) yazip bu dosyayi tum uygulamamda include ediyorum en basta. Boylece eger birisi authenticate edilmeden ulasmaya calisirsa http auth ile karsilaniyor.

PHP’de diziler yerine nesnelerle çalışmaya alışmak

Javascript, jquery ile çok uğraşmaktan dizi kavramı php’de kullandığım birşey olarak kalmaya başladı. Yani jquery’de o her şeyi nesnel yazıyor, uğraştığınız şeylerin neredeyse tamamı DOM üzerinde bir nesne oluyor. PHP’de de genellikle yazdığınız bir sınıftan ürettiğiniz nesneler var. Onun dışında anlık yaptığınız bütün işleri dizilerle yapmaya alıştık.

Belki JSON ile back-end’de uğraşıyor olmak biraz daha nesnelerle çalışmayı zorluyor çünkü encode ettiğiniz veya decode ettiğiniz her şey nesnelere dönüşüyor.

Neyse, 2 satır kod ile diziler yerine anlık yaptığınız basit işleri nesneler üzerinde yapabileceğinizi gösterebilirim.

Nesne, dizi ve nesne şeklinde karışık kullanabilirsiniz.
Mesela son arabanın markasına;

şeklinde ulaşabilirsiniz.

PHP’de gelen isteğin Ajax çağrısı olup olmadığını tespit etmek

Her yerde ajax kullanımından geçilmez oldu. Ajax, hem kolaylıklarından hem de RIA’in (Rich Internet Applications) temeli olduğundan popülerliği gitgide artıyor. Karşımıza her yerde çıkıyor ve artık jquery gibi frameworkler sayesinde ajax çağrıları yapmak için tek satırda 5-10 karakterlik bir javascript kodu bile yeterli oluyor.

Bir php kodunda genelde çıktı verirken normal html etiketleri kullanıp tüm sayfayı tasarlıyoruz fakat genelde bu sayfalar bir verit yapısının görüntüleri (view) oluyor ve aynı çıktıyı javascript ile alıp basmak, hatta bazen ajax ile dışarıya bile vermek gerekebiliyor.

Artık az sonra bahsedeceğim method ile, dosyaları tasarlarken 2 türlü kullanımı için tasarlayacaksınız. Yani hem normal erişim ile hem de o sayfayı ajax ile kullanabilecek şekilde düşüneceksiniz. Burada ajax çağrısı olduğunu yakalamak için genel bir teknik olarak get methodu ile bir değişken gönderip onu izleyebilirsiniz. Mesela kayit.php?ajax=1

Bu, işin ilkel noktası. Ajax çağrısı olup olmadığını yakalamak için artık sunucu ortam değişkenleri arasında $_SERVER[“HTTP_X_REQUESTED_WITH”] değişkeni ile çağrı türünde değer xmlhttprequest ise yapan client’in kullandığı protokolu alabiliyorsunuz. Genellikle içindeki değer “xmlhttprequest” oluyor zaten. Yani bir çağrının ajax olup olmadığını bu şekilde kolayca kontrol edebilirsiniz.

Ufak şekilde örneklemek gerekirse:

Bu kodda isimleri liste çıktısı alırsınız. Eğer javascript ile bu veriye erişmek istersek ajax çağrısı ile bu sayfayı çağırabiliriz ama işlenmiş html kodundan o isimleri almak zor olur. Ya da sadece belirli bir kısmını almak isteyebiliriz. Bunun için basitçe:

Bu kod eğer normal istek yapılırsa

çıktısı; ajax ile istek yapıldığı zaman:

çıktısı verecektir.

Bu şekilde gelen çağrılardan ajax olanlarına sadece kisiler dizisini jsona çevirip sayfayı durduruyoruz. Javascript ile gelen json’u kolayca işleyebilirsiniz.

Burada json’a çevirip javascriptde işlemek zorunda değilsiniz. Ajax ile aldıktan sonra içeriği basmak istediğiniz yere uygun html kodu da üretebilirsiniz bu noktada.

RSS’lerden Lifestream

Lifestream da nesi?

Kelime açılımından anlyabileceğiniz birşey ama bilmeyenler için özetliyim. Şu an sağda solda bir sürü web servisinde, hayatınıza dair bilgisayarda yaptığınız herşeyi paylaştığınız servisler var ve bunları kullanıyorsunuzdur illaki. Örneğin :

  • last.fm ile müziğinizi,
  • delicious ile linklerinizi,
  • tumblr, wordpress vs ile yazılarınızı,
  • flickr ile fotograflarınızı

Bu servislerin neredeyse hepsi RSS ile içeriklerinizi paylaşıyorlar. Bu dökümanda bunun gibi çeşitli servislere ait içerikleri RSS aracılığı ile süzgeçleyip kronolojik bir sıraya sokup sosyal geçmişinizi listelemeye yönelik bir uygulama yazacağım. Nasıl birşey olduğunu merak ediyorsanız http://mfyz.org adresinden benim sosyal servislerdeki akışımı görüntüleyebilirsiniz.

Tamamiyle dinamik

Bu işin güzel yanı, hazırladığınız sayfa tamamen organik bir yapıda sürekli sizin farkında olmadan kaydettiğiniz sosyal verilerinizi derleyecektir. Mesela müzik dinlerken beğendiğim bir şarkı veya bookmarklarıma eklediğim bir link bu servislere herhangi bir çabama gerek kalmadan ekleniyor. Bu eklenen içerikler yine hiçbir müdahale olmadan benim lifestream sayfamda görüntüleniyor.

Simple pie

Bunu yapmak için bu sosyal medya servislerindeki rss kaynaklarınızı işleyerek yapacağız. Bunun için php’de simple pie kütüphanesini kullanacağız ve bu kütüphanenin kullanımı ve rss okumak için yardımcı fonksiyon açılımı için önce Simplepie ile rss işlemek (okumak) dökümanını inceleyin.

Simple pie ile rss okuma konusunda bilgi sahibi olduğunuzu varsayarak dökümana devam ediyorum (eğer yoksa öncelikle verdiğim dökümanı uygulayın).

Hazırlık ve Başlangıç

Öncelikle içerik kaynaklarınızı (rss) bir dosyada çıkartın. Bu kaynakları bir dizi şeklinde tanımları tutacağımız dosyaya yazalım. Bunun için config.php diye bir dosyada $feeds adında bir dizi içerisinde kaynak url’i ve adı olarak saklayacağım. Örnek kaynak dizisi şöyle olacaktır :

Bu şekilde istediğiniz kadar rss kaynağı tanımlayabilirsiniz. Az sonra simplepie kullanarak bu kaynakları okuyacak, kronolojik sıralayıp çıktısı sayfalar halinde oluşturacağız.

Şimdi index.php dosyasında kaynakları okumaya başlayalım.

Yukarıda config ve mypie dosyalarını include ettik. Config’de rss kaynakları tanımları var, mypie’de ise simplepie kullanarak rss kaynağı okuyan fonksiyonumuz var. Bu fonksiyon hakkında daha detaylı bilgi almak için Simplepie ile rss işlemek (okumak) dökümanını inceleyin.

$feeds dizisini dönerek feed bilgilerini ve anahtar kelimesini alıyoruz. Döngü içinde ise feed url’deki kaynağı okuyoruz. Eğer hata olursa o feed ingore edilip bir sonrakine geçiliyor. Eğer okundu ise $allItems adlı bir diziye okunan veri ekleniyor. Tabi haber eklenirken tür olarak da o feed’in anahtar kelimesi ekleniyor. Bu sayede ekrana basarken, farklı haber kaynakları için farklı çıktı verebileceğiz.

Şimdi elimizde tüm kaynaklardaki tüm haberler $allItems adlı dizide tutulmakta. Bu dizideki veri yapısın daha iyi anlamanız için dizideki ilk elemanı verelim :

Gördüğünüz gibi tarih, başlık, url, kaynağı ve içerik olarak basit anahtarlarla ihtiyacımız olan tüm bilgiler mevcut. Şimdi bu diziyi tarihsel sıraya sokalım. Bunun için multi-dimmension dizilerde kolona göre sıralama yapan yardımcı bir fonksiyon kullanacağız.

Bu fonksiyonu çağıdrıktan sonra $allItems dizisindeki haberler artık kronolojik sıraya girmiş oldu. Tam istediğimiz kıvama geldi fakat elimizdeki dizide yüzlerce haber olabilir isterseniz bu diziyi belirli bir tarihe kadar kırpabilirsiniz. Mesela son 2 haftaki haberleri listelemek isterseniz $allItems’i dönerek date alanını timestamp’a çevirip 2 haftadan eski haberleri tespit edebilirsiniz. Doğal olarak onları temizleme şansınız da olur.

Ben herhangi bir kırpma işlemi yapmadan tüm haberleri sayfalayarak göstereceğim.

config.php dosyasında $limit adında bir değişkende her sayfada kaç girdi gösterileceğini belirleyin. Bunu bu sayfa içinde de yapabilirsiniz ama config.php’de tüm tanımların durması daha mantıklı olacaktır. Yukarıda bilinen sayfalama algoritması kullanarak sayfa sayısı ve şu anki sayfa hesabı yapılıyor. array_slice ile de o sayfada gösterilecek haberler $pagedItems dizisine parçalanıyor. Artık sayfada:

  • $page
  • $pageCount
  • $pagedItems

değişkenlerini kullanarak sayfalamayı ve haber içeriklerini basabiliriz. Gerekli basit html yapısını da kullanarak haberleri ekrana basacak html kodu da şöyle olacak (yani index.php dosyasının devamı)

Bu dökümanda anlatılan kod, proje olarak http://projects.mfyz.com/lifestream/ adresinde Lifestream olarak bulunabilir. Buradaki kodun çıktısını merak ediyorsanız : http://projects.mfyz.com/lifestream/demo/ adresinde biraz şekillendirilmiş şekilde bulabilirsiniz.

Bu kodu biraz daha özelleştirerek http://mfyz.org‘daki gibi bir lifestream elde edebilirsiniz.

PHP’de Pratikçe Sorgu Cümlesi Oluşturmak

Daha önce SQL injection ve MDB2 hakkında birşeyler yazmıştım.

Bu döküman birkaç konuda size yardımcı olacak, pratikleştirecek sorunlar :

  • Çok alan (4-5+) kullanırken sorgu cümlesi oluşturmak zor
  • Gözden kaçırıp alanları kontrol etmek bazen mümkün olmuyor.
  • Yukarıdaki 2 maddeyi yapmak için satırlarca duplicate kod yazmak gerekebiliyor

Kısaca 3-4 adımda kocaman bir sorgu cümlesini oluşturacağız. Genel olarak bu dökümandaki sorun insert ve update türü sorgularda çıkan kargaşayı kolaylaştıracaktır. Zira select sorguları hem çok veri içermiyor hem de özel cümleler olabiliyor.

Bu methodolojide doğal olarak bir otomatizasyon var. Bunun için verinin düzenli olması gerekiyor. Bu noktada genelde bir dizi içinde verilerin tutulduğunu düşünelim.

Verinin anahtarları veritabanındaki alan adları ile aynı olmalı. Zaten bu veri dizisini oluştururken gerekli sql injection kontrolleri yapılıp kolayca kurtulabilinir fakat her değerde bir ton fonksiyon çağırmaya gerek yok. Kısaca :

kullanımıyla tüm diziye mysql_real_escape_string() uygulayabiliriz.

Sonra zaten cümleyi oluşturmak için genel method olan sprintf ile alanları ve değerleri basacağız. Ancak işin güzelliği burada bu alanlar ve değerler kısımlarını bir sürü döngü ile çözmeyeceğiz.

Gördüğünüz gibi array_keys ve array_values ile hızlıca alanlar ve değerleri alıp implode ile aralarına virgül ve tırnak ekleyebiliriz. Burada dikkat edeceğimiz şey implode sadece değerlerin aralarına tırnak ve virgül ekleyecektir. En dışda kalan tırnakları sprintf içinde tanımlayacağız.

Sonuç olarak bu noktada $sql değişkeninde, değerler ve alanlar giydirilmiş, aşağıdaki gibi bir sql cümlesi elde etmiş olacağız.

Bu cümleyi de mysql_query($sql) ile çalıştırıp sonucu işlemede bitiyor olay.

MDB2 Kullanımı ve SQL Injection

MDB2 Nedir?

MDB2 ilk başta DB olarak başlayan sonra MDB olan ve en son MDB2 ismine dönüşen PEAR’ın veritabanı yönetim paketlerinden birisidir. Oldukça fazla türde veritabanı sürücüsü (driver) bulunduğu için, projenizde bu kütüphaneyi kullanıp fakrlı veritabanı yapılarını aynı kodda rahatça kullanabilmenizi sağlar. Ayrıca “prepare & execute” gibi yapılarla hem sql sorgularınızı daha anlaşılır yapar, hem de injection gibi saldırılar için veri türü kontrollerini otomatik yapar.

Sonuç olarak güvenlik, daha taşınabilir kod, kolaylık gibi özelliklerinden dolayı tercih edilmesi gereklidir diye düşünüyorum. Genel olarak PHP’nin PDO’suna benzeyen bir yapısı var (özellikler bakımından).

Örneklerle Genel Kullanımı

PEAR’ı sisteminize kurmanız gerekiyor. Ya da PEAR’ı kendi projenize gömerek de kullanabilirsiniz. http://pear.php.net/package/MDB2 adresinden MDB2’yi indirebilirsiniz. PEAR dizininizi include_path’a tanıtırsanız şu şekilde sayfa başında MDB2’yi çalıştırabilirsiniz :

Bağlantı

MDB2’yi bağlamak çok kolay. Bağlantı fonksiyonunda DSN (Data Source Name) denilen bir cümle ile veritabanı türü, kullanıcı, şifresi, sunucu, port, veritabanı adını bir url olarak veriyorsunuz. Yani fonksiyona 100 tane parametre girmek zorunda kalmıyorsunuz.

Aşağıdaki örnekten rahatça anlayacaksınız zaten DSN’nin nasıl birşey olduğunu :

gördüğünüz gibi bir web sitesi url’si tanımlamak gibi. Daha doğrusu ftp erişimi yapmak gibi.
protokol türü + “://” + kullanıcı + “:” + şifre + “@” + sunucu (+”:port”) + “/” veritabanı

Yani siz aynı veritabanı yapısını oluşturduğunuz sürece projenizi ileride mysql:// yerine pgsql:// yazarak kolayca çevirebileceksiniz.

Neyse, bağlantı kısmı işin başlangıcı. Asıl sık sık kullanacağımız olan şey sorgu işletmek, sonuçları işlemek vs.

Sorgu işletmek

Örnekte tüm detayları açıkladım 🙂 Eğer çok boyutlu sonuçlarla çalışıyorsanız fetchAll ile halletmenizi öneririm işlerinizi. Eğer tek boyutlu sonuç bekliyorsanız fetchRow işinizi görecektir.

Injection için güzellikler

En sevdiğim kısmı ise sizi verilerinizin türünü kontrol etme işini üstünüzden alması. Bunun için iki yol var. Birincisi query kullanarak quote yapmak. Yani Türkçesi, yukarıdaki methodu kullanarak sorgu işletmek, ama işletirken de değişkenleri tek tek bir fonksiyondan geçirmek. Örnekle anlatırsam :

görüldüğü gibi sql içinde herhangi bir tırnak kullanmadan doğrudan quote() fonksiyonunu kullandım. ilk parametrede veri ikinci parametrede de veri türünü belirtiyorsunuz. Eğer text ise sql injection önlemlerini alıyor. integer ise zaten sayısallaştırıp kaydediyor.

Ancak yine de sqliniz oldukça karışık görünüyor. Yani baksanıza bir sürü tırnak ile SQL cümlesini oluşturan string’den kaçmak için uğraştık. Ayrıca sürekli $db->quote(…) gibi bir fonksiyon çağırmak, elinizde 20 tane alan varsa sıkıcı bir işe dönüşecektir. Bunun için prepare & execute yapısını kullanacağız.

Prepare & Execute

quote kullanımından biraz daha uzun. Ancak eğer sorgunuzda kullanıcıdan gelebilecek bir veri kullanıyorsanız KESİNLİKLE bu yapıyı kullanmanızı öneririm. Yani sonuçta gözünüzden kaçabiliyor bazen değişkenlerinizi izlemek ve kontrol etmek. Bu kullanıma alışırsanız farkında olmadan vereceğiniz açık sayısı en az inecektir.

Gelelim kullanıma, bunu da örnekleyerek anlatacağım :

Bu örnekte tek değişken gösterdiğim için pek anlaşılmamış olabilir. Ancak alttaki örnekte prepare & execute yapısının önemini kavrayacaksınız.

Son kısımda bahsettiğim detayı umarım anlayabilmişsinizdir. Çünkü bu şekilde uygulama geliştirdiğiniz zaman, uygulamanız daha esnek, daha rahat müdahale edilebilir ve daha rahat geliştirilebilir hale gelecektir. Siz üye kayıt sayfasını daha sadeleştirmiş olacak, eğer gerekirse üye veritabanında yapacağınız bir değişiklik için gidip üye kayıt sayfasının içinde HTML, PHP karışık kodun içinde aramak yerine doğrudan fonksiyonunuzdaki sql’i güncelleyerek daha hızlı çalışacaksınız.

Bu noktada iş gruplarına ait fonksiyonları sınıflandırırsanız zaten Nesne Tabanlı Programlama (OOP)’ya adım atmış olacaksınız 🙂

PHP dosyanıza resim (dosya) gömmek

Böyle birşeye neden ihtiyaç duyarsınız?

En büyük nedeni, tek dosyadan oluşan bir script yazıyor olabilirsiniz (konuyla ilgili olarak PHP ile tek dosyadan oluşan proje üretmek dökümanını okuyabilirsiniz). Ya da yazdığınız projede kullandığınız ufacık ikonların bir sürü dosya şeklinde durmasını istemiyor olabilirsiniz. Başka bir tercih de dosyalarınızı bir veritabanında tutuyormuşcasına tek dosyada depolamak isteyebilirsiniz. Çok küçük boyutlu resimler için bahsettiğim konu daha yaygın kullanılır.

Yani yazdığınız betik kendi içindeki css kuralları ile şekillendirilmiş, ikonlarla da güçlendilirmişse ve ikonlar için ek dosyalar koymak istemiyorsanız bu yöntemi kullanabilirsiniz.

Teknik

Aslında yapılan iş oldukça basit. Öncelikle dosyalarımızı php dosyamızın içine nasıl gömeceğiz? PHP dosyalarımız ascii dosyalar, binary içeriği alabilmek ve saklayabilmek için base64 ile şifreleyeceğiz. Sonuçta ortaya çıkacak olan şey bir ascii şifre olacaktır. Dosya boyutuna göre bu şifrenin uzunluğu artacaktır. Unutmayın ki bu anlattığım yöntem tamamen ufak dosyaları gömmek içindir 100kb üzeri dosyaları php dosyanıza gömerseniz, ya da php dosyanızın boyutu megabyte’ları aştığı zaman işlenmesi zorlaşacaktır. Birkaç ufak dosya için kullandığınız sürece verimli olacaktır.

Dosyalarımız encode etmek için bir kod kullanacağız. Bu işlemi başka bir php dosyası oluşturarak yapın.

Bu kod resim.gif dosyasını ekrana ascii karakterlerle şifrelenmiş şekilde uzun bir metin şeklinde basacaktır. Bu metini kopyalayarak kullanacağız ve orjinal proje dosyamız şöyle olacak

Yukarıda gördüğünüz şey aslında çok uzun bir string. Yani o satırlar yan yana bitişik fakat ben bu dökümanda açıkca görülebilmesi için bu hale getirdim. Bu gördüğünüz string 258 byte’lık 16×16’lık bir ikonun base64 şifresidir. 258 byte’ın bu kadar sürdüğünü düşünürseniz 10-20kb’lık bir dosyanın ne kadar uzun süreceğini tahmin edebilirsiniz. Onun için büyük dosyalarınızı php dosyanıza gömmeyin.

Yukarıdaki şekilde tüm dosyalarınızı base64_encode’dan geçirip $dosyalar dizisine dosyanın adını taşıyan indiste yazın.
Unutmayın bu dizi proje dosyanızın en üstünde tanımlanmalı. Yani proje dosyanızın içinde her türlü işlemi yapıyor olabilirsiniz ama bu teknikteki kodlar dosyanın en üstünde durmalı.

Neyse, dosyalarınızı $dosyalar dizisine kendi adları indis olacak şekilde kaydettiniz. php dosyanızın boyutu kabardı farkındaysanız (kontrol ediniz). Şimdi bu tanımların ardına ufak bir kod ile işlemi bitireceğiz.

Eğer get methodu ile islem değişkeni dosya olarak gelmişse ve get methodu ile dosya değişkeninin içeriği bizim $dosyalar dizisinde indis olarak varsa $dosyalar dizisindeki o elemanın içeriğini base64_decode edip ekrana basıyoruz. Yoksa dosya bulunamadı hatası verip duruyoruz.

Nasıl kullanacaksınız?

Projenin devamındaki bir kısımda

şeklinde kullandığınızda dosyanız resim olarak görüntülenecektir. Aynı şeyi bir arşiv dosyası için de yapabilirsiniz.

gibi.

Dosya deposu

Yukarıdaki kodları ayrı bir dosya olarak kaydedip dosyalarınızı tek parça hale getirdiğiniz bir veritabanı gibi düşünebiliriz. Yani

Bu dosyaya goster.php, resimler.php veya indir.php diyebilirsiniz. Kullanırken yukarıda index.php olarak gösterdiğimiz yola dosyanızın adını yazın. Ayrıca islem=dosya parametresine de gerek kalmadı çünkü bu dosya zaten sadece bu işi yapıyor 🙂

Çok fazla işinize yarar mı bilmiyorum ama yine de bazı yerlerde kullanılan bir teknik olduğu için paylaşma gereği duydum. Umarım faydası dokunur.

Tek dosyalı projeler (siteler) üretmek

Bazen yazdığınız/yazacağınız modül/sayfa/proje çok işlem ve bölüm içermeyebilir. Farklı içeriğe sahip kısa ama çok metin olabilir elinizde. Ya da modülünüzde işlemler kısadır. Ya da tamamen ilginçlik olsun diye tek dosyada birçok işi yaptırmak isteyebilirsiniz.

Mesela sadece bir dizini listeleyip, dosyalar üzerinde ufak işlemler yaptıran bir betik yazıyor olabilirsiniz. Ya da bir reklam kampanyası için reklam sayfasının yanında ufak bir bilgi (hakkında) sayfası ve iletişim formu olan ufak bir site yapıyor olabilirsiniz.

Ufak işlemler içeren sayfalara bir sürü dosya oluşturup dosya kalabalığı yaptırmaktansa tek dosyada toplayabilirsiniz. Bu dökümanda ufak bir örnekle tek dosyadan oluşan bir site/sayfa yapacağım.

Başlıyoruz

Önce basit html yapınızı modüler yapıdaki gibi hazırlayalım.

gördüğünüz gibi oldukça basit. Site başlığı, ufak bir menü iki HR arasında sayfa içeriği ve sayfa sonu notu. Sayfa içeriği kısmına modüler yapıdaki gibi içerğimizi basacağız.

Şimdi 4-5 tane sayfamız var bunların içeriklerini gömeceğiz dosyamızın içine. Aslında hepsi basit bir kontrol mekanizması ile hallolacak.

Yukarıda gördüğünüz gibi sayfa içeriklerini kontrole göre ekrana bastık. Burada dikkatinizi 2 şey çekmiştir. ob_start, ob_get_contents ve ob_end_clean fonksiyonlarını ekrana basılan şeyleri $icerik değişkenine aktarabilmek için yaptım.

kullanımı ise “HTML_SON” kelimesini bitirme kelimesi olarak görerek içeride tırnakları istediğimiz gibi kullanma özgürlüğü sunduğu için yaptım. Yani HTML_SON’ların arasında özgürce istediğiniz her karakteri kullanabilirsiniz. Bu sayede html olarak hazırladığınız sayfa içeriklerini 1-1 kopyala yapıştırarak rahatça işinizi halledebilirsiniz.

Gelelim neden çıktıyı tamponladığıma, bu işlemi hiç echo, tamponlama kullanmadan şöyle de yapabilirdiniz :

Ama bir sürü tırnak sorunu ile uğraşmanız gerekebilirdi.

Neyse içeriklerimizi get ile gelen bolum parametresine göre belirlediğimize göre htlm’imizde konumlandırabiliriz. Sayfanızdaki “içerik kısmı” yazan yere

$icerik değişkenini basıyoruz. Böylece tek sayfada içerik basabiliyoruz.İşin bir de işlem kısmı var. Yani tek dosyada toplamaya çalıştığınız site/sayfa sadece içerikten oluşmak zorunda değil. Aynı zamanda php’ye bazı işler yaptırmanız gerekebilir. Hatta modül için bu tek dosya mantığını düşünürseniz işlem modüllerinde içerik değil sadece işlemler vardır. Aynı mantıkla bunu da yapabilirsiniz.

Örnekte gördüğünüz gibi iletişim bölümünde bir iletişim formu var. Bunu işleyen kısmı buraya gömmek için sayfa içeriklerini seçtirmeden önce işlemler için de bir kontrol bloüu koyuyoruz.

işlemleri de sayfaya gömdükten sonra son sayfa şuna benzer olacak:

Modüler yapıya ne oldu?

Daha önce http://mfyz.com/tr/bir-sitenin-kod-duzeni-nasil-olmali/ dökümanında bahsettiğim bir modüler yapı vardı. Her türlü projenizde bu mantığı kullanmanızı önermiştim. Bu dökümanın amacı ufak projeler için zaten. Farkındaysanız örnekte verdiğim kodlar müthiş kısa kodlar. Çok basit bir site bile yapsanız bu kodlar uzayıp gidecektir. Bir de şunu unutmayın : eğer kodlarınız (yani bölümler veya işlemlerdeki) genellikle 20-30 satırı geçen kodlar ise bu yöntem hata yakalamanızı, sorun yaşadığınızda çözme sürenizi, çalışabilirliğinizi ve kodun temizliğini kötüleştirecek/zorlaştıracaktır. Onun için çok paranoyak veya ihtiyaç duymadığnız sürece bu mantığı kullanmayın. Modüler yapıyla ilgili yazdığım döküman çok daha faydalı olacaktır.