Ben algılamak ve PHP ile MySQL Uyarılar ele miyim?

9 Cevap php

Ben UNIQUE olarak işadı sütunu tanımlayan bir MySQL tablo ile uğraşıyorum. Biri veritabanında zaten bir işadı kullanarak veritabanına yeni İşi kaydetmek çalışırsa, MySQL bir uyarı atar.

Benim PHP komut dosyası, sadece bir hata gibi, bu uyarıyı algılar ve uygun şekilde onunla baş edebilmek istiyorum. İdeal Ben bunu işlemek için kod şube böylece atmış MySQL uyarı ne tür bilmek istiyorum.

Bu mümkün mü? Değilse MySQL bu yeteneği yok, çünkü o, PHP bu yeteneği, ya da her ikisi de yok?

Şimdiden teşekkürler.

KN

9 Cevap

Uyarılar PHP "bayraklı" olması için doğal olarak bu sorunun kapsamı dışında tabii ki mysql / mysqli sürücü, değişiklik gerektirecektir. Bunun yerine temelde uyarıları için veritabanı üzerinde yaptığınız her sorgu denetlemek zorunda gidiyoruz:

$warningCountResult = mysql_query("SELECT @@warning_count");
if ($warningCountResult) {
    $warningCount = mysql_fetch_row($warningCountResult );
    if ($warningCount[0] > 0) {
        //Have warnings
        $warningDetailResult = mysql_query("SHOW WARNINGS");
        if ($warningDetailResult ) {
            while ($warning = mysql_fetch_assoc(warningDetailResult) {
                //Process it
            }
        }
    }//Else no warnings
}

Açıkçası bu en-kitle uygulamak iğrenç pahalı olacak, bu yüzden ne zaman ve nasıl uyarılar ortaya çıkabilir (onları ortadan kaldırmak için refactor size yol açabilir) dikkatle düşünmek gerekebilir.

Başvuru için, MySQL SHOW WARNINGS

edit

* Tabii ki, size yürütme başına bir sorgu kaydetmek istiyorsunuz SELECT @ @ warning_count, için ilk sorgu sakınabileceğini, ama bilgiçlik bütünlüğü için dahildir. *

Önce turn warnings off böylece ziyaretçilerin MySQL hataları görmüyorum gerekir. Sana mysql_query() çağırdığınızda İkincisi, bunu false döndürdü görmek için kontrol etmelisiniz. Öyle olsaydı, çağrı mysql_errno() neyin yanlış gittiğini öğrenmek için. Numarası üzerinde hata kodları döndü maç this page.

Bu aradığınız hata numarasıdır gibi görünüyor:

Hata: 1169 sqlstate: 23000 (ER_DUP_UNIQUE)

Mesaj: tablo '% s' için, çünkü benzersiz kısıtlaması, yazamıyor

UNIQUE sınırlamasıyla ihlal eden bir MySQL WARNING değil, bir hata verir. Ben gün boyu hataları tespit biliyorum, ama ben bunlar oluştuğunda uyarılar hakkında bilmek istiyorum. Ben bir INSERT deyim çünkü UNIQUE sınırlamasıyla başarısız olan bir hata olarak ele alınması gerektiğini düşünüyorum, ancak MySQL mysqli_errno tarafından yakalandı olmayan bir uyarı olarak geri dönüyor ()

ini_set('mysql.trace_mode', 1)

aradığınız şey olabilir.

PHP hataları sonra bir özel PHP hata işleyicisi ile ele alınabilir, ama aynı zamanda sadece genellikle bir günlük dosyası (php yapılandırma bağlıdır) oturum olarak php hataları gösterir kapatabilirsiniz.

Eğer kullandığınız ne (varsa) çerçevesinde bağlı, ben jobName kendinizi kontrol edin ve formu için doğrulamaları kalanı ile kullanıcıya doğru bilgi oluşturmak için bir sorgu yapmanızı öneririm.

Jobnames sayısına bağlı olarak, formu içeren görünümüne isimleri göndermek ve alınır kullanımını anlatmak için javascript kullanabilirsiniz.

Bu sizin için bir anlam ifade etmiyorsa, o da şu görüşümü özetlemek gerekirse: dont program ve / veya kullanıcı yasadışı şeyler yapmaya çalışın ve bunu yaptıklarında hataları yakalamak ve sonra işlemek için tasarım. Bu hataları yapmamak için, sistem tasarımı, imho, çok daha iyidir. Gerçek hatalar hataları tutmak :)

