MVC Kullanırken PHP'de Hataları İşleme


12

Son zamanlarda Codeigniter'ı çok kullanıyorum, ancak sinirlerime bulaşan bir şey hataları işlemek ve kullanıcıya göstermek. Hiç dağınık olmadan hataları idare hiç iyi olmamıştı. Temel kaygım kullanıcıya hata döndürürken.

İşlevlerden 0 veya 1 döndürmek ve daha sonra hataları işlemek için if / else kullanmak yerine istisnalar kullanmak ve istisnalar atmak / yakalamak istisnalar kullanmak iyi bir uygulamadır. Böylece kullanıcıyı sorun hakkında bilgilendirmeyi kolaylaştırır.

İstisnalardan uzaklaşmaya meyilliyim. Birkaç yıl önce üniversitedeki Java öğretmenim "üretim kodunda istisnalar kullanılmamalı, hata ayıklama için daha fazla" dedi. Yalan söylediğini anlıyorum.

Ancak, bir örnek, bir veritabanına bir kullanıcı ekleyen kod var. İşlem sırasında bir veritabanı sorunu, yinelenen bir giriş, bir sunucu sorunu, vb. Gibi 1'den fazla şey yanlış gidebilir. Kayıt sırasında bir sorun meydana geldiğinde, kullanıcının bilmesi gerekir.

Bir MVC çerçevesi kullandığımı akılda tutarak PHP'deki hataları işlemenin en iyi yolu nedir?

Yanıtlar:


14

İşlevlerden 0 veya 1 döndürmek ve daha sonra hataları işlemek için if / else kullanmak yerine istisnalar kullanmak ve istisnalar atmak / yakalamak istisnalar kullanmak iyi bir uygulamadır. Böylece kullanıcıyı sorun hakkında bilgilendirmeyi kolaylaştırır.

Hayır hayır hayır!

İstisnaları ve hataları karıştırmayın. İstisnalar, olağanüstü. Hatalar değildir. Bir kullanıcıdan bir miktar ürün girmesini istediğinizde ve kullanıcı "merhaba" olarak girdiğinde, bu bir hatadır. Bu bir istisna değildir: kullanıcıdan geçersiz bir girdi görmekte istisnai bir şey yoktur. Girişleri doğrularken olduğu gibi, istisnai durumlarda neden istisnalar kullanmıyorsunuz? Diğer insanlar bunu zaten açıkladı ve giriş doğrulaması için geçerli bir alternatif gösterdi.

Bu aynı zamanda kullanıcı umurumda değil demektir istisnalar ve özel durumları gösteren düşmanca ve tehlikelidir . Örneğin, bir SQL sorgusunun yürütülmesi sırasında bir istisna genellikle sorgunun kendisini gösterir. Böyle bir mesajı herkese göstermek için risk almak istediğinizden emin misiniz?

bir veritabanı sorunu, yinelenen bir giriş, bir sunucu sorunu, vb. gibi 1'den fazla şey yanlış gidebilir. Kayıt sırasında bir sorun meydana geldiğinde, kullanıcının bilmesi gerekir.

Yanlış. Bir kullanıcı olarak, gerçekten umurumda değil vs ben veritabanı sorunları, yinelenen girdileri, bilmek gerekmez senin sorunlarına. Ne yapmak bilmesi gerek ben zaten mevcut bir kullanıcı adı girilen olmasıdır. Daha önce de belirtildiği gibi, benden yanlış bir girdi bir istisna değil bir hatayı tetiklemelidir.

Bu hatalar nasıl çıktılanır? Bu koşullara bağlıdır. Zaten kullanılmış bir kullanıcı adı için, formu göndermeden önce, kullanıcı adının zaten kullanıldığını söyleyerek, kullanıcı adının yanında görünen küçük bir kırmızı bayrak görmek istiyorum. JavaScript olmadan, aynı bayrak gönderildikten sonra görünmelidir.

AJAX etkin bir hata örneği

Diğer hatalar için, hata içeren bir tam sayfa gösterir veya kullanıcıyı bir şeyin yanlış gittiğini bildirmek için başka bir yol seçersiniz (örneğin, görüntülenecek bir mesaj, ardından sayfanın üst kısmında kaybolur). Bu durumda soru, programlamadan çok kullanıcı deneyimi ile ilgilidir .

Programcılar açısından, hatanın türüne bağlı olarak, hatayı farklı şekillerde yayacaksınız. Örneğin, önceden alınmış bir kullanıcı adı durumunda, AJAX isteği, aşağıdakileri http://example.com/?ajax=1&user-exists=Johngösteren bir JSON nesnesi döndürür:

  • Kullanıcının zaten var olduğunu,
  • Kullanıcıya gösterilecek hata mesajı.

