maccy93 Posted November 14, 2011 Share Posted November 14, 2011 Is this even possible? I'm trying to call function nameGen from in the function nameGen but I just get an error saying cannot redeclare. I only want it to return $newName when it is not in the array $takenVals. can this only be done with another loop and a constant somewhere? $newVarVals = array(); $takenVals = array(); $varCount = count($varArray); // contents are set else where and is fine for($i = 0 ; $i < $varCount; ++ $i) { function nameGen(&$varCount,&$takenVals){ $newName = rand(0,$varCount); if(in_array($newName,$takenVals)) { nameGen(&$varCount,&$takenVals); } else{ return $newName; } } $newName = nameGen(&$varCount,&$takenVals); $takenVals[] = $newName; $newNameToKeep = '$_'.$newName; $newVarVals[] = array('oldName' => $varArray[$i], 'newName' => $newNameToKeep); } error: Cannot redeclare nameGen() Quote Link to comment https://forums.phpfreaks.com/topic/251129-call-the-same-function-within-it-self/ Share on other sites More sharing options...
Vitamin Posted November 14, 2011 Share Posted November 14, 2011 I don't believe this can be done because it would cause a endless loop. Quote Link to comment https://forums.phpfreaks.com/topic/251129-call-the-same-function-within-it-self/#findComment-1288068 Share on other sites More sharing options...
kicken Posted November 14, 2011 Share Posted November 14, 2011 Your error is not because your calling nameGen from within nameGen. That is perfectly legal (but you need to be careful not to cause an endless loop). Your problem is because your declaring the function nameGen inside of a for loop, so on the first iteration of that loop it declares the function. On the second iteration it attempts to declare it again, but it's already been declared so you receive that error. Move the function declaration out of the for loop, then just call it from inside the loop. Quote Link to comment https://forums.phpfreaks.com/topic/251129-call-the-same-function-within-it-self/#findComment-1288071 Share on other sites More sharing options...
maccy93 Posted November 14, 2011 Author Share Posted November 14, 2011 Hmm, when i put the function out of the for loop I got the $newName to just be empty all the time. I removed the function and just put a while loop in and it worked: $newVarVals = array(); $takenVals = array(); $varCount = count($varArray); for($i = 0 ; $i < $varCount; ++ $i) { $newName = ''; while($newName == '') { $newName = rand(0,$varCount); if(in_array($newName,$takenVals)) { $newName = ''; } } $takenVals[] = $newName; $newNameToKeep = '$_'.$newName; $newVarVals[] = array('oldName' => $varArray[$i], 'newName' => $newNameToKeep); } Quote Link to comment https://forums.phpfreaks.com/topic/251129-call-the-same-function-within-it-self/#findComment-1288080 Share on other sites More sharing options...
phporcaffeine Posted November 14, 2011 Share Posted November 14, 2011 Can I see the whole script? What is it exactly that your trying to do? Quote Link to comment https://forums.phpfreaks.com/topic/251129-call-the-same-function-within-it-self/#findComment-1288082 Share on other sites More sharing options...
KevinM1 Posted November 14, 2011 Share Posted November 14, 2011 There's a difference between defining a function and invoking a function. A function definition looks like: function someFunction(/* argument list */) { // function body } Function definitions should be written first, before any other code in order to ensure that they're available when you want to use them. Funciton invocations look simply like: someFunction(/* arguments */); // or, if the function returns a value $var = someFunction(/* arguments */); In order to have a recursive function (that is, a function that calls itself), you need to do something along the lines of: function someFunction(/* argument list */) { someFunction(/* args */); // escape clause } Note the escape clause. Without that, the function would loop for an infinite amount of time. An escape clause is the part of your code that says "Stop calling yourself." An example: function factorial($x) { if ($x == 0) // escape clause return 1; else return $x * factorial($x - 1); } echo factorial(5); Quote Link to comment https://forums.phpfreaks.com/topic/251129-call-the-same-function-within-it-self/#findComment-1288083 Share on other sites More sharing options...
maccy93 Posted November 14, 2011 Author Share Posted November 14, 2011 What is it exactly that your trying to do? To assign $newName a number between 0 and the count of $varCount on the proviso that the number has not already been used for use further down. Nightslyr, thanks That's awesome! Quote Link to comment https://forums.phpfreaks.com/topic/251129-call-the-same-function-within-it-self/#findComment-1288096 Share on other sites More sharing options...
phporcaffeine Posted November 14, 2011 Share Posted November 14, 2011 What is it exactly that your trying to do? To assign $newName a number between 0 and the count of $varCount on the proviso that the number has not already been used for use further down. Nightslyr, thanks That's awesome! Alright, I have a solution for you to try. I understand the output you're trying to achieve, but without knowing the intention of your application I am making some assumptions. This example is done using OOP; if you're not familiar with OOP - this will also serve as a good place to start learning OOP. There are other ways to do what I think you're trying to do; but I'll stick with your methodology for now. <?php class namer { var $newVarVals = array(); var $takenVals = array(); var $varArray = array(); var $varCount = NULL; var $newName = NULL; function nameGen($iteration) { $this->newName = rand(0,$this->varCount); if (in_array($newName, $this->takenVals)) { $this->nameGen($iteration); } else { echo $newName; $this->newVarVals[] = array( 'oldName' => $this->varArray[$iteration], 'newName' => '$_' . $this->newName ); } } } //INSTANTIATES CLASS $namer = new namer(); //VARIABLE SETUP //SET THE VALUE OF THE $takenVals $namer->takenVals = array(1,2,3,4,5,6,7,8,9,10); //SET THE VALUE OF THE $varArray $namer->varArray = array(5,2,7,34,13,9); //SET THE VALUE OF $varCount $namer->varCount = count($namer->varArray); /************************************/ //Careful, $namer->varCount determines //The iterations in the loop. //Since a class method is self-referenced, //The loop could potentially iterate exponentially, //based on the contents of takenVals. //Since the count of $varArray //is used to setup the loop, //the number of base iterations //in the loop is known while the number of //operations in the loop is theoretically //unknown and unpredictable. //Each base iteration could spawn //a child reference to the class method, //which could spawn another child reference // to the class method ... etc. //rand() is a pseudo-random generator. Since //it isn't truly random, it has a greater potential //to generate the same number over multiple //iterations in the same loop. /************************************/ for ($x = 0; $x < $namer->varCount; $x++) { $newName = $namer->nameGen($x); } print_r($namer->newVarVals); ?> Quote Link to comment https://forums.phpfreaks.com/topic/251129-call-the-same-function-within-it-self/#findComment-1288108 Share on other sites More sharing options...
maccy93 Posted November 15, 2011 Author Share Posted November 15, 2011 Cool, thanks. Sorry I only just came back on here and saw it now. I'll have to have a look at that in the morning tho now I don't really know anything about OOP yet so that's cool thanks! Quote Link to comment https://forums.phpfreaks.com/topic/251129-call-the-same-function-within-it-self/#findComment-1288190 Share on other sites More sharing options...
maccy93 Posted November 16, 2011 Author Share Posted November 16, 2011 OK, sorry for the belated reply. I'm trying to grasp the concept of a class and the point of it. The snippet from the OP was from variable renamer for php I just wrote. This is the whole thing as a function and works ok (just need to send the source as a variable to the function): <?php function simpleObfusicate($phpSource){ //1 -- Check for the variables then place all into if(preg_match("/([$][a-zA-Z_][a-zA-Z0-9_]*)/m", $phpSource)) { $array = preg_match_all("/([$][a-zA-Z_][a-zA-Z0-9_]*)/m", $phpSource, $varArray); } //2 -- Filter out all the duplicates in the array, reset the numeric values and count $varArray = array_unique($varArray[0]); $varArray = array_values($varArray); $varCount = count($varArray); //3 -- create new random names for each variable found and store in array with old names //setting some variables ready to catch info from the loops $newVarVals = array(); $takenVals = array(); for($i = 0 ; $i < $varCount; ++ $i) { $newName = ''; while($newName == '') { $newName = rand(0,$varCount); if(in_array($newName,$takenVals)) { $newName = ''; } } $takenVals[] = $newName; $newNameToKeep = '$_'.$newName; $newVarVals[] = array('oldName' => $varArray[$i], 'newName' => $newNameToKeep); } //4 -- now using placeholders and a foreach loop cycle though replacing the $phpsource $newVarValsCount = count($newVarVals); for($i = 0 ; $i < $newVarValsCount ; ++$i) { $phpSource = str_replace($newVarVals[$i]['oldName'], $newVarVals[$i]['newName'], $phpSource); } //5 -- return the source to the user return $phpSource; } //a -- call the function into a variable $source = simpleObfusicate($phpSource) ?> But then phporcaffeine turned my while loop back into a function and then placed it in a class so the function could do what i originally thought... be called in a loop... but i don't really get the purpose of a class. I mean arent they really just the same as functions? I've just read up a little about classes and had a go at changing phporcaffeine class to embody all of the function simpleObfusicate: <?php class namer { //passed from outside var $phpSource = NULL; //passed from inside var $varArray = array(); var $varCount = NULL; var $newVarVals = array(); var $takenVals = array(); var $newName = NULL; //1 -- Check for the variables then place all into varArray if(preg_match("/([$][a-zA-Z_][a-zA-Z0-9_]*)/m", $this->phpSource)) { $array = preg_match_all("/([$][a-zA-Z_][a-zA-Z0-9_]*)/m", $this->phpSource, $this->varArray); } //2 -- send relavent data to this class $this->varCount = count($this->varArray); function nameGen($iterationX) { //getting a random number between 0 and the number of elements in varArray (varCount) $this->newName = rand(0,$this->varCount); //check to see if the number has not already been used if (in_array($this->newName, $this->takenVals)) { $this->nameGen($iterationX); } //if not then place the number into the takenVals so not used again and pass the new name and old name into the final array else{ $this->takenVals[] = $newName; $this->newVarVals[] = array('oldName' => $this->varArray[$iterationX],'newName' => '$_' . $this->newName); } } //4 -- loop through creating new names for all the variables in the php source for ($x = 0; $x < $this->varCount; $x++) { $this->newName = $this->nameGen($x); } //5 -- str_replace the source $newVarValsCount = count($namer->newVarVals); for($i = 0 ; $i < $newVarValsCount ; ++$i) { $phpSource = str_replace($namer->newVarVals[$i]['oldName'], $namer->newVarVals[$i]['newName'], $phpSource); } } //a -- start the class $namer = new namer(); //b -- pass the php source to the class $namer->phpSource = $phpSource; //c -- obfusicated source $source = $namer->phpSource; ?> There is actually more code required to convert it as a class. If the class and the function were kept in separate files then both would be need to be called with require_once or other but then the class version would require more code again to get the same result. http://www.phpbuilder.com/board/archive/index.php/t-10379417.html These guys say "helps decreasing redundancy and making coding alot easier". So i'm guessing then for much more complex coding the classes come into their own...? Quote Link to comment https://forums.phpfreaks.com/topic/251129-call-the-same-function-within-it-self/#findComment-1288545 Share on other sites More sharing options...
maccy93 Posted November 16, 2011 Author Share Posted November 16, 2011 Sorry i just realised the class namer i previously posted was missing the filtering at step two so would no make sense... <?php class namer { //passed from outside var $phpSource = NULL; //passed from inside var $varArray = array(); var $varCount = NULL; var $newVarVals = array(); var $takenVals = array(); var $newName = NULL; //1 -- Check for the variables then place all into varArray if(preg_match("/([$][a-zA-Z_][a-zA-Z0-9_]*)/m", $this->phpSource)) { $array = preg_match_all("/([$][a-zA-Z_][a-zA-Z0-9_]*)/m", $this->phpSource, $this->varArray); } //2 -- Filter out all the duplicates in the array, reset the numeric values and count $this->varArray = array_unique($this->varArray[0]); $varArray = array_values($this->varArray); $this->varCount = count($this->varArray); function nameGen($iterationX) { //getting a random number between 0 and the number of elements in varArray (varCount) $this->newName = rand(0,$this->varCount); //check to see if the number has not already been used if (in_array($this->newName, $this->takenVals)) { $this->nameGen($iterationX); } //if not then place the number into the takenVals so not used again and pass the new name and old name into the final array else{ $this->takenVals[] = $newName; $this->newVarVals[] = array('oldName' => $this->varArray[$iterationX],'newName' => '$_' . $this->newName); } } //4 -- loop through creating new names for all the variables in the php source for ($x = 0; $x < $this->varCount; $x++) { $this->newName = $this->nameGen($x); } //5 -- str_replace the source $newVarValsCount = count($namer->newVarVals); for($i = 0 ; $i < $newVarValsCount ; ++$i) { $phpSource = str_replace($namer->newVarVals[$i]['oldName'], $namer->newVarVals[$i]['newName'], $phpSource); } } //a -- start the class $namer = new namer(); //b -- pass the php source to the class $namer->phpSource = $phpSource; //c -- obfusicated source $source = $namer->phpSource; ?> Quote Link to comment https://forums.phpfreaks.com/topic/251129-call-the-same-function-within-it-self/#findComment-1288552 Share on other sites More sharing options...
maccy93 Posted November 16, 2011 Author Share Posted November 16, 2011 This answered it .....: http://stackoverflow.com/questions/1993638/classes-whats-the-point in particular this bit (number8): "While it may at first look simpler to just use a set of functions and include them, classes have their strong points. Classes can store variables and those variables are there "later."" Quote Link to comment https://forums.phpfreaks.com/topic/251129-call-the-same-function-within-it-self/#findComment-1288682 Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.