Jump to content

[SOLVED] OO template variables w/helpers


gijew

Recommended Posts

I'm writing a class to help automate all of the cron jobs I run at work and integrated a small template system. It worked well until I tried to integrate a few "other" features, this happens.

 

The template variables are formatted like Smarty (because I already use Smarty so I figured it would be easier for me to remember).

Ex: {$variable|capitalize}

 

Now, since I don't feel like typing out a bunch of database fields and assigning them like Smarty ($smarty->assign('name', $var) - which I would have to do the Smarty way) it loops through an array of database fields.

 

What I'm thinking it should be doing (which it does not do) is replace the variable {$loan_type} with the database field `loan_type`. It would also parse the template variable to see if there is any special formatting or instructions like in this example {$loan_type|capitalize} and capitalize it.

 

So, an example of what it actually does...

Example (using 3 records)

 

Database rows

`loan_type | data: purchase`

`loan_amount | data: 850000`

`cltv | data: 88`

 

Template

`{$loan_type|capitalize}`

`{$loan_amount|currency}`

`{$cltv|percentage}`

 

Expected output

`Purchase`

`$850,000`

`88%`

 

Here's a bit of code to work with (only throwing this one out because it was much simplier approach than my first time out). This one is totally broken and I'm at my wits end here so sorry if it's effed up.

 

<?php
/* Example of what is being returned from mysql - 
(mysql): SELECT loan_type,loan_amount,cltv FROM form_loan_scenarios WHERE emailed = 0 ORDER BY date_submitted desc */

public function process_cronjob() {
$sql = $this->db->GetAll("
	SELECT	" . $this->db_rows 	. "
	FROM 	" . $this->db_table 	. "
	" . $this->db_join_table . "
	" . $this->db_join_table_on . "
	" . $this->db_criteria . "
	" . $this->db_sort 	. "
	" . $this->db_limit . "
");

if (count($sql) != 0) {
	$counter 			= -1;
	$db_rows 			= explode(',', $this->db_rows);
	$mailer_template 	= file_get_contents($this->mailer_template);

	foreach ($sql as $r) {
		$counter++;
		for ($f = 0; $f <= $this->db_row_count - 1; $f++) {
			$output = $this->helpers(str_replace($db_rows[$f], $r[$f], $mailer_template));
		}
		echo $output;

		echo '<hr />';
	}
}
}

private function helpers($t) {
if (preg_match('/({\$)([a-z0-9_]+)[(|)]?([a-z]+)(})/', $t, $matches)) {
	$split_matches 	= explode('|', $matches[0]);
	$data 			= $split_matches[0];
	$format 		= $split_matches[1];

	switch ($format) {
		case 'capitalize';
			if (!empty($data)) $replace = ucwords(strtolower($data));
		break;

		case 'percentage';
			if (!empty($data)) $replace = number_format($data, 0) . '%';
		break;

		case 'currency';
			if (!empty($data)) $replace = $this->readable_number($data);
		break;
	}

	return str_replace($matches[0], $replace, $t
}
}

/* 
Outputs:
Loan Type  		[nothing]
Loan amount 	{$loan_amount|currency}
CLTV 			{$cltv|percentage}
*/
?>

Link to comment
Share on other sites

just use str replace :)

 

foreach ($row as $k => $v) {

  str_replace('{'.$k.'}',$v,$data);

}

 

if you want to add those 'flags' in you might want to use substr and strpos to look for { and then get the rest to } remove the { } in the variable and then explode by | and then loop thru the parameters, or just pass it to a function which expects the parameters ion the order they were expecting them, either way its doable.

Link to comment
Share on other sites

I thought about the str_replace, strpos and what not but I was having trouble coming up with a solution that would allow me to wildcard the string (like regex allows for). Using the approach you suggested (albeit probably not the best implementation on my part) only lets me retrieve / match the first part but I have no other way of knowing ahead of time what the format type should be as it's stored in the template, which I must read first. I think I just went cross-eyed.

 

<?php
foreach ($sql as $k => $v) {
for ($f = 0; $f <= $this->db_row_count - 1; $f++) {
	if (!empty($v[$f])) {
		$string1 	= $db_rows[$f];
		$pos1 		= stripos($mailer_template, $string1);

		if ($pos1 !== false) {
			$word = substr($mailer_template, $pos1, strlen($string1));

			echo str_replace($word, $v[$f], $word) . '<br />';
		}
	} else {
		echo 'empty <br>';
	}
}
echo '<hr />';
}
?>

Link to comment
Share on other sites

Dunno if this is exactly what you want, but I fancied playing anyway;

 

<?php
/**
* The functions you want to use
* I've made three cheap and chearful ones
* To fit your OP
*/
function capitalize($value) {
return ucfirst($value);
}
function currency($value) {
return '$' . number_format($value);
}
function percentage($value) {
return $value."%";
}

/**
* Emulate your sql results
* Should make sense
*/
$data = array(
"loan_type" => "purchase",
"loan_amount" => "850000",
"cltv" => "88"
);

/**
* Test Content
* This would be your template
*/
$content = 'The details<br />
Loan Type: {$loan_type|capitalize}<br />
Loam Amount: {$loan_amount|currency}<br />
CLTV: {$cltv|percentage}';

//Loop through each field of the returned table (array for me)
foreach($data as $k => $v) {
//regex pattern to find the temp string
$pattern = '#{\$'.$k.'\|[a-z]+}#';
preg_match($pattern, $content, $matches);
$match = $matches[0];

//get just the function you want to run
$func_array =  explode("|", $match);
$func = str_replace("}", "", $func_array[1]);

//run the function on the data (if it exists)
if(function_exists($func)) {
	$value = $func($v);
}//you may want a fallback here

//replace the temp string with your formatted content
$content = str_replace($match, $value, $content);
}

echo $content;

Link to comment
Share on other sites

SO CLOSE!

That's almost exactly right except...

 

Now all the variables are switching out correctly and the helpers are being applied BUT now they aren't switching out with the template. Example time...

 

<?php
if (count($sql) != 0) {

$counter 			= -1;
$db_rows 			= explode(',', $this->db_rows);
$mailer_template 	= file_get_contents($this->mailer_template);

foreach($sql as $k => $v) {
	for ($f = 0; $f <= $this->db_row_count - 1; $f++) {
		$pattern = '#{\$' . $db_rows[$f] . '\|[a-zA-Z0-9\=\-\_\: ]+}#';
		preg_match($pattern, $mailer_template, $matches);
		$match = $matches[0];

		if (!empty($match)) {
			$split 		= explode('|', $match);
			$data 		= str_replace('{$', '', $split[0]);
			$format 	= str_replace('}', '', $split[1]);
			$helper 	= $this->helpers($v[$f], $format);

			echo $data . ' | ' . $format . ' | ' . $helper . '<br />';

			$content 	= str_replace($match, $helper, $mailer_template);
		}
	}
	echo $content;
	echo '<hr />';
}
}
?>

 

That outputs the following:

loan_type | capitalize | Purchase

loan_amount | currency | 612,000

cltv | percentage | 80%

 

The template however still outputs

Loan Type    {$loan_type|capitalize}

Loan amount {$loan_amount|currency}

CLTV           {$cltv|percentage}

Link to comment
Share on other sites

change;

 

            $content    = str_replace($match, $helper, $mailer_template);
         }
      }
      echo $content;

