...

View Full Version : Dynamic function generation using include()?



WA
11-29-2006, 12:52 PM
I was wondering what the best approach to my problem is. Basically I need to dynamically generate a portion of a function (not its output), with that portion coming from say an external file. So instead of:


function test(){
$x="whatever";
for ($i=0; $i<5; $i++){
echo date("l \\t\h\e jS");
echo '<b>Example</b>';
}
}

I need to have the code in red come from an external file (mostly output codes), and dynamically included as part of the function code:



template1.php:

<?
echo date("l \\t\h\e jS");
echo '<b>Example</b>';
?>

Modified function:

function test(){
$x="whatever";
for ($i=0; $i<5; $i++){
include("template1.php");
}
}


Now, the modified function above works, but I know it's very inefficient (ie: including the same piece of code 5 times), not to mention perhaps poorly thought out. Are there more elegant ways to dynamically generate a portion of a function from an external file, especially inside a for loop? The task I'm trying to accomplish is basically to create user swappable templates for the code portion in red of the function.

Thanks,

chump2877
11-29-2006, 01:01 PM
Is there only the one file: template1.php,

Or are there many different files: template1.php, template2.php, template3.php, template4.php, etc...?

My guess is there is only one, because you are not passing the template file name into the function?

WA
11-29-2006, 11:31 PM
Nope, there will be many, as it will be user customizable at the top of the script. So something like:


$templatepath="template2.php";

Spookster
11-30-2006, 12:10 AM
If you need to dynamically include other files then just pass the name of the include file into the function.

marek_mar
11-30-2006, 12:46 AM
Why not use other functions? You are using the include as if it was a function...

jkd
11-30-2006, 12:56 AM
Why not use a wannabe lambda construct:
http://us3.php.net/create_function

Fou-Lu
11-30-2006, 01:20 AM
Wow, so many old faces :)

Since it appears to be used as templates for output, perhaps using a specially defined eval function would work best for you? Something simple, just read the file in, parse the file, and return the output? You can use that in a loop as well, and I think it would work quite well so long as you are using it as output templates.

ralph l mayo
11-30-2006, 01:22 AM
Any reason you don't just enclose the code in the includes in a function wrapper so you can include once and just call the function in the loop? Here's a function that'll wrap them for you, but whether it'll be any faster than just including in the loop, meh.



<?php
function inclose($filename)
{
$code = file_get_contents($filename);
if (!$code)
{
throw new Exception('oh noes');
}
$code = preg_replace('/(?:\<\?(?:php)?|\?\>)/xms', '', $code);

return create_function('', $code);
}

$func = inclose('template1.php');
for ($i = 0; $i < 5; ++$i)
{
$func();
}
?>


Edit for another even slower version with enterprisey caching:



abstract class Inclosure
{
public static function inclose($filename)
{
static $func_repo;
if (!isset($func_repo[$filename]))
{
$func_repo[$filename] = Inclosure::load_file($filename);
}
return $func_repo[$filename];
}

private static function load_file($filename)
{
$code = file_get_contents($filename);
if (!$code)
{
throw new Exception('oh noes');
}
$code = preg_replace('/(?:\<\?(?:php)?|\?\>)/xms', '', $code);

return create_function('', $code);
}
}

$func = Inclosure::inclose('myinc.php');
for ($i = 0; $i < 5; ++$i)
{
$func();
}

chump2877
11-30-2006, 01:31 AM
it seems like your best bet is to open some or all of your files outside of the function and for loop, and dump them into variables.

Store your template code in text files, so template1.txt could be:


echo date("l \\t\h\e jS");
echo '<b>Example</b>';

Let's say $template is an array of your template file names,


$template = array('template1.txt','template2.txt','template3.txt','template4.txt');

foreach ($template as $val) {
$template_contents[] = file_get_contents('/path/to/templates/'.$val);
}then use eval() (http://us2.php.net/manual/en/function.eval.php) inside your function, and pass the template file contents as an argument....so this function:


function test($the_code){
$x="whatever";
for ($i=0; $i<5; $i++){
eval($the_code);
}
} would be called like:


test($template_contents[2]); // To pass the file contents of template3.php into your function
Edit: And if the user is selecting a template via GET or POST, then all you need to do is:


$template = array('template1.txt','template2.txt','template3.txt','template4.txt');

if (in_array($_POST['template_name'],$template))
$template_contents = file_get_contents('/path/to/templates/'.$_POST['template_name']);

test($template_contents);And use the same function as above.

WA
12-02-2006, 08:01 AM
Thanks guys for all the responses, and sorry for the delay in posting back. I haven't had a chance to revisit this issue until now. Chump2877, your solution looks like it could be what I need, thanks. I'm a little hesistant of using eval() though for security reasons, though I don't see any issues right out of the bat on the above.

chump2877
12-02-2006, 10:32 AM
Another thing I was thinking, too, if you're worried about storing code in flat files, and the potential security issues with that -- then store the code in a MySQL database.

It might speed up your script too, since there will be no opening up and reading of files. Just database queries.

Food for thought.

WA
12-02-2006, 11:43 AM
Thanks Chump2877, I've been thinking about that as well. mySQL certainly would make things more secure, especially with such a setup.



EZ Archive Ads Plugin for vBulletin Copyright 2006 Computer Help Forum