İkinci nokta önemlidir: hem formu JavaScript devre dışıyken gönderirken hem de JavaScript etkin olarak yinelenen bir kullanıcı adı yazarken aynı iletinin göründüğünden emin olmak istersiniz. Hata iletisi metnini sunucu tarafı kaynak kodunda ve JavaScript'te çoğaltmak istemezsiniz!

Bu aslında Stack Exhange web siteleri tarafından kullanılan tekniktir. Örneğin, kendi yanıtımı yükseltmeye çalışırsam, AJAX yanıtı görüntülenecek hatayı içerir:

{"Success":false,"Warning":false,"NewScore":0,"Message":"You can't vote for your own post.",
"Refresh":false}

Ayrıca başka bir yaklaşım seçebilir ve form doldurulmadan önce HTML sayfasındaki hataları önceden ayarlayabilirsiniz. Artıları: Hata mesajını AJAX yanıtında göndermek zorunda değilsiniz. Eksileri: erişilebilirlik ne olacak? CSS olmadan sayfaya göz atmayı deneyin; olası tüm hataların göründüğünü göreceksiniz.


Cevabı takdir ediyorum. Tam da bununla mücadele ediyorum. Hataları bildirme konusunda, özellikle kullanıcı deneyimi açısından herhangi bir kaynağınız var mı?
James Jeffery

Dediğim gibi, bu gerçekten hataya bağlıdır ve hataların kullanıcıya bildirilmesi kullanıcı arayüzüne güçlü bir şekilde bağlıdır. Ayrıca hataları rapor etmenin iki ana yolunu da vurguladım: sıkı entegrasyon (girişe yakın bir değeri yanlış olan AJAX etkin kırmızı bayrak) ve daha ciddi durumlar için daha az dostu olan tam sayfa hataları. Bu, sorunuza cevap vermiyor mu?
Arseni Mourzenko

2
+1 daha teknik bir sorun değil, bir kullanıcı deneyimi sorunu olduğu için
Charles Sprayberry

2
Saçmalık, MainMa. Sadece saçmalık. Hata kodları 80s ve 90s'dir. İstisnalar, yanlış girdi (örneğin ValidationException) gibi özel durumları ele almanın çok daha temiz bir yoludur. Kullanıcıya her istisnayı göstermek zorunda değilsiniz. Size daha iyi cevaplar gördüm.
Falcon

2
Ve bilmiyor olmanız durumunda: Kullanıcıya hangi istisnaları sunmak ve hangilerinin sunulmasını istemediğinizi kontrol edebilirsiniz. Yani bu gerçekten bir tartışma değil.
Falcon

13

İşlevlerden 0 veya 1 döndürmek ve daha sonra hataları işlemek için if / else kullanmak yerine istisnalar kullanmak ve istisnalar atmak / yakalamak istisnalar kullanmak iyi bir uygulamadır. Böylece kullanıcıyı sorun hakkında bilgilendirmeyi kolaylaştırır.

Evet evet evet!

Temiz kod almak istiyorsanız, neredeyse sadece istisnalar kullanmalısınız ve hata kodlarını kullanmaktan çekinmeyin. Hata kodları anlamsızdır. Neredeyse her zaman fazla bilgi elde etmeyen bazı sayısal sabitlere bağlanırlar. Kodunuzu okunamaz hale getirebilir ve hata ile birlikte veri yayılmasını zorlaştıracaktır.

Ancak istisnalar sınıflardır ve istediğiniz bilgileri içerebilir. Böylece kullanıcı bir sayı alanı için 'abc' gibi yanlış bir girdi girmiştir. Bir hata kodu ile çok fazla köpürmeden bu bilgiyi hatanın işleyicisine yayamazsınız. İstisnaların ücretsiz sağladığı bir şey. Ayrıca, istisnalar, yine de zarif bir şekilde başarısız olma yoluna sahipken, işlevlerde ve yöntemlerde anlamlı dönüş değerlerine sahip olmanızı sağlar. Daha da iyisi, İstisnalar, onları ele almak istediğiniz yere yayılır! Bir veya iki katman üzerindeki bir işleyiciye anlamlı veriler içeren bir hata kodu yaymak için ihtiyaç duyacağınız spagetti kodu miktarını düşünün.

Ayrıca, istisnalar hata kodlarından çok daha semantik olarak ifade edilir. Hata kodları, istisna işlemenin temiz koda yol açtığı spagetti koduna yol açar.