to

 

            $mailer_template    = str_replace($match, $helper, $mailer_template);
         }
      }
      echo $mailer_template;

Link to comment
Share on other sites

Pfft, you're smart'n me...today (probably tomorrow too but I'm not keeping track) :P

 

I hate to be a PITA but this script has broken me. Any suggestions on why it keeps outputting the same record? Just for fun I opened up 3, 4 records to see how it would perform and they are all the same one. I tried unsetting the $mailer_template variable but nuttin.

Link to comment
Share on other sites

Without seeing the whole script, and the class that your using I can't comment on more than is on the screen. Feel free to add more script if you fancy. I've been thinking about building a simple template system for a framework, this is good practice ;)

 

With more time there might be a more efficient way to do it, though I think my first post is pretty decent

Link to comment
Share on other sites

Actually all of the magic is happening in that method because I ripped out everything else to try and get it to output the right data. I'm glad I can help you practice hehe.

 

Anyhoo, here is the entire guy in all it's barebones glory (not much has changed besides the template processing).

 

Now, what I've found is that if I comment out the line:

$mailer_template 	= str_replace($match, $helper, $mailer_template);

 

And print out the data directly:

echo $data . ' | ' . $format . ' | ' . $helper . '<br />';

 

It displays all of the records. As soon as I try and output the $mailer_template again it just uses the same record again and again.

 

