PHP Besucherzähler in PHP OOP

Hallo,

ich habe mich gerade ein wenig an die objektorientierte Programmierung rangetastet und einen Besucherzähler geschrieben. Evtl. könnt ihr ja mal drüber schauen und eure meinung dazu sagen, insbesondere ob die OOP hier auch richtig umgesetzt worden ist.

Zuerst habe ich die Datei filehandle.class.php mit folgendem Inhalt
Code:
<?php
 
class filehandle {
 
var $filename;
var $contentread;
var $contentwrite;
var $handle;
 
function readfile{
 
  $handle = fopen($filename, "r");
  $contentread = fgets ($handle);
  fclose($handle);
 
}
 
function writefile{
 
  $handle = fopen($filename, "w");
  fwrite ($handle, $contentwrite);
  fclose($handle);

}
}

?>

Dann die Datei gbcounter.class.php

Code:
<?php
 
include "filehandle.class.php";
 
$visitcount = new filehandle;
$visitcount->filename="counter.txt";
 
class gbcounter{
 
var $counter;
 
function setcounter{
 
$visitcount->readfile();
$counter = $visitcount->contentread;
echo $counter++;
 
}
 
function savecounter{

$visitcount->contentwrite = counter;
$visitcount->writefile();

}
}
?>

Und hier die Datei zum anzeigen index.php

Code:
<html>
<head>
.
.
.
<?php

include "gbcounter.class.php";

</head>
 
<body>
.
.
.
.
.
<footer>

<?php
 
$besucherzaehler = new gbcounter;
$besucherzaehler->setcounter;
$besucherzaehler->savecounter;
 
?>
</footer>
 
</html>
 
Wenn savecounter() sowieso immer nach setcounter() aufgerufen wird, dann pack doch besser gleich ein $this->savecounter() in die setcounter-Funktion.

Zur index.php sei anzumerken, dass zumindest ich persönlich und auch einige PHP-Devs, die ich kenne, Augenkrebs bekommen, wenn sie in HTML eingebettetes PHP sehen. Entweder man schreibt HTML oder PHP. Schreib also deinen HTML-Code einfach in ein Template, packe dort Platzhalter für die Stellen rein, wo dynamisch Inhalte eingefügt werden sollen und lasse diese durch den PHP-Code auffüllen. Passende Template-Systeme finden sich im Netz zuhauf.
 
Nimms mir nicht übel, aber die einzelnen Funktionen einfach in Klassen zusammenzufassen, hat wenig mit OOP zu tun. Letzten Endes hast du hier einfach nur eine Liste von Funktionen, die du in bestimmten Mustern aufrufst (z.B. readfile() vor writefile()) und die keinerlei Beziehungen (Eltern-Kind/Vererbung, Interfaces, ...) untereinander aufweisen.

Aber mal unter uns: Funktioniert dein Code überhaupt? Als ich noch php programmiert habe - zu der Zeit waren php3 und php4 noch aktuell - musste man damals beim Funktionsaufruf noch Klammern angeben und der Scope von Variablen ging nicht bis in die Klasse rein...

Mein Tipp: Beschäftige dich von Anfang mit den sog. Design Patterns, oder zu gut deutsch "Entwurfsmuster". Versuch, die Prinzipien von Objekt-orientierter Programmierung auf einige dieser Muster anzuwenden und - natürlich nur sofern möglich - diese Muster einzusetzen.
 
Zuletzt bearbeitet:
Hallo,

erstmal danke für eure Antworten, ich habe mir mal eure Kritik zu Herzen genommen und es etwas geändert.

filehandle.class.php

Code:
<?php

	error_reporting(-1);
	ini_set('display_errors', 1);  
 
	class filehandle {
 
		public $filename;
		public $contentread;
		public $contentwrite;
		public $hand;
 
		public function rfile() {
 
  			$this->hand = fopen($this->filename, "r");
  			$this->contentread = fgets ($this->hand);
  			fclose($this->hand);
 
		}
 
		public function wfile() {
 
  			$this->hand = fopen($this->filename, "w+");
  			fwrite ($this->hand, $this->contentwrite);
  			fclose($this->hand);

		}
	}