Ayrıca, durum kodlarını kontrol etmeyi unutmak kolaydır. Java gibi dillerde, istisnaları (örneğin, C # 'ın kaçırdığı bir şey) ele almak zorunda kalırsınız.

Bir MVC çerçevesi kullandığımı akılda tutarak PHP'deki hataları işlemenin en iyi yolu nedir?

İstisnaları kullanın ve denetleyicilerinizde kullanın.


Sana çok katılıyorum !! İstisnalar diğer dillerde olduğu gibi PHP kadar zorlanmış olmasa da, birçok kişinin onları rahatsız ettiğini bilmek iyidir ...
David Conde

6
Çoğu durumda hata kodlarının oldukça anlamsız olduğunu kabul ediyorum. Ancak, nilly willy istisnalar atmak son derece kötü! İstisnalar yalnızca istisnai durumlar için ayrılmalıdır. İstisnalar öngörülemeyen program akışına neden olur, kodun izlenmesini zorlaştırabilir (ve dolayısıyla sürdürür) ve PHP'de IF / THEN / ELSE ile karşılaştırıldığında oldukça önemli bir performans cezası taşırlar. Başarıyı doğru, başarısızlığı yanlış döndürme yöntemlerini tercih etme eğilimindeyim ve sadece bir şey istisnası yanlış gidiyor.
GordonM

6

Bu kullanışlı küçük sınıfı düşünün:

class FunkyFile {               

    private $path;
    private $contents = null;

    public function __construct($path) { 
        $this->setPath($path); 
    }

    private function setPath($path) {
        if( !is_file($path) || !is_readable($path) ) 
            throw new \InvalidArgumentException("Hm, that's not a valid file!");

        $this->path = realpath($path);
        return $this; 
    }

    public function getContents() {
        if( is_null($this->contents) ) {
            $this->contents = @file_get_contents( $this->path );
            if($this->contents === false) 
                throw new \Exception("Hm, I can't read the file, for some reason!");                                 
        }

        return $this->contents;            
    }

}

Bu, istisnaların mükemmel şekilde kullanılmasıdır. Gönderen FunkyFile'sperspektiften yolu ya geçersiz veya eğer situtation giderilmesi için yapılabilecek hiçbir şey yoktur file_get_contentsbaşarısız olur. Gerçekten olağanüstü bir durum;)

Ancak, kullanıcınızın kodunuzun herhangi bir yerinde yanlış bir dosya yoluna rastladığınızı bilmesi gereken herhangi bir değer var mı? Örneğin:

class Welcome extends Controller {

    public function index() {

        /**
         * Ah, let's show user this file she asked for
         */                 
        try {
            $file = new File("HelloWorld.txt");
            $contents = $file->getContents();   
            echo $contents;
        } catch(\Exception $e) {
            log($e->getMessage());

            echo "Sorry, I'm having a bad day!"; 
        }                           
    }        
}

İnsanlara kötü bir gün geçirdiğinizi söylemek dışında seçenekleriniz şunlardır:

  1. Geri çekil

    Bilgiyi almanın başka bir yolu var mı? Yukarıdaki basit örneğimde, bu olası görünmüyor, ancak bir master / slave veritabanı şemasını düşünün. Efendi cevap vermemiş olabilir ama belki sadece köle hala oradadır (ya da tam tersi).

  2. Kullanıcının hatası mı?

    Kullanıcı hatalı girdi gönderdi mi? Ona anlat. Bir hata mesajını havlayabilir veya doğru yolda yazabilmesi için bu hata mesajına bir formla eşlik edebilirsiniz.

  3. Bu senin hatan mı?

    Ve sizin tarafınızdan, yani kullanıcı olmayan herhangi bir şey , yani yanlış bir dosya yolu yazmanızdan sunucunuzda ters giden bir şeye kadar değişir. Kesin olarak, 503 HTTP hatası zamanı , ayrıca hizmet kullanılamıyor. CI bir show_404()işlevi vardır, kolayca inşa edebilirsiniz show_503().

Tavsiye kelimesi, haydut istisnaları dikkate almalısınız. CodeIgniter dağınık bir kod parçasıdır ve bir istisnanın ne zaman açılacağını asla bilemezsiniz. Benzer şekilde, kendi istisnalarınızı unutabilirsiniz ve en güvenli seçenek bir catch all istisna işleyicisini uygulamaktır. PHP'de bunu set_exception_handler ile yapabilirsiniz :

function FunkyExceptionHandler($exception) {
    if(ENVIRONMENT == "production") {
        log($e->getMessage());
        show_503();
    } else {
        echo "Uncaught exception: " , $exception->getMessage(), "\n";
    }   
}

set_exception_handler("FunkyExceptionHandler");

Ayrıca set_error_handler aracılığıyla hileli hataları da halledebilirsiniz . İstisnalarla aynı işleyiciyi yazabilir veya alternatif olarak tüm hataları dönüştürebilir ErrorExceptionve istisna işleyicinizin bunlarla ilgilenmesine izin verebilirsiniz:

function FunkyErrorHandler($errno, $errstr, $errfile, $errline) {
    // will be caught by FunkyExceptionHandler if not handled
    throw new ErrorException($errstr, 0, $errno, $errfile, $errline);
}

set_error_handler("FunkyErrorHandler");

Bu gerçekten bilgilendirici, şerefe!
James
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.