<?php
public function process_cronjob() {

$sql = $this->db->GetAll("
	SELECT	" . $this->db_rows 		. "
	FROM 	" . $this->db_table 	. "
	" . $this->db_join_table 		. "
	" . $this->db_join_table_on 	. "
	" . $this->db_criteria 			. "
	" . $this->db_sort 				. "
	" . $this->db_limit 			. "
");

if (count($sql) != 0) {

	$counter 			= -1;
	$db_rows 			= explode(',', $this->db_rows);
	$mailer_template 	= file_get_contents($this->mailer_template);

	foreach($sql as $k => $v) {
		for ($f = 0; $f <= $this->db_row_count - 1; $f++) {
			$pattern = '#{\$' . $db_rows[$f] . '\|[a-zA-Z0-9\=\-\_\: ]+}#';
			preg_match($pattern, $mailer_template, $matches);
			$match = $matches[0];

			if (!empty($match)) {
				$split 		= explode('|', $match);
				$data 		= str_replace('{$', '', $split[0]);
				$format 	= str_replace('}', '', $split[1]);
				$helper 	= $this->helpers($v[$f], $format);

				echo $data . ' | ' . $format . ' | ' . $helper . '<br />';

				//$mailer_template 	= str_replace($match, $helper, $mailer_template);
			}
		}
		echo $mailer_template;
		echo '<hr />';
	}
}
}
?>

Link to comment
Share on other sites

I'm can't really get my head around it, without seeing the methods working on db_rows, what is set in $sql etc...

 

 

Can you give me an example of the output without the final string replace (as your code is above), so;

 

first iteration

echo $data . ' | ' . $format . ' | ' . $helper . '<br />';

echo $data . ' | ' . $format . ' | ' . $helper . '<br />';

echo $data . ' | ' . $format . ' | ' . $helper . '<br />';

 

second iteration

echo $data . ' | ' . $format . ' | ' . $helper . '<br />';

echo $data . ' | ' . $format . ' | ' . $helper . '<br />';

echo $data . ' | ' . $format . ' | ' . $helper . '<br />';

 

If you're figuring it out yourself don't worry ;)

Link to comment
Share on other sites

I attached all files associated (except configs, adodb libs, etc). It's pretty raw so please don't beat me :)

 

I know the database structure blows but I'm not allowed to change it.

 

I included:

  • The class
  • The page used to call it
  • The mail template
  • Sample db structure with 2 test records
  • Sample output

 

I really can't thank you enough for taking as much time as you have already. I guess it pays to be part of a good community :)

 

And FYI: I'm still working on getting this resolved myself but I figured I put what I had out there in case you're quicker hehe.

 

 

[attachment deleted by admin]

Link to comment
Share on other sites

Well, I've got it working, but I substituted all your db stuff for my own, so I've changed a load of variables and may make no sense.

 

can you do this;

 

echo '<pre>';
var_dump($sql);
echo '</pre>'

 

straight after $sql is set. So I can just duplicate your db result and try and get you something.

Link to comment
Share on other sites

Though on a quick though try this;

 

change

$mailer_template 	= file_get_contents($this->mailer_template);

to

$template 	= file_get_contents($this->mailer_template);

 

and....

change

foreach($sql as $k => $v) {
for ($f = 0; $f <= $this->db_row_count - 1; $f++) {

to

foreach($sql as $k => $v) {
$mailer_template = $template;
for ($f = 0; $f <= $this->db_row_count - 1; $f++) {

Link to comment
Share on other sites

Holy crap. It works. To be honest, I was just throwing a few variables around and don't even know what did it to make it work but it works lol.

 

This was the final go. I'll have to compare the last try to this one. Maybe the browser cached something, dunno.

 

Either way, I can't thank you enough for the time you spent helping me along with this. It is VERY much appreciated! If you're ever in Southern California, expect to get free beer!

 

<?php
public function process_cronjob() {

$sql = $this->db->GetAll("
	SELECT	" . $this->db_rows 		. "
	FROM 	" . $this->db_table 	. "
	" . $this->db_join_table 		. "
	" . $this->db_join_table_on 	. "
	" . $this->db_criteria 			. "
	" . $this->db_sort 				. "
	" . $this->db_limit 			. "
");

if (count($sql) != 0) {

	$counter 			= -1;
	$db_rows 			= explode(',', $this->db_rows);
	$template    		= file_get_contents($this->mailer_template);

	foreach($sql as $k => $v) {
		$mailer_template = $template;

		for ($f = 0; $f <= $this->db_row_count - 1; $f++) {
			$pattern = '#{\$' . $db_rows[$f] . '\|[a-zA-Z0-9\=\-\_\: ]+}#';
			preg_match($pattern, $mailer_template, $matches);
			$match = $matches[0];

			if (!empty($match)) {
				$split 		= explode('|', $match);
				$data 		= str_replace('{$', '', $split[0]);
				$format 	= str_replace('}', '', $split[1]);
				$helper 	= $this->helpers($v[$f], $format);

				$mailer_template 	= str_replace($match, $helper, $mailer_template);
			}
		}
		echo $mailer_template;
		echo '<hr />';
	}
}
}
?>

Link to comment
Share on other sites

This thread is more than a year old. Please don't revive it unless you have something important to add.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.