Page 1 of 2
A hint of globalizing
Posted: Tue Apr 19, 2005 12:47 am
by phice
I'm currently building a templating system and would like to know how to check if a variable is set in the php document, inside a function.
I currently have:
Code: Select all
function replace_var( $var )
{
if ( @$GLOBALS[ $var[1] ] )
{
return $GLOBALS[ $var[1] ];
}
else
{
return $var[0];
}
}
$contents = preg_replace_callback ( "#{\\$([A-Za-z0-9]+)}#i", "replace_var", $contents );
If you notice, if the variable $var[1] (what's found inside the parenthesis) is previously created then it returns it's contents; otherwise it returns back to what it was. I would like to replace the if ( @$GLOBALS[ $var[1] ] ) (or modify it) so that I can use replace_var('thisvar') or replace_var("that['array'][1][346]"). I don't want to have to globalize anything because I want to be able to use any variable (aside from get, post, session and cookie because those are already in a custom variable).
Your help is greatly appreciated.
Posted: Tue Apr 19, 2005 12:50 am
by phice
I would also like to be able to give a list of variables that are restricted from access (eg, config variables) if you would be so inclined to help.
Posted: Tue Apr 19, 2005 7:06 am
by feyd
probably should use a preg_split to break apart the array bits, then reconstruct it in an isset-type loop.

Posted: Tue Apr 19, 2005 9:16 am
by phice
Could you show me what you're talking about? I've never used preg_split before.
Posted: Tue Apr 19, 2005 9:25 am
by feyd
Code: Select all
<?php
$test = 'testї\'some\']ї"e;more"e;]ї4]їplay]';
$parts = preg_split('#\ї(ї"e;\']?)(.*?)\\1\]#', $test, -1, PREG_SPLIT_DELIM_CAPTURE );
var_export($parts);
?>
Code: Select all
array (
0 => 'test',
1 => '\'',
2 => 'some',
3 => '',
4 => '"e;',
5 => 'more',
6 => '',
7 => '',
8 => '4',
9 => '',
10 => '',
11 => 'play',
12 => '',
)

Posted: Tue Apr 19, 2005 10:18 am
by phice
Now that was just confusing.
Could you show me how to build a $GLOBALS[] variable out of that? Many thanks.
Posted: Tue Apr 19, 2005 10:40 am
by feyd
Code: Select all
<?php
function getGlobal( $str )
{
$parts = preg_split('#\ї(ї"e;\']?)(.*?)\\1\]#', $str, -1, PREG_SPLIT_DELIM_CAPTURE );
$var =& $GLOBALS;
foreach( $parts as $v )
{
if( $v != '\'' && $v != '' && $v != '"e;' )
{
if( isset( $varї$v] ) )
{
$var =& $varї$v];
}
else
{
unset($var);
break;
}
}
}
return isset($var) ? $var : null;
}
$str = 'testї\'some\']ї"e;more"e;]ї4]їplay]';
$str2 = 'thisїdoes]їnot]їexist]';
$testї'some']ї'more']ї4]ї'play'] = 'hi I\'m a global variable!';
var_export(getGlobal( $str ));
echo "e;\n\n"e;;
var_export(getGlobal( $str2 ));
?>
could potentially use a reference as the return, and the return just gives you a flag of success fail. (could return an array too, I guess)
Posted: Tue Apr 19, 2005 10:47 am
by vigge89
I've done this recently, it required a lot of work to get it to properly work :/
You have too split the variable name and the array-bits, and the do an eval ("return $var;");.
Here's a function I made for the purpose of converting variable- and array-names to global names:
Code: Select all
function parser_var2globals ($string) {
$string = preg_replace ('#\$([a-zA-Z0-9_\-]+)#', '$GLOBALS[\\1]', $string);
return $string;
}
If you want to return the value of the variable immidiately, swap the return-line with this:
Code: Select all
return eval ('return '.$string.';');
What it does is that it looks after patterns matching "${varname}" and replaces them with "$GLOBALS[{varname}]". This works for arrays too, since it stops after the name of the variable, for example: "${varname}[array][1]" is replaced with "$GLOBALS[{varname}][array][1]". The [array][1] stays, it's just the {varname} which gets replaced.
EDIT: feyd's method seems to be a little better, as you recieve an reference to the variable. That's what I myself tried to do from the start, put I couldn't manage to find a way to do it. Anyway, my method is at least less code

