Gå til innhold

[Løst]PHP template system


Anbefalte innlegg

Holder på å lage et lite CMS, som skal kunne endre innholdet på sider jeg lager (dvs legge til sider, ta vekk sider og endre innholdet på dem). Med tanke på utbygging av dette systemet i fremtiden, så vil jeg lage det 100% OOP. Har dessverre litt begrenset kunnskap om OOP, men ser på dette som et læringsprosjekt.

 

Jeg vil selvfølgelig skille logikk og presentasjon, så jeg har skrevet min egen lille template-klasse. Det jeg lurer på er hvordan jeg skal implementere resten av klassene mine i denne template-motoren, slik at de kan brukes i sider som blir hentet inn av templaten.

 

F.eks både meny og innhold på siden skal bestå av egne filer, som skal settes sammen med template-filen av template-motoren. Disse sidene trenger begge tilgang til database-klassen min, men jeg vil helst slippe å lage et nytt objekt av denne klassen i hver av filene. Er det mulig at alt innhold på siden, som blir generert av template-klassen, får tilgang til de andre nødvendige klassene mine, kun ved å lage objekter av dem en gang?

 

lib/template.php

 

<?php

 

class template

{

 

public $output;

 

function __construct($templateFile = 'template.html')

{

require_once('lib/error_object.php');

 

if(file_exists($templateFile))

{

$this->output = file_get_contents($templateFile);

}

else

{

$this->error[] = new error_object('Template file not found.');

}

}

 

function parseTemplate($tags = array())

{

if(count($tags) > 0)

{

foreach($tags as $tag=>$data)

{

if(file_exists($data))

{

$data = $this->parseFile($data);

}

 

$this->output = str_replace('#' . $tag . '#', $data, $this->output);

}

}

else

{

$this->error[] = new error_object('No tags were provided for replacement in template file.');

}

}

 

function parseFile($file)

{

ob_start();

 

if(!require_once($file))

{

$this->error[] = new error_object('Could not put file content into template - file not found.');

}

 

$content = ob_get_contents();

ob_end_clean();

 

return $content;

}

 

function display()

{

return $this->output;

}

 

}

 

?>

 

 

index.php

 

<?php

 

require_once('lib/template.php');

 

$template = new template();

 

$tags = array('page'=>'test',

'menu'=>'menu.php',

'content'=>'content.php');

 

$template->parseTemplate($tags);

echo $template->display();

 

?>

 

 

Slik som her, må jeg lage et objekt av database-klassen inni både menu.php og content.php? Hva vil være den mest pratiske løsningen?

 

Takker for svar :)

Endret av Bakke
Lenke til kommentar
Videoannonse
Annonse
Om cake.php skal ha tilgang til $foo må du bruke [..]

Dette stemmer ikke helt. Faktisk ikke i det hele tatt, i nyeste versjon. Men nok om det.

 

Trådstarter - det virker som du blander to måter å lage templates på; en hvor man bruker PHP filer og henter ut det genererte innholdet via output buffering, samt den andre hvor man lager sin egen syntaks, som i ditt tilfellet er #whatever#. Å blande disse er fullstendig unødvendig og kan føre til utrolig mye rart. F.eks. kan brukergenerert innhold blir tolket som tags.

 

La meg vise det hvordan jeg (nesten) pleier å gjøre det.

 

<?php

class Presenter {

	public function GetFromTemplate ( $data, $template ) {

		extract ( $data );
		ob_start ();
		require ( $template );
		return ob_get_clean ();

	}

}

?>

Index-filen kan typisk se noe lignende som følger.

 

<?php

$includes = array_map ( function ( $file ) {
	return pathinfo ( $file, PATHINFO_FILENAME );
}, glob ( '/includes/*.php' ) );

if ( array_key_exists ( 'page', $_GET ) &&
	 array_key_exists ( $_GET['page'], $includes ) )
	$page = $_GET['page'];
else
	$page = 'home';

$presenter = new Presenter ();

echo $presenter -> GetFromTemplate ( array (
	'page_title' => 'My Site!',
	'page' => $page,
), '/templates/index.php' );

?>

.. og hvor template-filen kanskje ser slik ut.

 

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
	<title><?= $page_title; ?></title>
</head>
<body>
	<?php require ( '/templates/' . $page . '.php' ); ?>
</body>
</html>

Endret av Jonas
Lenke til kommentar

Kødder du nå med meg nå? Hadde sikkerhet vært topic, så hadde jeg kanskje brydd meg et sekkund om det, men siden det ikke er det, så gjør jeg ikke det. Det skal samtidig nevnes at da hadde det ikke skjedd noe som helst. Ta en kikk på koden en gang til.

 

Edit: Copy that..

Endret av Jonas
Lenke til kommentar

Takk for hjelpen. Skrev om template-motoren slik som du viste, Jonas :)

 

Jeg har nå puttet

<?php require($config) ?>

helt på toppen av template-filen min. Config-filen inneholder en __autoload funksjon og laster inn alle de nødvendige klassene som websiden vil trenge. Er dette en grei løsning, eller burde jeg aktivere klassene en annen plass?

Endret av Bakke
Lenke til kommentar

Tja.. Du kommer garantert til å trenge flere funksjoner i template-ene dine, så jeg ville f.eks. laget en mappe med alle og inkludert de i presenter-klassen.

 

<?php

class Presenter {

	public function GetFromTemplate ( $data, $template ) {

		$functions = glob ( '/presenters/functions/function.*.php' );

		foreach ( $functions as $function )
			require_once ( $function );

		extract ( $data );
		ob_start ();
		require ( $template );
		return ob_get_clean ();

	}

}

