Cotonti ile hata ayıklama

#1. Hata ayıklama hakkında

Çoğumuz için hata ayıklama biraz korkutucu veya yapmak istemediğimiz bir şey gibi geliyor. Ama aslında bunu kolayca bir av oyununa dönüştürebilirsiniz, bu sadece seçtiğiniz bir silah meselesidir. Tüm kodlarınıza mikroskopla bakabilirsiniz, gözünüzü bağlayarak bir sopayla vurmayı deneyebilirsiniz ama XXI. yüzyılda bunu yapmak için başka bir şey var.

#2. En İyi Çözüm

En iyi çözüm, özel bir PHP hata ayıklayıcısı kullanmak olacaktır. Örneğin, XDebug. İşte güçlü IDE'ler ile XDebug kullanımına dair bazı eğitimler:

Bu eğitimde eski yöntemleri kullanacağız; yani PHP ve Cotonti dışında özel hata ayıklama araçlarını kullanmayacağız. Neden böyle yapalım? Çünkü XDebug, her sunucuda bulunmayan bir PHP eklentisidir ve yerel sunucunuza yüklemek biraz çaba gerektirir. Ayrıca, bazı geliştiriciler hata ayıklamayı manuel olarak yapmaya alışkındır. Bu nedenle Cotonti'nin dahili hata ayıklama araçlarını kullanarak işleri kolaylaştıracağız.

#2.1. Hata Ayıklama Modunu Etkinleştirme

Dahili hata ayıklama araçlarını kullanmak için datas/config.php dosyasında hata ayıklama modunu etkinleştirmeniz gerekir:

$cfg['debug_mode'] = true;

Ya da hata ayıklama çekirdek modülünü manuel olarak dahil edebilirsiniz:

require_once $cfg['system_dir'].'/debug.php';

#3. Değişkenleri Yazdırma ve İzleme

Bir değişkenin değerini öğrenmek istiyorsanız en basit yol onu ekrana yazdırmaktır. Ancak Cotonti, çıktı tamponlama ve şablon motoru kullanır, bu nedenle her yere doğrudan yazdırma yapamazsınız. Boş bir ekrana çıktı almak için cot_print() fonksiyonunu kullanabilirsiniz:

