Page 1 of 1

Static variable in function returning incorrect value...

Posted: Sat Dec 11, 2004 8:58 pm
by Bennettman
Okay, this is a bit of a complicated one, so bear with me. Probably be best to explain how it works first.


The script works by having the designer use tags like <=path[forum]> for calling variables and whatnot, and the script going through the code at the end, recognising the custom tags through regexp and getting the right value.

This also includes functions - the code is <#func(args)> where func is the function name and args is the arguments. It does work - I've been able to call predefined and user-created functions with it and they work as they should.

Now, I've got a function that uses a static variable $vinc to go back and forth between 1 and 2 every time the function is called (to do alternating row colours in tables and whatnot). When it's used (the code is <#varinc()>) it goes through the regexp function and the function-calling function, but it returns the same value all the time. For example, if $vinc is set to 1 in the first run, it is always returned 1, despite the fact that $vinc is being set to 2 correctly inside the function. If it's set to, say, 63 in the first run, it's always 63.

Anyway, I've tested it by printing the value of $vinc every time it's called, and I get a regular 1-2-1-2-1 result, but when it's returned a line later, it's 1-1-1-1-1. Tried switching to global, same result. However, when I call the function in PHP, it works.


Here's the applicable code. I hope someone here can help because I'm tearing my hair out figuratively here :roll:

Code: Select all

<?php

// scan_page(STRING html) - scans html for email addresses, large images, and var/array/function references, and returns fixed code
function scan_page($html) {
// only showing function part - the rest are practically the same anyway ;p
	preg_match_all("/<#([_a-z0-9]+)\((.*)\)>/i", $html, $temp_func);
	for ($i = 0; $temp_func[1][$i]; $i++) {
		$find_func[$i] = $temp_func[0][$i];
		$replace_func[$i] = get_func($temp_func[1][$i], $temp_func[2][$i]);
	}
	$html = str_replace($find_func, $replace_func, $html);

	return $html;
}

// get_func(STRING function, STRING values) - returns the value of the function specified by function
function get_func($func, $values) {
	$values = explode(',', $values);
	return call_user_func_array($func, $values);
}

// varinc(NULL) - returns an alternating number between 1 and 2
function varinc() {
	static $vinc;
	if ($vinc != 1) $vinc = 1;
	else $vinc = 2;
	print $vinc .':'; // my happy-happy test ¬_¬
	return $vinc;
}

// $index_content has all the HTML and tags at this point
$index_content = scan_page($index_content);

// output
print $index_content;

?>
Update: Tried using modular division, same result. Also tried putting the static variable earlier in the system and passing it through to varinc() but same result again.

Posted: Mon Dec 13, 2004 10:07 am
by Weirdan
basically your problem boils down to this simple test:

Code: Select all

$txt = <<<EOF
  a()
  sdf
  a()
  b()

EOF;

$search = array(
        'a()',
        'a()',
        'b()',
        );
$replace = array(
        'first a''s return value',
        'second a''s return value',
        'b''s return value',
        );
echo str_replace($search, $replace, $txt);

Posted: Tue Dec 14, 2004 4:25 am
by Bennettman
How so? I don't really understand what you're getting at.

Is it something to do with the repeating "a()"s in your example corresponding to the repeating calls to the function?

Edit: Wait, oh! I get it. You mean all the calls to the same function are being replaced with the replacement for the first call, since they're identical, yeah? I couldn't actually do the test since I'm at college, so it took a while to figure it out >_>

Posted: Tue Dec 14, 2004 6:14 am
by Weirdan
Bennettman wrote: Edit: Wait, oh! I get it. You mean all the calls to the same function are being replaced with the replacement for the first call, since they're identical, yeah?
Exactly. I would suggest to implement a replacement for str_replace :) which will replace matches one by one, something like this:

Code: Select all

function my_str_replace($search, $replace, $txt) {
    $ret = $txt;
    foreach(array_keys($search) as $i)
        $ret = preg_replace('/' . preg_quote($search[$i],'/') . '/', $replace[$i], $ret, 1);
    return $ret;
}
It will affect the perfomance, but will work according to your expectations :D

Posted: Tue Dec 14, 2004 6:32 am
by Bennettman
Heh, I'd just gotten it working when you posted that ;p

I ended up replacing the str_rep with the str_replace_count function in php.net's notes for str_rep (omg theif!!11!), and switching the organisation around a bit. It uses strpos and substr so it's likely more efficient than preg_rep anyway.

Anyway, thanks for helping me out there! ^_^

Ian