Web teknolojileri ile ilgili teknik bir blog…

Zend Framework’e giriş ve örnek proje

Zend Framework‘ün dokümanlarını okuyarak hızlı bir başlangıç yapmanız (quickstart) neredeyse imkansız. Bu nedenle Zend Framework’e başlamak isteyenler için örnek bir proje hazırlamaya karar verdim.

Hazırladığım sıkıştırılmış dosyayı açıp web sunucusu ayarlarında yaptıktan sonra çalışan, basit bir örneğe sahip olacaksınız. Kodlar bir sürü yorumumla dolu, dolayısıyla kodları okuyarak birçok şeyi anlayabilirsiniz.

Baştan şunu belirtmeliyim ki Zend Framework bana göre kesinlikle acemiler için bir framework değil. Otomasyon özellikleri de çok zayıf. Eğer Ruby on Rails (RoR) ayarında bir framework arıyorsanız CakePHP ya da CodeIgniter‘ı (CI) takip etmelisiniz.

Zend Framework’ün avantajı tamamen bağımsız kullanılabilen modülleri sayesinde kendi kurallarını koymak isteyen ustalar için sağlam ve hızlı bir altyapı sunması. Dolayısıyla ZF kullanılarak Rails, CI ya da CakePHP ayarında bir alt-framework yaratılabilir.

Örnek Zend Framework Projesi

zf_ornek_proje.zip 18 kB (ZF ayrıca indirilip lib altına konmalı)
zf_ornek_proje_full.zip 3.05 MB (ZF 1.5.2 içerir)

Gereksinimler

  1. Nesne yönelimli PHP bilgisi olan bir programcı!
  2. Apache uzmanı olmasa da temel apache konfigürasyonu yapabilecek bir zat-ı muhterem. Bu zat programcı ile aynı kişi olursa tadından yenmez…
  3. PHP 5, Apache, MySQL . ZF’nin php4′ü desteklemediğini hatırlatırım.
  4. Apache için mod_rewrite
  5. PHP5 için mysqli ya da PDO extension’ı. Mysql extension’ı desteklenmiyor. Ben mysqli kullandım, PDO için application/config.ini‘yi değiştirin.
  6. PHP ayarlarından short_open_tag : on olarak ayarlanmalıdır. Eğer bu ayarı yapamıyorsanız application/view/scripts/ altındaki dosyalardaki <?= geçen yerleri <?php echo ile değiştirmeniz gerekebilir. (Bkz. php.ini)

Notlar

  1. Windows XP Pro, PHP 5.2.5, Apache 2.2, MySQL 5 kullandım. Farklı platformlar için yorumlamak size kalmış.
  2. Bu doküman ZF 1.5.2 için hazırlandı. Yeni versiyonlarda kullanmak isterseniz mutlaka uyumluluk (compatibility) notlarına göz atın. Yeni versiyonlar çıktığı zaman temel mantık aynı kalmasına rağmen ufak tefek uygulama farkları olabiliyor.
  3. Internetteki diğer dokümanlarda dizin adları fark edebilir, özellikle de lib dizini ile public. Bu dizinlerin isimleri çok önemli değil, ancak application dizini ve altındaki isimler önemli.
  4. Zend Framework UTF-8 ile çalışılmasını önerir. Ben de öneririm ve örnekler utf-8′dir. Kullandığınız editörün utf-8 ile problemi varsa dosyaları bozabilir bu da türkçe karakter sorunu yaşamanıza neden olabilir.

Örneği Nasıl Çalıştıracaksınız?

  1. Hazırladığım zip dosyasını bilgisayarınıza indirin
  2. Webroot olarak tanımlanmamış bir dizine zip’i açın.
  3. Web sunucusundan public dizinine erişim sağlayın (alias, vhost ya da documentroot yaparak)
  4. Web sunucusunda gerekli rewrite tanımlamasını yapın.
  5. application dizini altındaki config.ini‘den veritabanı ayarlarını yapın.
  6. sql dizini altındaki zftest.sql’i mysql’e import edin ve zftest veritabanına gerekli yetkileri verin.

Dizin Yapısı

