If you are unable to read Danish i recommend using Google Translate in order to translate this page in to your preferred language

Christian Selch

Web-udvikler & kommunikations-haj

Object-Oriented PHP: Dag 2

Dette er anden afsnit af min serie omkring Objekt-Orienteret PHP. Jeg vil anbefale du læser Objekt-Orienteret PHP: Dag 1 først, hvis du ikke har nogen erfaring med Objekt-Orienteret PHP, da alt det basale er forklaret der.

Dag 2: Con- & Destrutors og variabler

Den færdige kode kan hentes her: http://selch.me/wp-content/uploads/2011/04/OO_PHP_Dag_2.zip

Som lovet, sidste gang, kigger vi nærmere på constructors, destructors, variabler delt mellem alle classen funktion, og instances i dag.

Jeg har besluttet at vi denne gang laver en class, der i fremtiden kan bruges når du udvikler andre projekter. Målet med classen bliver nemlig at måle tiden, det tager for en server at udføre en særlig bid PHP kode – dette kan være umådeligt brugbart når ens kode skal optimeres. Jeg har som udgangspunkt bygget denne class som vi gennemgår linie for linie om lidt:

<?php
class benchmark{

	private $start_time = 0;

	private $end_time = 0;

	private $execution_time = 0;

	function get_time(){
		$time = explode('', microtime());
		return ((float)$time[0] + (float)$time[1]);
	}

	function start_watch(){
		$this->start_time = $this->get_time();
	}

	function stop_watch(){
		$this->end_time = $this->get_time();
	}

	function get_execution_time(){
		$this->execution = $this->end_time - $this->start_time;
		return $this->execution;
	}

}

$benchmark = new benchmark();

$benchmark->start_watch();

$i = 0;

while ($i < 100000000){
	$i++;
}

$benchmark->stop_watch();

echo $benchmark->get_execution_time();
?>

Som sagt kræver denne kode lidt forklaring. Særlig linie 4-8 indeholder en helt ny ting – vi declear 3 variabler, ude for funktion men inden i classen. Det der er særligt ved disse 3, og den måde vi normalt bruger ‘udefra kommende’ variabler inde i funktioner på, er at de ikke skal declears global. Lige så snart de er blevet decleared inden i sammen class som funktion, sker der det automatisk, at bliver tilgængelige for alle funktionerne i classen. Jeg har tilføjet keywordet private for an dem for at de, som vi lærte sidst, ikke kan tilgås uden for classen, og vi derfor slipper for man ved et uheld kommer til at pille ved dem.

Det næste de muligvis kræver lidt forklaring er linierne 16, 20 & 24 – det er nemlig her vi gør brug af vores tidligere definerede variabler. Som du kan se tilgår vi dem, næsten lige som vi gjorde med funktionerne sidst. Vi bruger $this-> til at sige de findes i classen, og skriver navnet på det vi vil have bagefter pilen. Der er dog en forskel fra funktioner til variabler – måden vi siger det er en variabel på er ved IKKE skrive de velkendte () efter.  Resten af koden burde give sig selv nogle lunde. I tilfælde af man ikke bruger keywordet private foran dem vil de også kunne tilgås uden for classen lige som man kan med funktioner. Husk dog igen at undlad ().

Under classen har vi lidt test-kode, hvor vi afprøver hvor lang tid det tager for PHP, at tælle fra 0 til 100.000.000, ved hjælp af vores class. Men hvad nu hvis vi gerne ville slippe for at skulle skrive den her linie kode?:

$benchmark->start_watch();

men i stedet bare ville have den startede med at tælle, lige så snart vi skrev den her linie kode?:

$benchmark = new benchmark();

På det punkt er vi så heldige at der er en indbygget funktion til den slags i PHP, vi med fordel kan tage brug af. Den følgende kode gør outputter det sammen som den overstående – vi har bare ‘sparet’ linie 32 væk

<?php
class benchmark{

	private $start_time = 0;

	private $end_time = 0;

	private $execution_time = 0;

	function __construct(){
		$this->start_watch();
	}

	function get_time(){
		$time = explode('', microtime());
		return ((float)$time[0] + (float)$time[1]);
	}

	function start_watch(){
		$this->start_time = $this->get_time();
	}

	function stop_watch(){
		$this->end_time = $this->get_time();
	}

	function get_execution_time(){
		$this->execution = $this->end_time - $this->start_time;
		return $this->execution;
	}

}

$benchmark = new benchmark();

$i = 0;

while ($i < 100000000){
	$i++;
}

$benchmark->stop_watch();

echo $benchmark->get_execution_time();
?>

Som du kan se har jeg tilføjet den lidt særligt udsende funktion, __construct(), til classen. Det der gør denne class så speciel er at PHP5+, automatisk søger efter en funktion kaldet __construct(), når vi instanciere dem. Altså – så længe vi ikke har en funktion der hedder __construct sker der intet når vi starter classen. Hvis vi derimod har en udføres den lige i det vi skriver en linie ligende den her:

