Zend Framework Doctrine 2 Entegrasyonu

1 Comment

PHP yazanlar için en iyi framework ve en iyi ORM yi entegre edelim.

Kaynak : http://www.oelerich.org/?p=315

Zend Framework ün kurulu olduğunu varsayarak anlatacağım.

Efendim ilk olarak http://www.doctrine-project.org/projects/orm/download adresinden stabil olan Doctrine 2.0 sürümünü indiriyoruz.Daha sonrasında Doctrine dizinini Zend de bulunana library dizini altına koyuyoruz. bin dizinini ise zf nin root dizinine koyuyoruz.

application.ini dosyamızda Doctrine entegrasyonunuda kullanacağımız konfigürasyonları belirtiyoruz.

doctrine.conn.host = '127.0.0.1'
doctrine.conn.user = 'root'
doctrine.conn.pass = root''
doctrine.conn.driv = 'pdo_mysql'
doctrine.conn.dbname = 'zf-test'
doctrine.path.models = APPLICATION_PATH "/models"

Bu ayarlamayı yaptıktan sonra Bootstrap dosyasında belli değişiklikler yapıyoruz. Doctrine kütüphanelerini Bootstrap.php dosyasında yüklüyoruz.Örnek kod aşağıdaki gibidir.

<?php

class Bootstrap extends Zend_Application_Bootstrap_Bootstrap
{
    /**
     * generate registry
     * @return Zend_Registry
     */
    protected function _initRegistry(){
        $registry = Zend_Registry::getInstance();
        return $registry;
    }

    /**
     * Register namespace Default_
     * @return Zend_Application_Module_Autoloader
     */
    protected function _initAutoload()
    {
        $autoloader = new Zend_Application_Module_Autoloader(array(
            'namespace' => 'Default_',
            'basePath'  => dirname(__FILE__),
        ));
        return $autoloader;
    }

    /**
     * Initialize Doctrine
     * @return Doctrine_Manager
     */
    public function _initDoctrine() {
        // include and register Doctrine's class loader
        require_once('Doctrine/Common/ClassLoader.php');
        $classLoader = new \Doctrine\Common\ClassLoader(
            'Doctrine',
            APPLICATION_PATH . '/../library/'
        );
        $classLoader->register();

        // create the Doctrine configuration
        $config = new \Doctrine\ORM\Configuration();

        // setting the cache ( to ArrayCache. Take a look at
        // the Doctrine manual for different options ! )
        $cache = new \Doctrine\Common\Cache\ArrayCache;
        $config->setMetadataCacheImpl($cache);
        $config->setQueryCacheImpl($cache);

        // choosing the driver for our database schema
        // we'll use annotations
        $driver = $config->newDefaultAnnotationDriver(
            APPLICATION_PATH . '/models'
        );
        $config->setMetadataDriverImpl($driver);

        // set the proxy dir and set some options
        $config->setProxyDir(APPLICATION_PATH . '/models/Proxies');
        $config->setAutoGenerateProxyClasses(true);
        $config->setProxyNamespace('App\Proxies');

        // now create the entity manager and use the connection
        // settings we defined in our application.ini
        $connectionSettings = $this->getOption('doctrine');
        $conn = array(
            'driver'    => $connectionSettings['conn']['driv'],
            'user'      => $connectionSettings['conn']['user'],
            'password'  => $connectionSettings['conn']['pass'],
            'dbname'    => $connectionSettings['conn']['dbname'],
            'host'      => $connectionSettings['conn']['host']
        );
        $entityManager = \Doctrine\ORM\EntityManager::create($conn, $config);

        // push the entity manager into our registry for later use
        $registry = Zend_Registry::getInstance();
        $registry->entitymanager = $entityManager;

        return $entityManager;
    }

}


