Forum Moderators: coopster

Message Too Old, No Replies

Ideas please. private class function workaround

How to make this function do what I want it to

         

Matthew1980

8:50 pm on Sep 2, 2010 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Hi all,

After a month or so of doing something else I have decided to see if I can finish this little project off, and this function is all that is annoying me now

private function UniqueKey(){

$setOne = range('A','Z');
$setTwo = range(0,9);

$UniqueKeyArray = array_merge($setOne,$setTwo);
shuffle($UniqueKeyArray);

$this->UniqueCode = "#".$UniqueKeyArray[rand(0,35)].$UniqueKeyArray[rand(0,35)].$UniqueKeyArray[rand(0,35)].$UniqueKeyArray[rand(0,35)]."#";
return $this->UniqueCode;
}


The idea is to produce the same code twice - then make another unique key on the third call; optionally though I would like this to be a parameter that can be set, but as yet I cannot figure that part out, so for now just producing unique id's on the third call.

echo $this->UniqueKey();//output code <- first call
#HJYE#

echo $this->UniqueKey();//output code <- second call
#HJYE#

echo $this->UniqueKey();//output code <- Third call
#567E#

(Obviously I couldn't do that in situ, but in the context of the example...)

That is the preferred output that I would like to have happen, I'm guessing that I should use $_SESSION somewhere, but for the life of me I cannot fathom it out. For something pretty simple I can't see how to logically do this, maybe I have been doing VB.Net for too long and it's rotting my brain ;-p

Any idea's/suggestions appreciated.

Cheers,
MRb

CyBerAliEn

10:31 pm on Sep 2, 2010 (gmt 0)

10+ Year Member



First off: Why in the world would you call a function like "UniqueKey()" and expect/want the SAME return the first 2 times, and a different return the 3rd time? This doesn't seem logical. By definition, your "UniqueKey()" SHOULD always return a unique key, correct?

If all you're doing is 3 consecutive calls, why not do something like this?
$code1 = $this->UniqueKey(); //#HJYE#
$code2 = $this->UniqueKey(); //#567E#
$sequence = $code1.$code1.$code3; //#HJYE##HJYE##567E#
echo $sequence;

//or however u need it to be, ie:
echo $code1;
echo $code1;
echo $code2;


Or is there something more to your process ... ?

Matthew1980

8:32 am on Sep 3, 2010 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Hi there CyBerAliEn,

Yes, I agree, my semantics on this particular function are not entirely accurate :)

I should call it KeyGen() I suppose, but the idea is that I want to have the flexibility of reproducing the key, depending on the options that a user requests when signing up, at the moment I am just assigning the first (and only call) to a var, then copying that into the various places that it's needed.

I just want to eliminate having to use the var and just use multiple calls to the same function instead, then once the 2nd call has been done, regenerate the key for the third.

Sorry if I'm not making much sense, but this method of multiple calls seems the logical way of doing things to me, rather than wasting memory assigning data to a var, when really function calls would be simpler (and makes the code easier to follow).

I shall see if I can wrap this up today.

Cheers,
MRb

astupidname

5:17 pm on Sep 3, 2010 (gmt 0)

10+ Year Member



All you really need in your class is a counter to check, plus would also be good for the UniqueKey method to ensure no duplication after the repeatLimit has been reached as even though using rand() to pull random indexed members from $UniqueKeyArray you still run the (slim) chance of duplication. This should get 'er done:
<?php

class Tester {
private $UniqueCode;
private $calls = 0; //counter to track which call to UniqueKey we are on
private $codes = array(); //storage to track codes output by UniqueKey

public function getKey() {
return $this->UniqueKey(4);
}

private function UniqueKey($repeatLimit = 2) { //optional parameter $repeatLimit (int) defaults to 2
$this->calls++;
if ($this->calls <= $repeatLimit && isset($this->UniqueCode)) {
return $this->UniqueCode;
}
$UniqueKeyArray = str_split('ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789');
//no need to shuffle, since we're already using rand()
$uniqueCode = "#".$UniqueKeyArray[rand(0,35)].$UniqueKeyArray[rand(0,35)].$UniqueKeyArray[rand(0,35)].$UniqueKeyArray[rand(0,35)]."#";
//ensure the code is truly unique and has not been previously output
//(at this point in the code we are either beyond the $repeatLimit or this is the very first call to UniqueKey)
while (in_array($uniqueCode, $this->codes)) {
$uniqueCode = "#".$UniqueKeyArray[rand(0,35)].$UniqueKeyArray[rand(0,35)].$UniqueKeyArray[rand(0,35)].$UniqueKeyArray[rand(0,35)]."#";
}
$this->UniqueCode = $uniqueCode;
array_push($this->codes, $uniqueCode); //track that we've used the code
return $this->UniqueCode;
}
}

$T = new Tester();

for ($i = 0; $i < 10; $i++) {
echo $T->getKey().'<br>';
}

?>

Matthew1980

6:07 pm on Sep 5, 2010 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Hi there astupidname,

Firstly; thanks for taking the time to work that out! I have taken the framework of this example and currently trying to merge it with something else I have already done, so thanks for that.

The idea is to produce 'keys' in sets of two, two identical sets; so four calls to the function will give 4 results 2 of which are duplicates.

Cheers,
MRb

Matthew1980

9:42 pm on Sep 7, 2010 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Hi all,

Just an update really, this is what I have ended up with. So thanks to everyone for the suggestions/ideas.

<?php

class Tester {

private $UniqueCode;
private $calls = 1; //counter to track which call to UniqueKey we are on
private $codes = array(); //storage to track codes output by UniqueKey

public function getKey() {
return $this->UniqueKey('2');
}

private function UniqueKey($repeatLimit=null) {

//Increment the number of calls to the function
$this->calls++;

//Catch here if the limit of repeats hasn't been reached & code is set/has state
if (($this->calls <= $repeatLimit) && isset($this->UniqueCode)) {
//return the same code until the $repeatLimit is reached
return $this->UniqueCode;
}

//reset the calls to 1 so that the counter starts at 1 because starting at 0 means the repeats is 1
$this->calls = 1;

//String to array, this is instead of using 2 seperate calls to range
$KeyArray = str_split('ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789');

//Arrange the 4 digit code
$uniqueCode = "#".$KeyArray[rand(0,35)].$KeyArray[rand(0,35)].$KeyArray[rand(0,35)].$KeyArray[rand(0,35)]."#";

return $this->UniqueCode = $uniqueCode;
}
}

$T = new Tester();

for ($i = 0; $i < 10; $i++) {
echo $T->getKey().'<br>';
}
?>


Does just what I want it too. Thanks astupidname for the inital idea, I just looked at it logically and realised that all I needed was a counter reset after the 'catch'.

Happy chappy now.

Cheers,
MRb