FREEWARE: db Klasse für MySQL mit Fehler-LOG!

Original geschrieben von _voodoo
Mal so ne Frage: Warum die Fehler in einer Textdatei und nicht in die DB?

hehe, angenommen die DB kracht zusammen, oder die db-table wird zerschossen.. oder das db-PW wird geändert! wie erfahre ich dass denn? :)

keep it simple!
 
Original geschrieben von Ben Ben
@pxl: Da braucht man mich nicht zufrieden stellen ;) Das war nur ein Vorschlag, da ich es bei meiner DB-Klasse so realisiert habe.

Ich nehme dies auch als n Vorschlag gern an und werde so eine alternative beim nächsten update berücksichtigen!
 
is doch ok so! nicht jeder hat eine DB, man muss nichts einrichten. Und später sollten eh keine Fehler mehr da sein, da ist die Performance doch eh egal *g*
Schön, dass man mich heute noch zum Schmunzeln bringen kann. Wenn man keine Datenbank hat, wozu braucht man dann eine Datenbankklasse? :)

ich muss sagen, dass mir das ganz gut gefällt! Leider kann ich die Klasse erst bei meinem nächsten Projekt benutzen, da ich momentan eine andere habe. Ich müsste dann 1.000 SQL-Abfragen ändern
Ich habe mir die vorgestellte Klasse zwar noch nicht angeschaut, aber Du könntest mit Deiner bereits vorhandenen Klasse die neue Klasse erweitern (extends). Dann müsstest Du nur Anpassungen an Deiner alten Klasse vornehmen und könntest dennoch die neuen Funktionalitäten nutzen.

snuu
 
snuu hat gesagt.:
Schön, dass man mich heute noch zum Schmunzeln bringen kann. Wenn man keine Datenbank hat, wozu braucht man dann eine Datenbankklasse? :)

aaaaaaaaaaaaaaaaaahh! Wie blöd muss man eigentlich sein!? :eek: *schäm* *weglauf*

snuu hat gesagt.:
Ich habe mir die vorgestellte Klasse zwar noch nicht angeschaut, aber Du könntest mit Deiner bereits vorhandenen Klasse die neue Klasse erweitern (extends). Dann müsstest Du nur Anpassungen an Deiner alten Klasse vornehmen und könntest dennoch die neuen Funktionalitäten nutzen.

snuu

hm, stimmt eigentlich.... Aber leider kann ich noch nicht so gut zw. fast gar nicht mit Klassen umgehen (außer benutzen das geht wohl *g*)
 
Original geschrieben von snuu
Ich habe mir die vorgestellte Klasse zwar noch nicht angeschaut, aber Du könntest mit Deiner bereits vorhandenen Klasse die neue Klasse erweitern (extends). Dann müsstest Du nur Anpassungen an Deiner alten Klasse vornehmen und könntest dennoch die neuen Funktionalitäten nutzen.

snuu

Danke für den Tip, allerdings muss die quasi "abstrakte" klasse bereits allen sipmlen Anforderungen gerecht werden, um sie mit reinem Gewissen einfach mit "extend" erweitern zu können :) Deshalb gibts vorerst nur n Update. Extends kommen später :)

wenn man in Richtung PHP5 schaut, dann gibts noch viele, viele Möglichkeiten, diese klasse zu erweitern (xml, webservices etc.)
 
Habe mir die Klasse immer noch nicht angeschaut, aber die Struktur Deiner Klasse ist eigentlich egal - erweitern kann man sie trotzdem. In der neuen Klasse wird dann einfach auf die Methoden Deiner Klasse zugegriffen. Die neue Klasse ist also eine Art "Mantel" um die Deinige.

snuu
 
Hab auch noch was anzumerken:

Code:
/////////////////////////
db::tableExists()
/////////////////////

for ($i = 0; $i < mysql_num_rows($result); $i++) {
        	if (mysql_tablename($result, $i)==$tableName_str) {
				mysql_free_result($result);
				return true;
			}
		}

