Frage zu der Globalität einer Classe

Bash, Shell, PHP, Python, Perl, CGI
twisterchen
Anbieter
Posts: 233
Joined: 2005-07-14 14:13

Frage zu der Globalität einer Classe

Post by twisterchen » 2006-12-16 17:19

Hallo

Nachdem ich mich nun mal mit PHP classen abgegeben habe von dem ich mich eigentlich immer gedruckt habe, habe ich folgendes problem zu dem ihr mir vielleicht netterweise dazu was erklähren könntet.

Beispiel:

Code: Select all

class database{
	var $host;
	var $database;
	var $user;
	var $password;
	var $port;

	function database($host,.......){
        }
        u.s.w
}
jetzt habe ich in einer anderen Datei auch funktionen die nicht zur classe gehören und inizialisiere die classe auch.

Code: Select all

$db=new database("mysql",$sql_host,$sql_db,$sql_user,$sql_pass);

function ssetcokieadmin($adminname,$adminpass) {
 global $db_admin;
 $adminname = htmlspecialchars($adminname);
 $adminpass = htmlspecialchars($adminpass);
 
 $db->query("SELECT * FROM $db_admin WHERE BINARY admin='$adminname'"); 
 $setinfo = $db->get_row(); 
 	
$adminn = $setinfo['admin'];
$adminp = $setinfo['pw'];   
$adminr = $setinfo['rang'];

$adminpass = md5($adminpass);  
   
if($adminn == "$adminname" && $adminp == "$adminpass"){
$info = base64_encode("$adminname:$adminpass:$adminr");
setcookie("webinterface","$info",time()+60000);
}
header("Location: ".https_pfad."/login.php");
}
jetzt wenn ich aber mein Script aufrufe bekomme ich einen Fehler:
Fatal error: Call to a member function query() on a non-object in /inc/function.php on line 425
Das sagt mir, dass er das opject query innerhalb einer function nicht kennt, wenn ich meine classe ausserhalb einer function aufrufe funktioniert alles wunderbar.
Hier habe ich wohl einen Denkfehler da ich dachte das classen (hab ich noch so im kopf ) immer Überglobal wären oder liege ich da flasch.

Muss ich jetzt die inizialisierung der classen in jeder funktion machen in der ich sie verwenden will.?

Könnt ihr mir da mal bitte meiner falschen Denkensweise auf die Sprünge helfen.

Vielen Dank schonmal

Gruss
Gerhard

twisterchen
Anbieter
Posts: 233
Joined: 2005-07-14 14:13

Re: Frage zu der Globalität einer Classe

Post by twisterchen » 2006-12-16 17:43

Ich glaube ich habe den Fehler selber gefunden mann sollte halt seine GLOBAL auch anschauen

Code: Select all