$qa_abuse = ($usr['id'] == 0 || $row['fp_posterid'] == $usr['id'] ? ''
     : cot_rc_link(cot_url('plug', 'e=modcp&m=report&post='.$row['fp_id']), $L['qa_report_abuse']);

// <DEBUG>
cot_print($usr['id'], $row['fp_posterid'], $qa_question); // değişkenleri yazdır
// </DEBUG>

$qa_best = ($qa_question['q_state'] == QA_QUESTION_OPEN && $usr['id'] == $ft_firstposterid) ?
// ...

İstediğiniz kadar değişkeni parametre olarak verebilirsiniz. Çıktı şu şekilde görünecektir:

cot_print() fonksiyonunun sorunu, komut dosyası yürütmesini durdurmasıdır. Bu nedenle, çağrıldıktan sonra kodun devamında ne olacağını bilemezsiniz. Değişkenlerin nasıl değiştiğini görmek için, onları izlemeye alabilirsiniz.

Cotonti'de "manuel" izlemeler mevcuttur. Bu, değişkenleri otomatik olarak izlemese de, hata ayıklama günlüğüne değişkenleri kaydeder.

cot_watch() ve hata ayıklama günlük dosyası kullanan diğer fonksiyonları kullanabilmek için datas/config.php dosyasında günlük dosyasının yolunu belirtmelisiniz:

/**
 * Hata ayıklama günlüğünün kaydedileceği dizin.
 * Bu yol, yabancılar (örneğin HTTP üzerinden) tarafından erişilemez olmalıdır.
 * .htaccess ile koruyabilir veya yalnızca FTP üzerinden erişilebilen bir dizin belirleyebilirsiniz.
 */
$cfg['debug_logpath'] = '/tmp';

Günlük dosya adındaki tarih bölümü, her hata ayıklama işlemi için benzersiz bir günlük dosyası oluşturur.

İncelemek istediğiniz değişkenleri kaydetmek için cot_watch() fonksiyonunu şu şekilde kullanabilirsiniz:

cot_watch($my_var, $my_array, $obj->id, $arr['item']);

cot_watch() fonksiyonunu istediğiniz kadar çağırabilirsiniz. Tek yaptığı, değişkenleri ve bulunduğu konumu günlük dosyasına kaydetmektir. Komut dosyası çalıştırıldıktan sonra günlük dosyasını açarak değişkenlerin nasıl değiştiğini görebilirsiniz.

#4. Geriden İzleme (Backtrace)

Backtrace, belirli bir noktaya kadar çağrılan tüm dosyaları ve fonksiyonları (argümanlarıyla birlikte) listeleyen bir işlemdir.

En yaygın senaryo, sitenizin bir SQL hatası nedeniyle çökmesi ve bu sorgunun nerede yer aldığını bilmemenizdir. Kendinize yardımcı olmak için hata ayıklama çıktısını datas/config.php dosyanızda etkinleştirin:

/**
 * Kritik hatalar için hata ayıklama bilgilerini görüntüleme seçeneği.
 * Yeni bir şeyler denerken TRUE olarak ayarlayın.
 * Canlı sitelerde FALSE olarak ayarlayın.
 */
$cfg['debug_mode'] = TRUE;

SQL hatası gerçekleştiğinde, aşağıdaki gibi bir hata ayıklama çıktısı görünecektir. Bu, hatanın kaynağını bulmanıza yardımcı olacaktır:

Gerekli olduğunda hata ayıklama komut dosyalarınızda geriden izleme çıktısı almak için cot_backtrace() fonksiyonunu kullanabilirsiniz:

cot_backtrace(); // çağrı yığınını göster

cot_backtrace() gibi bazı fonksiyonlar, varsayılan olarak TRUE olan $clear_screen parametresine sahiptir. FALSE olarak geçerseniz, ekranı temizlemeden mevcut sayfa içeriğinde çıktıyı gösterecektir.

cot_backtrace(FALSE); // ekranı boş bırakma

#5. Değişken Dökümleri ve Kontrol Noktaları

İzleme ve geriden izleme bazen yeterli olmayabilir, özellikle değişkenleri daha derinlemesine analiz etmek istiyorsanız. Bu durumda, değişken dökümleri ve kontrol noktaları işinize yarayacaktır.

cot_vardump();

cot_vardump() çağrıldığı anda mevcut olan tüm global değişkenlerin yapısını ve içeriğini yazdırır. Genellikle büyük bir HTML sayfası üretir, bu nedenle ilgilendiğiniz değişkeni bulmak için Ctrl+F kullanmanız gerekebilir.

Bir fonksiyon içinde hata ayıklıyorsanız ve yerel değişkenleri görmek istiyorsanız, COT_VARDUMP_LOCALS makrosunu kullanabilirsiniz:

function foo($arg1, $arg2)
{
    global $cfg;
    $my_var = 'test';
    
    eval(COT_VARDUMP_LOCALS);
}

Bu, $arg1, $arg2, $cfg ve $my_var değişkenlerinin içeriğini yazdıracaktır.

Bazen değişkenleri ekrana yazdırmak yerine bir günlük dosyasına kaydetmek daha faydalıdır. Profesyonel hata ayıklama araçlarında "kesme noktaları" (breakpoints) kullanılır; programınızı adım adım çalıştırıp belirli noktalarda durarak değişkenleri analiz edebilirsiniz. Ancak PHP yalnız başına çalıştırıldığında bu şekilde durdurup devam ettirme işlemi yapamayız, bu yüzden "kontrol noktaları" kullanırız.

Kontrol noktası (checkpoint) karşılandığında, betik günlüğe geçerli konumunu ve değişkenlerin değerlerini kaydeder. Birden fazla kontrol noktası belirleyerek betiğinizin her adımda ne yaptığını ayrıntılı bir şekilde görebilirsiniz.

#5.1. Gerçek Bir Cotonti Eklentisini Hata Ayıklama

Bir kullanıcının seviyesini puanlarına göre senkronize eden bir fonksiyonu hata ayıklamak istiyorum. Bunun için COT_CHECKPOINT_LOCAL makrosunu şu şekilde kullanıyorum:

function qa_sync_scorelvl($user_id = NULL)
{
    global $usr, $qa_levels, $db_users;
    if (is_null($user_id))
    {
        $user_id = $usr['id'];
        $urr['score'] = $usr['score'];
        $urr['scorelvl'] = $usr['scorelvl'];
    }
    else
    {
        $urr = qa_get_score($user_id);
    }
    
    // 
    eval(COT_CHECKPOINT_LOCALS); // yerel değişkenleri dök
    // 
    
    if (isset($qa_levels[$urr['scorelvl'] + 1])
        && $urr['score'] >= $qa_levels[$urr['scorelvl'] + 1]['minscore'])
    {
        // ...
    }
    // ...
    return $urr['scorelvl'];
}

Sonra web tarayıcımda bazı işlemler yapıyorum ve hata ayıklama günlüğünü açıyorum. Şu tür bir çıktı görüyorum:

/home/trustmaster/htdocs/answers/plugins/answers/inc/points.php, 184:
user_id = 2
usr = Array
(
    [id] => 1
...

    [score] => 4
    [scorelvl] => 6
    [logpoint] => 1241583533
    [isadmin] => 1
    [auth_write] => 1
    [auth_read] => 1
)

qa_levels = Array
(
    [0] => Array
        (
            [name] => None
            [minscore] => -1000
        )

    [1] => Array
        (
            [name] => One
            [minscore] => 0
        )

    [2] => Array
        (
            [name] => Two
            [minscore] => 50
        )
... ETC.
)

db_users = cot_users
urr = Array
(
    [0] => 76
    [1] => 2
)

----------------

urr = Array kısmına bakıyorum ve indekslerin sayısal olduğunu görüyorum. Ancak bu fonksiyon, ilişkilendirilmiş anahtarlar bekliyor. Bu sorunu düzelttikten sonra fonksiyon sorunsuz çalışıyor.

#5.2. Global Değişkenleri Kontrol Noktası ile Hata Ayıklama

Bir eklentinin global değişkenlerle çalışan bir kısmını hata ayıklamak için cot_checkpoint() fonksiyonunu kullanıyorum:

$qa_abuse = ($usr['id'] == 0 || $row['fp_posterid'] == $usr['id'] ? ''
     : cot_rc_link(cot_url('plug', 'e=modcp&m=report&post='.$row['fp_id']), $L['qa_report_abuse']);

// 
cot_checkpoint(); // global değişkenleri kaydet
// 

$qa_best = ($qa_question['q_state'] == QA_QUESTION_OPEN && $usr['id'] == $ft_firstposterid) ?
// ...

Günlük dosyası oldukça büyük olabilir çünkü her tam döküm yaklaşık 1 MB boyutundadır (çoğu web motoruna göre yine de küçüktür). Bu yüzden, ilgilendiğim değişkenleri bulmak için metin düzenleyicimde arama yapıyorum:

#6. Sonuç

Elbette, bu basit fonksiyonlar özel hata ayıklama araçları kadar kullanışlı olmayabilir (eğer nasıl kullanılacağını biliyorsanız). Ancak kodunuzu hata ayıklarken "echo 'Burada ne yanlış gidiyor?'" gibi şeyler eklemeyi düşündüyseniz, bu araçlar işinizi büyük ölçüde kolaylaştıracaktır.

Ve unutmayın, hata ayıklamak düşündüğünüzden çok daha eğlenceli olabilir! Sadece elinizde makineli tüfek yok, ama kod hatalarını yok etmek için bolca aracınız var!



1. tensh  2009-07-30 05:39
Thanks! It will help me much. :)
Yalnızca kayıtlı kullanıcılar yorum yapabilir