Anasayfa | Giriş Yapın | Üye Olun | Gökçe Kim? | İletişim
Gökçe’nin Web Güncesi (gwg)

Gökçe’nin Web Güncesi (gwg)

Welcome to darkside of the Source, we have cookies!

Gökçe’nin Web Güncesi (gwg) RSS Feed
 
 

Google’ın yeni icon’u

Çok küçük değişiklikler bile insanlar tarafından hemen anlaşılabiliyor. Google, küçük favicon’ununu değiştirmeye gitti, fGoogle’ın büyük G’sini, küçük olan g aldı. İşte öncesi ve sonrası:

Eskiden:
Google's New Blue Fav Icon

Şimdi:
Google's New Blue Fav Icon

Eğer yenisini görmüyorsanız google.com/favicon.ico sayfasına bir kaç kere ctlr+r yapın, yeni iconu göreceksiniz.

 

Eskisi bundan daha iyi değildi fakat özlüyorum. FF sekmelerinde açtığım Google sonuç sayfalarını ararken zorlanıyorum, yabancılaşmışım. Niye böyle bişey yaptı Google? kendileri açıklamadan bilemeyeceğiz tabii ki, belki kendilerini daha iyi ifade ettiği için, Google’a isim ilhamı veren Googol sayısı ( 10100 ) bu çok büyük sayıya sonsuzluk kolayca yakıştırılabilir, küçük el yazısı g ise sonsuzluk sembolünü (∞) anımsatıyor. Belki de insanların Google’ın küçücük bir değişimine nasıl tepki gösterdiğini anlamak için yaptılar bunu. Fakat sonuç değişmiyor, böyle büyük bir alışkanlıkta küçücük bir şey değişimde dahi insanlar bunu konuşur, tepki gösteriyor işte, yenisi daha iyisi olsa bile.

Not: Bu aralar işten güçten çerez yazı yazabiliyorum ancak. Taslak yazı olarak üç yazım (MySQL ile Hiyerarşik veritabanı şemaları, Framework’süz MVC ve Türkçe Stemming) tamamlanmayı bekliyor, uygulama yapılarıyla uğraşanların ilgisini çekeceğini umuyorum.

Acid Testleri, peki gerçekten kim birinci?

Acid testlerini Web’in bir kenarıyla uğraşan herkes aşinadır. Bu testlerde Opera ve Safari kendilerini testlerden başarılı olarak ilk ilan edilenlerdi. Fakat bir başka bakış açısından bakmakta da yarar var, testler nasıl kurgulanıyor? Kimler aday sayılır ve başarı neye göre belirleniyor?

Acid2′ye dair

Acid2 CSS/HTLM testi (gülen yüz) sonuçlarını hepimiz biliyoruz, Opera birinci, Konqueror ve Safari takipçisi. Bu sonucu nasıl kabullendik; Opera’nın çalışır dağıtılmış sürümü, acid testi çıktığında Internet Explorer’dan kötü olmasın, kötüydü. Buna rağmen Firefox test çıktığında 1.0.2 sürümüyle en güzel sonucu aldıysa da son düzeltmeleri nightly’de kaldı ve gecko bunu kullanarak Konqueror’ı Acid2 ‘den geçirdi. Opera? Opera acid2′den geçtiğinde 2 versiyon yayınlamıştı, yani sınavın sorularını çoktaan almıştı.

Bir sınavın cevapları yayınlandıktan sonra, %100′le geçen’e başarılı diyebilir miyiz?


Acid2 yayınlanınca, o anki geçerli sürüm olan Firefox 1.0.2 sonucu.

Acid2 yayınlanınca, o anki geçerli sürüm olan Opera 7.0.4 sonucu

Saphari? O zaman yoktu.

Acid3 ‘e dair

Acid3 Testi çıktığında ise, stable’lar kapıştığında Firefox 52/100, Opera 9 46/100, Saphari 39/100 ile sonuncu çıktı. Internet Explorer 6 ve 7 ise 10-12/100 ‘de süründü. Fakat daha dağıtımda olmayan nightly sürümlerde, henüz kurulumu düzgün yapılamayan Saphari Webkit’le 100/100 ile bir gecede birinci olurken, Mindfield ile dağıtımı yapılan Firefox 3.x şimdi 90′larda. Ben buradan, çok daha geniş geliştirici kitlesi olan ve yayınlanmış bulunan Firefox 3′ün, yapacak daha önemli işleri olduğunu çıkarıyorum. Webkit’i ise sadece soruları gördükten sonra cevap üretme hızından dolayı tebrik ediyorum.