function ssetcokieadmin($adminname,$adminpass) {
 global $db_admin,$db; 
Ich denke mal das wars !! :cry:

immer diese kleinen sachen :roll:

twisterchen
Anbieter
Posts: 233
Joined: 2005-07-14 14:13

Re: Frage zu der Globalität einer Classe

Post by twisterchen » 2006-12-17 14:39

Hallo jetzt muss ich mich doch nochmal melden

Code: Select all

$db->query("SELECT * FROM $db_admin ORDER BY id ASC");
	while($row = $db->get_row()) {
		echo"<tr>
            <td><span class='schriftnormalrot'>$row[admin]</span></td>
            <td><span class='schriftnormalrot'>$row[rang]</span></td>
            <td><span class='schriftnormalrot'>$row[email]</span></td>
            <td><span class='schriftnormalrot'>";
		$db->query("SELECT * FROM $db_webface_berechtigung WHERE admin = '$row[admin]'");
		while($rowl = $db->get_row()) {
			echo "ID:$rowl[serverid] | ";
		}
		echo"</span></td>
            <td>";
		if($row['rang'] != "superadmin"){
			echo"<a href="".https_pfad."/index.php?funktion=adminhinzu&adminloeschdb=del&id=$row[id]&nameberechtigung=$row[admin]"><img src="".https_pfad."/img/delete.gif" border='0' alt='L&ouml;schen'></a>";
		}
		echo"</td><td>
       <a href="".https_pfad."/index.php?funktion=adminupdate&id=$row[id]&nameberechtigung=$row[admin]"><img src="".https_pfad."/img/neustart.gif" border='0' alt='Bearbeiten'></a>     
       </td>";

		echo"</tr>";
	}
Könnt ihr mir sagen warum ich innerhalb des while nicht nocheinmal eine abfrage machen kann bzw die abfrage macht er zwar aber dann hört er auf er gibt mir aus dem ersten while nur einen Datensatzaus

Sollte ich es nicht verständlich genung erklährt haben mich bitte bitte drauf aufmerksam machen.

Ich wusste es warum ich nicht mit classen arbeiten wollte :!: :roll:


Vielen Dank schonmal
Gruss

Gerhard

twisterchen
Anbieter
Posts: 233
Joined: 2005-07-14 14:13

Re: Frage zu der Globalität einer Classe

Post by twisterchen » 2006-12-17 14:53

Also ich hab herrausgefunden, dass wenn ich die classe ein 2 tes mal inizialisiere, dann funktioniert es wenn ich bei dem 2 ten while dann db2-> nehme.

Nur ist das wirklich die Lösung oder gibt es da auch noch eine andere Lösung ?


Vielen Dank

Gerhard

User avatar
Joe User
Project Manager
Project Manager
Posts: 11138
Joined: 2003-02-27 01:00
Location: Hamburg

Re: Frage zu der Globalität einer Classe

Post by Joe User » 2006-12-17 15:30

Sieh Dir mal phpBB2 an, dort wird Deine Variante genutzt...
PayPal.Me/JoeUserFreeBSD Remote Installation
Wings for LifeWings for Life World Run

„If there’s more than one possible outcome of a job or task, and one
of those outcomes will result in disaster or an undesirable consequence,
then somebody will do it that way.“ -- Edward Aloysius Murphy Jr.

static
Posts: 437
Joined: 2002-10-27 19:56
Location: Schweiz

Re: Frage zu der Globalität einer Classe

Post by static » 2006-12-17 15:42

Hi
ohne jetzt genau zu wissen, was du in dieser DB Klasse genau machst geh ich davon aus, dass du im Endeffekt (ohne Nutzung von Objekten) folgendes ausführst:

Code: Select all

$connection = mysql_connect($server, $user, $password);
mysql_select_db($db, $connection);

$result = mysql_query("SELECT * FROM $db_admin ORDER BY id ASC");

while($row = mysql_fetch_array($result)) {

	$result = mysql_query("SELECT * FROM $db_webface_berechtigung WHERE admin = '$row[admin]'");
	
	while ($row1 = mysql_fetch_array($result)) {

	}
}
Mit deinem 2. Aufruf der Methode query überschreibst du sehr wahrscheinlich dein Result Set aus dem 1. Aufruf. Beim nächsten Schleifendurchgang der 1. Schleife greifst du dann auf die Resultate der 2. Abfrage zu.

In dem du eine 2. Instanz erstellst, hast du 2 verschiedene Objekte mit 2 unabhängigen Result Sets, darum funktionierts dann.

Imho "richtig" müsstest du das mit 2 Klassen machen, einmal Database und einmal Query. In der Database Klasse regelst du Zugriff auf die Datenbank und in der Query Klasse, zugriff auf die Result Sets. Dann hättest du in deinem Beispiel 1 Database Objekt und 2 Query Objekte.

Das alles sind aber nur Vermutungen, ohne zu wissen was deine Database Klasse genau macht kann ich nur spekulieren :)

.static

twisterchen
Anbieter
Posts: 233
Joined: 2005-07-14 14:13

Re: Frage zu der Globalität einer Classe

Post by twisterchen » 2006-12-17 16:07

Hallo Joe User und static danke schonmal für eure Antworten

