Reputation: 4111
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?
Upvotes: 2
Views: 2289
Reputation: 27525
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"
Upvotes: 0
Reputation: 4142
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) {}
}
Upvotes: 1
Reputation: 20286
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.
Upvotes: 3