/application   (Kodlama işlerinizin %99'u bu dizin altında  yapılacak)
  /controllers
  /models
  /views
    /helpers
    /scripts

/lib         (Kütüphaneler burada yer alacak, ZF de  dahil)
  /Zend

/public      (Webroot dizini.  Doğrudan erişilecek dosyalar burada)
  /images
  /css
  /js

/sql         (Örnek veritabanının sql'i burada)

Web Sunucusu Ayarları

Uygun bir dizin altında zftest adında bir dizin açın.
Örneğin benim bilgisayarımda webroot c:\apache\htdocs olarak tanımlı ve ben c:\apache\zftest olarak açmayı tercih ettim.
Doğrudan htdocs altında açmadığıma dikkatinizi çekerim!

Zip dosyasının içeriğini zftest altına taşıyın, elinizde şu dizinler olacak:

  C:\apache\zftest\application
  C:\apache\zftest\lib
  C:\apache\zftest\public
  C:\apache\zftest\sql

Apache’nin ayarlarından zftest projemiz için bir alias tanımlayalım:

alias /zftest  "c:\apache\zftest\public"
<Directory "c:\apache\zftest\public">
  AllowOverride All
  Order allow,deny
  Allow from all
  
  RewriteEngine on
  
  # RewriteBase sadece alias yapıldığı zaman  gerekli. 
  # Vhost ya da DocumentRoot'a kurarsanız gerek yok
  RewriteBase /zftest
  RewriteCond %{SCRIPT_FILENAME} !-f
  RewriteCond %{SCRIPT_FILENAME} !-d

  # Adres kısmına ne yazılırsa yazılsın public/index.php handle edecek
  RewriteRule !\.(js|ico|gif|jpg|png|css)$  index.php
</Directory>

Notlar

  1. zftest/public yerine zftest dizinini webroot yapsaydık, diğer dizinlerin altındaki dosyalar doğrudan çağırılabilir ve güvenlik açığı çıkabilirdi. Örneğin http://localhost/application/config.ini adresini keşfeden biri veritabanı şifrenizi öğrenebilir.
  2. Alias oluşturmak benim kişisel tercihim. Birden fazla proje olursa her biri için alias tanımı yapmak daha kolay olacaktır. Ama arzu ederseniz web sunucunun DocumentRoot’unu da c:\apache\zftest\public yapabilirsiniz. Bir başka yöntem de virtual host tanımlamak olabilir.

Oluşabilecek Muhtelif Hatalar

Apache’yi yeniden başlatıp sunucuya bağlandığınızda izin hatası (forbidden) alırsanız

  1. <Directory "c:\apache\zftest\public"> kısmındaki dizin yolu ile alias’ta verilen dizin yolu aynı olmayabilir.
  2. Apache ayarlarından DirectoryIndex komutu index.php’yi içermiyor olabilir. Şuna benzer bir satır olması lazım:
    DirectoryIndex index.html index.php
  3. PHP için short_open_tags parametresinin açık olduğundan emin olun…

Eğer sayfa yerine dizin yapısını görüyorsanız yine DirectoryIndex komutunda index.php yer almıyor olabilir.

Rewrite ile ilgili problemlerde mod_rewrite’ın yüklendiğinden emin olun. Debian sistemlerde a2enmod ile aktif hale getirmeniz gerekebilir.

Karşılaştığınız diğer hataları bana iletirseniz buraya eklerim.

Nereden Başlamak lazım?

Örnek çok basit bir telefon rehberi. Yeni kayıt ekleyin, silin, güncelleyin. Daha sonra sırasıyla aşağıdaki dosyaları inceleyerek nasıl çalıştığını anlamaya çalışın. İçerlerine bol bol yorum (comment) yazdım:

Public/index.php
Application/controllers/IndexController.php
Application/views/scripts/index/index.phtml
Application/models/Phone.php

Daha sonra "deneme" sayfalarına bakabilirsiniz: Model, View ve Controller kısımlarını anlamanızda faydası olacaktır.

Örnekteki yaklaşım ile ilgili

Zend Framework; Rails, CakePHP, CodeIgniter, Django gibi frameworklerin aksine gerekli altyapıyı sunup çözümleri programcıya bırakan bir yapı. Dolayısıyla aynı problemleri farklı yöntemlerle çözebilirsiniz. Bu konuda bazı tercihlerim var:

  1. View ile ilgili: Template sistemlerinde genelde iki türlü yaklaşım tercih edilir. Biri her template’ın başına header, sonuna footer koymak; diğeri ise bir layout belirleyip o layouttaki boşluklara içerik koymak. Her ne kadar layot yöntemi birçok durum için daha pratik de olsa ben bu örnekte header / footer yöntemini kullandım.
  2. Model ile ilgili: Model’da Zend_Db_Table kullanmak da bir opsiyon ancak kişisel görüşüm bu yapının çok kullanışsız olduğu yönünde olduğu için ve internetteki diğer tüm dokümanlarda zaten Zend_Db_Table ile örnek verildiği için Zend_Db kullanarak model’i oluşturmayı tercih ettim.
  3. Controller ile ilgili: Birçok benzer örnekte tüm “controller”ları kapsayan tanımlamaların nasıl yapılacağına pek değinilmemiş. Bu konuda ben bir “DefaultController” kullandım ve diğer controller’ları DefaultController’dan extend ettim. Farklı bir yaklaşım olarak “plug-in”ler kullanılabilir. DefaultController’a göz atmayı unutmayın…

Neler Eksik?

Bu örnekte proje geliştirirken sıkça kullanılan bazı gereksinimleri içermedim. Bazılarını basitlikten ödün vermemek için, bazılarını — dürüst olmak gerekirse — tam olarak bilmediğim için, bazılarını ZF dokümanlarından okuyup uygulayabileceğiniz, bazılarını ise ZF tarafından üretilen çözümlerinden hoşlanmadığım ya da uygulamasından hoşlanmadığım için…

Eksikler:

  1. Veri kontrolleri (Data Validation and Sanitization)
  2. Sayfalandırma (Pagination)
  3. Layout
  4. Önbellekleme (Caching)
  5. Birim testleri (Testing)
  6. Çoklu dil desteği (Localization & Internationalization)
  7. ZF ile verilen servisler (Services)
  8. Otomatik form üretimi (Zend_Form)
  9. ORM – ActiveRecord Pattern

Bu önemli eksiklere rağmen Zend Framework’e başlayanlar için işe yarayacağını düşünüyorum.

Kolay gelsin ;)

İlgili Yazılar

  • [...] önce ZF 1.5.2 için bir örnek oluşturmuştum. Ancak 1.8 versiyonundan itibaren işler biraz değişti. Aslında proje yaratmak [...]

  • [...] [...]

  • Örnek için teşekkürler. Benzer örneği bende kullandım. örnekte CD kolleksiyonu , album ekle/çıkar/sil/düzenle şeklinde yani CRUD yapısı.

    Zend Studio for Eclipse kullanıyorum, PDO kurulu olduğu halde.

    Fatal error: Uncaught exception ‘Zend_Db_Adapter_Exception’ with message ‘The PDO extension is required for this adapter but the extension is not loaded’

    Bi fikrin varmı

  • Zend Studio’nun içerisinden debug edince falan mı veriyor bu hatayı yoksa localhost’tan bağlanınca mı? Sistemde birden fazla PHP olabilir, Zend Studio’yu kullandığında farklı bir PHP’yi alıyordur, Neon’un alt dizinlerine bir göz atmakta fayda var…

  • Hata şöyle oluşuyor, Zend Studio içinde iken, test veya debug işlemlerinde alınıyor. Yani localde test edince sorun yok.

    Zend Studio nun internal browser’i ve default PHP server’ında test edildiğinde PDO yu es geçiyor gibi geliyor bana. Ayrıca workspace htdocs’da (XAMMP kurulu). Bir konfigürasyon yapılması gerekiyor olabilir

  • ben de kurdum, sayfada nedense

    <?

    leri falan gösterdi, halbuki magentocommerce tıkır tıkır çalıştırmıştım. acaba bu işin bir kursu vs yok mudur bildiğiniz?

  • Ozan,

    Eline sağlık. Demo uygulamanı inceledim. Fakat dikkat etmen gereken birkaç konu var.

    /application/config.ini dosyasını, örnek olarak, bir /config klasörü açarak, bu klasör altına alabilirsin ve bir .htaccess dosyası ile bu klasöre public erişimi engelleyebilirsin. Demo uygulamanın şu anki durumu ile config.ini dosyası içerisindeki database connection bilgilerine anonim olarak herkes erişebilir.

    Tabii ki, ZF’ün dispatch aşamasında ki yapılan işlemleri bir class altında düzenli bir şekilde toparlayarak, daha geliştirilebilir bir yapı kurabilirsin.

    Tekrar eline sağlık.

  • Erol Soyöz: “public” dizini webroot olarak ayarlanmalı. Dolayısıyla bir üst dizindeki application dizinine doğrudan zaten erişilemez.

    Dispatch aşaması için benim kişisel görüşüm bu haliyle daha esnek olduğu yönünde ama yöntemler tabii ki programcının tercihlerine bağlı. Zend Framework’ün güzel yanı da o zaten.

    Teşekkürler.

  • bu zf’ye yeni başladım türkçe kaynak ararken siteni gördüm ve yazdığın demoyu indirdim ama bir türlü çalıstıramadım.

    takıldığım nokta şuki sunucu ayarları dediğin yukaridaki yazında o direktifleri tam olarak nere yazacağımı anlayamadım .alias olarak zf yi çalıstıramadım

  • Bilgehan: Apache’nin ayarları farklı yerlerde olabilir. Windows’daki standart apache kurulumunda C:\Program Files\Apache Software Foundation\Apache2.2\conf\httpd.conf dosyasına bakabilirsin.

  • çalışma türkçe olarak önemli bir eksikliği kapatmış. ayrıca eksikler olarak belirttiğin konular da gerçek bir uygulamada olmazsa olmaz olduğu için ileriki dönemlerde bu eksiklikleri de uygulamaya dahil etmen çok yerinde olur.

    çalışma için teşekkürler.

    bunun yanında yorum yazan arkadaşların önemli bir kısmı bırakın nesne yonelimli php yi bilmeyi. php yi bile tam olarak bilmiyor anlaşılan. arkadaşlar herhangi bir dile ait bir frameworku kullanmaya başlamadan önce o frameworke temel olan dili çok iyi bilmek gerekiyor. php yi iyice öğrenmeden framework öğrenmek yanlış olur. php yi öğrenmek ise hazır scriptleri editleyebilmekten çok daha öte birşey… zaten makaleyi paylaşan arkadaş da ön gereksinimlerde bunu yazmış….

  • Oncelikle bu çalışman için teşekkür ediyoerum. Emek vermişssin. iyi de olmuş. Ancak yeterli olmadığında hemfikiriz. Devamı gelirse sevineceğiz.

    Konuyu biraz değiştirip sormak istediğim bir soru var. Şöyleki: yeni bir projede zend framework alt yapısını kullamaya karar verdikten sonra , örneğin smarty ve/veya jquary ile aynı anda kullanmanın sakıncaları varmıdır? Şayet versa bunlar neler olabilir? Birlikte kullanılırsa avantaj ve dezavantajları nelerdir?

    Soru OsYemyi aratır gibi oldu ama yinede soru sorudur.

  • Teşekkürler. Devamını getirmek istiyorum aslında ama çok vakit alan bir iş olduğu için vakit ayıramadım henüz.

    Zend Framework ile smarty’yi beraber kullanmadım, zaten oldum olası sevmem smarty’yi. Ama Zend_View yerine smarty’nin nasıl kullanılabileceğini anlatan dokümanlar mevcut. ZF yapı olarak çok düzgün bir şekilde organize edildiği için bir problem yaratacağını zannetmiyorum. Herşey modüler, Zend_View’ı aradan çıkartıp başka herhangi bir template mekanizmasını sokmak problem olmayacaktır. Tabii henüz piyasada yeterli doküman olmadığı için ilk kurulumda bir miktar baş ağrısı yapabilir.

    jquery ise sonuçta bir javascript kütüphanesi. PHP’yle tek bağlantısı Ajax olabilir ki onda da belirli bir formatta çıktı (output) verdikten sonra ne kullandığınızın bir önemi yok. En son Dojo desteği çıktı sanırım ama o da sonuçta dojo kullanımını kolaylaştırmak için çıkmış bir şey. Yani Zend_Dojo çıkmadan önce de dojo kullanılabiliyodu. jquery, script.aculo.us, mootools vs. hangi javascript kütüphanesini kullanırsanız kullanın sorun çıkmaz.

    Yeni bir projeye Zend Framework ile başlayacaksanız deadline’ı uzun olan bir proje seçin, zira framework’lere alışana kadar oldukça yavaşlatıyor insanı. Her framework için geçerli bu. Ama alışınca da normal kod yazası gelmiyo insanın.

  • Bence anlatımınızın sonunda “Neler Eksik?” bölümünün başlığı çok yanlış olmuş.

    Bence başlık şöyle olabilirdi:
    Eh Artık Bunları da Zend Türkçeleştirerek Örneklendirsin

    Zend Framework kullanan biri olarak uygulamayı üşenmedim kurdum. Burdaki bilgilerle Zende geçiş yapmak isteyen bir Php programcısı saatlerce, belki de günlerce süre kazanır.

    Tebrik ediyorum

  • selamlar ve teşekkürler
    örneği kurdum ve çalıştırdım. URL yapısı olarak bir sorum olacaktı

    örneğin ben asagidaki gibi bir gezinti istiyorum.
    http://localhost/zftest/index/edit/9

    ama Zend Framework örneklerinde bu hep http://localhost/zftest/index/edit/id/9 olarak anlatılıyor.
    Sizin örneğiniz de böyle. ilk verdiğim URL örneğine aşağıdaki gibi ulaşmak istiyorum.
    $id = $this->_request->getParam(‘id’);

    bunu nasıl yapabiliriz? açıklarsanız çok yardımcı olacaksınız. teşekkürler

  • URL yapısını ilgili dosyaya aktaran komponentin adı “router”dır ve Zend_Controller içerisinde yer alır.

    Belirli bir adres için bunu yapmak kolay, ZF dokümantasyonunda örneği de var ama tüm sistem çapında nasıl yapılır açıkçası kurcalamadım hiç…
    Bkz. http://framework.zend.com/manual/en/zend.controller.router.html#zend.controller.router.routes.regex

  • Başlangıç için gerçekten iyi bir kaynak olmuş. Zend Framework için türkçe kaynak ve forum sıkıntısı var kanımca. Bu ve benzeri yazıları bir araya toplamak gerek.

    Özellikle “Muhtelif Hatalar” kısmını çok beğendim ;)

  • öncelikle ellerinize sağlık.
    çok çok güzel olmuş, tebrikler.
    zf’ye başlangıç için gayet anlaşılır ve yeterli bi yazı.
    gerisinide bi zahmet zf öğrenmek isteyen kişi getirsin.
    eksiklikler kısmı için ise, bunlar eksik tamam eyv. ama, bu bir başlangıç yazısı.
    onlarıda yapıp yazyınlarsan orta seviye bi yazı olur herhalde.
    tekrar tebrikler.

  • Merhaba,
    Örneğinizi indirdim ve yazdığınız bütün ayarlamaları yaptım ama tarayıcımdan çalıştırmak istediğimde boş bir sayfa sonucu alıyorum. Acaba nerde neyi eksik yapıyorum. Yardımcı olursanız sevinirim.
    İyi çalışmalar.

  • php.ini’den hata mesajlarını açmakla başlayabilirsiniz:
    display_errors: on,
    error_reporting: E_ALL gibi

  • Hataları açınca böyle bir hata aldım:
    Notice: Zend_Loader::Zend_Loader::registerAutoload is deprecated as of 1.8.0 and will be removed with 2.0.0; use Zend_Loader_Autoloader instead in C:\Program Files\Zend\Core For Oracle\ZendFramework\library\Zend\Loader.php on line 207
    Zend_Loader_Autoloader’ı nasıl kullanabilirim?

  • O hatayı düzelttim. Şimdi de şöyle bir hata alıyorum.
    Fatal error: Class ‘DefaultController’ not found in C:\Program Files\Zend\Apache2\htdocs\zftest\application\controllers\ErrorController.php on line 2
    Neden, niçin, nasıl düzeltirim?
    Yardımcı olursanız sevinirim. Biraz fazla mı soru sordum ne ?:)

  • Son sorduğum soruyu da IndexController.php de en üste şu iki satırı ekleyerek çözdüm.
    -include_once(‘DefaultController.php’);
    -include_once(‘Phone.php’);

    Neden bu iki satırı eklemek zorunda kaldım. Bu iki satırı eklemek yerine daha pratik bir çözüm bulabilir miyim? Örneğin config dosyasında bir parametreyi değiştirmek gibi.?
    Bu da son sorum olacak.
    Teşekkür ediyorum.
    İyi çalışmalar.

  • Eski Zend_Loader, yeni Zend_AutoLoader’ın görevi o include_once satırlarından sizi kurtarmak. Benim yazdığım örnek eski olduğu için ZF 1.8′le tam uyuşmuyor o yüzden sorun yaratıyor.

    Bu örnek yapıyı basitçe anlamak için hazırlandı, denemek için eski ZF sürümlerini kullanarak deneyebilirsiniz. Arşiv sayfalarından tüm versiyonlar indirilebiliyor.

    ZF 1.8 için ise işler biraz daha farklı ve bir yönden daha kolay… O yüzden bu yazıyı ZF1.8′e uyarlamak çok doğru olmaz ama ZF 1.8 ile ilgili ayrı bir doküman hazırlamak daha doğru olacaktır…

  • Bilgilerinizi paylaştığınız ve zamanınızı ayırdığınız için teşekkür ederim.
    İyi çalışmalar.

  • :) Zend Framework ile ilgili çok güzel bir makale olmuş Elinize Sağlık

  • emeğinize sağlık. gerçekten bir framework e başlamak istiyordum. zend’in hayatımın 8/1,7 ini kurtaracağına eminim x)

  • tekrar merhaba hocam,
    örneğinizi çalıştırdım fakat;
    Mysqli statement execute error : No data supplied for parameters in prepared statement

    ve
    #0 /var/www/zf/zftest/lib/Zend/Db/Statement.php(283): Zend_Db_Statement_Mysqli->_execute(Array)
    #1 /var/www/zf/zftest/lib/Zend/Db/Adapter/Abstract.php(405): Zend_Db_Statement->execute(Array)
    #2 /var/www/zf/zftest/lib/Zend/Db/Adapter/Abstract.php(483): Zend_Db_Adapter_Abstract->query(‘INSERT INTO `ph…’, Array)
    #3 /var/www/zf/zftest/application/models/Phone.php(44): Zend_Db_Adapter_Abstract->insert(‘phone_directory’, Array)
    #4 /var/www/zf/zftest/application/controllers/IndexController.php(80): Phone->insert(Array)
    #5 /var/www/zf/zftest/lib/Zend/Controller/Action.php(502): IndexController->insertAction()
    #6 /var/www/zf/zftest/lib/Zend/Controller/Dispatcher/Standard.php(293): Zend_Controller_Action->dispatch(‘insertAction’)
    #7 /var/www/zf/zftest/lib/Zend/Controller/Front.php(914): Zend_Controller_Dispatcher_Standard->dispatch(Object(Zend_Controller_Request_Http), Object(Zend_Controller_Response_Http))
    #8 /var/www/zf/zftest/public/index.php(50): Zend_Controller_Front->dispatch()
    #9 {main}

    Şu an bakmakta olduğunuz view dosyası: /var/www/zf/zftest/application/views/scripts/error/error.phtml;

    değerlerini geri dönderiyor? ne yapmalıyım.

    teşekkürler

    • Bu doküman çok ama çok eski 1.5.2 versiyonu diyor, şu anki versiyon 1.11 gibi birşey neredeyse tamamen değişti…
      Eğer zend framework’ün son hali ile denediyseniz çalıştırmıyor olabilir.

  • Üstad Selamlar,
    Dün zend in dokümantasyonunu incelediğimde quickstart la hızlıca framework ku kullanabilmemin pek mümkün olmadığına karar kıldım. Ancak yazdığın örnek aplikasyonun kodlarını incelediğimde kafamdaki tüm soru işaretleri sonlandı.

    Klasör structure ını da ayrıca beğendim. Public dizininin root directory olarak tanımlanıp dış dünyanın aplikasyona erişimini önlemek oldukça mantıklı. Ellerine sağlık.

  • Warning: The magic method __isset() must have public visibility and cannot be static in D:\wamp\www\zend\lib\Zend\Config.php on line 182
    Call Stack hatası alıyorum sorunu nasıl çözebilirim. teşekkürler.

Bu yazıya gelen cevapları takip etmek için bu RSS 2.0 linkini kullanabilirsiniz.