mod_rewrite sayesinde sayfalarımızın adreslerini istediğimiz formda gösterebiliyoruz (İlgili makale için:http://mfyz.com/htaccess-yardimiyla-tum-trafigi-te......n-yonetmek). Kullanımı çok yaygınlaşsa da bu kullanımın bazı ufak problemleri beraberinde getirdiği göz önünde bulundurulmalı.

Bu yazıda iki çok açık problemden ve basit çözümlerinden bahsedeceğim.

İlk problemlerden birisi sayfanızda kullandığınız tüm medya veya eklentilerin yollarını domain seviyesinden belirtmek durumunda olmanızdır. Eğer htmlinizi yazarken sayfanızdaki görselleri, stilleri, scriptleri bu şekilde tanımlamadıysanız tüm sayfalarınızdaki yolları güncellemeniz gerekiyor.

Basit bir örnekle, ana dizinde duran bir index.php veya html dosyanızın olduğunuz varsayalım ve images, css ve js olarak 3 medya dizininiz olsun. html'inizi kodlarken yolları su şekilde belirtmeniz dogal:
<html>
	<head>
		<title>Blah blah</title>
		<link rel="stylesheet" href="css/style.css" />
		<script src="js/myscript.js"></script>
	</head>
	<body>
		<div>
			<h1>Test page</h1>
			
			<img src="images/cat.jpg" alt="Cat" />
		</div>
	</body>
</html>
Eğer bu uygulmanızda bu sayfayı sunan kodu domain.com/about/license gibi, birden fazla derinlikte bir url ile sunduğunuz zaman, tarayıcınız o sayfa kodunun /about/ dizininde çalıştığını varsayarak medya dosyalarınızı /about/js/, /about/images/ gibi dizinlerde arayacaktır.

Çözümü ise basit. İki seçeneğiniz var bu noktada. Her medya yolunu belirtirkenhttp://domain/images/cat.jpg şeklinde tam yolu belirtebilirsiniz veya dosya/dizin yollarını belirtirken "/" işareti ile başlayarak domain seviyesinden itibaren işaret edeceksiniz yollarınızı yani yukarıdaki html kodunda her yol tanımlamasını "/" işareti ile başlayarak (ekleyerek) düzeltebilirsiniz.

Başında bir protokol ile belirtilmemiş her url domain üstündeki bir yolu ifade eder. "/" işareti ile başlayan yollar ise domain seviyesini işaret eder. Yani sadece "/" şeklinde tanımlanmış bir link aslında domain ana dizinini işaret eder. Ama bizim amacımız domain seviyesinden itibaren bir dizini işaretlemek, dolayısıyla /images/icons/plus.png gibi bir yol sızı nerede olursanız olur her zamanhttp://domain.com/images/icons/plus.png'yi işaret ederek istediğiniz dosyaya ulaştıracaktır.

Cookie Problemi

Bir diğer problem ise çerez (cookie) problemidir. Çerezlerin tarayıcıda kaydedildiğini hatırlamakta fayda var. Sunucu tarafında dahi çerez kaydetmek isteseniz o çerez aslında o isteğin cevabında gelen headerlar'da olacak ve tarayıcı istek cevabındaki değerlere göre çerezleri kaydedecek, silecek veya güncelleyecektir. Yani tarayıcının çerezleri yönettiğini bilmeniz gerekiyor, ayrıca çerezlerin dizin bağımlı olduklarını da belirtmek gerek. Yani bir çerezi /A/B/C dizininde iken ayarlarsanız bu çerez sadece C dizini ve alt dizinlerinden erişilebilir olacaktır. C dizinindeyken aryıca ana dizin, A ve B dizininde kaydedilmiş çerezlere de erişebilirsiniz. Tarayıcı, alt dizinlerdeki bir çereze erişimi bir üst dizinden veya paraleldeki bir dizinden vermez.

Bu durumda url'lerinizi klasör şeklinde ayarladıktan sonra uygulamanızda nerelerde çerez kaydediyor, siliyor veya güncelliyor olduğunuzu hatırlamanız ve güncellemeniz gerekiyor. Bu güncellemeyi hem javascript'deki cookie kullanımınız için hem de sunucu tarafındaki çerez kullanımınız için güncellemeniz gerekiyor. Sunucu tarafında bütün dillerde çok bilinen bir problem olduğu için yazdığınız sunucu taraflı dile ilişkin çerez methodlarını inceleyin. Ben kısaca php'de nasıl yapacağınızı anlatacağım.

Önce javascript ile çerez işlemlerinizi güncellemek için, normalde kullandığınız:
document.cookie = "";
koduna ek olarak "path=/" eklemeniz gerekecektir (tabi ki ; ayracını kullanarak diğer çerez cümlenize ekleyebilirsiniz.

Bu size karışık gelmiş olabilir çünkü javascript ile çerez yönetimini herhangi bir kütüphane kullanmadan yapmanın yolu bu. Ancak muhtemelen jquery veya en azından çerezlerinizi okumak, silmek veya kaydetmek için bir kütüpahne kullanıyor iseniz kullandığınız kütüpahenin "path" yani çerez dizinini belirtebileceğiniz bir yöntemi vardır, bu yöntemi uygulayarak tüm çerezlerinizi ana dizininizde ayarlamalısınız, böylece çerezleriniz her yerden erişilebilir hale geleceklerdir.

PHP'de bu problemi çözmek için tüm "setcookie" fonksiyonunun (name, value, expire) standart kullanımına 4. parametre olarak "/" yani dizin parametresi eklemeniz yeterli olacaktır. Bu noktadan sonra kaydettiğiniz tüm çerezler ana dizine kaydedilecek, böylece her yerden erişilebilir hale geleceklerdir.


Bu konu, daha teknik noktalarda başka problemleri de beraberinde getiriyor fakat url'lerinizi klasör şeklinde ayarladıktan sonra ilk karşılaşacağınız iki büyük problemden ve çözümünden kısaca bahsetmiş oldum.


Hazırlayan: Mehmet Fatih YILDIZ
Yine URL şemaları üstüne bir yazı hazırladım. Bu sefer htaccess'den çok dinamik bir url şeması hazırlamayı da anlattım. Bu yazı ile:

- apple.com/ipod/nike
- sahibinden.com/kiralik

veya kullanıcı sayfaları:

- twitter.com/mfyz
- twitter.com/mfyz/followers

Şeklindeki url şemaları oluşturmak için gerekli mantığın anlamış olacaksınız.

http://mfyz.com/dokuman/131/htaccess-yardimiyla-tu......n-yonetmek
URL şemaları, SEO amacıyla önem taşımakta. Bunun yanı sıra, her geliştirici ürettiği uygulamanın URL şemasının anlaşılır ve güzel görünmesinı ister. Eğer bir framework kullanıyorsanız muhtemelen bunu yönetebileceğiniz bir yer, yardımcı vs vardır. Fakat kendi kodunuzu yazıyorsanız htaccess ile mod_rewrite yardımıyla her url şema tipine göre bir rewrite kuralı yazmanız gerekecektir.

Basit bir proje örneği vereceğim, diyelim ki basit bir ürün katalogu hazırlıyorsunuz, katalog anasayfasında son ürünler ve kategoriler listeleniyor. Her her ürün de bir kategoride listeleniyor. Yani kategori sayfaları ve ürün detay sayfalarınız var. Basit bir php projesi ile bu uygulamayı 3 parçaya ayırdınız, anasayfa, kategori ve ürün detay. Her parçanın kendine ait kodu var. Normalde bu parçaları birer php dosyası olarak hazırladığınızı düşünürsek her parçayı birbirine
  • anasayfa.php
  • kategori.php?kategori_id=21
  • urun_detay.php?urun_id=2320
gibi linklerle bağlıyorsunuz.

URL şemasını su şekilde kurgulamak istediğinizi düşünelim:
  • /
  • /kategori/21
  • /urun/2320

Bunun için klasik yöntemlere göre htaccess dosyanıza her link şeması için bir kural yazıp gerekli yönlendirmeyi yapmanız gerekir. Fakat her kural için düzenli ifade (regex) yazmak hem yorucu olabilir hem de her yeni url şeması için yeni regex hazırlamanız ve htaccess dosyanızı güncellemek durumunda kalırsınız. Eğer url şemalarınız belirli bir mantığa göre hazırlıyorsanız -ki MVC frameworkleri genelde buna benzer kurallara sahiptir- bu kuralı algoritmaya çevirmeniz çok kolay.

Mesela Codeigniter kullanarak hazırladığınız aynı yapı için, anasayfa, kategori ve ürün detayı için ayrı controller ve ayrı view'lar yazmak durumunda olacaksınız. Gerçekten de olması gereken bu zaten. Ama controller'ı yazarken size bazı kurallar koyar Codeigniter. Verdiğiniz sınıf adı ve method'a URL üstünden doğrudan ulaşabilirsiniz eğer methodunuz public bir method ise. Atıyorum ürün detay controller'ının adını Urun koydunuz ve method adını da detay koydunuz. Bu methodu tetiklemek (ulasmak) için kullanacağınız url: /Urun/Detay/ekstra/parametreler şeklinde olabilir. Methodunuz içinde ekstra parametreleri yakalayabilirsiniz.

Kendiniz yazarak hazırlayacağınız kod ıle url şeması böyle ikili bir kurala sahip olmak zorunda değil. Tekil bir tanımlayıcı yeterli olacaktır, ama daha karışık bir mekanizma kurarak siz de çoğul (ikili veya üçlü) bir adresleme mekanizması oluşturabilirsiniz. Tekil bir adresleme için kurallı bir mekanizma olarak şöyle bir algoritmanız olabilir:
/Urun/3452/yazci-uyumlu-versiyon şeklindeki bir url'i, ilk parça controller adı, geri kalanlar da hem opsiyonel hem de controller tarafından yakalanıp işlenecek olan veri olarak düşünürseniz, ilk parçada gelen adda controller'a sahip olup olmadığınızı kontrol edebilirsiniz. Bunun için bütün controller'larınızı "Controllers" gibi bir dizinde toplu tutmanızda fayda var. Çok ilkel bir mekanizmayla controller'larınızın sınıf değil, düz php dosyaları olduklarını varsayıyorum ve böyle bir url çağırıldığında tek bir dosyadan gerekli controller'i tespit edip include ederek calıştırdığınızı düşünelim.

Peki bu url'ler nasıl tek merkezden geçecek?

Şimdi size önce anlatmam gereken kısma geldik, bütün trafiği tek dosyaya yönlendirmek. İşte bunun için htaccess'a oldukça genel bir kod koyuyoruz:
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php?path=$1 [L,QSA]
Yukarıdaki kod sitenize gelen tüm istekleri index.php dosyasına yönlendirir. Örnek olarak:
http://example.com/
http://example.com/kategori/123
http://example.com/urun/8765
gibi istekleri index.php?path=/kategori/123 şeklinde tek parametre olarak index.php dosyasına iletilecektir. Ama yukaridaki kod teknik olarak eğer url'de geçerli bir dizin adresi veya dosya adresi yoksa istekleri index.php'ye yönlendirecektir. Yani "kategori" adında bir dizininiz varsa istek index.php'ye gitmez. Bunda da bir detay daha var. Eğer "kategori" adında bir dizininiz var ve url /kategori/sdjfhsdkfjshd ise bu URL'de aranan dosya orada olmadığı için istek yine index.php dosyasına aktarılır.

Burada ilk problemin çözümü için, controller adlarınız projenizin kök dizininde varolmayan bir klasör adı olmalıdır. İkinci problem ise, siz kullanmıyor olsanız bile herhangi bir dizin içinde bulunamayan istek index.php dosyasına yönlenecek ve siz bunu kontrol etmek zorunda kalırsınız. Olmayan dosyalara yapılan istekler web'in doğasında olan bir şeydir. En basit örneği, sitenizi tarayan botlar (google bot etc...) sitenize robots.txt, favicon.ico, sitemap.xml veya crossdomain.xml gibi sorgular yapacaktır. Olmadığı için 404 hatası almaları gerekir yaptıkları şeyi doğru yapmak için. Bunun yanı sıra siz de bu gereksiz istekleri işlemenize gerek kalmazsınız.

Bunun için, yani ikinci problemi çözmek için, projenizin asset dizinlerini (stiller, js, resimler, imges, files etc...) bu url ayrıştırma mekanizmasından ayırmak isteyebilirsiniz. Aşağıdaki satırları yukaridaki kodun üstüne yerleştirmeniz yeterli.
RewriteCond %{REQUEST_URI}  !^/resimler.* [NC]
RewriteCond %{REQUEST_URI}  !^/proje.* [NC]
Böylece bu dizinler ve altındaki isteklere dokunulmayacaktır. Ama yine de kök dizindeki her spesifik isteği ya htaccess'da ya da index.php dosyanızda işlemeniz gerekmektedir.

index.php istekleri nasıl ayrıştıracak?

Artık sitenize gelen tüm istekler index.php'nin elinin altında. "path" parametresini "/" karakterine göre parçalayarak ilk parçayı controller adı olarak rezerve edebilirsiniz. Dizinin geri kalan elemanlarını global bir dizide tutarak controller'larinizin içinde yakalayabilirsiniz. Unutmayın hala $_GET dizisiyle soru işareti ve sonrasında kullanacağınız GET parametrelerini yakalayabilirsiniz. Yani /urun/67845?ref=facebook_campaign gibi bir url hala doğru şekilde calışacaktır.

Çok ilkel bir yapıda controller adını "Controllers" dizininde öyle bir dosya olup olmadığını kontrol ederek ve eğer dosya varsa o an include ederek basit bir yapı kurabilirsiniz.

Size biraz daha farklı bir yapı sunacağım şimdi


mfyz.com'un kodu çok eski sürümlerde Türkçe idi, sonrasında ilkel bir modüler yapıya evrimleşti, sonrasında dil değiştirdi, sonrasında ilkel bir MVC modeline evrimleşti, ve şu an oldukça gelişmiş bir MVC modeline sahip. Kod 95% İngilizce, çünkü hala Türkçe yazılmış ve refactor edilmeyi bekleyen eski kodlar duruyor hala derinlerde :-) Neyse, bu örneği çoklu dile sahip bir projede çalışma ihtimali için veriyorum. Kod, controller'lar ve method adlarınız hep ingilizce (veya başka bir dilde) olmak zorunda olabilir veya ölyle olmasını isteyebilirsiniz. Böyle bir durumda Türkçe bir domain altında yoresel-organik-sabun.com/product/detail/1231231 gibi bir url şemasından çok yoresel-organik-sabun.com/urun/1231231 gibi bir URL tercih edersiniz değil mi? Şimdi bunun için kuralsal bir yaklaşımdan çok bir yol haritasının yolu gösterdiği bir mekanizmayı anlatacağım. Bu mekanizmanin bir diğer avantajı da aynı controller ve method'lara birden fazla farklı url şemaları oluşturabilmenizdir. Yani örneğin bir iletişim formuna sahipsiniz ve example.com/contact ve example.com/callus gibi iki url hatta aynı zamanda example.com/iletisim gibi farklı dildeki adresleri oluşturabilirsiniz. Sonra otomatik dil değişimi yapıp yapmamak sizin controller'da yaptığınız hünerli kodlara kalmış.

Bir yol haritası oluşturmak aslında bu url şemalarını htaccess'da her şema için ayrı ayrı kural yazmaya benziyor, ama çok daha dinamik olabilir ve düzenli ifade yerine basit dizilerde tutulabilir. İlkel bir yol haritası dizisi yazacağım yukaridaki örnek proje için.
$router = array(
  'kategori' => array('controller'=>'kategori', 'method'=>'index'),
  'ürün' => array('controller'=>'ürün', 'method'=>'detail'),
  'urundetay' => array('controller'=>'ürün', 'method'=>'detail'),
)
Gördüğünüz gibi ürün için iki farklı adresleme kullanabilirsiniz. Daha dinamik bir yol haritasını veritabanınızda saklayabilir hatta otomatik güncelleyebilirsiniz. Bunun en güzel örneği kullanıcı adı ile adresleme yapabilmektir. Yani example.com/mfyz ve example.com/mfyz/links gibi kullanıcınıza domain.com/kullanici_adi gibi bir sayfa adresleyebilmenizdir. Gelen isteğinizi, sitenizin ana yol haritası kontrollerinizi yaptıktan sonra, eğer istekte bulunulan adres yol haritanızda bir yeri işaret etmiyorsa kullanıcı dizininizde aratarak adresin bir kullanıcı profili veya kullanıcı sayfasını işaret ettiğini yakalatabilirsiniz.


Hazirlayan: Mehmet Fatih YILDIZ

Popüler Etiketler

apple macosx license wanda proje kampanya css kitap dokuman portfolio form button jquery örnek kod mysql sql optimizasyon analyse procedure javascript ipucu iphone ipad spam less compile compiler windows linux app on-the-fly ie css3 support browser mootools ajax xmlhttprequest mobile itunes php apache kurulum cache logo html5 html lifestream rss mfyz subversion svn kontrol yapıları if while mail signature imza www subdomain redirect crossdomain tebrik ruffles doritos facebook connect api session cookie digital xml nedir http server switch fstab ntfs newsletter subscription icon ikon grafik download firefox banner calendar xhtml wordpress plugin opengraph graph share social js input textarea select ios browsers object twitter statistics istatistik insanlar network ubuntu osx player internet framework mdb2 pear injection prepare execute media sosyal konsol login startups link medya oyun pharma hack wireless terminal regex blog widget table fql optimization query design app store store in-app purchase purchase verification storekit itunes connect db code meta cms lisans google chart applications free sitemap seo service box date diff workspace ui development radio style tytz generator language iOS nasıl job developer gimp howto bootstrap database integration search screen git version control deployment parse editor coding auth htaccess route router mod_rewrite export tool url assets ux webkit phpstorm jetbrains pgsql mssql ide notebook laptop icons internet explorer web app open source zaman tarih music