NewbieContest

Programmation => Langages Web => Discussion démarrée par: Baelrog le 26 Août 2010 à 16:00:39



Titre: [PHP] Error handler
Posté par: Baelrog le 26 Août 2010 à 16:00:39
Salut à tous,

Après pas mal de googuelage et n'ayant rien trouvé d'utile, je viens voir si un maniaque de la gestion des erreurs aurait une réponse à mon problème.

Un petit exemple de mon soucis avec un bout de code stupide mais mettant bien les choses en valeurs:

<?php

$record = new stdClass();
$record->truc = 1;

eval('return $record->bidule == 1;');

?>

Dans cet exemple, on créé une stdClass, on défini un attribut nommé "truc", et dans un eval, on test un attribut "bidule" qui n'existe pas.
PHP dans sa grandeur et sa sagesse va donc tout naturellement me retourner une jolie notice m'indiquant le problème, et c'est la qu'intervient mon soucis.

Comment catcher cette notice ?

Avant de répondre, il faut tenir compte d'un paramètre. Je code sur un framework (Jelix pour ceux que ca intéresse) et je ne peux pas me permettre un "set_error_handler" vu que le framework le fait déjà a sa sauce.
J'ai trouvé un type ErrorException en natif sur php mais faut utiliser le set_error_handler, donc c'est mort.

Bref, j'ai besoin de savoir quand la notice est levée pour balancer une exception et faire un affichage des variables ayant générées le problème.

Si vous avez une idée, je suis preneur ! :)

