Jump to content

Call the same function within it self?


maccy93

Recommended Posts

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()

Link to comment
Share on other sites

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.

 

Link to comment
Share on other sites

 

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);
	}

Link to comment
Share on other sites

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);

Link to comment
Share on other sites

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);
?>

Link to comment
Share on other sites

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...?

 

 

Link to comment
Share on other sites

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;
?>

Link to comment
Share on other sites

This thread is more than a year old. Please don't revive it unless you have something important to add.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.