Değerlendirme sizin.

Not düşeyim, burada önemli olan birinciliklerden çok, tarayıcıların bütün kurallara düzgün uyması ve dolayısıyla biz webcilerin, özellikle frontend’de duranların (dizayn) düzgün birşey çıkarmak için birton tarayıcıyla test çalışmasını engellemenin yanı sıra sitelerin her tarayıcıda aynı görünmesini başarmak. Micro$oft uslanacak gibi görünmese de Acid testleri bu anlamda çok büyük bir adım.

Programlamada Geleneksel veya Nesne Tabanlı Seçim

Ne anlamı var bu yazının?

Son zamanlarda, bir OOP çılgınlığıdır gidiyor. 100 satırlık kod, ben bunu nasıl OO ile yaparım sorularıyla süsleniyor. Sizce niye OOP? diye sorulduğunda kimisi “daha düzenli” diyor, kimisi “yeni teknoloji, eskide kalmayalım” diyor, kimisi “bence BMC” diyor. Benim bunlara bulduğum yanıtlar ise, daha düzenli mi? yerine göre evet. Yeni teknoloji? bilgisayar tarihinde 20 yıllık bir geçmiş, yeni değildir. BMC? Gene reklamları gelmiş TV’ye, kaplanlı falan, eski reklamları daha samimiydi.

Bu yazıyı oluştururken hem kendi bilgilerimi kullandım, hem de internetin fikrini aldım. İnternette araştırma yaparken bu konuda onlarca procedural ve OOP fanının taraflı yazıları arasında, konuya objektif bakan açıklayıcı iki metini seçtim. Birisi Zend’de yayınlanan OOP vs Procedural diğeri Pascal’da iki yöntemin farklılığını ve methodlarını anlatan Modular Software Design. Açıkçası ben PASCAL makalesine daha fazla önem veriyorum, bu makale aynı zamanda modüler programlama eşit değildir OOP’nin anlatımı.

Takımlarınızı tuttuysanız, işe unutmakla başlayın

Bilişim dünyasında, nedense takım tutmak çok rastlanır bir durum. /*buradan sonrası sırf sevdiğim bi lafa credit vermek için Bu biraz neofobik olmamızla (”Bütün programcılar neofobiktir.” -Koray BİLGİ“), biraz da yaptığımız işi kendimizle dolayısıyla seçimlerimizle kişiselleştirdiğimizden ortaya çıkıyor. credit bitişi*/ Örneğin Linuxda pico/nano’da kod yazan adam, Eclipse’de kod yazmayı pisleyebilir, tersi de mümkün. İki durumun da kendi hak noktaları var. Örneğin;

Eclipse kullananın argümanları,
Bütün projeye mouse tıklamalarıyla elimin altında,
Otomatik tamamlama özelliğiyle, uzun fonksyion isimlerini yazmıyorum,
Hemen her dilde syntax hightlight edip, yazdığım gibi syntax hatalarını çıkarıyorum,
Resimleri bile eclipse’in içinde düzenleyebiliyorum,
..
Vi/Emacs/Nano/Pico kullanın argümanları,
Heryerden işimi yapabilirim,
işimi yapmak için 200 MB lık editöre ihtiyacım yok, 100KB’lik SSH’ım olsun, yeter.
Kocaman dosyaları açmam, saniye sürmüyor.
Herşeyim klavyeden, herşeyin kısa yolu var, hızlı çalışıyorum
Benim çalışma ortamım zaten sunucunun kendisi, kaydediyorum ve çalışıyor!
..

Devamı »

Dizayn, 960 Grid System

Web uygulamalarının frontend kısmıyla çok uğraşan biri değilim. Temiz CSS,  biraz hareket katmak ve gerektiği yerlerde uygulamaya erişilebilirlik destekleri için tercihen lightweight zengin javascript kütüphaneleriyle javascript veriyorum. Bunun dışında ucundan User Interface/Kullanıcı Arayüzü bilgisiyle birşeyler tasarlıyorum.