İlk iki metod Doctrine ile ilgili bir işlem yapmıyor. Sadece Zend in Autoloader ve Registry modüllerini oluşturuyor. _initDoctrine metodunda ise gerekli belirtilen konfigürasyonlara göre Doctrine nesnesini oluşturuyoruz.Doctrine e bağlı olarak ArrayCache Proxy ve EntitiyManager oluşturuluyor.Bunları tam olarak incelemediğim için pek yorum yapamıyorum.Kaynakta belirtilen ise ArrayCache performansı daha üst seviyede tutabilmek için Doctrine in cache mekanizması, Proxy sanırım o da incelememiş :) , EntityManager veritabanı ve bizim modellerimiz arasındaki bir interface.Daha detaylı incelediğimde umarım bu konu hakkında da bir yazı yazabilirim :)

Sonrasında bir model yeni adıyla bir entity oluşturuyoruz.

<?php

/**
 * @Entity
 * @Table(name="test123")
 */
class Default_Model_Test
{
    /**
     * @Id @Column(type="integer")
     * @GeneratedValue(strategy="AUTO")
     */
    private $id;

    /** @Column(type="string") */
    private $name;

    public function setName($string) {
        $this->name = $string;
        return true;
    }
}

Doctrine 2 ile gelen yeni bir olay ise model oluşturma veya modelden DB oluşturma işlerini bin adlı dizinden yapabiliyor olmanız.Kaynakta söylendiği gibi bin/doctrine.php dosyasını aşağıdaki şekilde değiştirdim.

<?php

define('APPLICATION_ENV', 'development');

define('APPLICATION_PATH', realpath(dirname(__FILE__) . '/../application'));

set_include_path(implode(PATH_SEPARATOR, array(
    realpath(APPLICATION_PATH . '/../library'),
    get_include_path(),
)));

// Doctrine and Symfony Classes
require_once 'Doctrine/Common/ClassLoader.php';
$classLoader = new \Doctrine\Common\ClassLoader('Doctrine', APPLICATION_PATH . '/../library');
$classLoader->register();
$classLoader = new \Doctrine\Common\ClassLoader('Symfony', APPLICATION_PATH . '/../library/Doctrine');
$classLoader->register();
$classLoader = new \Doctrine\Common\ClassLoader('Entities', APPLICATION_PATH . '/models');
$classLoader->setNamespaceSeparator('_');
$classLoader->register();

// Zend Components
require_once 'Zend/Application.php';

// Create application
$application = new Zend_Application(
    APPLICATION_ENV,
    APPLICATION_PATH . '/configs/application.ini'
);

// bootstrap doctrine
$application->getBootstrap()->bootstrap('doctrine');
$em = $application->getBootstrap()->getResource('doctrine');

// generate the Doctrine HelperSet
$helperSet = new \Symfony\Component\Console\Helper\HelperSet(array(
    'db' => new \Doctrine\DBAL\Tools\Console\Helper\ConnectionHelper($em->getConnection()),
    'em' => new \Doctrine\ORM\Tools\Console\Helper\EntityManagerHelper($em)
));

\Doctrine\ORM\Tools\Console\ConsoleRunner::run($helperSet);

Sonrasında oluşturduğum bin dizinine giderek doctrine i executable yapıyorum.

chmod +x ./doctrine

Şu şekilde de modelden veritabanını oluşturuyorum.Pardon entitiy den :)

./doctrine orm:schema-tool:create

Kullanımı da şu şekilde oluyor :

<?php

class IndexController extends Zend_Controller_Action
{
    public function init()
    {
        $registry = Zend_Registry::getInstance();
        $this->_em = $registry->entitymanager;
    }

    public function indexAction()
    {
        $testEntity = new Default_Model_Test;
        $testEntity->setName('Zaphod Beeblebrox');
        $this->_em->persist($testEntity);
        $this->_em->flush();
    }

}

Fakat siz de benim gibi ters bir adamsanız şöyle birşeye ihtiyaç duyacaksınız.”İşte efendim ben DB yi oluşturayım entitiyler buna göre oluşsun” der iseniz eğer şunu yapıyoruz.

./doctrine orm:convert-mapping --from-database php /tmp/
Böylece /tmp dizinine tablolarınızın php çıktısını alabilirsiniz.Aynı şekilde ph p yerine yaml ve xml de alabiliyorsunuz.Bunun için php yerine xml veya yaml yazmanız yeterli.
İyi gönler efendim… :)