?>

Endret av Jonas
Lenke til kommentar

Off topic, rettet mot Jonas: Når man bruker include() eller lignende funksjoner inne i en class, blir da funksjonene i filen man includer del av classen? I så fall, kan man erstatte funksjoner på noe samme vis som en class som extender en annen kan?

 

EDIT: Til trådstarter: Jeg ville ikke plasser annet enn konfigurasjonsvariabler i konfigurasjonsfilen.

Endret av Jckf
Lenke til kommentar

Nei, slik er det ikke. En funksjon er bare en funksjon, uansett hvor den er definert. Den er samtidig tilgjengelig uansett hvor den er definert. Derfor er det viktig at man i en slik klasse bruker require_once og ikke require. Følgende eksempel vil f.eks. printe ut «z0mg».

 

<?php

class Foo {
	public function __construct () {
		function Bar () {
			echo 'z0mg';
		}
	}
}

$myObject = new Foo ();

Bar ();

?>

Lenke til kommentar

Leit. Har prøvd å lage et mer dynamisk system for class extension, men så langt har det kun blitt objekter med underobjekter som har en ref til parent-objektet for å kunne bruke sine "brødre og søstre". Idé?

 

EDIT: Eksempel:

class pappa {
public $navn;
function nytt_barn($navn,$objekt) {
	$this->$navn = $objekt;
	$this->$navn->parent = &$this;
}
}
class unge {
function sutre() {
	echo 'Buhu og wahwah, ' . $this->parent->navn . '!';
}
}

$pappa = new pappa();
$pappa->navn = 'Hans';
$pappa->nytt_barn('kjetil',new unge());
$pappa->kjetil->sutre();

Endret av Jckf
Lenke til kommentar

En familie representert ved objekter (med inheritance og composition)

 

 

<?php

class Person {

protected $name;
protected $children = array();
protected $parent;

public function __construct($name) {
	$this->name = $name;
}

public function setName($name) {
	$this->name = $name;
}

public function getName() {
	return $this->name;
}

public function addChild(Person $child) {
	$child->setParent($this);
	$this->children[$child->getName()] = $child;
}

public function getChildren() {
	return $this->children;
}

public function setParent(Person $parent) {
	$this->parent = $parent;
}

public function getParent() {
	return $this->parent;
}

public function __toString() {
	return $this->name;
}
}


// A little boy IS a person
class LittleBoy extends Person {
public function whine() {
	return 'buhuhuhuhu';
}
}

// A little girl IS also a person
class LittleGirl extends Person {
public function whine() {
	return 'meeeeeee';
}
}

$dad = new Person('Nils');

// a person HAS a child
$dad->addChild(new LittleBoy('Thomas'));
$dad->addChild(new LittleGirl('Blair'));

$children = $dad->getChildren();

echo $children['Thomas']->getParent()->getName();

foreach ($children as $child) {
echo $child->whine();
}

 

 

Lenke til kommentar
Klaska bare sammen et eksempel i farten. Jeg ønsker å skrive en klasse som inneholder et sett funksjoner, men jeg ønsker også å kunne erstatte disse med andre funksjoner. F.eks. for å implementere et annet brukersystem i en CMS-klasse.

Isåfall er det ikke verre enn å opprette en ny klasse som arver fra CMS-klassen din og skrive over metoden ved å enkelt og greit lage en ny med samme navn.

Endret av Jonas
Lenke til kommentar

Klasser kan arve fra klasser som arver fra klasser som arver ... osv. Det er dog rimelig statisk og det virker som du ønsker det dynamisk. Jeg tipper du har et CMS og forskjellige applikasjoner som skal modifisere virkemåte eller output på noe vis. Ofte brukes et observer-pattern til slikt. Du skal ikke se bort ifra at det allerede er implementert i CMSet du benytter deg av.

 

https://www.diskusjon.no/index.php?showtopi...8&hl=plugin

http://en.wikipedia.org/wiki/Observer_pattern

Lenke til kommentar

Jeg tenkte på å gjøre alle klassene tilgjengelige for siden som blir hentet inn i templaten, ikke bare funksjoner, men det fungerte jo på noe lunde samme viset. Løsningen ble slik :)

 

lib/template.php

 

class template
{

public function getFromTemplate($tags, $template='templates/index.php')
{
	// Check that the autoload function is not already declared
	if(!function_exists('__autoload'))
	{
		// Autoload a class when requested
		function __autoload($class)
		{
			require_once('lib/' . $class . '.php');
		}

		// Initiate classes
		$db = new db();

		// Connect to database
		$db->connect();
	}

	// Load the page
	extract($tags);
	ob_start();
	require($template);
	return ob_get_clean();

	// Disconnect from database
	$db->disconnect();
}

}

 

Lenke til kommentar
Å gjøre database-klassen tilgjengelig fra templates strider på en måte litt i mot hele prinsippet med å separere logikk og presentasjon, men..

Så jeg bør heller koble til databasen i index.php? Men kan jeg gjøre resten av klessene tilgjengelige fra templaten?

Lenke til kommentar

Opprett en konto eller logg inn for å kommentere

Du må være et medlem for å kunne skrive en kommentar

Opprett konto

Det er enkelt å melde seg inn for å starte en ny konto!

Start en konto

Logg inn

Har du allerede en konto? Logg inn her.

Logg inn nå
  • Hvem er aktive   0 medlemmer

    • Ingen innloggede medlemmer aktive
×
×
  • Opprett ny...