Aslında çok ilgi alanım değil, fakat zengin içerikde gerekliliğini gördüğüm  tasarım design pattern’lerini araştırıyordum. Burada gezinirken buna rastladım. 960 Grid System, 1024 çözünürlüklü ekranlarda temiz gözükecek 960px genişliğindeki dizaynlara bir kolonlama standartı getirmiş. Sistem oldukça matematiksel, 960′ın bir dizaynda rahat gözükecek ortak bölenleri çıkartılarak kolonlar arası aralama (spacing) pixelleri çıkartılmış. Sıkışık içerikte 16 kolon, daha rahat tasarımlarda ise 12 kolonluk sürümleri var.

960gs, bu sistemin kolay kullanımını sağlamak için PDF, HTML, Photoshop, vb formatlarda bu standarta göre tasarım oluşturmak için template’ler (şablonlar) da sağlıyor. Tasarımla ilgilenenlerin bir gözatmasını öneririm.

SYN Flood, DoS Atağı

SYN flood kısaca nedir; TCP/IP de bir bağlantı açmak için ilk SYN gönderilir, fakat bu noktada kesilirse, SYN quoe denilen sıralama deposu eninde sonunda dolar ve sunucu yeni bağlantı kabul etmez. Benim sunucum 1200 ‘e kadar thread destekliyordu, 3 kişi 6-12 yaş arası çocuklar için yazılmış sözüm ona saldırı oyuncakları ile 400-500 ‘er packet’ler yollamışlar sağolsunlar, nihayetinde önlem alma gereği duydum.

Korunma yöntemi, tcp packetleri spoofingle (pakette yanlis ip adresi) ile birlikte gelince iptables veya harici bir firewall. Benim harici (fireslayer) firewall’um saldırıyı 15 dakikada anca anlayıp engellediğinden, işimi hızlıca görecek kısmını iptables’dan yaptım.

Aslında bu syn flood koruması module olarak apache güncelleştirmesinin yanında geliyor, fakat ben performans ihtiyacımdan dolayı litespeed kullanıyorum, bunu da not düşeyim.

#!/usr/bin/php -q
< ?
while(true) {
unset($exec);
//sort edilmis, 80 portuna yapilan iplere gore gruplanmis baglanti sayilari
exec("netstat -plan|grep :80|awk {'print $5'}|cut -d: -f 1|sort|uniq -c|sort -nk 1",$exec);
foreach($exec as $i => $v) {
        //trim
        $v = trim($v);
        while(strpos("  ",$v)) //tembel parse
        $v = str_replace(array("  ","   ")," ",$v);
        $d = explode(" ",$v);
        //print_r($d);
        if ($d[0] > 30 && !in_array($d[1],$giden)) {
        echo "Gidici: {$d[0]} tane {$d[1]}\n";
        exec("iptables -A INPUT -s ".$d[1]." -j DROP");
        $giden[] = $d[1]; //giden bidaha islenmesin
        }
}
sleep(30); // & ile backgrounda birakalim, devamli baksin..
}
?>

PHP ile OOP Serisi: Singleton Class

Belki OOP için biraz fazla ileri bir konu ama, Singleton design pattern’i oldukça gerekli olabiliyor. Pek çok arkadaşımız aslında tek instance’i olması gereken classlarını singleton yapmıyor, biryerlerde aynı object’in tek bir instance’i gerekse bile boyuna çağırıyor. Dolayısıyla PHP boşu boşuna performans kaybediyor, boşu boşuna onca sistem kaynağı gidiyor. Yazık değil mi? Ağlar o memmory blocklar sonra arkanızdan.

Konumuza dönersek, singleton class’ın özelliği kendisinden sadece bir tane çağırılabilmesidir, tıpkı class içine alınmamış geleneksel fonksiyonlar gibi.

<?php

if (!interface_exists('Singleton_Interface')) {
    /**
     * singleton interface - phpclasses.org'dan alinmistir, standart interface
     * @author Matthieu MARY <matthieu@phplibrairies.com>
     * @license http://opensource.org/licenses/gpl-license.php GNU Public License
     */

    interface Singleton_Interface
    {
        /**
         * singleton standardı getInstance ile alınır, öylesi hoş..
         * @access public
         * @static
         */

        public static function getInstance();
        /**
         * __clone overload methodunun üstesinden gelinmeli
         * exception throw edelim
         */

        public function __clone();
    }
}


    /*
     * A true singleton in PHP - phpclasses.org'dan alinmistir biraz da gelistirilmistir.
     * @author Sourav Ray - GY
     * @version 1.0.0
     * @name singletone.class
     */

