# Benutzerverwaltung Website mit PHP und MySQL



## eee (25. Januar 2012)

Hallo,

ich betreibe ein kleines Online-Museum. Als neues Feature sollen angemeldete Benutzer kurze Kommentare zu den Ausstellungsstücken schreiben können. Der ein oder andere vertrauenswürdige Benutzer soll auch Mod Rechte erhalten, um z.B. Spam oder unerlaubte Werbung zu löschen. Als Betreiber möchte mir selbst Admin Rechte vergeben. Ich habe mir bereits Gedanken gemacht, wie ich mein Problem der Rechteverwaltung lösen könnte. Allerdings kann ich nicht beurteilen, ob mein Lösungsweg ein guter ist:


```
/* MySQL - siehe Spalte benutzer_status*/

create table benutzer
(
benutzer_id int unsigned not null auto_increment primary key,
benutzer_name char(20) not null unique,
passwort char(40) not null,
email char(40) not null unique,
benutzer_status tinyint unsigned not null, /* 1 = Benutzer, 2 = Mod, 3 = Admin */
registrierung_datum datetime not null
) engine=InnoDB default character set UTF8 collate utf8_general_ci;


// PHP - Login Abfrage nach Variablenprüfung
$abfrage = "select benutzer_id, benutzer_name, benutzer_status from benutzer where benutzername  = '$benutzername' and passwort = sha1('$passwort')";
$ergebnis = $db->query($abfrage);
$zeilen = $ergebnis->num_rows;

if ($zeilen > 0) {
	$benutzer = $ergebnis->fetch_assoc();
	$_SESSION['benutzer'] = array($benutzer['benutzer_id'], $benutzer['benutzer_name'], $benutzer['benutzer_status'])
}

if (isset($_SESSION['benutzer'])) {
	// Mitglied
	if ($_SESSION['benutzer'][2] == 2) // 2 für Mod
		// Mod
	}
}
```

Was ist von dieser Lösung zu halten?

Schöne Grüße!


----------



## Napofis (26. Januar 2012)

Hi eee,

darin würde ich langfristig ein Problem sehen:

```
if (isset($_SESSION['benutzer'])) {
    // Mitglied
    if ($_SESSION['benutzer'][2] == 2) // 2 für Mod
        // Mod
    }
}
```

Es wird schon funktionieren aber wenn du später deine Seite weiter ausbauen und neue Benutzerklassen anlegen oder entfernen willst müsstest du alle Scripte nach diesen Zeilen durchsuchen.

Mach aus deinen Benutzer ein Objekt:

```
class Benutzer {
	private $_id	= 0;
	private $_name	= 'Gast';
	private $_state	= 0;

	public function __construct(){}
	public function __destruct(){}

	public function tryToLogIn($login, $pw, $db){

$sql=<<<SQL
		SELECT `benutzer_id`, `benutzer_name`, `benutzer_status`
		FROM `benutzer`
		WHERE 	`benutzername`= '$login'
				`passwort`= sha1('$pw')
		LIMIT 1
SQL;
		$ergebnis = $db->query($sql);
		if ($ergebnis->num_rows===1) {
			$tmp = $ergebnis->fetch_object(); 
			$this->_id = $tmp->benutzer_id;
			$this->_name = $tmp->benutzer_name;
			$this->_state = $tmp->benutzer_state;
			return true;
		} else return false;
	}
	public function isBenutzer(){
		return ($this->_state==1);
	}
	public function isMod(){
		return ($this->_state==2);
	}
	public function isAdmin(){
		return ($this->_state==3);
	}

	public function getId(){
		return $this->_id();
	}
	public function getName(){
		return $this->_name();
	}
}
```


Wenn wissen willst ob dein Benutzer ein Admin ist:

```
if($benutzer->isAdmin()){
  // ...
}
```

So hast du alles schön in einer Klasse gekapselt, wenn du etwas modifizieren willst dann weißt du sofort wo du nachschauen musst. Für das User Objekt würde sich die Bauart eines Singelton eignen aber das eher etwas Fortgeschrittene Programmierer.

Durch diese Variante entkoppelst du die Abhängigkeiten das zu wartbaren Code führt.


Gruß Napofis

PS:

http://de.wikipedia.org/wiki/Singleton_(Entwurfsmuster)
Hab den Code nur schnell runter getippt und nicht getestet!


----------



## Raisch (26. Januar 2012)

Wenn Du eine vernünftige und erweiterbare Rechteverwaltung haben willst, dann informiere dich mal über _Access Control List_.

Gruß


----------



## eee (26. Januar 2012)

Hey Napofis,

danke für deine Hilfe. Das mein Code nicht sehr wartungsfreundlich ist, klingt logisch (nach deinem Hinweis). Das Kapitel "Objektorientieres PHP" habe ich in meinem Buch quasi übersprungen. Im weiteren Verlauf des Buches spielt es auch keine Rolle mehr. Wie schon öfters vermutet, war das offenbar ein Fehler.

Deinen Code habe ich mir gleich ausgedruckt und durchgeackert. Zum Aufruf des Objektes habe ich aber noch ein bis zwei Fragen.


```
$benutzer->new Benutzer() // Objekt $benutzer von Typ Benutzer() wird erstellt
$benutzer->tryToLogIn($login, $pw, $db); // Operation tryToLogIn wird aufgerufen
if($benutzer->isMod() || $benutzer->isAdmin()){
  // Inhalt für Mod oder Admin
}
```

Kann man den Aufruf so durchführen oder ist das Mumpitz?

Auch verstehe ich nicht, welche Rolle Session Variablen in deinem Beispiel spielen. Immerhin möchte ich nicht auf jeder Seite, auf welcher sich Member, Mod oder Admin Inhalt befindet, neu einloggen müssen. Hast du vielleicht diesbezüglich noch ein kurzes ( ! ) Codeschnipsel für mich?

Schöne Grüße!

Edit: 

@ Raisch

Danke, ich werde mich am Abend informieren. Wobei es bei mir wirklich nur um eine Hobby Website geht. Vernünftig programmiert soll sie natürlich trotzdem sein.


----------



## Napofis (26. Januar 2012)

```
$benutzer = new Benutzer();
```

Ungefähr so:

```
class Benutzer {
    private $_id    = 0;
    private $_name    = 'Gast';
    private $_state    = 0;

    public function __construct(){
    	if(isset($_SESSION['benutzer']) $this->_restore();
    }
    public function __destruct(){}

    public function tryToLogIn($login, $pw, $db){
$sql=<<<SQL
        SELECT `benutzer_id`, `benutzer_name`, `benutzer_status`
        FROM `benutzer`
        WHERE `benutzername`= '$login'
                `passwort`= sha1('$pw')
        LIMIT 1
SQL;
        $ergebnis = $db->query($sql);
        if ($ergebnis->num_rows===1) {
            $_SESSION['benutzer'] = $ergebnis->fetch_object();
            $this->_restore();
            return true;
        } else return false;
    }
    private function _restore(){
    		$this->_id = $_SESSION['benutzer']->benutzer_id;
			$this->_name = $_SESSION['benutzer']->benutzer_name;
			$this->_state = $_SESSION['benutzer']->benutzer_state;
    }
    // restlicher Code
}
```


----------