Posted: Tue Apr 19, 2005 10:51 am
by feyd
vigge89:
you actually can use the evaluate modifier in the regular expression, and lose the eval

... the problem is, yours is intended for single level variables, not arrays.
Posted: Tue Apr 19, 2005 10:52 am
by phice
Indeed, I was about to say that.
Posted: Tue Apr 19, 2005 10:53 am
by vigge89
feyd wrote:vigge89:
you actually can use the evaluate modifier in the regular expression, and lose the eval

... the problem is, yours is intended for single level variables, not arrays.
As I said, it works for arrays, the reason is that it just replaces the varname, and leaves the array-bit, try it out for yourself
Edit: btw, just a tiny question for you feyd; If I'd use the evaluate-modifier, how should the call look like? Like this?
Code: Select all
function parser_var2globals ($string) {
$string = preg_replace ('#\$([a-zA-Z0-9_\-]+)#e', 'return $GLOBALS[\\1];', $string);
return $string;
}
Posted: Tue Apr 19, 2005 4:17 pm
by phice
Both return Array as the variable contents. feyd's way makes every variable replaced into the whole contents of $GLOBALS, and I slightly modified vigge's code to do exactly the same as what my previous code does.
I now have:
Code: Select all
$name = "e;Don"e;;
$that = "e;huh?"e;;
//$jksdf = "e;dsjfjkref"e;;
$array = array ( );
$arrayї'key'] = "e;value, hehehehehehehehehehehehe"e;;
function replace_var( $var )
{
/*if ( @$GLOBALSї $varї1] ] )
{
return $GLOBALSї $varї1] ];
}
else
{
return $varї0];
}*/
$string = preg_replace ('#\$(їa-zA-Z0-9_\-]+)#', '$GLOBALSї\\1]', $var);
$string = eval ( "e;return "e; . str_replace ( array ( "e;{"e;, "e;}"e; ), "e;"e;, $stringї0] . "e;;"e; ) );
if ( $string )
{
return $string;
}
else
{
return $varї0];
}
}
$contents = "e;<p>Hello, {$name}. Welcome to my site. {$jksdf} {$that} {$name}</p><p>what about {$arrayї'key']} ?</p>{template=\"e;another.tpl\"e;}"e;;
$contents = preg_replace_callback ( "e;#{\\$(їA-Za-z0-9]+)}#i"e;, "e;replace_var"e;, $contents );
Code: Select all
Hello, Don. Welcome to my site. {$jksdf} huh? Don
what about {$arrayї'key']} ?
As you can see, array's still aren't working.
Posted: Tue Apr 19, 2005 4:58 pm
by feyd
vigge89 wrote:Edit: btw, just a tiny question for you feyd; If I'd use the evaluate-modifier, how should the call look like? Like this?
Code: Select all
function parser_var2globals ($string) {
$string = preg_replace ('#\$(їa-zA-Z0-9_\-]+)#e', 'return $GLOBALSї\\1];', $string);
return $string;
}
Code: Select all
$string = preg_replace ('#\$(їa-zA-Z_]їa-zA-Z0-9_]+)(ї^\s]*?)(?=\s)#se', '$GLOBALSї"e;\\1"e;]\\2', $string);
is more accurate, I believe.
Posted: Tue Apr 19, 2005 5:31 pm
by feyd
as for your current problem Phice, you have your test string in double quotes.. (PHP is parsing all the variables first)

Although fixing it, is another story.
Posted: Tue Apr 19, 2005 6:24 pm
by phice
Finally I got it to work...
Code: Select all
function replace_var( $var )
{
$string = preg_replace ('#\$([a-zA-Z_][a-zA-Z0-9_]+)([^\s]*?)#se', '$GLOBALS["\\1"]\\2', $var);
if ( str_replace ( array ( "{", "}" ), "", $string[0] ) != "" )
{
return eval ( 'return $GLOBALS[\'' . $string[1] . '\']' . $string[2] . ';' );
}
else
{
return $var[0];
}
}