class sTonClass implements Singleton_Interface  {
    static $TheInstance; //singeTon'u sağlayacak degisken
    public $deneme; //denemesi..
    // class'ın constructor'i private, sinifin disarisindan kendisi cagirilamayacak { }  
    private function sTonClass() {
    }
    public static function getInstance() //Class'ın örneğini yaratan ayni zamanda donduren fonksyon.
{
        if (sTonClass::$TheInstance == NULL) //Eger daha once bir ornegi mevcut degilse class'i yaratip dondurur.
            sTonClass::$TheInstance = new sTonClass ( );
       
        $instanceReferance = & sTonClass::$TheInstance; // Eger ornegi mevcutsa, eski ornegi dondurur
        return $instanceReferance; // Eski ornegin referansi.
    }
    public function __clone() { throw new Exception('Bu sınıf singleton'); } //bu sınıfın clone'u olmaz.
} // bitis

//kullanim
$x = sTonClass::getInstance ();
$x->deneme = "hede";
$y = sTonClass::getInstance();
echo $y->deneme;
?>

Singleton’un ne olduğu ve kullanımı ile ilgili daha detaylı bilgi için tıklayın.

Eclipse bana wordwrap yap

Eğer yazılımla ilgileniyorsanız, hangi programlama diliyle uğraşırsanız uğraşın Eclipse IDE’yi mutlaka duymuşsunuzdur. Neredeyse her popüler bilgisayar dilinin editörünü içine katan ve katmaya devam eden Eclipse’in bir büyük sorunu var. Eclipse’de Wordwrap yok.

Notepad dahil hemen hemen her metin editöründe bulunan wordwrap (satır kaydırma) özelliği Eclipse’de es geçilmiş. Çekirdeğinde olmayınca da maalesef eclipse’in gelişmiş modüler yapısını kullanarak pluginlerle adam akıllı çözüm getirilemiyor.

Gene de yazılımın Javasından bakan azimli Eclipse IDE kullanıcıları, eclipse için bir soft-wordwrap yapmış [burada görebilirsiniz]. Soft wordwrap’den kastımız şu:

Yüklenen wordwrap plugini eğer satır editör penceresinin dışına kadar uzanıyorsa, Eclipse çekirdeğine aslında bu dosyanın 3-4 satırı daha var diyerek ve satırları bölerek gerçek satır sayısını yükseltiyor. Dolayısıyla bunu yapınca Eclipse’in hata bildirimlerini, (problem view) hata ayıklama penceresi (debug view) gibi satır numaralarıyla alakalı pluginler çuvallıyor. Bu yüzden istediğimiz zaman soft wordwrap’i açmak, işimiz bitince kapatmak durumundayız.

Soft wordwrap’i yükleme

Eclipse’in plugin update servisini açıyoruz: üst menüden (menubar) sırayla Help / Software Updates / Find and Install menüsünü izleyin.

Karşınıza çıkan pencerede, Search for new features to install seçili olarak Next butonuna tıklayın. Soldan New Remote Site ‘a girin. Gene çıkan pencerede name kısmına “Dandik Wordwrap” url kısmına http://ahtik.com/eclipse-update/ yazın. Ok ‘ye tıklayın. Artık Dandik Wordwrap’in plugin listenize yerleşmiş olması lazım. Sistemimize zaman zaman bol bol spyware bulaştıran “devamlı next“, “arada ne çıkarsa accept” , “he gülüm” politikası sizi sonuca götürecektir. Korkmayın, spyware / adware gibi şeyler yok burada.

İyi çalışmalar..

Code Igniter’ın View’una Layout eklemek