Zend Framework ile subdomainlerinizi ilgili modüllere yönlendirin

No Comments

Gecenin saat 2 sinde beni bu yazıyı yazmay iten şey inat etmemdir :) Efendim geleim konuya.Diyelim li domainim.com adında bir domaininz olsun.Zend Framework ile kodlamışsınız bir güzel. İşte bunun mobil versiyonunu yaptınız, servisler modülü falan var admin i var falan filan işte tüm bu modüllerin ayrı domainlerde hizmet vermesini istiyorsunuz.İşte tam bu konuda Zend_Router devreye giriyor.Bilmeyene bela öğrenene sefa hesabı.1 saatlik araştırmalarım sonucunda yine çözümü stackoverflow da bulldum.** Bu siteyi yapanlardan Allah razı olsun :)

Gelelim koda application.ini dostama şu satırları ekledim (Bu arada benim domainim cevremdenevar.com ve bunun mobile modülünü farklı bir domain ile hizmete sunacağım.)

resources.router.routes.mobile.type = “Zend_Controller_Router_Route_Hostname”
resources.router.routes.mobile.route = “mobile.cevremdenevar.com”
resources.router.routes.mobile.chains.list.route = “:controller/:action/*”
resources.router.routes.mobile.defaults.module = “mobile”
resources.router.routes.mobile.defaults.controller = “index”
resources.router.routes.mobile.defaults.action = “index”

resources.router.routes.mobile.type = “Zend_Controller_Router_Route_Hostname”
resources.router.routes.mobile.route = “mobile.cevremdenevar.com”
resources.router.routes.mobile.chains.list.route = “:controller/:action/*”
resources.router.routes.mobile.defaults.module = “mobile”
resources.router.routes.mobile.defaults.controller = “index”
resources.router.routes.mobile.defaults.action = “index”

Efendim olay budur.Ne .htaccess iniz ile ne de bootstrap iniz in ayarları ile oynamayınız.Bu arkadaş bunu hallediyor.Yani boşa işte domain i . lardan explode edip işte onu buraya route edip falan filan bilmem ne gibi şeylerle uğraşmayınız.Değerli vaktinize yazık…

PHP Web Güvenliği

No Comments

Şöyle bir yazı buldum paylaşmak istedim.Gayet güzel ve açıklayıcı bir şekilde temel PHP güvenliğini anlatmış.

Coğrafi Lokasyon Arama

1 Comment

Bu yazımda sizlere coğrafi lokasyon aramadan bahsedeceğim.Verilen enlem ve boylam bilgisi ile bu lokasyona ait belirli bir uzaklıkta bulunan yerleri bulmak.Tabi bulunacak bu yerlerin bir yerlerde tutulduğunu düşünüyorum.Bunun için ihtiyacımız olan şeyler Mysql Sphinx ve PHP.

Mysql için şöyle basit bir tablonuz olsun

CREATE TABLE IF NOT EXISTS `location` (
 `locationId` int(11) NOT NULL AUTO_INCREMENT,
 `locationName` varchar(255) NOT NULL,
 `locationType` tinyint(4) NOT NULL,
 `locationLat` decimal(10,8) NOT NULL,
 `locationLon` decimal(10,8) NOT NULL,
 PRIMARY KEY (`locationId`),
 KEY `locationType` (`locationType`)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8 AUTO_INCREMENT=80908 ;

Evet tablomuzu oluşturduktan sonra gelelim sphinx olayına.Sphinx bir açık kaynaklı arama sunucusudur.Detaylı bilgi için bkz : http://sphinxsearch.com/

Ben Sphinx i Ubuntu 10.10 üzerine şöyle kurdum.

sudo apt-get install sphinxsearch

Sonrasında /etc/default/sphinxsearch te otomatik başlatma parametresini yes olarak ayarladım.Gelelim veri indexlemeye.

Bunun için /etc/sphinxsearch/sphinxsearch.conf u biraz kurcalamanız gerekir.İşte source ve indexleri ayarlamanız icab edecek.Detayları sphinx in sayfasında bulabilirsiniz.Ben conf dosyamı şu şekilde oluşturdum.


source geo
{
 type                 = mysql
 sql_host             = 127.0.0.1
 sql_user             = root
 sql_pass    = root
 sql_db        = test
 sql_port    = 3306
 sql_query_pre    = set names utf8
 sql_query_pre    = set session query_cache_type=OFF
 sql_query    = SELECT l.locationType, RADIANS(l.locationLon) AS longitude, RADIANS(l.locationLat) AS latitude FROM location l
 sql_attr_float           = longitude
 sql_attr_float          = latitude
 sql_attr_uint        = locationType
 sql_ranged_throttle      = 0
 sql_query_info           = select * from location where locationId = $id
}

index geo
{
 source                  = geo
 path                    = /etc/sphinxsearch/data/geo/geo
 docinfo                 = extern
 mlock                   = 0
 morphology              = none
 min_word_len            = 1
 charset_type            = utf-8
 charset_table           = 0..9, A..Z->a..z, _, a..z, U+410..U+42F->U+430..U+44F, U+430..U+44F
 ignore_chars            = U+00AD
 html_strip              = 0
 enable_star             = 0
}

indexer
{
 mem_limit            = 512M
}

searchd
{
 listen                = 127.0.0.1
 listen                = 3312
 listen                = /var/run/searchd.sock
 log                    = /var/log/sphinxsearch/searchd.log
 query_log            = /var/log/sphinxsearch/query.log
 read_timeout        = 5
 client_timeout        = 300
 max_children        = 30
 pid_file            = /var/run/searchd.pid
 max_matches            = 1000
 seamless_rotate        = 1
 preopen_indexes        = 0
 unlink_old            = 1
 mva_updates_pool    = 1M
 max_packet_size        = 8M
 max_filters            = 256
 max_filter_values    = 4096
}

bunu oluşturduktan sonra indexer ı çalıştırıyoruz ki datamız indexlensin.İlk başta hata alabilirsiniz.Sebebi indexlenecek datanın olmaması.Datanızı oluşturup

indexer –rotate geo şeklinde geo adlı kaynağı indexleyebilirsiniz.Gelelim sorgumuzu çalıştırmaya:

<?php
require_once 'sphinxapi.php';

$lat = $_GET['lat'];
$lon = $_GET['lon'];
$_radius = $_GET['r'];
 $search = new SphinxClient();
 $search->SetServer("localhost", 3312);
 $search->SetMatchMode(SPH_MATCH_ALL);
 $search->SetArrayResult(true);
 $search->SetLimits(0, 100);
 $search->SetGeoAnchor('latitude', 'longitude', (float) deg2rad($lat), (float) deg2rad($lon));
 $circle = (float) $_radius;
 $search->SetFilterFloatRange('@geodist', 0.0, $circle);

 $search->SetFilter('locationType', array(10));    
 $result = $search->Query('', 'geo');

Şeklinde kullanmanız mümkün.İndireceğiniz sphinxapi.php nin sürümüne dikkat etmeniz gerekir.Çünkü cilent ve sunucu arasında versiyon farklılığı yaşayabilirsiniz. Evet kabaca bu şekilde gerçekleştirmeniz mümkün.

PHP Framework Seçimi ve Performans Sorunu

No Comments

PHP konusunda junior seviyesinin üzerine çıkmış iki kişi bir araya geldiğinde büyük bir tartışma konusudur frameworkler ve performansları.

Frameworkler kod yazarken okurken ve düzeltirken can kurtarsa da performans olarak değerlendirildiği zaman sonuç biraz hüsran oluyor ben sizler için 2 gözde framewok Codeigniter ve Zend i ayrıca bunlara ek olarak Core php yi kıyasladım. Bunun içinhttp://avnetlabs.com/php/php-framework-comparison-benchmarks adresindenden aynı işleri yapan kodları indirip lokalize ettim ve sonra bunları Apache Benchmark Tool ile test ettim.

5 concurrency ve 1000 request göndererek kendi bilgisayarımda bu testi gerçekleştirdim.

Zend için test sonuçları :

mustafa@mustafa-laptop:~/public_html/test/zend/application$ ab -n 1000 -c 5 http://localhost/test/zend/
This is ApacheBench, Version 2.3 <$Revision: 655654 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/

Benchmarking localhost (be patient)
Completed 100 requests
Completed 200 requests
Completed 300 requests
Completed 400 requests
Completed 500 requests
Completed 600 requests
Completed 700 requests
Completed 800 requests
Completed 900 requests
Completed 1000 requests
Finished 1000 requests

Server Software:        Apache/2.2.14
Server Hostname:        localhost
Server Port:            80

Document Path:          /test/zend/
Document Length:        1375 bytes

Concurrency Level:      5
Time taken for tests:   17.165 seconds
Complete requests:      1000
Failed requests:        0
Write errors:           0
Total transferred:      1588000 bytes
HTML transferred:       1375000 bytes
Requests per second:    58.26 [#/sec] (mean)
Time per request:       85.827 [ms] (mean)
Time per request:       17.165 [ms] (mean, across all concurrent requests)
Transfer rate:          90.34 [Kbytes/sec] received

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:        0    0   0.1      0       2
Processing:    39   86  24.3     82     191
Waiting:       39   85  24.2     82     191
Total:         39   86  24.3     82     191

Percentage of the requests served within a certain time (ms)
  50%     82
  66%     94
  75%    101
  80%    106
  90%    119
  95%    131
  98%    143
  99%    149
 100%    191 (longest request)

Codeigniter için test sonuçları :

mustafa@mustafa-laptop:~/public_html/test/zend/application$ ab -n 1000 -c 5 http://localhost/test/codeigniter/
This is ApacheBench, Version 2.3 <$Revision: 655654 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/

Benchmarking localhost (be patient)
Completed 100 requests
Completed 200 requests
Completed 300 requests
Completed 400 requests
Completed 500 requests
Completed 600 requests
Completed 700 requests
Completed 800 requests
Completed 900 requests
Completed 1000 requests
Finished 1000 requests

Server Software:        Apache/2.2.14
Server Hostname:        localhost
Server Port:            80

Document Path:          /test/codeigniter/
Document Length:        1400 bytes

Concurrency Level:      5
Time taken for tests:   7.937 seconds
Complete requests:      1000
Failed requests:        0
Write errors:           0
Total transferred:      1613000 bytes
HTML transferred:       1400000 bytes
Requests per second:    125.99 [#/sec] (mean)
Time per request:       39.684 [ms] (mean)
Time per request:       7.937 [ms] (mean, across all concurrent requests)
Transfer rate:          198.47 [Kbytes/sec] received

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:        0    0   0.7      0      22
Processing:    18   40  13.4     38      86
Waiting:       18   39  13.3     38      86
Total:         18   40  13.4     38      86

Percentage of the requests served within a certain time (ms)
  50%     38
  66%     46
  75%     49
  80%     52
  90%     58
  95%     63
  98%     70
  99%     72
 100%     86 (longest request)

Evet şekilde de görüldüğü gibi bu kodlar için ki bu basit işlem yapan kodlar sadece veritabanına bağlanarak 4 adet satır çekip ekrana basıyor, görmüş olduk ki Codeigniter Zendframework e göre 2 kat civarında daha hızlı gibi duruyor.Fakat bu demek değildirki Codeigniter Zend den daha iyi bir framework.Zend in zengin kütiphanesi, esnekliği ve çok biçimli obje yönelimli yapısı ile Codeigniter ın ki kıyaslanamaz bile.

Burada temel sorun şu performans mı hızlı ve anlaşılabilir kod geliştirme mi ?

Mesela aynı işi core php yazarak yaptığımızda:

mustafa@mustafa-laptop:~/public_html/test/zend/application$ ab -n 1000 -c 5 http://localhost/test/php/
This is ApacheBench, Version 2.3 <$Revision: 655654 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/

Benchmarking localhost (be patient)
Completed 100 requests
Completed 200 requests
Completed 300 requests
Completed 400 requests
Completed 500 requests
Completed 600 requests
Completed 700 requests
Completed 800 requests
Completed 900 requests
Completed 1000 requests
Finished 1000 requests

Server Software:        Apache/2.2.14
Server Hostname:        localhost
Server Port:            80

Document Path:          /test/php/
Document Length:        157 bytes

Concurrency Level:      5
Time taken for tests:   0.359 seconds
Complete requests:      1000
Failed requests:        0
Write errors:           0
Total transferred:      369000 bytes
HTML transferred:       157000 bytes
Requests per second:    2784.41 [#/sec] (mean)
Time per request:       1.796 [ms] (mean)
Time per request:       0.359 [ms] (mean, across all concurrent requests)
Transfer rate:          1003.37 [Kbytes/sec] received

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:        0    0   0.2      0       2
Processing:     1    2   0.6      1       6
Waiting:        0    1   0.6      1       6
Total:          1    2   0.7      2       7
WARNING: The median and mean for the processing time are not within a normal deviation
        These results are probably not that reliable.

Percentage of the requests served within a certain time (ms)
  50%      2
  66%      2
  75%      2
  80%      2
  90%      3
  95%      3
  98%      4
  99%      4
 100%      7 (longest request)
mustafa@mustafa-laptop:~/public_html/test/zend/application$

gibi inanılmaz bir sonuç ortayha çıkıyor. Framework seçerken kriterimiz performans mı yoksa hızlı geliştirme mi? Mesela paranız var ve bir proje geliştireceksiniz.Para sizin için sorun değil ise Zend framework kullanıp sunucu sayısını çoklayabilir böylece hızlı ve okunaklı kod yazılmasını sağlayabilirsiniz.Zend framework ün o süper lifecycle ından doğan problemleri sunucu sayısını çoğaltarak aşabilirsiniz.

Diğer türlü evet sunucu sayınız az olur fakat core php yazıldığını düşünürsek herkesin kafasına göre kod yazdığı bir ortamda bir önceki yazılımcının işinin başka bir yazılımcı tarafından devam ettirilmesi çok zor olacaktır.Geliştirme süreçleri uzayacak, kodda bug çıkma ihtimali inanılmaz artacaktır.

Şu da yapılabilir. Frameworklerin biraz hantallaşmış yapılarından kurtulmak ve kodun aynı zamanda kodun anlaşılabilir olması için nasıl bir yol izlenmeli?

Bunun içinde kendi MVC yapınızı yazıp onu kullanmanız bir alternatif olarak değerlendirilebilir.Ama kabul edelim ki tek başınıza geliştirdiğiniz ve belli bir süre ayırdığnız kendi framework ünüz hiçbir zaman mevcut frameworklerden daha iyi olmayacak . Karar sizin, bence framework olmadan geliştirilen kod ciddi anlamda sıkıntı :)

PHP JAVA ve C# Inheritance Yapısı

2 Comments

Şöyle bir durum var. A diye bir sınıfım var.Bu A sınıfı B den miras alıyor.Peki A objesi oluşturulduğunda hangisinin constructor ı önce çalışacak.OOP yi az buçuk bilen bir kişi önce parent(B) sonra (A) nın constructorları çalışacak diyebilir.

Şimdi 3 örnek kod inceleyelim.PHP ve Java ve ASP.NET te ne gibi tepkiler veriyor. Java

public class Sinif1 extends Sinif2 {

    public Sinif1()
    {
        System.out.println("Sınıf1 constructor çalıştı");
    }
    public static void main(String[] args) {
        Sinif1 a = new Sinif1();
    }

}

public class Sinif2 {
    public Sinif2()
    {
        System.out.println("Sinif2 constructor çalıştı");
    }
}

Ekran çıktısı şu olacaktır:

Sinif2 constructor çalıştı
Sınıf1 constructor çalıştı

.NET Örneği

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ConsoleApplication1
{
    public class Sinif2
    {
        public Sinif2()
        {
            Console.WriteLine("Base constructor çalıştı");
        }
    }
}

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ConsoleApplication1
{
    class Sinif1 : Sinif2
    {
        public Sinif1()
        {
            Console.WriteLine("Inherited ctor çalıştı");
        }
    }
}

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            Sinif1 cls = new Sinif1();
            Console.ReadLine();
        }
    }
}

Ekran Çıktısı :

Base constructor çalıştı.
Inherited ctos çalıştı.

şekinde olacaktır.

PHP örneğinde ise

<?php
  class Sinif2
  {
    function __construct()
    {
      echo "Sinif2 constructor calisti.
";
    } 

  }

  class Sinif1 extends Sinif2
  {
    function __construct()
    {

      echo "Sinif1 constructor calisti.
";
    }
  } 

  $x = new Sinif1();

Ekran çıktısı şu şekilde oluyor:

Sinif1 constructor calisti.

Eğer üst sınıftaki constructor veya destructor ı çalıştırmak istiyorsanız. Mesela ilk olarak parent constructor çalışmasını istiyorsanız

  class Sinif1 extends Sinif2
  {
    function __construct()
    {

      parent:__construct();
    }
  }

Şeklinde kullanmalısınız.

Çok Kademeli Kategori Sistemi (Multilevel Category System)

No Comments

Özellikle e ticaret ile uğraşan arkadaşlar yakından bilirler. Bu kategori mantığı eğer kötü kurulursa çok büyük sıkıntılar yaratabilir. Peki nasıl yapmalı? İşte bu bölümde bu konuyu anlatmaya çalışacağım?

Sınırsız alt kategori

Sınırsız alt kategori gibi bir sistem düşünüyorsak bu işi tek tabloda Parent- Child ilişkisine göre yapmamız mantıklı olacaktır.Tablomuzu şu şekilde tasarladığımızı düşünelim.

category_id, category_name,parent_category_id

burada belli olduğu gibi categoryid bir kategoriye ait id değerini, name o kategorinin adını, parentcategory_id ise o kategorinin ana hangi ana kategoriye ait olduğunu söyler.

Şu şekilde düşünebiliriz.Tabloların id değerleri 1 den başladığı için Ana kategoriler için parentcategoryid değerini 0 vermeliyiz ki parent_id si 0 dediğimiz zaman bize bütün ana kategoriler gelsin.

Bu mantık ile ilerlersek

id = 1, category_name = Araba, parent_category_id = 0

şeklinde bir kategori ekledim.Şimdi bunu dallandırıp iyice alt kategorilere ayırmaya geldi sıra.

id=2, category_name = BMW, parent_category_id = 1

şeklinde Araba -> BMW yi ekledim.Şimdi BMW altına model ekleyeceğim.

id=3, category_name = 3.18, parent_category_id = 2

Burada önemli noktalardan birisi eklediğim 3.18 modelinin parentcategoryid si 1 değil 2 olarak verdim çünkü 3.18 i arabalar altına değil BMW altına koymak istediğim için… Şimdi yapımız şu oldu

Araba->BMW->3.18 şeklinde oldu bunu istediğimiz kadar uzatabiliriz. İyi ama kod tarafında bunu nasıl bir ağaç yapısında oluşturabiliriz?

İşte tam bu sırada recursive dediğimiz yapı devreye giriyor.

Basit olarak şu yapıda oluşturabiliriz.

function buildTree($ar, $parent = 0)
{
    $op = array();
    foreach( $ar as $item )
    {
        if( $item['parent_category_id'] == $parent )
        {
            $op[$item['category_id']] = $item;
            $children =  buildTree( $ar, $item['category_id'] );
            if( $children )
            {
                $op[$item['category_id']]['children'] = $children;
            }
        }
    }
    return $op;
}

Yukarıdaki kod bloğu (PHP için :) ) bize diziyi bir ağaç yapısı şeklinde elde etmemizi sağlar. Diziyi yazdırmak için

function printTree($arr)
{
    foreach ($arr as $item)
    {
        echo "<li><span class='file'>" . $item['category_name'] . "</span>";
        if (!empty($item['children']))
        {

            echo "<ul><li><span>";
            printTree($item['children']);
            echo  "</span></li></ul>\n";

        }
        echo "</li>";
    }

şeklinde yazdırabiliriz.

Not: bununla beraber Jquery nin bir treeview eklentisini kullanabilir, çok daha hoş işler yapabilirsiniz.

PHP Filtervar

No Comments

PHP 5.2 ile gelen güzel bir özellik filter_var Henüz kod içinde kullanmaya fırsatım olmadı.Değerli büyüğüm Hasan Özgan ın blogunda okudum ve kendi bloguma mutlaka eklemem gerekiyor diye düşündüm.

Hasan Özgan ın da belirttiği gibi bu metod veri girdilerini tipe göre filitreleme işini yapıyor.

Nedir bu tipler? Neler yapabiliyoruz bu filter_var ile???

<?php
print_r(filter_list());
?>

kodu ile şu anda destek verilen filtre türleri listelenebilir.

Array
(
    [0] => int
    [1] => boolean
    [2] => float
    [3] => validate_regexp
    [4] => validate_url
    [5] => validate_email
    [6] => validate_ip
    [7] => string
    [8] => stripped
    [9] => encoded
    [10] => special_chars
    [11] => unsafe_raw
    [12] => email
    [13] => url
    [14] => number_int
    [15] => number_float
    [16] => magic_quotes
    [17] => callback
)

burada da gözüktüğü gibi validate email, validate ip gibi regexp ile yapılmış çok güzel filitrelemeler var gibi gözüküyor :)

Örnek kod uygulamalarını yakında burada bulabiliriz diye düşünüyorum.

Codeigniter Üzerine Smarty Kurulumu

No Comments

Öncelikle application/libraries altına son smarty sürümünü indirin ve konumlandırın.

<?php if (!defined('BASEPATH')) exit('No direct script access allowed');

require "Smarty-2.6.26/libs/Smarty.class.php";

/**
* @file system/application/libraries/Mysmarty.php
*/
class Mysmarty extends Smarty
{
    function Mysmarty()
    {
        $this->Smarty();

        $config =& get_config();

        // absolute path prevents "template not found" errors
        $this->template_dir = (!empty($config['smarty_template_dir']) ? $config['smarty_template_dir']
                                                                      : BASEPATH . 'application/views/');

        $this->compile_dir  = (!empty($config['smarty_compile_dir']) ? $config['smarty_compile_dir']
                                                                     : BASEPATH . 'cache/'); //use CI's cache folder        

        if (function_exists('site_url')) {
            // URL helper required
            $this->assign("site_url", site_url()); // so we can get the full path to CI easily
        }
    }

