Mads-b Skrevet 29. desember 2008 Del Skrevet 29. desember 2008 Jeg lagde en templateklasse for noen måneder siden, men jeg skal verken skryte på på meg skills eller tålmodighet, og trenger friske øyne til å ta en titt på koden, for å se om jeg må fikse på programmeringspraksisen min før jeg lager et helt system med samme programmeringsteknikk.. <?php class template { private $rawFile; private $extractedTemplate; private $tempArray; private $rawTag; public function __construct($fileURL) { global $templateCache; //Making a global cahce var to store templates imported! if(isset($templateCache[$fileURL])) $this->rawFile = $templateCache[$fileURL];// File in cache array. Return it. elseif($templateCache[$fileURL] = file_get_contents('templates/' . $fileURL)) { $this->rawFile = $templateCache[$fileURL]; } //add to cache else return "Could not fetch template file $fileURL!"; } public function parse($wrapperTag) { preg_match('/\{'. $wrapperTag . '\}(.+?)\{\/'. $wrapperTag . '\}/is',$this->rawFile,$this->extractedTemplate); //Fetch the piece of the template in question $this->extractedTemplate = $this->removeGarbage($this->extractedTemplate,'odd'); //remove the useless results.. } public function set($tag,$value) { if(!is_array($value)) { //There are not multiple values for this tag. Just replace it.. $this->extractedTemplate = str_replace('{' . $tag . '}',$value,$this->extractedTemplate); } else { //Uh oh.. We need to repeat a portion of the template in order to proceed. /*In this case, there should be a wrapper $tag ({tag}...{/tag}) containing {$value}s * $value array should be as follows: array('tagname' => 'contentOfTag') * If there are multiple set->array() commands nested inside each other, the innermost one must be set first.*/ preg_match('/\{'. $tag . '\}(.+?)\{\/'. $tag . '\}/is',$this->extractedTemplate,$hit); //Get tags to replace $finalizedLine = $hit[1]; //choose the variant from the command above without tag ^^ $this->rawTag[$tag] = $hit[0]; //Put the raw tag into an array for further reference.. foreach($value as $replaceTag => $replaceValue) { $finalizedLine = str_replace('{' . $replaceTag . '}',$replaceValue,$finalizedLine); } @$this->tempArray[$tag] .= $finalizedLine; } } public function getTemplate() { if(is_array($this->tempArray)) { //Information has been set as array(s) foreach($this->tempArray as $tag => $value) { $this->extractedTemplate = str_replace($this->rawTag[$tag],$value,$this->extractedTemplate); } } return $this->extractedTemplate; } private function removeGarbage($array,$type) { //function to remove every other value in array. $output = array(); foreach($array as $i => $value) { if(!is_int($i/2) && $type=='odd') $output[] = $value; if(is_int($i/2) && $type=='even') $output[] = $value; } if(count($output) == 1) $output = $output[0]; //If array consists of one string, make it a string! return $output; } } ?> Templatene lagde jeg i dette oppsettet, så jeg kan totalt atskille all kode fra innholdet.. {pluginList} <h2>List of Plugins, Alphabetically</h2> <table> <tr><th>Name</th><th>Location</th><th>Plugin Size</th><th>Description</th><th>Settings</th></tr> {plugin} <tr><td>{name}</td><td>{location}</td><td>{size}</td><td>{description}</td><td><a href="{editLink}">Edit</a></td></tr> {/plugin} </table> {/pluginList} Poenget er da at en templatefil kan inneholde flere wrappertags som pluginList. Jeg laster hele filen inn i et objekt, så jeg har den om jeg trenger flere wrappertemplates på en gjennomkjøring. Inni wrapperen er to typer innholdstags: Simple replace-tags, (som name og location), samt repetisjonstags (som plugin), som kan kopieres i templaten for å få (i dette tilfellet) en liste over plugins.. Jeg synes konseptet er greit, men hvordan er gjennomføringen? Lenke til kommentar
Jonas Skrevet 29. desember 2008 Del Skrevet 29. desember 2008 (endret) Konseptet er naturligvis flott. Ikke noe er så ekkelt som å se en haug med echo's blant PHP-linjer. Kan derimot gjennomføres annerledes. F.eks. så parser du statisk innhold som om det skulle være dynamisk. Filene endrer seg jo ikke før du laster opp en ny en, og i mellomtiden burde det ikke være nødvendig å parse en template mer enn én gang. I tillegg virker den ganske primitiv, kan ikke se for meg at du klarer å bygge noe særlig til side oppå den. Det finnes allerede en relativt stor og fin templatemotor i PHP, nemlig Smarty. Den introduserer en egen syntaks, i likhet med din templatemotor, men som bare oversettes til PHP. Selv er jeg mye større fan av å bare skrive templates i PHP med en gang. Separasjon av business logic og presentasjon betyr ikke nødvendigvis at det må skrives i forskjellige språk. <h1>List of Plugins, Alphabetically</h1> <?php foreach ( $plugins as $plugin ) : ?> <h2><?= $plugin['name'] ?></h2> <p><?= $plugin['description'] ?></p> <?php endforeach; ?> Endret 29. desember 2008 av Jonas Lenke til kommentar
Mads-b Skrevet 30. desember 2008 Forfatter Del Skrevet 30. desember 2008 Hmm.. Jeg skjønner poenget, men det ligger en del tankegang bak. Hele cluet med motoren var at den skulle brukes til høyst kompliserte/dynamiske sider, og den utviklet seg etter hvert som jeg brukte den og trengte features. Jeg ser behovet for en med kodeøkonomisk løsning, men systemet funker, og jeg kan bruke en templatefil til en hel dynamisk side med mye forskjellig output lagret i den ene templatefilen. Et eksempen på noe drit jeg hadde liggende som viser den i bruk: public function __construct() { //Import the required template and parse.. $this->container = new template('adminContainer.tpl'); $this->container->parse('container'); } private function addTopMenu($active) { //function to add the tabs in the top. $topMenu = array(); $menuSelections = array('Menu1','Menu2','Menu3'); foreach($menuSelections as $menuSelection) { $buttonTemplate = new template('adminContainer.tpl'); if($menuSelection == $active) {//we want to set an active tab. use active template $buttonTemplate->parse('adminButtonLinkActive'); } else { //Not an active tab.. $buttonTemplate->parse('adminButtonLinkInactive'); } $buttonTemplate->set('link','?admin=' . $menuSelection); $buttonTemplate->set('name',$menuSelection); $topMenu[] = $buttonTemplate->getTemplate(); $this->container->set('adminButtonRow',array('adminButtonLink' => $buttonTemplate->getTemplate())); unset($buttonTemplate); } } Problemet med smarty (faktisk sjekket den opp), er at den ikke kjører samme konsept, så vidt jeg har forstått, og jeg vil kombinere språkpakke, dynamisk content og template i en og samme fil. Dog ser jeg rom for forbedring, da koden er nokså keitete med tanke på kodemengde+ytelse.. Lenke til kommentar
Anbefalte innlegg
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 kontoLogg inn
Har du allerede en konto? Logg inn her.
Logg inn nå