Page 1 sur 1

Exception : générer une erreur 404

Posté : 18 mars 2009, 10:06
par BaLiSTiK
Je voudrai savoir si il est possible de générer une erreur 404 en levant une exception personallisée.
Pour illustrer un peu plus, je code un site de questions réponses. Sur la page question, l objet question est crée avec deux parametre : id_question et url_question.
Dans ma classe, je retourne donc la question correspondante dans ma BD avec ses deux parametres.
Je me suis arrengé pour que si, l id et l url ne corresponde pas, ça me lève une exception. Mais pour des soucis de référencement, je désirerai que l exception leve une erreur 404.
try{
		//Recuperation de l ID passé en parametre dans l URL	
		$id_question 	= $_GET['num_quest'];
		$url_question 	= $_GET['url_quest']; 
		$oQuestion 	= new question($id_question,$url_question);
$oQuestion->_affichQuestion(); 		//Methode affichant la question dont l'ID et l URL est passé en paramettre (requete SQL)
		if(empty($oQuestion->m_aAffichQuestion['qid_question'])){
			throw new MyException('<div class="msg_err"><p>La question n\'existe pas ou a &eacute;t&eacute; &eacute;ffac&eacute;e.</p></div>');
		} //levé exception 404 ici demandé
	
/** suite du code **/
}catch(MyException $e){
		echo $e->getError();
	}
Et voila ma classe MyException
class MyException extends Exception {
    
    // Constructeur de la classe.
    public function __construct($msg) {
        parent :: __construct($msg);
    }
    
    // Pour le fun, on ajoute une méthode qui récupère l'heure de l'erreur.
    public function getTime() {
        return date('Y-m-d H:i:s');
    }
    
    // Méthode retournant un message d'erreur complet et formaté.
    public function getError() {

        // On retourne un message d'erreur complet pour nos besoins.
       // $return  = '<br />Une exception a &eacute;t&eacute; g&eacute;r&eacute;e :<br/>';
        $return .= '<strong>'.$this->getMessage().'</strong><br/>';
        //$return .= 'A la ligne : ' . $this->getLine() . '<br/>';
        //$return .= 'Dans le fichier : ' . $this->getFile() . '<br/>';
        //$return .= 'Il &eacute;tait : ' . $this->getTime();
        
        return $return;
    }
}
J ai pensé à créé une nouvelle classe MyException404 mais je ne sais pas quoi mettre dans ma méthode.
Merci :)

Posté : 18 mars 2009, 11:32
par Berzemus
le plus important est d'envoyer un code réponse 404.

Tu peux afficher tant que tu veux, si ta page renvoie un code de réponse 200 (ou 202, saiplu), les moteurs de recherche ne le verront pas comme une erreur, l'indexeront, et des visiteurs risqueraient d'y aboutir.

Posté : 18 mars 2009, 11:53
par BaLiSTiK
Quelquechose qui ressemblerai à ça donc :
	public function getError404() {
		header("Status : 404 Not Found");
		header('HTTP/1.0 404 Not Found'); 
	}
Pour information, je gère le 404 comme ceci dans mon htaccess :

Code : Tout sélectionner

ErrorDocument 404 /index.php?page=17

Posté : 18 mars 2009, 12:20
par Hywan
Hey :-),

2 solutions à envisager (voire plus, mais ce sont des variantes).
La première est que tu lances tes en-têtes (appel de la fonction header()) directement dans ton constructeur. Avantage : rapide. Inconvénient : tu ne peux pas manipuler l'exception (ce qui perd un peu de sens).
La seconde est de lancer les en-têtes dans getMessage() par exemple. Avantage : plus souple et plus de contrôle. Inconvénient : y en a pas.

Typiquement, tu aurais :
<?php

class Error404 extends Exception {

    public function getMessage ( ) {

        header('...');

        return parent::getMessage():
    }
}
Et tu l'utiliserais de cette façon :
<?php

try {

    // sumthin'
}
catch ( Error404 $e ) {

    $e->getMessage(); // send the header.
}
Pourquoi getMessage() ? Pour que toutes les exceptions aient un comportement similaire :-).

Posté : 18 mars 2009, 12:28
par BaLiSTiK
Ta solution semble tres bien mais ça me retourne cette erreur :

Code : Tout sélectionner

Fatal error: Cannot override final method Exception::getMessage()
ça empiete sur l autre class MyException

J ai essayé avec getError() au lieu de getMessage(). Le seul probleme est le header, (erreur de header classique ^^)

Posté : 18 mars 2009, 16:36
par Hywan
Mince, j'avais oublié que la méthode getMessage() est finalisée. Elle est écrite de cette façon :
class ... {

    final public function getMessage ( ... ) { ... }
}
Ce que ça implique, c'est qu'on ne peut pas la surcharger dans les enfants.

Ce que je fais en général, c'est que j'ai une méthode raiseError() qui permet de lever l'erreur, et elle appelle getMessage() etc. Mon code deviendrait alors :
<?php

class My extends Exception {

    public function raiseError ( ) {

        echo $this->getMessage() /* ... */;
    }
}

class Error404 extends My {

    public function raiseError ( ) {

        header('...');

        return parent::raiseError();
    }
}

Posté : 19 mars 2009, 15:05
par BaLiSTiK
La classe doit fonctionner nickel, mais dans mon cas au final, je peux pas utiliser le header car je leve l exception à l'interieur de mon <body>, et vu que j ai du echo avant...ça plante ^^.
Mais dans le cas ou j aurai à utiliser dans le <head>, je reprendrai le code.

Je vais donc laisser tel quel, avec mon exception normale.
Merci bien les gars :wink:

Posté : 19 mars 2009, 17:33
par Hywan
Et pourquoi ne pas utiliser des tampons de sortie (voir http://php.net/outcontrol) ?

Posté : 19 mars 2009, 18:38
par BaLiSTiK
Je ne maitrise pas du tout même si je l utilise dans deux cas sur mon site.