(Merci d'avance aux futur coups de mains)



Titre: Re : [PHP] Error handler
Posté par: Nil le 26 Août 2010 à 16:06:00
En gros, tu veux lever un exception SI et seulement SI l'attribut X n'est pas définie dans ton objet? Est-ce que j'ai bien compris?


Titre: Re : [PHP] Error handler
Posté par: Baelrog le 26 Août 2010 à 16:24:20
En gros, oui. Je peux faire des test avec property_exists() sur l'objet, mais j'aimerais controler un peu mieux les possibles bug d'eval en général plutot que de me concentrer sur la résolution d'un cas particulier. D'où la gestion du notice.


Titre: Re : [PHP] Error handler
Posté par: Nil le 26 Août 2010 à 17:01:26
Je ne connais pas une solution spécifique à PHP parce que je ne suis pas un pro en PHP, mais voici quand même 2-3 points :

Problème
  • Ton truc de eval() ... c'est tout simplement horrible.  Même si tu étais capable de le faire fonctionner comme tu veux, essais pas ne pas recourir à ce genre de hack. Si tu montre ce bout de code à ta mère, elle ne sera pas fier de toi :)
  • Autre point moins important, les exceptions, c'est pour les traitements *exceptionnels*. Si tu t'attend à avoir cette erreur souvent, tu ne devrais pas lancer un exception, mais plutôt réorganiser ton code. Je ne peux pas vraiment t'aider davantage vu que je ne connais pas la structure de ton code, sorry.

Solutions
  • Tu pourrais te renseigner sur 'get_object_vars()' et ce genre de fonctions. La plupart des langages dynamiques offrent des fonctions/méthodes pratiques pour connaître le type des variables, les méthodes offertes par un objet, etc ... C'est probable que tu peux savoir que 'bidule' existe ou pas avec une de ces fonctions.
  • Tu pourrais te créer un attribut 'error' = true ou false, chaque fois que créé un objet stdClass. De cette façon, tu n'aurais qu'à regarder la valeur de 'error' et lancer ton exception selon la valeur. Mais je n'aime pas cette idée, la prochaine est meilleure.
  • Tu pourrais te créer une vrai classe au lieu d'utiliser ce genre de tableau associatif qu'est stdClass(). Dans ton constructeur, tu met '$this.error' à ce que tu veux, même concept que plus haut, mais tu n'as pas à initialiser toi-même l'attribut 'error' ... C'est important ce point, c'est le genre de détail qu'on oublie souvent. En plus, si ta classe évolue, ce sera beaucoup plus pratique d'avoir une vrai classe avec un vrai constructeur.

Voila, je crois que tu peux t'en sortir. Bonne chance.


Titre: Re : [PHP] Error handler
Posté par: Baelrog le 26 Août 2010 à 17:19:43
Pour eval: je suis d'accord. Le problème c'est que je bosse sur une appli assez complexe vu le dynamisme qu'elle requière et dans mon cas eval est la solution la plus simple sans passer X heures à coder un process similaire. Pour faire simple, je dev un logiciel de paie pour une société. Les commerciaux ont des primes en fonction de divers critères sur des info d'autres bases de données. et le tout doit être administrer par les gens de la compta qui bien sur, n'ont jamais vu une ligne de code de leur vie. Donc pour évaluer les critères de déclenchement de ces primes par rapport aux données extract des bases (voir meme certaines calculer à la volée), vu que je ne connais la condition logique qui va être tester à l'avance (et ne peux donc pas faire de bêtes "if" à la queue-leuleu), il faut que j'eval ce bazar.


Pour les exceptions, oui t'inquiètes :) En fait, l'application est stable (plus que prévu même :p), mais certains changement dans l'entreprise impliquent certaines refontes des modes de calcul à des endroits totalement imprévisible en fonction de la nature de ces modif. Mais j'ai codé cette appli en faisant converger les données nécessaires à certains endroits très localisés où du coup, les bug sont visibles directement. Et cet eval est le dernier bastions d'emmerdes que je souhaite faire tomber en posant un listener sur ses activités pour rapidement identifier les futurs sources de problèmes.


Titre: Re : [PHP] Error handler
Posté par: Harry41 le 27 Août 2010 à 02:44:40
Bonjour a vous deux !
Je suis d'accords avec Nil, il n'est jamais vraiment bon d'utiliser eval()...

Du coup, je vois 2 choix : faire un try catch dans ton eval() -> baaah, sale...
ou réfléchir un peux plus au problème.

Je pencherai plutôt sur la deuxième, ton problème peut se résoudre plus facilement et surtout plus sainement...
Si j'ai bien compris, en fonction d'un état ou d'un autre, tu va utiliser une valeur...

Du coup, pourquoi ne pas faire un truc du genre :
<?php

$record = new stdClass();
$record->rcdEtat = "monEtat";
$record->($record->rcdEtat) = "rcdValue";

du coup, on a $record->rcdEtat qui vaut le nom de l'état et $record->($record->rcdEtat) (ce qui reviens ici a faire $record->monEtat) vaut la valeur. Ainsi, 'aucune' chance de se planter.

du coup, au lieu de faire :
eval('if($record->rcdEtat == "etat1"){return $record->bidule == 1;}else if($record->rcdEtat == "etat2")[...]');

tu fais un switch sur $record->rcdEtat.  Mais tu peux aussi bien faire une fonction speciale dans ta classe qui fait ce que tu veux, car c'est elle qui semble avoir toutes les données, ce serait logique.

?>

Il faut savoir aussi que si tu cree une classe, autant y mettre les bons attributs de base et faire des getteurs setteurs appropries (soit un chacun si tu veux verif des trucs avant d'effectuer l'action, soit un getteur et un setteur global pour toutes les variables - voir plus bas).

La bonne programmation n'est pas en option ;)
Apres, je suis peut être a cote de la plaque niveau comprehension de ton besoin :D

PS: des "if" à la queue-leuleu seront toujours plus propres qu'un eval() :)

<?php
function get($key){
    return $this->$key;
}

function set($key, $value){
    return $this->$key = $value;
}
?>


Titre: Re : [PHP] Error handler
Posté par: Baelrog le 27 Août 2010 à 09:35:41
En fait, pour résumer, mon problème consiste à tracker les notice/warning sorties de l'eval. Ces erreurs ne sont pas catchable.

Mon exemple n'était qu'un bout de code générant ce problème et nullement mon utilisation actuel de l'eval.
Pour aller un poil plus loin dans l'explication de mon programme, voici un algo sommaire:


L'utilisateur saisie une liste de critère (champs en base + opérateur + valeur). Cette liste de critère est structuré par une condition logique (ex: 1 AND (2 OR 3), les chiffres nommant les numéros des critères ).

Ma classe prend un record de base de donnée, pour former avec ma condition logique précédente une truc du genre:
$record->champs1 operateur1 valeur1 AND ($record->champs2 operateur2 valeur2 OR $record->champs3 operateur3 valeur3)

Et la dessus j'applique un eval pour savoir si les critères au sein de la condition logique sont bon ou pas pour le record que je récupère.

Mais dans mon cas j'ai bêtement réglé le soucis en faisant un check dans l'objet pour savoir si les attribut à tester existent bien ou pas.


Par contre, mon besoin premier, est d'avoir un tracking efficace sur cette eval moisie vu que les notice/warning sont importante ici, et qu'un try catch ne permet pas de les chopper.


Titre: Re : [PHP] Error handler
Posté par: kony le 27 Août 2010 à 12:46:35
Salut regarde du coté du design pattern "interpreter", je l'ai jamais mis en œuvre mais ca peut correspondent a ce que tu cherches pour te passer de eval si j'ai bien compris ce dont tu parles ^^


Titre: Re : [PHP] Error handler
Posté par: Iansus le 27 Août 2010 à 17:30:53
Si le problème est simplement de cacher les notices quand elles apparaissent pour faire des tests sur des variables qui n'existent pas forcément, un simle @ devant l'instruction devrait suffire.

<? eval('return @($record->bidule == 1);'); ?>


Titre: Re : [PHP] Error handler
Posté par: Nil le 27 Août 2010 à 20:33:11
Pardonne mon ignorance Iansus, mais qu'est que l'opérateur @ est supposé faire? C'est quoi sa ou ses fonctions en PHP? Ça se cherche un peu mal sur google ^^


Titre: Re : [PHP] Error handler
Posté par: awe le 27 Août 2010 à 21:00:23
@Nil: @ ça cache les erreurs éventuelles (en tout cas ça le permet, peut être que ça fait plus).

sinon, j'ai pas très bien compris ce qui était demandé, mais tu peux créer un error/exception handler, puis restaurer l'ancien avec
restore_error_handler, par exemple, il me semble.

Et pour cacher les erreurs, ça doit se faire directement avec error_reporting();

J'espère ne pas être trop à côté de la plaque, ce qui est bien possible  :rolleyes:


Titre: Re : Re : [PHP] Error handler
Posté par: Iansus le 28 Août 2010 à 13:20:20
Pardonne mon ignorance Iansus, mais qu'est que l'opérateur @ est supposé faire? C'est quoi sa ou ses fonctions en PHP? Ça se cherche un peu mal sur google ^^

Désolé :p En effet, comme l'a dit awe, @ sert à masquer les notices engendrées par la fonction qu'elle précède.
Si on prend le code suivant :
Code:
<?php

$array 
= array("login" => "Iansus""pass" => "youdliketoknow");
if(empty(
$array["email"])) echo "Your email adress is missing !";

?>

La tu obtiendras une belle notice "email : no such index on line ...".
Si tu remplaces la condition par : if(@empty($array["email"])) echo "Your email adress is missing !";, plus de notice qui apparaît. Dasn ton cas, ça peut être utile, mais en général, c'est comme l'alcool, à consommer avec modération. Ça fait joli, mais c'est con de se ballader avec une notice qui pourra se transformer en Fatal error dans une version future de PHP.


Titre: Re : Re : Re : [PHP] Error handler
Posté par: ThunderLord le 28 Août 2010 à 14:41:45
Code:
<?php

$array 
= array("login" => "Iansus""pass" => "youdliketoknow");
if(empty(
$array["email"])) echo "Your email adress is missing !";

?>

La tu obtiendras une belle notice "email : no such index on line ...".

Ou pas... Justement empty() tout comme isset() à quelques différences près, peut être utilisé pour tester la présence d'un élement dans un tableau, donc le code au dessus ne va certainement pas provoquer une notice, mais bien afficher "Your email adress is missing" (en passant, address prend deux d en anglais)


Titre: Re : [PHP] Error handler
Posté par: Baelrog le 31 Août 2010 à 16:07:31
@awe: Non tu n'es pas à coté de la plaque :) le restore_error_handler peut en effet etre une option, mais comme je l'ai dis au début, le framework a bien dérouté la gestion des erreur pour avoir quelque chose de bien foutu (point de vue très subjectif :) ), et vu qu'il peut y avoir des erreurs ailleurs, je n'ai pas envi de feinter la gestion actuelle pour me rendre compte dans 6 mois qu'il y avait un coin où ca crashait mais que l'appli ne pouvais me le dire :). Je cherche donc une gestion de l'erreur très précise géographiquement dans le code. Si le try/catch fonctionnait sur les notice, j'aurais pas ce genre de problème :(.

Et pour les aficionados du @ en php, pour ma part je suis totalement contre. Autant fermer les yeux, on verra pas que l'appli crash :) Le framework se charge entre autre de récupérer ces notices pour les logger ou les envoyer par mails tout en les masquant (sur un serveur en prod). Je suis plutôt un partisan du 0 erreur et le @ n'aide pas à atteindre cet objectif.


Titre: Re : [PHP] Error handler
Posté par: Harry41 le 01 Septembre 2010 à 02:15:22
hum... de meme, je ne suis pas pour l'@.
Mais vraiment, il faut oublier eval...
tu peux y arriver sans, et c'est comme un challenge, apres, tu te sens fort ;)

Je pense qu'une fonction dans ton objet retournerai bien ta solution.
il faut bien sur utiliser qu'une seule variable pour l'operateur, et pour le champs et la valeur

$record->operateur = "+";
$record->key = "nomDuChamp";
$record->value = "valeurDuChamp";

et dans la fonction de ta classe, tu fais ce qu'il faut faire...
Si tu as besoins de plusieurs variable (plusieurs operateurs, etc)
tu peux faire un tableau d'objets.

voila, bon courage a toi


Titre: Re : Re : [PHP] Error handler
Posté par: Nil le 01 Septembre 2010 à 02:20:59
hum... de meme, je ne suis pas pour l'@.
Mais vraiment, il faut oublier eval...
tu peux y arriver sans, et c'est comme un challenge, apres, tu te sens fort ;)

Respect pour Harry41++;


Titre: Re : [PHP] Error handler
Posté par: Baelrog le 02 Septembre 2010 à 13:27:50
Après pour l'utilisation de l'eval à proprement parler, je reste assez mitigé quant à sa nuisance au sein d'un programme quelconque.

Ca n'est qu'une façon de différer une exécution de code. Les instructions données a une eval ne sont pas moins pourrit en étant exécuter en dehors de cette dernière.


Une raison concrète justifiant cet apriori vis-à-vis de cette fonction ?


Titre: Re : [PHP] Error handler
Posté par: Spl3en le 03 Septembre 2010 à 01:43:08
Eval, en plus d'être un trou béant du côté performance (http://www.php.net/manual/fr/function.call-user-func.php#61553), est une fonction à manipuler avec des pincettes. Dans le cadre d'une application sécurisée, si l'utilisateur arrive à mettre la main sur cet eval et lui faire exécuter ce qu'il veut, il devient libre de détourner le serveur à sa guise.

Bref, c'est une fonction à utiliser dans un contexte particulier, et dans un cas très particulier. Sinon, à éviter.

Pour rester dans le cadre du topic, je suis d'avis avec Harry41... Je n'ai pas vraiment d'autres solutions qui me viennent par la tête, du moins rien de "tout fait"...


Titre: Re : [PHP] Error handler
Posté par: Baelrog le 06 Septembre 2010 à 09:04:13
Okai c'est bien ce que je me disais pour l'eval :)

Sinon pour mon bout de code, j'ai donc finalement mis des check dans mes class en amont pour éviter que ma notice pointe le bout de son nez. De toute façon je n'ai presque plus de bug à cet endroit (et encore je dis "presque" en supposant un autre problème mais rien n'est moins sur :) ), et je me contenterais donc des mails d'alertes.

Merci d'avoir participé à cette **orthographe !** !

@+