İlk web modeli RoR olan MVC’nin PHP gibi yüksek sayıda takipçisi olan bir web sunucu dili ile gündeme gelmesiyle View’un özellikleri de çeşitlilik gösterdi. Önceleri, sadece template sistemi gibi olan dosyalar varken, View zamanla Layout ve Element özelliklerini de kendine kattı. Konumuz ise Code Igniter (CI)’da olmayan element (aslında gene recursive view) ve daha geniş bir çerçeveden bakan Layout sistemini CI’a kazandırmak. Buarada küçük ve konumuzla alakası olmayan bir bilgi, web’e ilk olarak RoR (Ruby on Rails) ile gelen bu MVC’nin V’sinin helperıymış, layoutuymuş gibi eklektik olayları yüzünden, gerçek MVC pattern‘inin kötü bir uyarlamasını düşünen ve haklı noktalarının olduğunu düşündüğüm argümanlar var, gene cümleyi hem uzattım hem böldüm hem de konu dağıttım bunu ayrı bir yazıda uzun uzun anlatayım iyisi.

Konumuza yavaştan dönersek; daha önce de bahsettiğim gibi, büyük (esnek, modüler, ve bakımı gittikçe zorlaşan) web uygulamalarında tercihim Zend Framework (ZF) iken; özel CMS, küçük/orta ölçekli yönetim paneli, veya benzeri küçük web uygulamalarında tercihim şu anda Code Igniter. Hala konuya gelemedim, ama devam..

Code Igniter’dan frameworklerle ilgili ilk yazımda kısaca bahsetmiştim. Code Igniter’ın benim için en kötü özelliği, herşeyin birbirine bağımlı olması ve pek modüler olmamasıydı. Buna rağmen, kodları PHP’ye başlayalı 3-4 ay olmuş ve OOP ile önceden tanışmış biri için çok kolay modifiye edilebiliyor olması bu dezavantajı ortadan kaldırıp yerini esnekliği getirebiliyor. Yani, özel birşey istediğinizde ya da Code Igniter yapısıyla ilgili bir sorunla karşı karşıya kaldığınızda bunun için düşünülmüş bir yapı yerine, Code Igniter içine özel kod yazmanın kolaylığını bulacaksınız.

Benim en büyük sorunum web uygulamalarında çok büyük rahatlık sağlayan Layout idi. Evet, sanki konuya yaklaşıyoruz gibi bir his var. Buradaki sorunumuz Layout’un View’un üstünde tanımlanması gereken birşey olduğu ama aynı zamanda View’un bir parçası olması gerektiği sorunuyla karşı karşıya kalmamız. Dolayısıyla Code Igniter’a bir yapısal değişiklik getirmek sözkonusu.

Ve Layout’a başladık.

Layout yapısını eklememiz için, CI Core’unun view’unu üstlenen display birimini değiştirmek durumdayız. Böyle büyük değişiklikleri CI’ya Core’unu doğrudan değiştirmeden uygulamamız için hooker sistemi var. Bu sayede CI core’u düzenlemediğimizden, Evillabs’dan gelen CI güncelleştirmelerini huzurla uygulayabiliyoruz.

Hook tanımlamak

Hook’lar CI’in hazır gelen bootsrap’ine dahil olmayabilir, açıkçası hatırlamıyorum :-). Ama yapmak çok basit, öncelikle bootsrap’de hooku açıyoruz.

Aşağıdaki satırı application/config/config.php ‘deki enable_hooksatırını bulup değiştirin veya dosyanın sonuna ekleyin.

$config['enable_hooks'] = TRUE;

Bu durumda Code Igniter artık yaşadıkça öğreneceğiniz meşhur tek singleton class’ı olan CI ‘yı başlamadan application/config/hooks.php dosyasını değerlendirecektir.

Bu dosyada prototipi burada olup, kendim geliştirdiğim Yielder hookunu tanımlayacağız.

hooks.php içeriği

< ?
$hook['display_override'][] = array(
'class' => 'Yielder',
'function' => 'yield',
'filename' => 'Yielder.php',
'filepath' => 'hooks'
);
?>

Bu dosyada tanımlanan Yielder hookunun ismi Yielder.php ve adı Yielder. Şimdi display işini CI ‘dan devralacak Yielder classını yaratalım. Gene CI hazır bootsrap’i sayesinde, yaratılan hookları application/hooks dizininde arayacaktır. Bizde dolayısıyla bu dizinin altında Yielder.php isimli dosyada classımızı oluşturacağız.

Yielder.php içeriği