?>

gbcounter.class.php

Code:
<?php
 
 	error_reporting(-1);
	ini_set('display_errors', 1);
	  
	include "filehandle.class.php";
 
	class gbcounter extends filehandle{
 		
		public $counter;
		
 		
		public function setcounter() {
 
 			$this->filename="counter.txt";
			$this->rfile();
  			$this->counter = $this->contentread;
			echo $this->counter+1;
 
		}
 
		public function savecounter() {
			
			$this->filename="counter.txt";
			$this->contentwrite = $this->counter+1;
			$this->wfile();

		}
	}

?>

Die Datei index.php habe ich erstmal so gelassen, werde mir die Sache mit den Templates noch anschauen, kam da noch nicht dazu, aber ist schon besser die zwei Sachen getrennt zu machen ;-).
 
Was hat denn die Klasse gbcounter mit der Klasse filehandle zu tun? Die Klassen sollten natürlich schon auch eine semantische Ähnlichkeit (Fisch hat etwas mit Karpfen zu tun, aber nicht mit Autoreifen :)) haben, wenn du Beziehungen zwischen ihnen herstellst.

Z.B. könntest du das Thema Persistenz gut dazu nutzen:
  1. Interface Persistenz: Spezifikation der Funktionen speichern(String wert) und lesen().
  2. Klasse DateiPersistenz, die das Interface Persistenz implementiert und den Zählerstand in einer Datei speichert.
  3. Klasse SQLPersistenz, die das Interface Persistenz implementiert, und den Zählerstand in einer SQL-Tabelle speichert.

Dein Hauptprogramm ist jetzt nur noch eine Klasse, die z.B. bei der Erzeugung des Objekts ein weiteres Objekt vom Typ Persistenz übergeben bekommt und die Funktionen "speichern" bzw. "lesen" aufruft, um Zählerstände zu speichern bzw. zu lesen und auszugeben:

PHP:
$persist = new DateiPersistenz(); 
// oder als Alternative: $persist = new SQLPersistence();
$zaehler = new Zahler($persist);
$zaehler->zaehlerstandAusgeben();
$zaehler->hochzaehlen();
$zaehler->hochzaehlen();
$zaehler->hochzaehlen();
$zaehler->zaehlerstandAusgeben();

Der Programmierer muss sich darum nicht kümmern, wann und was überhaupt gespeichert wird. Dennoch kann er festlegen, welcher Speicherort genutzt werden (Dateien, SQL-Datenbanken, ...) soll. Dem Programm dagegen ist es egal, welcher Speicherort genutzt wird, da es eh nur die Methoden speichern und lesen aufruft, welche in jeder implementierenden Klasse vorkommen müssen.

Willst du jetzt beispielsweise die Klasse DateiPersistenz noch erweitern, dann kannst du "extends" benutzen. Dies kann z.B. so aussehen, dass du nicht nur den Wert in der Datei speichern willst, sondern eine CSV-Zeile:

PHP:
class CSVDateiPersistenz extends DateiPersistenz {

function speichern(String wert) {
//...
$neuerWert = $wert . ";" . date();
parent::speichern($neuerWert)
}

function datumLesen() {
// ...
return $datum;
}

}

Damit sind dann z.B. solche Schweinereien möglich:

PHP:
$persist = new DateiPersistenz(); 
// oder als Alternative: $persist = new SQLPersistenz();
$zaehler = new Zahler($persist);
$zaehler->zaehlerstandAusgeben();
$zaehler->hochzaehlen();
$zaehler->hochzaehlen();
$zaehler->hochzaehlen();
if($persist instanceof CSVDateiPersistenz) {
    $zaehler->datumAusgeben();
}
$zaehler->zaehlerstandAusgeben();

Darüber hinaus ist es Konvention, dass Klassennamen mit einem Großbuchstaben beginnen und Funktionen mit einem Kleinbuchstaben ;) Weitere Konventionen findest du z.B. bei Zend
 
Zuletzt bearbeitet:
Zurück
Oben