jamesmpollard Posted October 5, 2015 Share Posted October 5, 2015 Hi Ladies & Gent's I was wondering if someone could help. Basically I have built a small script that will take a template file - like this one: <html> <head> <title>Test</title> </head> <body> <ul> <li>settings{name} - settings{value}</li> <li>settings{id} - settings{value} - settings{name}</li> <li>settings{value} - settings{name}</li> <li>members{name} - members{email}</li> <li>data{name} - data{email}</li> <li>data{test1} - data{test2}</li> </ul> </body> </html> And replace the tags. "data" stands is replaced with basic data tags and the rest are SQL tags, so settings{name} would indicate to ouput the column "name" from settings. All is working except on thing that I have been trying everything to fix.... On line one we have this: <li>settings{name} - settings{value}</li> and on line two we have <li>settings{id} - settings{value} - settings{name}</li> All ouputs fine, except that because there isn't a request for an ID column on line one (which the ID would in this instance be 1 as it's the first row request), it places the ID in line two's ID column. So on the second row, for ID, it displays 1, when it should display 2. Here is my source: <?phpif (!defined('ND')) { exit('Direct access to this file is not permitted.');} $template_name = 'template'; class template { private $Contents; private $DBTags; private $DTTags; private $TemplateName; public function __construct() { } public function init($TemplateName) { $this->TemplateName = $TemplateName; $this->setTemplate(); } public function addTag($key, $data) { if ($key === 'data') { $this->DTTags[$key] = $data; } else { $this->DBTags[$key] = $data; } } private function setTemplate() { if (file_exists('skins/default/templates/' . $this->TemplateName . '.tpl.php')) { $this->Contents = file_get_contents('skins/default/templates/' . $this->TemplateName . '.tpl.php'); } else { // ERROR HERE } } private function replaceTags() { foreach ($this->DBTags as $TagKey => $TagValue) { for ($i = 0; $i < FrameworkRegistry::getObject('db')->SQLCacheResultCount($TagValue[1]); $i++) { $Value = FrameworkRegistry::getObject('db')->resultsFromCache($TagValue[1]); if (!empty($Value)) { $this->DBTags[$TagKey]['RESULTS'][] = $Value; } } } foreach ($this->DTTags as $DTagKey => $DTagValue) { for ($e = 0; $e < FrameworkRegistry::getObject('db')->DataCacheResultCount(); $e++) { $Value = FrameworkRegistry::getObject('db')->dataFromCache($e); if (!empty($Value)) { $this->DTTags[$DTagKey]['RESULTS'][] = $Value; } } } $this->replaceDBTags(); $this->replaceDataTags(); } private function RemoveCacheItem($Tag, $ID, $Item) { unset($this->DBTags[$Tag]['RESULTS'][$ID][$Item]); } private function replaceDBTags() { foreach ($this->DBTags as $DBKey => $DBValue) { foreach ($DBValue['RESULTS'] as $DBVK => $DBVV) { foreach ($DBVV as $NK => $NV) { $this->Contents = $this->str_replace_first($DBKey . '{' . $NK . '}', (string)$NV); $this->RemoveCacheItem($DBKey, $DBVK, $NK); } } } } private function replaceDataTags() { foreach($this->DTTags['data']['RESULTS'] as $DTKey => $DTValue) { foreach($DTValue as $TK => $TV) { $this->Contents = $this->str_replace_first('data{' . $TK . '}', $TV); } } } private function str_replace_first($search, $replace) { $pos = strpos($this->Contents, $search); if ($pos !== false) { $this->Contents = substr_replace($this->Contents, $replace, $pos, strlen($search)); } return $this->Contents; } public function Output() { $this->replaceTags(); //echo '<pre>' . print_r($this->DTTags, true) . '</pre>'; return $this->Contents; } public function __destruct() { } } Is there anything I can do to stop this? As you can see I've tried writing a function to remove the result set after use so that it will allow it to move to the next one but this doesn't seem to work! All get's removed, but it still doesn't output right! Any help appreciated here. Many thanks James Quote Link to comment Share on other sites More sharing options...
jamesmpollard Posted October 5, 2015 Author Share Posted October 5, 2015 (edited) Sorry, forgot to add. This is the output once ran: <html> <head> <title>Test</title> </head> <body> <ul> <li>skin - default</li> <li>1 - ATestSite - sitename</li> <li>test - atest</li> <li>James - test@test.test</li> <li>jamess - hi</li> <li>test11 - test22</li> </ul> </body> </html> This is what it should be <html> <head> <title>Test</title> </head> <body> <ul> <li>skin - default</li> <li>2 - ATestSite - sitename</li> <li>test - atest</li> <li>James - test@test.test</li> <li>jamess - hi</li> <li>test11 - test22</li> </ul> </body> </html> Edited October 5, 2015 by jamesmpollard Quote Link to comment Share on other sites More sharing options...
QuickOldCar Posted October 5, 2015 Share Posted October 5, 2015 After reading this many times, it seems you have to check if id exists and handle it. So pass an id tag and a value of 1 if not there or -1 the rest of id's Quote Link to comment Share on other sites More sharing options...
jamesmpollard Posted October 5, 2015 Author Share Posted October 5, 2015 After reading this many times, it seems you have to check if id exists and handle it. So pass an id tag and a value of 1 if not there or -1 the rest of id's That last line confused me a bit lol. This is a print out of my example array: Array ( [members] => Array ( [0] => SQL [1] => 0 [RESULTS] => Array ( [0] => Array ( [id] => 1 [name] => James [email] => test@test.test ) ) ) [settings] => Array ( [0] => SQL [1] => 1 [RESULTS] => Array ( [0] => Array ( [id] => 1 [name] => skin [value] => default ) [1] => Array ( [id] => 2 [name] => sitename [value] => ATestSite ) [2] => Array ( [id] => 3 [name] => atest [value] => test ) ) ) ) Quote Link to comment Share on other sites More sharing options...
jamesmpollard Posted October 5, 2015 Author Share Posted October 5, 2015 I've uploaded a screenshot, that array look's ridiculous when pasted lol Quote Link to comment Share on other sites More sharing options...
jamesmpollard Posted October 5, 2015 Author Share Posted October 5, 2015 Using the "settings" key as an example here. What's happening is as it loop's through the system, on the first hit it find's settings{id} and replaces it with the first result set ID. When - if working right, it should be replacing it on the second hit because it's the second "request/line". I've tried making it so that the whole html is broken down line by line and processed that way but that's a massive nightmare and a benchmarking disaster Quote Link to comment Share on other sites More sharing options...
Solution QuickOldCar Posted October 5, 2015 Solution Share Posted October 5, 2015 Just an idea, instead of parsing line by line can't you do something like named blocks in your templates and let your code fill in the correct data as needed? Is a matter of adding the data versus editing them. Can do defines for included scripts or values, or add some unique naming to replace as doing now. <html> <head> <title><?php echo TPL_TITLE;?></title> </head> <body> <div> <?php echo TPL_HEADER;?> </div> <div> <?php echo TPL_CONTENT;?> </div> <div> <?php echo TPL_SIDEBAR;?> </div> <div> <?php echo TPL_FOOTER;?> </div> </body> </html> 1 Quote Link to comment Share on other sites More sharing options...
jamesmpollard Posted October 5, 2015 Author Share Posted October 5, 2015 Just an idea, instead of parsing line by line can't you do something like named blocks in your templates and let your code fill in the correct data as needed? Is a matter of adding the data versus editing them. Can do defines for included scripts or values, or add some unique naming to replace as doing now. <html> <head> <title><?php echo TPL_TITLE;?></title> </head> <body> <div> <?php echo TPL_HEADER;?> </div> <div> <?php echo TPL_CONTENT;?> </div> <div> <?php echo TPL_SIDEBAR;?> </div> <div> <?php echo TPL_FOOTER;?> </div> </body> </html> That's almost what it's going to do when I'm finished, it will have a separate TPL for the header and footer and only really change the body TPL. But for ease of development, I'm trying to get it to parse all the data passed through it correctly which apparently is harder than I thought lol. Basically once the first line (settings{name} & settings{value}) has been parsed, I need it to unset the first result set, then the second and so on. But because everything is dynamic (the results, the requests, etc) I can't set in stone the order, so it's a numbers game. So in essence I need to find a way for the script to go On this line - I need to replace 2 items for the first result set. Then the line after - I need to replace 3 items from the second result set and so on. I was thinking about making it run through every line, gathering a list of replacements needed per line, then sorting them to the results set and str_replace'ing them all using arrays but that didn't seem to work well lol Quote Link to comment Share on other sites More sharing options...
jamesmpollard Posted October 6, 2015 Author Share Posted October 6, 2015 Just an idea, instead of parsing line by line can't you do something like named blocks in your templates and let your code fill in the correct data as needed? Is a matter of adding the data versus editing them. Can do defines for included scripts or values, or add some unique naming to replace as doing now. <html> <head> <title><?php echo TPL_TITLE;?></title> </head> <body> <div> <?php echo TPL_HEADER;?> </div> <div> <?php echo TPL_CONTENT;?> </div> <div> <?php echo TPL_SIDEBAR;?> </div> <div> <?php echo TPL_FOOTER;?> </div> </body> </html> Thank you for your help! I'm going to hit the reset button and start over! Quote Link to comment 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.