< ? if (!defined('BASEPATH')) exit('No direct script access allowed');
class Yielder
{
function yield()
{
/*TODO yeni display.. eski benchmark ->; System/Libraries/Output.php _display replace, inherit edilecek. ediliyor. EDİLDİ. */
global $BM;

$CI= &amp; get_instance();
$output = &$CI->output->final_output;

if (!preg_match("/(.+).php$/", $CI->layout)){
$CI->layout .= ".php";
}

if ($CI->layout != -1)
{
$requested = 'application/views/layouts/' . $CI->layout;
$default = 'application/views/layouts/default.php';
if (!file_exists($default)) die("Hook failed: Yealder 404 $default");
if (file_exists($requested))
{
$layout = $CI-&gt;load->file($requested,true);
$view = $layout; //nerdeyse performans farkı yok 0.001-5 ms.
}
else
{
$layout = $CI->load->file($default, true);
$view = $layout;
}
}
else
{
$view = $output;
}
/* direk inherit? */
echo $CI->output->_display($view);
//echo $view;
}
}
?>

Artık Controllerımızda View çağrıldığında, doğrudan kendisi gelmeden önce hangi layout’un içine geleceğini bildiriyoruz. Bunun için koddan da anlaşılacağı gibi, henüz varolmayan application/views/layouts/ klasörünü ve onun altında default layout dosyasını (default.php) oluşturuyoruz.

default.php

<?php
/**
* GY_Lisans::callback("korktularmiAcaba");
* Bu basit layout dosya örneği, tamamen kendisinin de RoR 'dan arakladığı
* cakePHP'den araklanmıştır. Bankalarda hesaptan hesaba yapılan para transferleriyle
* aklanan insanların "Arakın arakının arakı, benimdir" pskolojisiyle,
* alnın akıyla tüm hakları Gökçe YALÇIN'ındır. Aşağıdaki lisansı, Gökçe YALÇIN dahi iplemez,
* ne de olsa Gökçe YALÇIN'ın da kimliğinde T.C uyruklu yazmaktadır.
* Bırakın biti, bir digit bile değişiklik yapılırsa itfaiye çağırırız,
* BSA'ya haber verir, prestijinizi ilgili reklamlarda gösterilen işadamlarından beter ederiz;
* cabası Micro$oft'un avukatlarıyla kokoreç yemeye zorlanırsınız.  İyi günner.
* GY_Lisans::dispatch();
*
* @author             Gokce YALCIN <breathalyse@gmail.com>
* @license            http://www.opensource.org/licenses/mit-license.php The MIT License
*/

?>
<html>
<head>
<?php
@include("head.php"); //burda da yaparız yani!
?>
</head>
<body>
<div id="container">
<div id="header">
<h1>Bu layout'a tabi statik bilgi</h1>
</div>
<div id="content">
<?php
echo $this->output->get_output();
?>
</div>

< ?@include_once("footer.php");?>

</div>
</body>
</html>

Peki, çeşit çeşit layout’lar kullanmak için ne yapacaksınız? Aşağıda bir controller örneği var.

<?php
class Main extends Controller {
    function Main()
    {
        parent::Controller();
        $this->layout = 'main'; //controllerin varsayilan layoutunu degistirmek, yani default.php yerine main.php layout u kullanilacak.
    }
    function index() {
        $this->load->view("index.php");
    }
    function bununLayoutuYok() { URI: /main/bununLayoutuYok
        $this->layout = -1;
                $this->load->view("bunun.php");
    }
    function bununBisiyiYok() {
                $this->layout = -1;
        }
}
?>

Buarada terimleri niye ingilizce kullandığıma dair bir eleştiri aldım. Aslında haklı bir eleştiri, fakat araçtırmacı insanlar genelde sırtını en bol kaynağı içerdiğinden ötürü ingilizce kaynaklara yöneliyor, dolayısıyla bunu yaparken de terimlerin ingilizce orjinlerine göre hareket ediyor. MVC’yi “Kalıp Görünüm Yönetici” diye çevirsem, kimse Googling ile birşey bulamazdı. Hiçbirşeyin doğrusu yanlışı yok, sadece ben pis bir pragmatistim ve microsoft çevirileri gibi benim hakkımda da ‘acaba bunun ingilizcesi ne olabilir, ne iğrenç çeviri’ diye konuşmalarını istemedim. Neyse layout konusuna gelince tekrar, yapılacak birşey kalmadı. Hepsi bu kadar.