$benchmark = new benchmark();

Det er vigtigt i forbindelse med udvikling af script, der også skal kunne køre på PHP4, er at PHP4 ikke automatisk kører funktion __construct, hvis den findes. I PHP4 autokøres i stedet en funktion, med sammen navn som classen. Det vil i dette tilfælde være benchmark. Den letteste måde at sørge for at ens script også virker i PHP4, vil være at skrive en funktion der hedder benchmark, med dette udsenede:

	function benchmark(){
		$this->__construct();
	}

På den måde har vi sørget for, at __construct() også bliver udført på en server, med PHP4 i stedet for PHP5. Men nok om hvordan vi sikre scriptet for PHP4 – tilbage til PHP5 og vores kode.

I vores class bruger vi __construct til at køre funktionen start_watch() med det sammen. Vi kunne lige så godt bruge den til at definere nogle variabler, eller udskrive noget særlig kode men, det har vi ikke behov for i denne class.  Det vil vi dog i en af de senere afsnit hvor vi foralvor får arbejdet med class variabler og hvordan __construct kan bruges. Den kan nemlig noget mere, der er utroligt brugbart: vi ved hjælp af den, kan kræve at man giver classen nogle variabler, i det øjeblik den instancieres. Det kunne i dette tilfælde,  f.eks. være om den skulle starte med at tælle lige når man starter instancen. Det kunne se sådan her ud:

<?php
class benchmark{

	private $start_time = 0;

	private $end_time = 0;

	private $execution_time = 0;

	function __construct($autostart){
		if($autostart){
			$this->start_watch();
		}
	}

	function get_time(){
		$time = explode('', microtime());
		return ((float)$time[0] + (float)$time[1]);
	}

	function start_watch(){
		$this->start_time = $this->get_time();
	}

	function stop_watch(){
		$this->end_time = $this->get_time();
	}

	function get_execution_time(){
		$this->execution = $this->end_time - $this->start_time;
		return $this->execution;
	}

}

$benchmark = new benchmark(true);

$i = 0;

while ($i < 100000000){
	$i++;
}

$benchmark->stop_watch();

echo $benchmark->get_execution_time();

?>

I den nye version her vil der blive smidt en fatal error, hvis man ikke opgiver en værdi til $autostart, når man starter instancen. En anden funktion ligende __construct, der også er meget smart, er __destruct. Fordelen ved __destruct er dog ikke lige så store, som ved __construct. Den er mest brugbar, i forbindelse med classes, der arbejder med MySQL. Som navet selv siger, bliver den nemlig udført i det øjeblik, classen bliver ‘lukket’. Man vil derfor oftest bruge den til at frigive filer i filsystemet, lukke forbindelser til MySQL databaser eller ligende.

Det var alt for nu. Du har nu lært lidt om hvordan man kan bruge variabler, samt hvordan du kan bruge de særlige funktion __construct og __destruct. Næste gang kigger vi nærmere på de lidt mere avancerede funktioner, så som implements, extends, parent, og muligvis lidt andet godt.

Hvis der er nogle spørgsmål, noget der er uforslåeligt, noget der er forkert eller noget helt fjerde – skriv en kommentar neden for.

6 kommentare til 'Object-Oriented PHP: Dag 2'

  1. Kasper skrev den 21. august 2010 - Svar

    Download link virker ikke :(
    http://christian-selch.dk/wp-content/uploads/2010/03/OO_PHP_Dag_2.zip

    Men nice guide takker :)

    • Christian H. Selch skrev den 21. august 2010 - Svar

      Hej Kasper

      Jeg beklager at der var gået noget galt med linket under min seneste opdatering – det hele burde virke nu :)

      Godt du kunne bruge guiden alligevel!

      //Christian Selch

  2. Dennis Kamp skrev den 6. april 2011 - Svar

    Download linket virker stadig ikke :(

    • Christian Selch skrev den 6. april 2011 - Svar

      Hej Dennis.

      Det burde meget gerne virke nu. Jeg beklager fejlen.

      Mvh
      Christian Selch

  3. Dennis Kamp skrev den 12. oktober 2011 - Svar

    Tusind tak for dine “guides”, de har virkelig hjulpet mig godt igang med forståelsen af OOP.

    Men kan det ikke passe, der er fejl i din kode ved: “$time = explode(”;, microtime());”

    Tegnet: “;”, skulle det ikke have været inde i “””‘erne?

    • Christian Selch skrev den 12. oktober 2011 - Svar

      Hej Dennis

      Først og fremmest – godt at høre du kan bruge det!
      Fejlen du har påpeget, er nu rettet – der er sket en eller anden fejl, da koden forlod min editor

      Mvh
      Christian Selch

Efterlad en kommentar