Also ich habe mir mal ein Paar Dateien von phpbb2 angeschaut und auch die classe von phpbb2 die ist auch etwas anders aufgebaut wie meine aber das ist ja so umfangreich an Dateien, dass ich mich hier erstaml voll einarbeiten müsste.
Hier ist halt jetzt die frage ob die das auch so machen mit mehrmaligem inizialisieren, kann ich mir aber nicht vorstellen.


@static

so wie dein Beispiel hatte ich es vorher nur halt dann im 2ten result dann $result2 bzw $row2
Ich will das ganze halt jetzt auf eine Classe umstellen.

Ich poste mal meine Classe aber bitte nicht lachen :!: :wink:

Code: Select all

<?php
class database{
	var $database_types="";
	var $db_connect="";
	var $db_close="";
	var $db_select_db="";
	var $db_query="";
	var $db_fetch_array="";
	var $db_num_rows="";
	var $host;
	var $database;
	var $user;
	var $password;
	var $port;
	var $database_type;
	var $dsn;
	var $sql;
	var $con; 
	var $con_string; 
	var $query_id; 
	var $errors; 
	var $error_count=0; 
	var $error_nr;
	var $error;
	function database($database_type,$host,$database,$user,$password,$port=false,$dsn=false){
		$database_type=strtolower($database_type);
		$this->host=$host;
		$this->database=$database;
		$this->user=$user;
		$this->password=$password;
		$this->port=$port;
		$this->dsn=$dsn;

		$this->database_types=array("mysql");

		if(in_array($database_type,$this->database_types)){
			$this->database_type=$database_type;
			$this->db_connect=$this->database_type."_connect";
			$this->db_close=$this->database_type."_close";
			$this->db_select_db=$this->database_type."_select_db";
			$this->db_query=$this->database_type."_query";
			$this->db_fetch_array=$this->database_type."_fetch_array";
			$this->db_num_rows=$this->database_type."_num_rows";


			return $this->connect();
		}else{
			$this->halt("Datenbank wird noch nicht Unterstützt");
			return false;
		}
	}
	function connect(){

		if($this->con==""){
			if($this->database_type=="mysql"){
				if(!$this->port){
					$this->con=call_user_func($this->db_connect,$this->host.":".$this->port,$this->user,$this->password);
				}
				else{
					$this->con=call_user_func($this->db_connect,$this->host,$this->user,$this->password);
				}
			}

			if(!$this->con){
				$this->halt("Keine Verbindung zur Datenbank möglich. Falsche Zugnangsdaten ?");
				return false;
			}else{
					if(!call_user_func($this->db_select_db,$this->database,$this->con)){
						$this->halt("Keine Verbindung zur Datenbank möglich. Falsche Zugnangsdaten ?");
						return false;
					}else{
						return true;
					}
			}
		}else{
			$this->halt("Verbindung zur Datenbank besteht bereits");
			return false;
		}
	}
	function disconnect(){
		if(@call_user_func($this->db_close,$this->con)){
			return true;
		}else{
			$this->halt("Nicht Verbunden");
			return false;
		}
	}
	function query($sql_statement){
		$this->sql=$sql_statement;
		if(!$this->query_id=call_user_func($this->db_query,$this->sql,$this->con)){
			$this->halt("Keine Verbindung zur Datenbank oder falsches Ouery");
		}else{
			if (!$this->query_id) {
				$this->halt("Falsches SQL Query");
				return false;
			}else{
				return true;

			}
		}
		return false;
	}
	function get_row(){
		
		$row=call_user_func($this->db_fetch_array,$this->query_id);
		return $row;
		
	}
	function count_rows(){
		$row_count=call_user_func($this->db_num_rows,$this->query_id);
		if($row_count>=0){
			return $row_count;
		}else{
			$this->halt("Kann keine Daten zaehlen bevor kein Query ausgeführt wurde.");
			return false;
		}
	}
	function halt($message){
			printf("<br>DB error: %sn", $message);
			//            if($this->error_nr!="" && $this->error!=""){
			//                printf("<br>MySQL Error: %s (%s)n",$this->error_nr,$this->error);
			//            }
			$description = mysql_error();
			$number = mysql_errno();
			$error = "nn";
			$error .= "MySQL Error: $number $description ".$this->error_nr." ".$this->error."n";
			$error .= 'Datum : '.date('D, F j, Y H:i:s')."n";
			$error .= 'IP : '.getenv('REMOTE_ADDR')."n";
			$error .= 'Browser : '.getenv('HTTP_USER_AGENT')."n";
			$error .= 'Referer : '.getenv('HTTP_REFERER')."n";
			$error .= 'PHP Version: '.PHP_VERSION."n";
			$error .= 'OS : '.PHP_OS."n";
			$error .= 'Server Name: '.getenv('SERVER_NAME')."n";
			$error .= 'Script Name: '.getenv('SCRIPT_NAME')."n";

			die ("<pre>$error</pre>Aktion angehalten");
	}
}