Ben şimdi sizin durumunuzda geçerli olmaz gerçekleştirmek errno işlevleri hakkında şeyler kaldırmak Güncelleme ...

UPDATE tablolar için dikkatli olmak MySQL tek şey: mysqli_affected_rows() sıfır WHERE deyimi eşleşen bile satırları döndürmek, ancak {[(3)] } fıkra aslında veri değerleri değişmedi. Bir sıfır bazı hata meydana geldiği anlamına geliyordu varsayarak, bir güncellemeden sonra hataları denetlemek için değer döndürmek kullanılan programcı - bu davranış keresinde baktım bir sistemde bir hata neden çünkü ben sadece bu söz. Sadece kullanıcı güncelleme düğmesini tıklamadan önce varolan herhangi bir değeri değişmedi anlamına geliyordu.

Her zaman yeni birtimestampdeğer atanacak masanızdaki bir update_time sütun gibi bir şey var sürece ben, mysqli_affected_rows() ya bu uyarıları bulmak için dayanıyordu olamaz kullanarak sanırım güncellendi. Geçici çözümün bu tür olsa biraz kludgey görünüyor.

Hiçbir mysqli deyimi hata kullanarak Benzersiz anahtar ihlallerini algılayabilir. Mysqli deyimi hata 1062 döndürür, o ER_DUP_ENTRY olduğunu. Sen hata 1062 için bakmak ve uygun bir hata mesajı yazdırabilirsiniz. Ayrıca hata mesajının bir parçası olarak sütun (işadı) yazdırmak istiyorsanız, o zaman deyim hata dizesini ayrıştırmak gerekir.

  if($stmt = $mysqli->prepare($sql)){
    		$stmt->bind_param("sss",
            $name,
    		$identKey,
            $domain);


    		$stmt->execute();
    		if($mysqli->affected_rows != 1)  {
                        //This will return errorno 1062
                trigger_error('mysql error >> '.$stmt->errno .'::' .$stmt->error, E_USER_ERROR);
    			exit(1);
    		}
    		$stmt->close();
    	} else {

    		trigger_error('mysql error >> '. $mysqli->errno.'::'.$mysqli->error,E_USER_ERROR);
    	}

Bu uyarıları almak mümkündür ve mysqli'nin ile daha verimli bir şekilde mysql ile daha.

İşte kod üzerinde önerilmektedir manuel page özelliği mysqli-> warning_count için php.net üzerinde:

$mysqli->query($query);

if ($mysqli->warning_count) {
    if ($result = $mysqli->query("SHOW WARNINGS")) {
        $row = $result->fetch_row();
        printf("%s (%d): %s\n", $row[0], $row[1], $row[2]);
        $result->close();
    }
}

Bastırmak uyarıları Not: Genellikle, bu önemli bir şey eksik olabilir bu yana görüntülenen uyarıları önlemek için iyi bir fikir değildir. Kesinlikle nedense uyarılar gizlemek gerekiyorsa, ifadenin önünde bir @ işareti koyarak bireysel bazda yapabilirsiniz. Bu şekilde tüm uyarı raporlamayı kapatmak zorunda değilsiniz ve belirli bir örneğine sınırlayabilir.

Örnek:

 // this suppresses warnings that might result if there is no field titled "field" in the result
 $field_value = @mysql_result($result, 0, "field");