Page 1 of 1

Static Variable in Recursive Function

Posted: Wed Apr 26, 2006 10:52 am
by Ollie Saunders
I have function that creates instances of a simple class from arrays.
It uses a recursive loop so that complex arrays can be used as the argument.
Here is how I am currently calling it:

Code: Select all

$foo = osisSafeVar::fromArray(array(1,2,3));
$bar = osisSafeVar::fromArray(array(4,5,6));
print_r($bar);

Code: Select all

Array
(
    [0] => osisSafeVar Object
        (
            [data] => 1
        )

    [1] => osisSafeVar Object
        (
            [data] => 5
        )

    [2] => osisSafeVar Object
        (
            [data] => 6
        )

    [3] => osisSafeVar Object
        (
            [data] => 4
        )

)
As you can see bar is getting confused with foo.
This code has to run work on PHP 4.06. But I am testing it on my server running PHP 5.0 atm.
Here's the class:

Code: Select all

/**
* Keeps variables secure by preventing unfiltered accesss to them
*/
class osisSafeVar {	
	function osisSafeVar($data) {
		$this->data = $data;
	}
	/**
	* Get the data exactly as it was set. Never use the return value
	* of this in output. Use only for strlen, conditions etc.
	*/
	function getRaw() {
		return $this->data;
	}
	/**
	* Get variable back as HTML as defined in tfb with 
	* strim functionality
	*/
	function getHTML($limitLength = null) {
		global $tfb;
		if(!$limitLength) {
			if(!isset($this->HTML)) $this->HTML = $tfb->htmlClean($this->data);
			return $this->HTML;
		}
		if(!(isset($this->HTML) && $this->limitLength == $limitLength)) {
			$this->limitLength = $limitLength;
			$this->HTML = $tfb->strimAndClean($this->data,$limitLength);
		}
		return $this->HTML;
	}
	/**
	* Get variable back escaped ready to be added to queries
	*/
	function getMySQL() {
		global $db;
		if(!isset($this->MySQL)) $this->MySQL = mysql_real_escape_string($this->data,$db);
		return $this->MySQL;
	}
	/**
	* Filter the data to a specific type
	*/
	function cast($type) {
		$this->data = eval('return ('.$type.')'.'$this->data;');
		$this->reset();											// cached strings are out of date
	}
	/**
	* Set the data to something else. You could use overloading
	* instead, at the sacrifice of portability
	*/                   
	function set($data) {
		$this->data = $data;
		$this->reset();											// cached strings are out of date
	}
	/**
	* Destroy cached processed strings to force their regeneration
	* @access private
	*/
	function reset() {
		unset($this->HTML,$this->MySQL);
	} 
	/**
	* @access public static
	*/
	function fromArray($arr,$key = null) {
		if(isset($this)) return false;
		static $safe = array();
		if(is_array($arr)) {
			foreach($arr as $key => $value) self::fromArray($value,$key);
		} else {
			if($key == null) $safe[] = new osisSafeVar($arr);
			else $safe[$key] = new osisSafeVar($arr);
		}
		return $safe;
	}
}
I've tried using the fromArray function outside of the class and I get the same results.
One obvious solution is to use a global variable rather than a static one and a separate function call to clear it but can anyone think of a better solution to this.

Many thanks.

Posted: Wed Apr 26, 2006 11:03 am
by feyd
Why not use the return you already have?

Posted: Wed Apr 26, 2006 11:18 am
by Ollie Saunders
Why not use the return you already have?
I already am:

Code: Select all

$foo = osisSafeVar::fromArray(array(1,2,3));
$bar = osisSafeVar::fromArray(array(4,5,6));
print_r($bar);

Posted: Wed Apr 26, 2006 11:53 am
by timvw
I see you using $this->data but i see nowhere where you've defined that member variable.. And i thought that was not allowed in php... what does error_reporting tell you?

(If i'm not mistaken, there was (or is) a bug in php4 that doesn't handle statis members well. But if you use the static member as an array, it does work).

Posted: Wed Apr 26, 2006 12:01 pm
by feyd
ole wrote:
Why not use the return you already have?
I already am:

Code: Select all

$foo = osisSafeVar::fromArray(array(1,2,3));
$bar = osisSafeVar::fromArray(array(4,5,6));
print_r($bar);
You're actually not because you are using a static.

Code: Select all

function fromArray($arr) {
                if(isset($this)) return false;
                if(is_array($arr)) {
                        $safe = array();
                        foreach($arr as $key => $value) {
                                $safe[$key] = self::fromArray($value);
                        }
                } else {
                        $safe = new osisSafeVar($arr);
                }
                return $safe;
        }

Posted: Wed Apr 26, 2006 12:39 pm
by Ollie Saunders
You're actually not because you are using a static.
Ahh so it turns out that statics in recursive functions suck ass. thanks feyd.

Posted: Wed Apr 26, 2006 12:40 pm
by Ollie Saunders
timvw wrote:I see you using $this->data but i see nowhere where you've defined that member variable.. And i thought that was not allowed in php... what does error_reporting tell you?
I did that to avoid using var keyword which generates an error in PHP 5.
(If i'm not mistaken, there was (or is) a bug in php4 that doesn't handle statis members well. But if you use the static member as an array, it does work).
the static was already an array and as i said i'm testing in php 5.

Posted: Thu Apr 27, 2006 1:03 am
by Weirdan
ole wrote: Ahh so it turns out that statics in recursive functions suck ass. thanks feyd.
Actually not. You just misused it. Static is a static, it preserves it's value across calls to the function that contains it, exactly what you've observed (and wanted it in the first place :) )

Posted: Thu Apr 27, 2006 1:10 am
by s.dot
wow, did the smurf, smurf up a bit :-D