Beste,
Ik heb de stap gezet.
Ik heb zonet mijn eerste klasse geschreven,
nu zou ik graag weten wat er beter aan kan (niet zozeer functionaliteit, maar het OOP programeren)
<?php
// Language Part
define(_errorocured,"De actie kon niet tot een succesvol einde gebracht woden vanwege de volgende reden(en)");
define(_toshort,"is te kort");
define(_tolong,"is te lang");
define(_min,", deze moet minimaal");
define(_max,", deze kan maar");
define(_char,"karakters bevatten.");
define(_numeric,"moet numeriek zijn");
define(_notemail,"is geen geldig email adres");
define(_founddb,"werd alreeds gebruikt, probeer een andere.");
define(_entertwicesame,"Je moet 2 maal dezelfde waarde ingeven voor");
define(_char,"karakters bevatten.");
define(_wait,"Je moet nog");
define(_beforenextaction,"alvorens je deze actie kan herhalen (flood protectie).");
//Class part
class error_handler{
var $error_array = array();
function add_error($error){//Add error to array, will be used in check_error, but can also be used 'manually'
$this->error_array[] = $error;
}
function check_error($value,$field_name,$minlength=0,$maxlength=0,$type=0,$extra_data=0){
if($minlength && $minlength > strlen($value)){//If minlength is set, check if value is not to short
$this->add_error($field_name." "._toshort._min." ".$minlength." "._char);
}
elseif($maxlength && $maxlength < strlen($value)){//If maxlengt is set, check if value is not to long
$this->add_error($field_name." "._tolong._max." ".$maxlength." "._char);
}
if($type){
if($type == 'numeric' && !is_numeric($value)){//Check if value = numeric
$this->add_error($field_name." "._notnumeric);
}
elseif($type == 'email' && (!eregi("^[0-9a-z]([-_.]?[0-9a-z])*@[0-9a-z]([-.]?[0-9a-z])*\\.[a-z]{2,4}$",$value) || strlen($value) == 0)){//Check if it is a valid email
$this->add_error($field_name." "._notemail);
}
elseif($type == 'unique' && $extra_data){//Test if a value is unique (could be for a username)
$query = query("SELECT * FROM ".$extra_data['table']." WHERE UPPER(".$extra_data['field'].") = UPPER('".$value."')");//Use your own query function here
if(num_rows($query)){//Same for num_rows
$this->add_error($field_name." "._founddb);
}
}
elseif($type == 'same' && $extra_data){//Check if two values are the same (email, password check)
if($value != $extra_data['value2']){
$this->add_error(_entertwicesame." ".$field_name);
}
}
}
}
function flood_protection($sec){
if(isset($_SESSION['wait']) && $_SESSION['wait'] > time()){
$this->add_error(_wait." ".($_SESSION['wait']-time())." "._beforenextaction);
}
elseif(!$this->check_errors()){//If they were no errors, so proces completed, add the session
$_SESSION['wait'] = $sec + time();
}
}
function check_errors(){//Check if the array contains any errors
if($this->error_array){
return true;
}
else{
return false;
}
}
function report_errors(){//Show report errors
$i=1;
if($this->check_errors()){//If array contains errors
$output = _errorocured."<br>\n";
foreach ($this->error_array as $value){
$output .= $i++.". ".$value."<br>\n";
}
}
return $output;//Return str.
}
}
//Exemple
if(isset($_POST['submit'])){
$error = new error_handler;
$error->check_error($_POST['username'],_username,4,20,'unique',array('table'=>'members','field'=>'username'));
$error->check_error($_POST['password'],_password,6,20,'same',array('value2'=>$_POST['password_repeat']));
$error->check_error($_POST['email'],_email,0,100,'email');
$error->flood_protection(60);
if($error->check_errors()){
echo $error->report_errors();
}
else{
$query = "...";
}
}
else{
//form
}
?>
<?php
// Language Part
define(_errorocured,"De actie kon niet tot een succesvol einde gebracht woden vanwege de volgende reden(en)");
if($type=='numeric'&&!is_numeric($value)){//Check if value = numeric
$this->add_error($field_name." "._notnumeric);
}
elseif($type=='email'&&(!eregi("^[0-9a-z]([-_.]?[0-9a-z])*@[0-9a-z]([-.]?[0-9a-z])*\\.[a-z]{2,4}$",$value)||strlen($value)==0)){//Check if it is a valid email
$this->add_error($field_name." "._notemail);
}
elseif($type=='unique'&&$extra_data){//Test if a value is unique (could be for a username)
$query= query("SELECT * FROM ".$extra_data['table']." WHERE UPPER(".$extra_data['field'].") = UPPER('".$value."')");//Use your own query function here
if(num_rows($query)){//Same for num_rows
$this->add_error($field_name." "._founddb);
}
}
elseif($type=='same'&&$extra_data){//Check if two values are the same (email, password check)
Ik zou geen constanten (buiten je class) definieren voor foutmeldingen.
Voor het toevoegen van errors hoef je niet per se een aparte methode te gebruiken. Je kunt ook zoiets doen: $this->error_array[] = "Je error";
In plaats van een if, elseif, ..., else statement in check_error() zou je ook een switch-statement kunnen gebruiken.
flood_protection hoort niet echt in een class die form-inhoud controleert (separation of concerns). Moet iemand ook een minuut wachten om een fout te herstellen bji wijze van straf?
check_errors zou je kunnen vereenvoudigen tot:
return sizeof($this->error_array)
niet leeg => fouten.
1e punt: defines in hoofdletters
2e punt: ik zou die flood_protection bovenaan zetten en dan je errors controleren
2.1: gebruik altijd een hoofdletter voor een classs.
3e punt: ik zou een constructor toevoegen en die wat uigebreid maken:
Ik zou geen constanten (buiten je class) definieren voor foutmeldingen.
Binnen dus ?
Citaat:
Voor het toevoegen van errors hoef je niet per se een aparte methode te gebruiken. Je kunt ook zoiets doen: $this->error_array[] = "Je error";
Ik heb daar een extra functie voor gemaakt om handmatige errors toe tevoegen.
dus $error->add_error('handmatige error 1'), stond ook in commentaar
Citaat:
Moet iemand ook een minuut wachten om een fout te herstellen bji wijze van straf?
Totaal niet Zou wel grappig zijn ,
Flood protection wordt als laatste opgeroepen, en als er geen fouten gevonden zijn, dus actie voltooid, maakt hij de sessie aan.
Van zodra er een fout is gevonden mag ie het direct opnieuw proberen (stond ook in opmerkingen ).
@ stijn
Citaat:
2e punt: ik zou die flood_protection bovenaan zetten en dan je errors controleren
Ik geloof dat je bedoelt om het eerst aan te roepen ...
Maar dan kan je niet zien of er al errors zijn gemaakt of niet.
Dan kom je in een situatie terecht waar als iemand een fout mag, het een minuut later maar opnieuw mag proberen, niet echt de bedoeling
Nog opmerkingen ?
Heb ik $this-> enz. goed gebruikt ?
Hoeft alleen als je het als een soort 'sessie' wilt gebruiken hé ? Dat de waarde onthouden blijft ..
Documentatie binnen het script kan veel beter. Ook moet je aangeven of je php4 of php5 gebruikt. Wanneer je php5 gebruikt in deze class staan er nog wat foutjes in zoals bijvoorbeeld:
Het grootste verschil tussen php4 en php5 op vlak van OO is encapsulatie (var is vervangen door public, protected en private, en deze kan je ook voor methodes gebruiken) en de constructor. Verder zijn er een hoop andere dingen aangepast betreffende magic methodes en nog wat andere zaken, maar encapsulatie en de constructor zijn de voornaamste.
maar ook als soort sessie, ik set $this->error_array om dat de error_array bij de volgende keer dat ik ze aanroep nog zou bestaan.
is niet waar , je moet dan met de functies __sleep en __wakeup werken in je class om data van je class op te slaan. Hier pas ik ff de functies toe op jou class:
<?php
class Error_handler
{
function __sleep()
{
//je returnt altijd een array met de var names die jij bewaard wilt
return array("error_array");
}
function __wakeup() {}
}
$obj = new Error_handler();
$_SESSION['object_slaapt'] = serialize( $obj );
//op pagina 2
$we_gaan_verder_met_onze_vorige_object = unserialize( $_SESSION['object_slaap'] );
$we_gaan_verder_met_onze_vorige_object->check_error(...);
?>
<?php
class Error_handler
{
function __sleep()
{
//je returnt altijd een array met de var names die jij bewaard wilt
de sleep zorgt ervoor dat je data van je variablen kan bewaren. Bijvoorbeeld je controleert ze op pagina 1 en je wilt die errors nog op pagina 2 behouden dan is __sleep en __wakeup daarvoor gemaakt.
OO in PHP4 en PHP5 verschilt veel. maar als je iets wilt private maken in een PHP4 class zet je er een '_'-teken voor de naam
nee!
Je kunt iets misschien virtueel private maken, door te zeggen tegen de end-user alles met _ voor kan je best niet aanroepen, maar echt private is het niet hoor. Je kan het ZONDER 1 probleem van buiten de klasse aanroepen.
Meer info over dat serializeren vind je hier: http://www.site...amp;id=439
kijk ook bij de comments, daar staan een hoop interessante reacties tussen.