    /**
    * @param $resource_name string
    * @param $params array holds params that will be passed to the template
    * @desc loads the template
    */
    function view($resource_name, $params = array())   {
        if (strpos($resource_name, '.') === false) {
            $resource_name .= '.tpl';
        }

        if (is_array($params) && count($params)) {
            foreach ($params as $key => $value) {
                $this->assign($key, $value);
            }
        }

        // check if the template file exists.
        if (!is_file($this->template_dir . $resource_name)) {
            show_error("template: [$resource_name] cannot be found.");
        }

        return parent::display($resource_name);
    }
} // END class smarty_library


şeklinde Mysmarty.php dosyasını oluşturun.ve aynı yere konumlanıdrın  yani application/libraries/ altına .

Sonra config/autoload.php de
$autoload['libraries'] = array('mysmarty');

değişikliğini yapıyoruz ki bu kütüphane otomatik yüklensin.
Örnek kullanım şekli :

$this->mysmarty->assign('test', 'Hello World.');
$this->mysmarty->view('welcome_message');

Smarty de Delimiter Değiştirme

No Comments

$this->mysmarty->left_delimiter = '{{';
$this->mysmarty->right_delimiter = '}}';

Ben codeigniter da mysmarty diye oluşturduğum için böyle yaptım. Anlatmak istediğim uygun değişim şekli budur aksi takdirde hard coding yapılırsa versiyon güncelleme de sizde güncellenmek zorunda kalırsınız :) Kolay gelsin :) :)