missing the obvious?

PHP programming forum. Ask questions or help people concerning PHP code. Don't understand a function? Need help implementing a class? Don't understand a class? Here is where to ask. Remember to do your homework!

Moderator: General Moderators

Post Reply
vwiley1
Forum Newbie
Posts: 8
Joined: Sun Oct 02, 2005 9:30 pm

missing the obvious?

Post by vwiley1 »

Hi,

I am almost done with a script I am writing but am hung up on the last part.

Here's the process I would like to see happen:
User fills out a form, hits send:
My main script processes the information.

I then want the main script to take an already existing HTML file and open it for reading....replace several variables thourghout, and then save the file in another location.

The existing HTML is actually a PHP. Here is an example of it:
<HTML><HEAD><TITLE>Blah</TITLE></HEAD><BODY>
<P>Firstname: <?php echo $firstname; ?>
</BODY>
</HTML>

I want that file to be opened, all the variables/php code replaced with the variables that were passed to the main script. And I want the main script to save the HTML with the variables replaced to another location.

I tried:
$content = include(/home/user/templates/template.php);

I also tried
$contents = file_get_contents("http://domain.com/templates/template.ph ... $firstname);

Their is actually alot more variables (about 10 total) that I want passed to the other script. I don't care what way it is done, I just want to open a file, replace the variables, and save the file in another location as a .html file.

I already know how to open a file for writing, that is no problem. I just need to find a way to load the template, process the php, and store the output in a string variable. Then I will be able to write that string to a new file.

Thanks
mickd
Forum Contributor
Posts: 397
Joined: Tue Jun 21, 2005 9:05 am
Location: Australia

Post by mickd »

i would do something like have the template page with

Code: Select all

<?php echo $_POST['firstname']; ?>
etc and when they submit the form go there, then in that page bottom use

file_get_contents

file_put_contents

provided file_get_contents returns the html output which im not sure it should work.
User avatar
John Cartwright
Site Admin
Posts: 11470
Joined: Tue Dec 23, 2003 2:10 am
Location: Toronto
Contact:

Post by John Cartwright »

First of all, if you have register globals set to OFF, which as of PHP v. 4.2 it is set to OFF your $firstname will not exist. Replace $firstname to $_POST['firstname'] if your form method is set to post, or $_GET if form method is set to GET (or if you transit the variable through the URL).

Your first example and second example are extremely different methods of handling templating. I'll explain case scenarios for you.

In the first example, what you've done is your including a template file with embedded PHP within the html.. this is fine but once again will not work with your register globals problem.

In your second example, what you've done is simply puts the contents of your template file (including the non-parsed php) into a string. If your going to want to replace certain elements of your template file into parsed data, much like favorable applications like smarty, then your going to have to break it down into a few more steps, and a little tweaking of your method (I'll explained in a second).

You've done the first step, which is getting the template file into a string. What you have to do next is compile a list of variables that you want replaced. I'll include an example of a simple template class that I commonly use for small applications.

So now you want to pass a list of variables and values you want processed by your templating class.

//just using dummy variables

Code: Select all