ist eine sehr langsame Implementierung. Es gibt schnellere Möglichkeiten zu testen ob eine Tabelle existiert:

unter mysql :
show tables like 'newsentrys';
 
Original geschrieben von Christian Fein
Es gibt schnellere Möglichkeiten zu testen ob eine Tabelle existiert:

unter mysql :
show tables like 'newsentrys';

ui! danke für deine Anmerkung, Christian! so ein Manual liest man nicht unbedingt als Abendlektüre sondern eher dann, wenn man ein Problem zu lösen hat. ;)
Da war ich wohl bei der Methode db::tableExists() mir zu sicher, dass es nicht anders geht. :)

muss mir den Thread mal ausdrucken, sonst habe ich zuhause wieder kein Plan ^^. bin @home offline :(((

Gruß
 
UPDATE auf 2.1!

Habe nun die Methoden zum Optimieren aller Tabellen und überprüfen, ob eine Tabelle besteht zunächst rausgenommen, da diese Aufgaben mit newQuery() ebenfalls zu bewältigen sind.

Die Fehlerbehandlung hat nun 3 Stufen:
- redirect auf home-index +log
- dezente Fehlermeldung + log
- Komplette Fehlermeldung + log
zu konfigurieren über die zwei bool-Variablen der Klasse.

Demnächst gibt es eine Erweiterungsklasse für besondere Abfragen, wie:
table exists, optimize db usw.

viel Spass!

hier der gesamte Quelcode:
PHP:
<?php
/**
* db
* 
* # Description #
* this simple db class makes your scripts able to access easily your MySQL database
*
* Features:
* 1. easy Methods like newEntry(), getEntry() and updateEntry() to manipulate database records
* 2. results are associative arrays and are simple to handle
* 3. method newQuery() allowes you do any personalized query to your database
* 4. secure errorhandling with switchable debug-mode and errorlog with two log-files
* 
* @package simple database handling
* @author R.Zotin <rusty@zotin.com>
* @copyright Copyright (c) 2004
* @version 2.1 engl.
* @access public
*/

class db 
{
	
#### START EDIT YOUR DATABASE-VARIABLES HERE ######################################

	// CONFIGURATION-VARIABLE: contains DB-server name (host)
	var $db_server 	= "localhost"; 	
	// CONFIGURATION-VARIABLE: contains DB-name
	var $db_name	= "test";		
	// CONFIGURATION-VARIABLE: contains DB-user name
	var $db_usr 	= "root"; 		
	// CONFIGURATION-VARIABLE: contains DB-password
	var $db_pwd		= ""; 			
	
	// CONFIGURATION-VARIABLE: contains name of directory to logfiles ex.: "logs" (set htaccess-password to it!)
	var $log_dir	= "logs";					// 
	// CONFIGURATION-VARIABLE: contains the name of the logfile to catch all DB-Errors 		(usefull to DEBUG)
	var $log_errors = "dbClass_errors.log";		// 
	// CONFIGURATION-VARIABLE: contains the name of the logfile to catch the last DB-Error	(usefull to DEBUG)
	var $log_lasterr= "dbClass_lasterror.log";	// 
	// CONFIGURATION-VARIABLE: contains URL to your homeindex for redirection if debug-mode ist set to FALSE
	var $home_url	= "http://localhost";		// 
	// CONFIGURATION-VARIABLE: to switch debug-mode (on|off) TRUE or FALSE
	var $debug		= TRUE;						// 
	// CONFIGURATION-VARIABLE: (on|off) TRUE or FALSE, secure output of errors in case of FALSE
	var $show_errors= TRUE;

#### STOP EDIT YOUR DATABASE-VARIABLES HERE! #####################################

####################################################################################
#### Do NOT EDIT anything after this line! #########################################
####################################################################################

	var $table;												// contains default database tablename
	var $link;												// contains link to database
	var $num_rows;											// contains number of affected rows since last query
	var $insert_id;											// contains an index (auto_increment) since last new entry
	var $ERR_PREFIX = "dbClass.inc.php tried: db::";		// contains prefix for the error messages
	
	/**
	 * db::db()
	 * # Description: #
	 * This is the constructor of the db class. You should set the default tablename here for the first access.
	 * @param string $table_str
	 * @access public
	 * @return 
	 **/
	function db($table_str = "") // Kommentar
	{
		$this->table = $table_str;
		$this->link = mysql_pconnect($this->db_server, $this->db_usr, $this->db_pwd) or
			die("<html><body>Sorry, our database seemes to be busy.\n
			Please, try to acces our site later (or just wait about 10 seconds for javascript-autorefresh).\n<script language=\"JavaScript\">window.setTimeout(\"window.location.reload()\", 10000);</script></body></html>");
		mysql_select_db($this->db_name, $this->link) or
			die($this->errorlog("Database ".$this->db_name." could not be found"));
	}
	
	/**
	 * db::errorlog()
	 * # Description: #
	 * Intern private class method to store all SQL-Errors with timestamp and scriptname in a logfile.
	 * @param string $error_string 
	 * @access protected
	 * @return string
	 **/
	function errorlog($error_string)
	{
		if (!is_dir($this->log_dir)) mkdir ($this->log_dir, 0774);
		$stamp="File: ".$_SERVER['PHP_SELF']." Time: ".date("Y-m-d H:i:s")." ERROR: ";
		$fp	= @fopen($this->log_dir.'/'.$this->log_errors,"a");
		fputs($fp, $stamp.$error_string);
		fclose($fp);
		$fp	= @fopen($this->log_dir.'/'.$this->log_lasterr,"w");
		fputs($fp, $stamp.$error_string);
		fclose($fp);
		if ($this->debug){
			if ($this->show_errors) {
		    	$returnstring='<font color="red">'.$error_string.'</font>';
			} else {
				$returnstring="Database <a href=\"{$this->log_dir}/{$this->log_lasterr}\">error</a> appeared. Apologies. Webmasters should take a look in their <a href=\"{$this->log_dir}/{$this->log_errors}\">logs</a>! [secure database handling by <a href=\"http://www.zotin.com/resources\" target=\"_blank\">www.zotin.com/resources</a> &copy;2004]";    
			}
			
		} else {
			$returnstring='<meta http-equiv="refresh" content="2; URL='.$this->home_url.'">';
		}
		return $returnstring;
	}
	
	/**
	 * db::newQuery()
	 * # Description: #
	 * Execute any MySQL query with this method. It will simply return the result provided your query was successful.
	 * @param string $query
	 * @param string $err_prefix
	 * @access public
	 * @result returns result provided your query was successful 
	 **/
	function newQuery($query,$err_prefix)
	{
		$result = mysql_query($query, $this->link) or
			die( $this->errorlog($err_prefix."\n - MySQL-Query failed: ".$query."\n - ".mysql_error()."\n"));
		$this->num_rows		=	@mysql_num_rows($result);
		$this->insert_id	=	@mysql_insert_id();
		return $result;
	}
	
	/**
	 * db::getEntry()
	 * # Description: #
	 * This method returns an multidimensional array with records wich fit to your WHERE clause.
	 * @param array $select_array
	 * @param string $where_str
	 * @param string $order_str
	 * @access public
	 * @return array multidimensional associative array
	 **/
	function getEntry( $select_array,  $where_str,  $order_str)
	{
		$err_prefix = $this->ERR_PREFIX."getEntry(".var_export($select_array,TRUE).",".$where_str." ".$order_str.")";
		$query = "SELECT ".implode(",", $select_array).
				" FROM ".$this->table.
				" WHERE $where_str $order_str";
		$result = $this->newQuery($query,$err_prefix);
		$entry = array();
		for ($i = 0; $i < $this->num_rows; $i++)
		{
			$entry[] = mysql_fetch_array($result);
		}
		return $entry;
	}

	/**
	 * db::newEntry()
	 * # Description: #
	 * Create new records by using this method. You will need an associativ array withsome default values.
	 * @param array $insert_assocArray
	 * @return integer returns the auto_increment index value of the new record, provides that it is set in the database table.
	 **/
	function newEntry($insert_assocArray)
	{
		$err_prefix = $this->ERR_PREFIX."newEntry(".var_export($insert_assocArray,TRUE).")";
		$insertKeys=array();
		$insertValues=array();
		while (list ($feld, $wert) = each ($insert_assocArray)) 
		{
			array_push($insertKeys,$feld);
			array_push($insertValues,$wert);
		}
		$query = "INSERT INTO ".$this->table." (".implode(",", $insertKeys).")".
				" VALUES ('".implode("','", $insertValues)."')";
		$result = $this->newQuery($query,$err_prefix);
		// RETURN INDEX of LAST INSERT
		return $this->insert_id;
	}

	/**
	 * db::updateEntry()
	 * # Description: #
	 * Update any value you want in records wich fit to your WHERE clause.
	 * @param array $update_assocArray
	 * @param string $where_str
	 * @return integer returns count of updated recordlines
	 **/
	function updateEntry($update_assocArray,$where_str)
	{
		$err_prefix = $this->ERR_PREFIX."updateEntry(".var_export($update_assocArray, TRUE).",".$where_str.")";
		$query = "UPDATE ".$this->table." SET ";
		foreach($update_assocArray as $key => $value)
		{
			$query.= $key."='".$value."'";
			if (next($update_assocArray)) {
			    $query.=", ";
			}
		}
		$query.= " WHERE $where_str";
		$result = $this->newQuery($query,$err_prefix);
		// 	OPTIONAL: count updated lines
			$entries = $this->num_rows;
			return $entries;
	}

	/**
	 * db::deleteEntry()
	 * # Description: #
	 * Easily delete records which fit to your searchcondition. Optional $where_str can contain the LIMIT condition.
	 * @param string $where_str
	 * @return integer returns count of deleted lines
	 **/
	function deleteEntry($where_str)
	{
		$err_prefix = $this->ERR_PREFIX."deleteEntry(".$whereStr.")";
		$query = "DELETE FROM ".$this->table.
				" WHERE $where_str";
		$result = $this->newQuery($query,$err_prefix);
		// 	OPTIONAL: get number of deleted lines
			$entries = $this->num_rows;
			return $entries;
	}

	/**
	 * db::entryExists()
	 * # Description: #
	 * Here you can prove if the record with certain condition already exists.
	 * @param string $where_str
	 * @return boolean returns TRUE if queried entry already exist and FALSE it it's not.
	 **/
	function entryExists($where_str)
	{
		$err_prefix = $this->ERR_PREFIX."entryExists(".$where_str.")";
		$query = "SELECT *".
				" FROM ".$this->table.
				" WHERE $where_str LIMIT 1";
		if ($result = $this->newQuery($query,$err_prefix)) 
		{
			$entry = mysql_fetch_array($result);
			mysql_free_result($result);
			if (empty($entry)) return false;
			return true; 
		} else return false;
	}
}
?>
 
Nun bin ich mal dazu gekommen grob drüber den Code zu fliegen.
Was mich am meisten stört, ist, dass die Anmeldeinformationen hart in der Klasse gesetzt werden. Von einer Klasse erwarte ich Wiederverwendbarkeit in unterschiedlichen Projekten, ohne die Klasse ändern zu müssen. Selbst das nachträgliche Setzen über $objekt->db_server ist nicht möglich, weil im Konstruktor gleich eine Abfrage abgesetzt wird.
Für mich gehört das Setzen der Anmeldeinformationen in den Konstruktor der Klasse. Den Rest habe ich mir noch nicht so genau angeschaut.

snuu
 
Zurück