Son söz

Kimileri “MVC’de hani outputun gösterilmesiyle ilgili herşeyin üstünde View olmalıydı? Burada resmen Layout View’u inherit ediyor, hatta içiçe” diyebilir. Bence haklılar ve bunun üzerine düşerken ZF’de Zend_Layout ve Zend_View ayrılmış olarak doğru kullanmanın iç rahatlığını yaşarken , Agavi’de bence MVC’yi en iyi uygulayan yapıyı görebilirler. Fakat Agavi’yi projenin dokümantasyon görevini üstlenecek yeterince geliştiricisi olmadığından, eşeleye eşeleye öğrenmek durumundayız. Bu da ayrı yazının konusu ve kokusu.

Bir diğer haber de Code Igniter ile ilgili yazım, “RoR’daki ve cakePHP’deki View’un renderElement özelliğini de eklemek” olacak. Aslında bence gereksiz, zaten view’un recursive kullanımı. Ama cakePHP’nin View’una alışmış ama sihirbazlığından usanmış insanlar için gene de yapalım.

Zend_Validation , Form Validation mesajlarını türkçeleştirmek

Bir önceki yazımda Zend_Translate’i anlatmıştım. Validation hatalarını da toptan dil ile birlikte çözme konusunu sonraya bırakmıştım fakat.. Gelin görin ki dayanamadım, yazdım.

Öncelikle Zend_Validation ‘a hangi translate’i kullanacağımızı söylüyoruz. Zend_Translate kullanımını geçtiğinizi ve yapılandırmanızı tamamladığınızı varsayıyorum, eğer takıldığınız noktalar varsa buradan benim yapılandırmama / örnek bootstrapime bakabilirsiniz.
Devamı »

Zend Framework : Zend Translate : ZF’ye çeviri yaptırmak

Kendi bootstrapimi oluştururken beni kendisine hayran bırakan iki Zend classlarından biri de Zend_Locale ve Zend_Translate. Öncelikle, yerellik ve dil’in farklı şeyler olduğunu ve ayrı ayrı ele alınması gerektiğini herhangi başka PHP framework sanırım önem vermemiş. Yerellik; para birimleri, tarih formatı, ölçüm, yerel saat, iki karakter kodlardan, ülkelerin listesi, ülkelerin insanları listesi, ülkelerin dillerinin adları listesi, vb şeylerin farklarını içerirken dil tamamen çeviriye adamış kendini.

Neyse, doğrudan anlatmaya başlayayım;

Dizin yapımız:

    / (root)

  • /application
  • /config
  • /garbage
    • /cache
    • /temp
  • /language
    • /tr
      • lang_genel.php
      • lang_validation.php
    • /en
    • /ru
  • public_html
    • /img
    • /js
    • /css
    • /index.php (işte geldik burdayız)

bootstrap dosyamız diyelim ki index.php ve herhangi başka config dosyası kullanmıyoruz.

<?php
require_once 'Zend/Loader.php';

error_reporting(E_ALL|E_STRICT);//debug
ini_set('display_errors', 1);

//istersek cagirilinca yuklensin, ben tercih etmiyorum, ama böyle kullanırsanız loadClass'lar kalkabilir. Buarada load etmeyi unuttuğum class'lar da olabilir
Zend_Loader::registerAutoload();

//dizin yapısı

define("BASE_PATH",$_SERVER['DOCUMENT_ROOT']."/..");
define("APP_PATH",BASE_PATH."/application");
define("CONFIG_PATH",BASE_PATH."/config");
define('LANG_PATH',BASE_PATH.'/language');
define('GARBAGE_PATH',BASE_PATH.'/garbage');
define('TEMP_PATH',GARBAGE_PATH.'/temp');
define('CACHE_PATH',GARBAGE_PATH.'/cache');
define("PUBLIC_PATH",BASE_PATH."/public_html");
define("IMG_PATH",BASE_PATH."/img");
define("DATA_PATH",BASE_PATH."/data");

//controllerımızı başlatıyoruz
$controller = Zend_Controller_Front::getInstance ();

/*
requestimizi tekrar yapılandırıyoruz.
/en/ , /ru/index.php 'yi dil parametresini ru yaparak devamını sağlıyor. Route_Regex le de çözülebilir, fakat sonuç performans kaybı.
*/

