2

I have the following function to generate a random string:

public function generateString(){
    function generateCharacter () {
        $possible = "1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
        $char = substr($possible, mt_rand(0, strlen($possible)-1), 1);
        return $char;
    }
    function generateNumber () {
        $GUID = generateCharacter().generateCharacter().generateCharacter().generateCharacter().generateCharacter().generateCharacter().generateCharacter().generateCharacter().generateCharacter();
        return $GUID;
    }
    $string = generateNumber();
    return $string;
}

I then need to be able to generate these random strings x amount of times using a for loop and insert them into my MySQL table:

$how_many is where i would select how many times i want to loop.

for ($i = 1; $i <= $how_many; $i++) {

        $random = $this->generateString();

        $query_params = array( 
            ':code' => $random,
        );
        $query = " 
            INSERT INTO table
            ( 
                code
            ) 
            VALUES 
            ( 
                :code
            )
        ";
        try { 
            $stmt = DB::get()->prepare($query); 
            $stmt->execute($query_params); 
        }  
        catch(PDOException $ex) {} 

    }

The above gives me an error though of:

Fatal error: Cannot redeclare generateCharacter() (previously declared in....

I know i cannot have the function in the for loop otherwise i get this error but if i have it outside the loop it just generates the string once and inserts the same string everytime.

How can i get it so each insert in my loop is a new random string?

1
  • 1
    why don't you use uniqid? Commented Jun 24, 2013 at 10:51

3 Answers 3

3

Don't write functions that are already written.

PHP has function for it called uniqid()

From manual

uniqid() Gets a prefixed unique identifier based on the current time in microseconds.

The value returned by uniqid() will be 13 characters long. If more_entropy is TRUE, it will be 23 characters.

To get random number you can use rand() function.

In your code you prepare same statement multiple times in loop. This is very bad habbit. Prepare statement before loop then only execute and bind parameters in loop. It is more effecive.

Sign up to request clarification or add additional context in comments.

2 Comments

was not aware of php's uniqid function. I started with this but then went with Rajeev's answer in the end as it meant i could customise the string possibilites a bit easier, thanks though
what possiblities? The length can be easily set with substr(uniqid(),0,9); where 9 is length of returned string.
1

you can try it better :-

function generateString()
 {
  $number = base64_encode(openssl_random_pseudo_bytes(20, $strong));
  $newstr = preg_replace('/[^a-zA-Z0-9\']/', '', $number);
  return substr($newstr,0,10); return string of 10 random character 
 }
 ///same code after this
  for ($i = 1; $i <= $how_many; $i++) 
   {
    $random = $this->generateString();
    $query_params = array( 
        ':code' => $random,
    );
    $query = " 
        INSERT INTO table
        ( 
            code
        ) 
        VALUES 
        ( 
            :code
        )
    ";
    try { 
        $stmt = DB::get()->prepare($query); 
        $stmt->execute($query_params); 
    }  
    catch(PDOException $ex) {} 

}

1 Comment

Thanks Rajeev, have used this instead now :)
0

I'll try to explain what happens briefly, so I'll use terms which may be not fully correct from the technical point of view.

In your code, two inner functions generateCharacter and generateNumber are defined in the body of the outer function generateString.

Initially, only the outer function (generateString) is "available" for the rest of your code.

When the outer function gets called, it "defines" the two inner functions, and these become available in the global scope. I.e. the inner functions are not really private - they are exported into the global, not even class scope!

When you call the outer function generateString more than once, the inner functions are getting "defined" more than once - as if you would define them more than once manually in the global scope. This is not allowed in PHP, since the error.


Possible fixes:

  • Move inner functions into the global scope (they are exported there on the first call anyway). This it the worst way to go.

  • Make generateCharacter and generateNumber simple private methods.

  • Use PHP's uniqid as suggested in the other answer.


Here a simplified scenario, to see what happens:

class Test {
  public function aaa() {
    function bbb() {
      echo("bbb");
    }
    echo "aaa";
    bbb();
  }
}

// bbb(); // would produce fatal error: undefined function bbb()
$test = new Test();
$test->aaa(); // outputs "aaabbb"
bbb(); // ok here, outputs "bbb"

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.