robgolding63 Posted June 5, 2007 Share Posted June 5, 2007 Hi, I am writing a simple template engine for my site, to make changes to layout and styling easier. At present, it's basically just an object-oriented find-and-replace script ie. replace {PAGE_TITLE} with the title of the page. I am stuck at the point of looping variables/database rows. How would one pass an array to the template, or make the template loop over multiple database rows, to output news items or menu items etc. I have looked into template engines already out there like Smarty, but I would like something fast and simple, as my site isn't very large yet, and I want to keep load times as low as I can (I will be writing a caching system once the engine is completed). Thanks for any help, Rob Quote Link to comment https://forums.phpfreaks.com/topic/54349-simple-template-engine/ Share on other sites More sharing options...
per1os Posted June 5, 2007 Share Posted June 5, 2007 I would suggest http://ets.sourceforge.net/ 1 file, very easy and very simple. Smarty is overly complex for most people. With the above once you have the file built to call the template it is simply printt('template.tpl', $etsobject); Building your own template system is a lot of work, especially with the looping portion and conditional system. I would highly suggest looking into the above. I use it on some of my code and it has yet to fail me on being speedy etc. Quote Link to comment https://forums.phpfreaks.com/topic/54349-simple-template-engine/#findComment-268769 Share on other sites More sharing options...
robgolding63 Posted June 6, 2007 Author Share Posted June 6, 2007 Well, this is more of a fun project than anything, I want to be able to maintain my own code, and know exactly how everything works. I much prefer running my own code, but if this becomes a huge project, then I will consider using ETS. If anyone knows a way to have a preg_replace() or similar function loop over a string for a given array (ie. in a foreach or something?), then I would be extremely grateful. Thanks for the reply, Rob Quote Link to comment https://forums.phpfreaks.com/topic/54349-simple-template-engine/#findComment-269169 Share on other sites More sharing options...
trq Posted June 6, 2007 Share Posted June 6, 2007 The whole thing is that once you start trying to impliment loops and conditionals within templates, your simple template engine is no longer simple. Ive never bothered with templates or template engines. IMO, PHP is a template engine. Quote Link to comment https://forums.phpfreaks.com/topic/54349-simple-template-engine/#findComment-269184 Share on other sites More sharing options...
per1os Posted June 6, 2007 Share Posted June 6, 2007 Well, maybe this will help you out. I created my own "Template system" a few years back, with the same attitude as yours. At any rate it does loops, but probably not as efficiently as it could be. Hope this will help you out trying to figure out what you need for the loopage part: <?php //Template Script v1.1 /* These are the functions that make the script work Do not edit these any type of editing may make it not work right. Modified: 5-06-2004 @ 5:47pm by FrosT :.:- LEGEND -:.: --Reviews GET{MOV_TITLE} - Movie Title GET{MOV_IMG} - Movie Image GET{MOV_AD} - Poster Ad (if applicable) To change id edit erevfunc.php GET{MOV_LEN} - Movie Length GET{MOV_RD} - Movie Release Date GET{MOV_GEN} - Movie Genre GET{MOV_DESC} - Movie Description GET{MOV_RATE} - Movie Rating GET{MOV_MPAA} - Movie MPAA Rating GET{COPYRIGHT} - Prints the required copyright unless paid $50 --Listings GET{LS_VDATE} - Viewing Date GET{LS_DATES} - Other dates GET{NAV_THEATERS} - Theater Navigation GET{LOOP_TH_MOV} - Start the looping for theater/movies GET{TH_NAME} - Theater Name GET{TH_ADDR} - Theater Address GET{TH_CITY} - Theater City GET{TH_STATE} - Theater State GET{TH_ZIP} - Theater Zip GET{TH_PHONE} - Theater Phone GET{TH_MAP} - Map to theater GET{TH_HAND} - Handicap image GET{TH_HEAR} - Heraing image GET{LOOP_MOV} - Start the movie Looping GET{MV_NAME} - Get the movie name GET{MV_RATE} - Movie Rating GET{MV_LEN} - Movie Length GET{MV_TIME} - Times playing GET{MV_NAME2} - Get the movie name (#2) GET{MV_RATE2} - Movie Rating (#2) GET{MV_LEN2} - Movie Length (#2) GET{MV_TIME2} - Times playing (#2) GET{END_MOV} - Ends the movie loop GET{END_TH_MOV} Ends the theater/mov Loop GET{COPYRIGHT} - Prints the required copyright unless paid $50 :.:- LEGEND -:.: */ //Start the Class class tpl_sys { var $structure; var $showme; var $content; var $filename; var $inc_file; var $theatar = array(); var $infoar = array(); // This is so we know what to display! var $dowhat = array("rev" => array("mov_title", "mov_img", "mov_ad", "mov_len", "mov_rd", "mov_gen", "mov_desc", "mov_rate", "mov_mpaa", "mov_star", "mov_dir", "mov_pro", "mov_c1rev_ti", "mov_c1rev_com", "mov_c1rev_grd", "mov_c2rev_ti", "mov_c2rev_com", "mov_c2rev_grd", "mov_c3rev_ti", "mov_c3rev_com", "mov_c3rev_grd", "mov_c4rev_ti", "mov_c4rev_com", "mov_c4rev_grd", "mov_other", "incfile", "copyright")); ################# # # # Initiation # # # ################# function template($filename) { $this->filename = $filename; $this->structure = array(); $this->structure = $this->loadfile($this->filename); $this->parse($this->structure); } function loadfile($filename) { if(file_exists($filename)) { $content = file($filename); /*$fo = fopen($filename, "r"); $content = fread($fo, filesize($filename)); fclose($fo);*/ } else $content = '[ERROR: "'.$filename.'" does not exist.]'; return $content; } function include_file($filename) { if(file_exists($filename)) { $this->inc_contents = file($filename); }else $include = '[ERROR: "'.$filename.'" does not exist.]'; return $include; } function parse($structure) { if ($this->showme == "rev") { $b=0; $cop = 0; $cnt_num = count($structure); while ($b < $cnt_num) { if (ereg("([G,g]){1}([E,e]){1}([T,t]){1}\{([a-zA-Z0-9_.]*)\}", $structure[$b], $m)) { list($first, $last) = split("([G,g]){1}([E,e]){1}([T,t]){1}\{([a-zA-Z0-9_.]*)\}", $structure[$b]); $name = strtolower($m[4]); $i=0; $error=1; if($name == "copyright") { $cop = 1; } foreach ($this->dowhat["rev"] as $info) { if ($name == $info) { print $first; $this->getBlockRev($name); print $last; $error = 0; } elseif (strstr($name, $info)) { list(, $filename) = split("=", $name); $this->inc_file = $this->loadfile($incfile); $this->parse($this->inc_file); $error = 0; } $i++; } if ($error == 1) { $this->error($error, $name . " is not a valid call statement"); print $structure[$b]; } }else { print $structure[$b]; } $b++; } } } ################# # # # Blocks # # # ################# function getBlockRev($dothis) { // This is so we know what to display! if ($dothis == "mov_title") { $titleyear = $this->infoar[0]; print $titleyear; } elseif ($dothis == "mov_img") { $img = $this->infoar[1]; print $img; } elseif ($dothis == "mov_ad") { $ad = $this->infoar[2]; print $ad; } elseif ($dothis == "mov_rd") { $reldate = $this->infoar[3]; print $reldate; } elseif ($dothis == "mov_gen") { $genre = $this->infoar[4]; print $genre; } elseif ($dothis == "mov_len") { $length = $this->infoar[5]; print $length; } elseif ($dothis == "mov_desc") { $desc = $this->infoar[6]; print $desc; } elseif ($dothis == "mov_rate") { $stars = $this->infoar[8]; print $stars; } elseif ($dothis == "mov_mpaa") { $mpaarating = $this->infoar[7]; print $mpaarating; } elseif ($dothis == "mov_star") { $stararray = $this->infoar[14]; // This is for cast and credits foreach ($stararray as $starred) { if (strstr($starred, "Directed")) { list($starring2, $junk) = split("</font>", $starred); print $starring2; }else { print $starred; } } } elseif ($dothis == "mov_dir") { $directarray = $this->infoar[15]; foreach ($directarray as $directed) { if(strstr($directed, "</font>")) { list($directed2, $junkmail) = split("</font>", $directed); print $directed2; }else { print $directed; } } } elseif ($dothis == "mov_pro") { $producearray = $this->infoar[16]; foreach ($producearray as $produced) { if(strstr($produced, "</font>")) { list($produced2, $junkmail) = split("</font>", $produced); print $produced2; }else { print $produced; } } } elseif ($dothis == "mov_c1rev_ti") { $critic_rever1_2 = $this->infoar[9][0]; print $critic_rever1_2; } elseif ($dothis == "mov_c1rev_com") { $critic_revcom1_1 = $this->infoar[9][1]; print $critic_revcom1_1; } elseif ($dothis == "mov_c1rev_grd") { $critic_revgrd1_1 = $this->infoar[9][2]; print $critic_revgrd1_1; } elseif ($dothis == "mov_c2rev_ti") { $critic_rever2_2 = $this->infoar[10][0]; print $critic_rever2_2; } elseif ($dothis == "mov_c2rev_com") { $critic_revcom2_1 = $this->infoar[10][1]; print $critic_revcom2_1; } elseif ($dothis == "mov_c2rev_grd") { $critic_revgrd2_1 = $this->infoar[10][2]; print $critic_revgrd2_1; } elseif ($dothis == "mov_c3rev_ti") { $critic_rever3_2 = $this->infoar[11][0]; print $critic_rever3_2; } elseif ($dothis == "mov_c3rev_com") { $critic_revcom3_1 = $this->infoar[11][1]; print $critic_revcom3_1; } elseif ($dothis == "mov_c3rev_grd") { $critic_revgrd3_1 = $this->infoar[11][2]; print $critic_revgrd3_1; } elseif ($dothis == "mov_c4rev_ti") { $critic_rever4_2 = $this->infoar[12][0]; print $critic_rever4_2; } elseif ($dothis == "mov_c4rev_com") { $critic_revcom4_1 = $this->infoar[12][1]; print $critic_revcom4_1; } elseif ($dothis == "mov_c4rev_grd") { $critic_revgrd4_1 = $this->infoar[12][2]; print $critic_revgrd4_1; } elseif ($dothis == "mov_other") { $titleyear = $this->infoar[0]; $offic_url = $this->infoar[13]; print " <ul> <li><font size=\"1\">$offic_url Visit $titleyear Official Website</a></font> <li><font size=\"1\"><a target=\"_new\" href=\"http://www.google.com/search?hl=en&ie=UTF-8&btnG=Google+Search&q=$titleyear\">Search Google for $titleyear </a></font> <li><font size=\"1\"><a target=\"_new\" href=\"http://www.emocium.com/forum/forumdisplay.php?f=8\">Discuss at Emocium Forum</a></font> </ul>"; } } function error($num, $msg) { if ($num == 1) { print "<font color=\"red\">".$msg."</font>"; } } } class tpl_sysls { var $structure; var $showme; var $content; var $filename; var $inc_file; var $theatar = array(); var $infoar = array(); // This is so we know what to display! var $dowhat = array("ls" => array("ls_vdate", "ls_dates", "ls_zip", "nav_theaters", "mv_name", "mv_rate", "mv_len", "mv_time", "mv_name2", "mv_rate2", "mv_len2", "mv_time2", "th_name", "th_city", "th_state", "th_phone", "th_map", "th_hand", "th_hear", "th_addr", "th_zip", "incfile", "copyright", "loop_th_mov", "end_th_mov", "end_mov", "loop_mov", "ls_title", "ls_bookm")); ################# # # # Initiation # # # ################# function template($filename) { $this->filename = $filename; $this->structure = array(); $this->structure = $this->loadfile($this->filename); $this->parse($this->structure); } function loadfile($filename) { if(file_exists($filename)) { $content = file($filename); /*$fo = fopen($filename, "r"); $content = fread($fo, filesize($filename)); fclose($fo);*/ } else $content = '[ERROR: "'.$filename.'" does not exist.]'; return $content; } function include_file($filename) { if(file_exists($filename)) { $this->inc_contents = file($filename); }else $include = '[ERROR: "'.$filename.'" does not exist.]'; return $include; } function parse($structure) { $b=0; $cop = 0; $cnt_num = count($structure); if ($this->showme == "ls") { while ($b < $cnt_num) { if (ereg("([G,g]){1}([E,e]){1}([T,t]){1}\{([a-zA-Z0-9_.]*)\}", $structure[$b])) { $gets = split("([G,g]){1}([E,e]){1}([T,t]){1}\{", $structure[$b]); $z=0; foreach ($gets as $get) { if($get != "") { if (!strstr($get, "}")) { $first = $get; } else { list($namez[$z], $last[$z]) = split("\}", $get); $z++;} } } $z=0; foreach ($namez as $name){ $name = strtolower($name); if (strstr($name, "loop_th_mov")) { $c = $b + 1; $a = 0; $stop = "no"; while ($stop != "yes") { $loop_info[$a] = $structure[$c]; if (strstr(strtolower($structure[$c]), "end_th_mov")) { $stop = "yes"; } $c++; $a++; } $place = array($b, $c); $this->loopIt($name, $loop_info, $th); $b = $c-1; }else { $error=1; if($name == "copyright") { $cop = 1; } foreach ($this->dowhat["ls"] as $info) { if ($name == $info) { if ($z == 0) { print $first; }; $this->getBlockLs($name, $th); $error = 0; } } if ($error == 1) { $this->error($error, $name . " is not a valid call statement"); print $loop_info[$i]; } } print $last[$z]; $z++; } } else { print $structure[$b]; } $b++; } } } ################# # # # Blocks # # # ################# function getBlockLs ($dothis, $th) { $theat_ar = $this->theatar['thinfo']; if (strstr($dothis, "mv_")) { $th2 = $th[0]; $i = $th[1]; $b = $i + 1; $theat_ar = $this->theatar; if ($theat_ar["disp"][$th2][$i] == "sorry") { if ($dothis == "mv_name") { print "<b>Sorry</b>"; } // check on this elseif ($dothis == "mv_rate") { print $theat_ar["mvsorry"][$th2][$i]; } elseif ($dothis == "mv_len") { print ""; } elseif ($dothis == "mv_time") { print ""; } } elseif ($theat_ar["disp"][$th2][$i] == "show" && !strstr($dothis, "2") || $theat_ar["disp"][$th2][$b] == "show" && strstr($dothis, "2")) { if ($dothis == "mv_name") { print $theat_ar["movname"][$th2][$i]; } elseif ($dothis == "mv_rate") { print $theat_ar["movrate"][$th2][$i]; } elseif ($dothis == "mv_len") { print $theat_ar["movlen"][$th2][$i]; } elseif ($dothis == "mv_time") { print $theat_ar["tmshow"][$th2][$i]; } elseif ($dothis == "mv_name2") { print $theat_ar["movname"][$th2][$b]; } elseif ($dothis == "mv_rate2") { print $theat_ar["movrate"][$th2][$b]; } elseif ($dothis == "mv_len2") { print $theat_ar["movlen"][$th2][$b]; } elseif ($dothis == "mv_time2") { print $theat_ar["tmshow"][$th2][$b]; } } elseif ($theat_ar["disp"][$th2][$i] == "buy" && !strstr($dothis, "2") || $theat_ar["disp"][$th2][$b] == "buy" && strstr($dothis, "2")) { if ($dothis == "mv_name") { print $theat_ar["movname"][$th2][$i]; } elseif ($dothis == "mv_rate") { print $theat_ar["movrate"][$th2][$i]; } elseif ($dothis == "mv_len") { print $theat_ar["movlen"][$th2][$i]; } elseif ($dothis == "mv_time") { $buytick = ereg_replace("\(", "", $theat_ar["buytm"][$th2][$i]); $buytick = ereg_replace("\)", "", $buytick); print $buytick; } elseif ($dothis == "mv_name2") { print $theat_ar["movname"][$th2][$b]; } elseif ($dothis == "mv_rate2") { print $theat_ar["movrate"][$th2][$b]; } elseif ($dothis == "mv_len2") { print $theat_ar["movlen"][$th2][$b]; } elseif ($dothis == "mv_time2") { $buytick = ereg_replace("\(", "", $theat_ar["buytm"][$th2][$b]); $buytick = ereg_replace("\)", "", $buytick); print $buytick; } } elseif ($theat_ar["disp"][$th2][$i] == "starts" && !strstr($dothis, "2") || $theat_ar["disp"][$th2][$b] == "starts" && strstr($dothis, "2")) { if ($dothis == "mv_name") { print $theat_ar["movname"][$th2][$i]; } elseif ($dothis == "mv_rate") { print $theat_ar["movrate"][$th2][$i]; } elseif ($dothis == "mv_len") { print $theat_ar["movlen"][$th2][$i]; } elseif ($dothis == "mv_time") { print $theat_ar["starts"][$th2][$i]; } elseif ($dothis == "mv_name2") { print $theat_ar["movname"][$th2][$b]; } elseif ($dothis == "mv_rate2") { print $theat_ar["movrate"][$th2][$b]; } elseif ($dothis == "mv_len2") { print $theat_ar["movlen"][$th2][$b]; } elseif ($dothis == "mv_time2") { print $theat_ar["starts"][$th2][$b]; } } } elseif ($dothis == "ls_zip") { print ereg_replace("%20", " ", $this->theatar["zip"]); } elseif ($dothis == "ls_title") { print $this->theatar["title"]; } elseif ($dothis == "nav_theaters") { print $this->theatar["thls"]; } elseif ($dothis == "ls_vdate") { print $this->theatar["vdate"]; } elseif ($dothis == "ls_dates") { print $this->theatar["dates"]; } elseif ($dothis == "th_name") { print $theat_ar['names'][$th]; } elseif ($dothis == "th_addr") { print $theat_ar["address"][$th]; } elseif ($dothis == "th_city") { print $theat_ar["cities"][$th]; } elseif ($dothis == "th_state") { print $theat_ar["state"][$th]; } elseif ($dothis == "th_zip") { print $theat_ar["zips"][$th]; } elseif ($dothis == "th_phone") { print $theat_ar["phone"][$th]; } elseif ($dothis == "th_map") { print $theat_ar["map"][$th]; } elseif ($dothis == "th_hand") { print $theat_ar["hand"][$th]; } elseif ($dothis == "th_hear") { print $theat_ar["hear"][$th]; } elseif ($dothis == "ls_bookm") { print $this->theatar["bm"]; } } function loopIt($dothis, $loop_info, $place) { $theat = array(); $loop_minfo = array(); if ($dothis == "loop_th_mov" && $bob != "no") { $theat = $this->theatar['thinfo']; $th = 0; $bob = "no"; } if ($dothis == "loop_th_mov") { while ($th < $theat["cnt"]) { $d = $place[0]; //b $e = $place[1]; //c $i=0; $cnt_loop = count($loop_info); while ($i < $cnt_loop) { $first = ""; $namez = ""; $last = ""; $get = ""; $name = ""; if (ereg("([G,g]){1}([E,e]){1}([T,t]){1}\{([a-zA-Z0-9_.]*)\}", $loop_info[$i])) { $gets = split("([G,g]){1}([E,e]){1}([T,t]){1}\{", $loop_info[$i]); $z=0; foreach ($gets as $get) { if($get != "") { if (!strstr($get, "}")) { $first = $get; } else { list($namez[$z], $last[$z]) = split("\}", $get); $z++;} } } $z=0; foreach ($namez as $name){ $name = strtolower($name); if (strstr($name, "loop_mov")) { $c = $i; $a = 0; $stop = "no"; while ($stop != "yes") { $loop_minfo[$a] = $loop_info[$c]; if (strstr(strtolower($loop_info[$c]), "end_mov")) { $stop = "yes"; } $c++; $a++; } $this->loopIt($name, $loop_minfo, $th); $i = $c-2; } else { $error=1; foreach ($this->dowhat["ls"] as $info) { if ($name == $info) { if ($z == 0) { print $first; }; $this->getBlockLs($name, $th); $error = 0; } } if ($error == 1) { $this->error($error, $name . " is not a valid call statement"); print $loop_info[$i]; } else { if ($last[$z] != "") { print $last[$z]; }} } $z++; } } else { print $loop_info[$i]; } $i++; } $th++; } }elseif ($dothis == "loop_mov") { //print_r($loop_info); $th = $place; $k=1; $cnt_loop = count($loop_info); $cnt_disp = count($this->theatar["disp"][$th]); $chk = $this->oddeven($cnt_disp); if ($chk == "odd") { $cnt_disp += 1;} while ($k <= $cnt_disp) { $i=0; while($i < $cnt_loop) { $first = ""; $namez = ""; $last = ""; $get = ""; $name = ""; if (ereg("([G,g]){1}([E,e]){1}([T,t]){1}\{([a-zA-Z0-9_.]*)\}", $loop_info[$i])) { $gets = split("([G,g]){1}([E,e]){1}([T,t]){1}\{", $loop_info[$i]); $z=0; foreach ($gets as $get) { if($get != "") { if (!strstr($get, "}")) { $first = $get; } else { list($namez[$z], $last[$z]) = split("\}", $get); $z++;} } } $z=0; $error=1; foreach ($namez as $name) { $name = strtolower($name); foreach ($this->dowhat["ls"] as $info) { if ($name == $info) { if($z == 0) { print $first; }; $thx = array($th, $k); $this->getBlockLs($name, $thx); $error = 0; } } if ($error == 1) { $this->error($error, $name . " is not a valid call statement"); print $loop_info[$i]; } else { if ($last[$z] != "") { print $last[$z]; }} $z++; } } else { print $loop_info[$i]; } $i++; } $k += 2; } } } function oddeven($x){ if($x & 1) return "odd"; else return "even"; } function error($num, $msg) { if ($num == 1) { print "<font color=\"red\">".$msg."</font>"; } } } ?> Hope it helps. Quote Link to comment https://forums.phpfreaks.com/topic/54349-simple-template-engine/#findComment-269186 Share on other sites More sharing options...
robgolding63 Posted June 6, 2007 Author Share Posted June 6, 2007 My only other idea for this would be to cheat, and have the PHP construct the loop into a variable, and then pass that to the template so all it would need to do it display the contents. ie. <?php $menu = ''; while ($row = mysql_fetch_array($sql)) { $menu .="<a href='".$row['href']."'>".$row['title']."</a><br />"; } ?> But that's not very neat at all, and I can't figure out any other way to solve the problem, is there an elegant solution that is simpler, or would my template system have to become very complicated to handle such functions. Thanks for all the help, Rob P.S. I will have a good look through that code, frost110, thanks for posting it! Quote Link to comment https://forums.phpfreaks.com/topic/54349-simple-template-engine/#findComment-269198 Share on other sites More sharing options...
robgolding63 Posted June 6, 2007 Author Share Posted June 6, 2007 Well, I finished it today I don't know how clear or "proper" my code it, but it's my first attempt at a neat, object-oriented project, so here's the main template code: <?php class template { var $page; var $template_path = "templates/"; var $vars; var $tpl_data; var $cur_loop; /* /* Constructor */ function template($template) { // Check if template file exists if (file_exists($this->template_path . $template)) { // Load contents into $this->page if (!$this->page = file_get_contents($this->template_path . $template)) { die ("Error loading template"); } } else { die("Could not find template file"); } } function assign_var($varname, $varval) { $this->vars[$varname] = $varval; return true; } function assign_vars($vararray) { foreach ($vararray as $key => $val) { $this->vars[$key] = $val; } return true; } function assign_block_vars($blockname, $vararray) { // Add a new iteration to this block with the variable assignments we were given. $this->tpl_data[$blockname][] = $vararray; } function loops() { foreach($this->tpl_data as $loop => $vararray) { $this->cur_loop = $this->tpl_data[$loop]; $this->page = preg_replace_callback('^<!--\s?LOOP\s('.$loop.')\s?-->(.+)<!--\s?END\sLOOP\s?-->^si', array('template', 'loop_callback'), $this->page); } } function loop_callback($matches) { $result = ''; foreach ($this->cur_loop as $vararray) { foreach ($vararray as $key => $val) { $result .= str_replace("{".$key."}", $val, $matches[2]); } } return $result; } function compile() { $this->loops(); foreach ($this->vars as $key => $val) { $this->page = str_replace("{".$key."}", $val, $this->page); } } function output() { $this->compile(); print $this->page; } } ?> It would be great if you had any tips or warnings about things that I may have done wrong, I need to make sure the code is OK before putting it into production Thanks for the help, Rob Quote Link to comment https://forums.phpfreaks.com/topic/54349-simple-template-engine/#findComment-269552 Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.