?>
Vielleicht könntet ihr mir auf bezug meiner Classe da einen anhaltspunkt geben damit ich das nicht mit zweimaligem inizialisierung machen müsste


Vielen Dank schonmal

Gruss
Gerhard

twisterchen
Anbieter
Posts: 233
Joined: 2005-07-14 14:13

Re: Frage zu der Globalität einer Classe

Post by twisterchen » 2006-12-17 17:22

Also ich habe jetzt mal die Classe von phpbb2 verwendet da funktioniert das wunderbar weil ich bei jeder abfrage mir ein eigenes result geben kann.

Code: Select all

$SQL1 = $phpbb->sql_query("SELECT * FROM $db_admin ORDER BY id ASC");
	while($row = $phpbb->sql_fetchrow($SQL1)) {
		echo"<tr>
            <td><span class='schriftnormalrot'>$row[admin]</span></td>
            <td><span class='schriftnormalrot'>$row[rang]</span></td>
            <td><span class='schriftnormalrot'>$row[email]</span></td>
            <td><span class='schriftnormalrot'>";
		$SQL2 = $phpbb->sql_query("SELECT * FROM $db_webface_berechtigung WHERE admin = '$row[admin]'");
		while($rowl = $phpbb->sql_fetchrow($SQL2)) {
			echo "ID:$rowl[serverid] | ";
		}
Nur ich will jetzt nicht einfach die classe von phpbb nehmen weils da funktioniert sonder ich möchte gern das auf meine classe übertragen damit ich das verstehe was ich da anders machen müsste

Ich denke hier wohl zu Binary oder ? wie mann so schön sagt

Könnte ihr mir mal meinem Binary denken etwas verändern ?

Gruss
Gerhard und danke schonmal :wink:

static
Posts: 437
Joined: 2002-10-27 19:56
Location: Schweiz

Re: Frage zu der Globalität einer Classe

Post by static » 2006-12-17 20:25

Wow, ähm ja, ich möchte mal sagen du hast das recht kompliziert gelöst 8O

Also wie gesagt du kannst entweder das Result Set oder die Resultate selbst an den Caller zurückgeben, zwischen mehreren Queries unterscheiden oder für jede Query ein Objekt erzeugen. Du kannst nicht ein und das selbe Objekt für 2 völlig unterschiedliche Queries verwenden und erwarten das die Resultate nicht durcheinander kommen.

1. Result Set zurückgeben:

Code: Select all

function query($sql_statement){ 
      $this->sql=$sql_statement; 
      if(!$this->query_id=call_user_func($this->db_query,$this->sql,$this->con)){ 
         $this->halt("Keine Verbindung zur Datenbank oder falsches Ouery"); 
      }else{ 
         if (!$this->query_id) { 
            $this->halt("Falsches SQL Query"); 
            return false; 
         }else{ 
            return true; 

         } 
      } 
      return false; 
   }
Anstatt hier nur true oder false zurückzugeben, das Resultat von call_user_func($this->db_query,$this->sql,$this->con) zurückschicken. Dann hast du im Hauptprogramm bspw. $SQL1 und $SQL2 wie bei deinem Beispiel aus dem phpbb. Natürlich müsstest du dann get_row() und count_rows() entsprechend anpassen, damit diese ein ResultSet erwarten und dieses verarbeiten.

Siehe db/mysql4.php von phpbb2:

Code: Select all

/* 	Zeile 100ff: 
		Alte Queries löschen	*/
		
		//
		// Remove any pre-existing queries
		//
		unset($this->query_result);

/*	Query ausführen */

/*	Zeile 144:
		Resultat der Query zurückgeben */
		
		return $this->query_result;
2. Resultate zurückgeben
Hier könntest du eine neue Methode schreiben, die dir die Resultate bspw. in ein Array schreibt und anschliessend dieses zurückgibt. D.h. du hättest dann in deinem Hauptprogramm bspw. $result1 und $result2 als Array mit den Resultaten.

3. Mehrere Queries verwalten
Du könntest jeder Query eine ID zuordnen und damit zwischen mehreren Aufrufen unterscheiden.

Einen Member $result = array(); einführen und bei jedem Aufruf der query Methode sowas wie

Code: Select all

$this->result[] = mysql_query($query, $connection);
return count($this->result);
Dann erhälst du mit $query = $db->query($sql); jeweils einen neuen Index, den du dann an Methoden wie get_row() oder count_rows() übergeben könntest, damit diese wissen auf welche Abfrage du dich beziehst.

4. Query Objekt
Wahrscheinlich würde ich es so, oder so ähnlich lösen (nur grober Aufbau):

Code: Select all

class Database {
	function Database($host, $user, $password, $database)	{
		// Zur DB verbinden
		return $DBHandle;
	}
}

class Query {
	function __construct($sql_statement, $database) {
		$this->SQL = $sql_statement
		$this->Database = $database;
	}
	
	function execute() {
		$this->Result = mysql_query($this->SQL, $this->Database);
	}
	
	function getRow() {
		return mysql_fetch_array($this->Result);
	}
}
Dein Code könnte dann bspw. so aussehen:

Code: Select all

$DB = new Database('localhost', 'luser', 'l33t', 'sampleDb');

$Query1 = new Query("SELECT * FROM $db_admin ORDER BY id ASC", $DB);
$Query1->execute();

while($result = $Query1->getRow()) {
	echo $result['sampleCol'];
	
	$Query2 = new Query("SELECT * FROM $db_webface_berechtigung WHERE admin = '$result[admin]'", $DB);
	$Query2->execute();
	
	while($result2 = Query2->getRow()) {
		echo $result2['serverid'];
	}
}
Das Ganze ist jetzt nur schnell aus dem Kopf hingeschrieben worden, da wird noch so einiges nicht passen, aber ich hoffe du verstehst was ich meine :)