$template->setVar(array( 
   'username' => $_GET['username'],
   'firstname' => $_GET['firstname']
);
Now that we have our list of variables lets grab all the variables in the template file that needs parsing.

Code: Select all

$add = '';
$pattern = '#\{(';
//this->vars comes from when you set the variables using $template->setVar
foreach($this->vars as $k => $v) {
   $add .= (!empty($add) ? '|' : '') . preg_quote($k,'#');
}
$pattern .= $add . ')\}#';
This is of course assuming that you have converted your template file to a certain format. In your template example, you embed php directly in the template file, but in this case we will simply have {username} in the template file. Now that little snipplet will create your pattern to match all the vars you inputted into setVar to the template file itself. In our case we used 'username' and 'firstname', so our pattern is dynamically made to fit the variables inputted.

Now this is when the variables are processed.

Code: Select all

while(preg_match($pattern, $this->allblock, $match)) {
  $content = str_replace($match[0], $this->vars[$match[1]], $this->allblock);
}
Now all your variables will have been replaced with the variables values. This is extremely useful from seperating presentation from logic.
Hope that helps.
vwiley1
Forum Newbie
Posts: 8
Joined: Sun Oct 02, 2005 9:30 pm

Post by vwiley1 »

Ok, here is what I have now: Please let me know if I am doing it right. I am not sure if I am using the variables correctly. Right now I am getting the following error.

The error is: Fatal error: Call to a member function on a non-object in /path/to/main.php on line 257

Code: Select all

253 : $load_file = $templates_dir."file.php";
254 :
255 : $content = file_get_contents($load_file);
256 : 
257 : $template->setVar(array(
258 :    'girlsname' => $_POST['girlsname'],
259 :    'girlsaddress' => $_POST['girlsaddress']
260 : ));
261 : 
262 : $add = '';
263 : $pattern = '#\{(';
264 : 
265 :      foreach($this->vars as $k => $v) {
266 :           $add .= (!empty($add) ? '|' : '') . preg_quote($k,'#');
267 :      }
268 : 
269 : $pattern .= $add . ')\}#';
270 : 
271 :     while(preg_match($pattern, $this->allblock, $match)) {
272 :           $content = str_replace($match[0], $this->vars[$match[1]], $this->allblock);
      }
mickd
Forum Contributor
Posts: 397
Joined: Tue Jun 21, 2005 9:05 am
Location: Australia

Post by mickd »

have you coded the class that $template should be pointed to?

example

Code: Select all

class ClassName
{
var $templete;
var $var2;
     function setVar($array)
     {
            foreach($array as $key => $value)
            {
             str_replace('{' . $key . '}', $_POST['firstname'], $this->templete);
            }
     }

}
that does nothing and prolly has some mistakes in it, just an example.
User avatar
John Cartwright
Site Admin
Posts: 11470
Joined: Tue Dec 23, 2003 2:10 am
Location: Toronto
Contact:

Post by John Cartwright »

Code: Select all

class template {
   
   //sets the vars
   function setVar($vars) { 
      while (list($key, $val) = each($vars)) {
         $this->vars[$key] = $val;
      }	
      $this->buildRegex();
   }

   //
   function loadFile($file) {
      $this->file = file_get_contents($file);
   }

   function buildBlocks($match) {
      if (preg_match("#(.*?)\[repeatable\](.*?)\[/repeatable\](.*)#s", $this->file, $match)) {
         $this->topBlock = $match[1]
         $this->midBlock .= $match[2];
         $this->botBlock = $match[3];
      }
   }

   //like I showed you before
   function buildRegex() {
      $add = '';
      $this->regex = '#\{(';
      foreach($this->vars as $k => $v) {
         $add .= (!empty($add) ? '|' : '') . preg_quote($k,'#');
      }
      $this->regex .= $add . ')\}#';
   }

   //perform the replacing
   function parse() {
      $this->buildBlocks();
      while(preg_match($this->regex, $this->file, $match)) {
         $this->file = str_replace($match[0], $this->vars[$match[1]], $this->file);
      }
   }
 
   //call very last line of your page
   //should be the only thing to output/print
   function output() {
      echo $this->topBlock;
      echo $this->midBlock;
      echo $this->botBlock;
   }
}
Now things will get slightly more complicated if your going to be looping over your results.
If your going to require "blocks" or "repeatable regions" then your going to have to do a couple more steps.
My my templating engine when I load the file into memory, I perform a simple regex to determine
what is inside [repeatable] [/repeatable]. What is inside that is those blocks is the repeatable region. Things will get much more complicated if you need multiple repeatable regions, but lets keep it simple (for now)..

Code: Select all

preg_match("#(.*?)\[repeatable\](.*?)\[/repeatable\](.*)#s", $this->file, $match)
Now when you are looping over your data, you only want to assign new content to $this->midBlock because that is the repeatable region.

So lets put this in context a little.

Code: Select all

$result = mysql_query('SELECT * FROM `table`') or die(mysq_error());
$template->loadfile('welcome.tpl');

while ($row = mysql_fetch_assoc($result)) {
   $template->setVar(array(
      'username' => $row['username'],
      'firstname' => $row['firstname'],
   ));
   $template->parse();
);

$template->output();
I wrote this whole thing from memory so I may have made a couple mistakes. But this is basically how templating engines work. Should be able to figure it out from here ;)
vwiley1
Forum Newbie
Posts: 8
Joined: Sun Oct 02, 2005 9:30 pm

Post by vwiley1 »

Thanks everyone for helping!

I finally got everything to work properly :D

My script now opens template.php, replaces all the {VARIABLES} and then saves the output to a new file.
Post Reply