$request = new Zend_Controller_Request_Http ( );
Zend_Registry::set ( 'request', $request );
$base_url = dirname ( $_SERVER ['PHP_SELF'] ); //index.php
$request->setBaseUrl ( $base_url );
if (preg_match("$^/\w{2}/$",$request->getRequestUri())) {
$dil = substr($request->getRequestUri(),1,2);
$request->setParam('dil',$dil);
$new_uri = substr($request->getRequestUri(),3);
$request->setRequestUri($new_uri);
}
$controller->setRequest ( $request ); //yeni requestimizi front controllerın kullanımına sunuyoruz

//cache ben backend olarak sqllite seçiyorum bu ozellik sqlite extensioni gerektiriyor, dileyen file'da tutabilir.
Zend_Loader::loadClass('Zend_Cache');

$cache_core = Zend_Cache::factory('Core','Sqlite',
array(
'automatic_serialization'=>true,
'lifetime'=>86400,
'ignore_user_abort'=>true
)
,
array(
'cache_db_complete_path'=>CACHE_PATH.'/core.sqllite'
)
);
Zend_Registry::set('cache_core',$cache_core); //ilerde biyerlerde Zend_Registery::get('cache_core') ile istedigimizde emrimize amade olsun

//Translate &amp; Locale call
Zend_Loader::loadClass ( 'Zend_Translate' );
Zend_Loader::loadClass ( 'Zend_Locale' );

$locale = new Zend_Locale ( ); //HTTP ACCEPT headeriyle default locale'i aliyor, dil sorunlarinda daha aciklayici olmamizi sagliyor.
Zend_Translate::setCache ( $cache ); // dil dosyalarimizi cache'lememize, dolayisiyla daha hizli calismasini sagliyor
/*
* Benim Zend Translate'im.
*  Extra olarak kendi dil parse fonksiyonumu koydum.
*  Genelde dillerin gramer farkını gözetmeyen %s ile yapılan ve sıralama kontrol edilemeyen
*  print_f çevirilerindeki
*  'Book %1 Edited by %2'
*  '%2, %1 kitabını düzenlemiştir' sorununu çözüyor, Aynen print_f gibi kullanılıyor.
*/

class My_Translate extends Zend_Translate {
public function dil($key) {
$numargs = func_num_args ();
$s = $this->_($key);
$arg_list = func_get_args ();
for($i = 1; $i < $numargs; $i ++) {
$s = str_replace ( "%$i", $arg_list [$i], $s );
}
return $s;
}
}
$translate = new My_Translate('array', LANG_PATH, null, array('scan' => Zend_Translate::LOCALE_DIRECTORY)); //Zend_Translate 'e dil dosyalarimin languages klasorunun altinda, ve dil isimleriyle ayrilmis oldugu bilgisini belirtiyoruz, dizin yapimiza gore burada biraz sihir sozkonusu.
$diller = $translate->getList(); //kullanilabilir dillerimiz

//Eğer dil kullanilabilir degilse, hata çıkarıyoruz
if ($dil = $controller->getRequest ()->getParam ( 'dil' )) {
if (! in_array ( $dil, $diller )) {
die ( "Sitemiz seçtiğiniz dilde (" . $locale->getLanguageTranslation ( $dil ) . ") yoktur,

ama şunlar olabilir:
<pre>"
. print_r ( $diller, 1 ) ) . "
"
;
}
} else {
//default locale
$dil = 'tr';
$controller->getRequest ()->setParam ( 'dil', 'tr' );
}//translate'e default olarak hangi dili kullanacağını söylüyoruz

$translate->setLocale ( $dil );

//kendi validatiorlarimizi kullanmasi icin
Zend_Validate_Abstract::setDefaultTranslator($translate);

//ve start veriyoruz.
$controller->dispatch();
?></pre>

Bootstrap dosyası biraz kalın, bu da ZF ‘nin azizliği, yapabileceğim çok birşey yok.
Son satırdaki Zend_Validate_Abstract::setDefaultTranslator($translate); sayesinde, aynı zamanda formlarda sıkça kullandığımız Zend_Validator’un kendi mesajlarını da çevirebiliriz. Bunu bir sonraki yazımda ayrıntılı anlatırım.