Abgesehen davon sind wir eh schon ziemlich OffTopic, sind ja kein PHP Forum hier, wenn du noch Fragen hast kannst du mir auch eine PM schicken...

.static

twisterchen
Anbieter
Posts: 233
Joined: 2005-07-14 14:13

Re: Frage zu der Globalität einer Classe

Post by twisterchen » 2006-12-17 21:05

Hallo static

vielen dank erstaml für deine Antwort ja ich denke auch, ich werde mir das morgen mal zu gemühte führen, werde dir dann ein PN schicken sollte ich da nicht zurecht kommen.


Gruss
Gerhard

lucki2
Posts: 427
Joined: 2006-10-03 01:31

Re: Frage zu der Globalität einer Classe

Post by lucki2 » 2006-12-18 09:44

oder das resultset festhalten. $result = query(...);

Code: Select all

 $result = mysql_query($query,self::$connection);
        if( !$result || mysql_num_rows($result) < 0 ){
           throw new DatabaseException($query,$query);
        }
        if( mysql_num_rows($result) == 0 ){
          throw new DatabaseEmptyResult($query,$query);
        }

        $entity = Array();
        while($row = mysql_fetch_assoc($result)){
typischer Codesnippet. Mit "self::$connection" statisch(heißt: nur eine). [query noch checken]