I have created E-commerce website, In user system, I created referral system works like this -> When a visitor create an account then unique referral code for that customer will be generated. I fear that referral code should not be matched when I'll have a lot of users. So, I wanna create unique referral code.
I am creating like this:
$referral_code = strtolower(substr($first_name,0,3)).$this->refer_code(3);
public function refer_code($limit){
return substr(base_convert(sha1(uniqid(mt_rand())), 16, 36), 0, $limit);
}
Here, I am picking first 3 letters from user name and 3 random letters. It's generating referral code like this:
illqhx
But my boss said that It's very difficult to read and tell to other. So, he wants that referral code should be only numbers or 3 letters from name and 3 numbers should be generated automatically and it should be unique, and limit should be 5 or 6.
Please help me
Try this
function random_strings($length_of_string)
{
$str_result = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890abcdefghijklmnopqrstuvwxyz';
return substr(str_shuffle($str_result), 0, $length_of_string);
}
// This function will generate
// Random string of length 10
echo random_strings(10);
?>
I recommend adding something like the following to your User class. You can use createReferralCode from the outside to retrieve the code. It will always return the same value. You could also just return $this and use an accessor method to retrieve the value.
How you save or validate your new key I'm leaving up to you.
/**
* Referral Code
*
* #var string
*/
protected $referralCode;
/**
* Create a referral code and store it on the User.
*
* #return string
*/
public function createReferralCode() : string
{
if (empty($this->referralCode)) {
// attempt to create a referral code until the one you have is unique
do {
$referralCode = $this->generateReferralCode();
} while (!$this->hasUniqueReferralCode($referralCode));
$this->referralCode = $referralCode;
}
return $this->referralCode;
}
/**
* Generate a referral code.
*
* #return string
*/
protected function generateReferralCode() : string
{
// generate crypto secure byte string
$bytes = random_bytes(8);
// convert to alphanumeric (also with =, + and /) string
$encoded = base64_encode($bytes);
// remove the chars we don't want
$stripped = str_replace(['=', '+', '/'], '', $encoded);
// get the prefix from the user name
$prefix = strtolower(substr($this->firstName, 0, 3));
// format the final referral code
return ($prefix . $stripped);
}
/**
* Check if the referral code is unique.
*
* #param string $referralCode
*
* #return boolean
*/
protected function hasUniqueReferralCode(string $referralCode) : bool
{
// check against database to enforce uniqueness
}
if($referrelid){
$condition = ' AND username LIKE "' . $referrelid. '" ';
$sql = $db->getRecFrmQry("SELECT ewallet FROM " . DB_TBLPREFIX . "_mbrs WHERE 1 " . $condition . "");
$ewallet = $sql[0]['ewallet'] + 50;
$data =array(
'ewallet' => $ewallet,
);
if (count($sql) > 0) {
$update = $db->update(DB_TBLPREFIX . '_mbrs', $data, array('username' => $referrelid));
}
}
When the new user creates an account with any refferel id, $50 added to his account when the account is created successfully.
If you want your referrer code to be only numbers, perhaps generating a unique code is not the best idea. Instead you can save the code in a database, start from 000001 and work your way up.
In this case you're guaranteed to have unique codes since you know all the previous codes.
This could also work with alphanumeric characters using the same principle. But starting with 000AAA or something similar.
Leaving aside the guaranteed non collision you can also keep track of issued referrer codes and invalidate them at will using a column such as is_active.
Concrete example from your code:
Lets assume that client Dave has referrer code illqhx. Lets also assume that client Linda wants a referrer code too.
Your code may look something like this:
// get dave's referrer code from the database
$dave_referrer_code = 'illqhx';
$linda_referrer_code = $dave_referrer_code++;
var_dump($dave_referrer_code); // illqhx
var_dump($linda_referrer_code); // illqhz
// Do note that this code won't work, it's just an example
What you should actually do is get the column with the largest id from the database, get the referrer code from there and increment that.
Having a unique index on the referrer_code column will guaranteed uniqueness since you can't have duplicate codes.
It makes much easier as far as I'm concerned.
Related
I understand the basics of $_SESSION vars in php. I currently have a site that passes several values to and from pages that manage SQL queries throughout. I ran into a new problem:
I am using an email address as a Primary Key in my users table. I wish to pass this email to a second page (once the additional infomration is gathered from the server) and dynamically load content when the links are selected. This is my setup for my problem:
//Data returned from server:
// $FName = bob, $LName = rogers, $Email = bob#rogers.com
$_SESSION['userEmail'] = $Email;
$_SESSION['FirstName'] = $FName;
$_SESSION['LastName'] = $LName;
When I load the content on the second page, I recieve these values:
echo $_SESSION['userEmail']; //bob#rogers_com !!!!! THIS is not correct
echo $_SESSION['FirstName']; //bob
echo $_SESSION['LastName']; //rogers
The email is gathered from a POST form on the page. it is the only value within the form. On the first page, I retrieve the email using end(array_keys($_POST)), which is where "$_SESSION['userEmail'] = $Email" comes from. It is, more specifially, :: $_SESSION['userEmail'] = end(array_keys($_POST))::
How do I make it so the Email is passed safely through the request without being transformed?
After further troubleshooting, I have been able to determine that this transformation occurs in the POST request of the form. When clicked the form is using the POST method, which is intercepted in PHP using if($_SERVER['REQUEST_METHOD'] == 'POST'){}, where I capture the array of values (in my case, just the one email) - where the email is now transformed.
If you want use not transformed text such as hash, encode, etc,
you can try use alternative key alternative to your email primary key.
You can take hit from auto_increment index key each row.
Before:
select * from users where email = 'johndoe#johndoe.com';
After:
select * from users where id = '1';
This is equals to:
select * from users where id in (select id from users where email = 'johndoe#johndoe.com');
Good luck.
I have search and found this thing its work in Xampp localhost.This will be helpful.
/**
* Return parsed body in array format (without converting dots and spaces to underscore).
* #return array result parsed
*/
function fetch_parsed_body_nodots()
{
function DANODOT($string) {
$bes1= explode("&", $string);
foreach ($bes1 as $bes2) {
$bes2= explode("=",$bes2);
list($kilil, $beha) = array_map("urldecode", $bes2);
if(!empty($kilil)){
$te[$kilil] = $beha;
}
}
return $te;
}
return DANODOT($this->result_body);
}
http://forum.directadmin.com/showthread.php?t=48001
I figured out a work-around:
When you have the email, you can replace the chars '.' with a different sequence of characters; this is something that would not be found in a usual email address. I found that -#- is a decent one that works (generally). This is how I did it:
$TempFormat = strtr($row['UserEmail'], array('.' => '-#-'))
Then, when I went to my if($_SERVER['REQUEST_METHOD'] == 'POST'){} function, i transformed the string back to it's (hopefully) original state by performing:
$OriginalFormat = strtr(end(array_keys($_POST)), array('-#-' => '.'))
This question already has answers here:
How to generate a random, unique, alphanumeric string?
(31 answers)
Closed 7 years ago.
I am new to laravel 5. I am working on a project where I want to assign some random-readable unique string to each application. I have knowledge of the each application id which may be use as a seed. Since the app is going to be use within the company I don't worry much about security. I expect the table size to grow so my goal is to achieve uniqueness as much as possible because the field in DB is unique. A code like (EN1A20, EN12ZOV etc). If the function can allow me to pass the length of the string I want to return, that would be really awesome.
Edit
Shown below is my attempt to the problem
private function generate_app_code($application_id) {
$token = $this->getToken(6, $application_id);
$code = 'EN'. $token . substr(strftime("%Y", time()),2);
return $code;
}
private function getToken($length, $seed){
$token = "";
$codeAlphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
$codeAlphabet.= "0123456789";
mt_srand($seed); // Call once. Good since $application_id is unique.
for($i=0;$i<$length;$i++){
$token .= $codeAlphabet[mt_rand(0,strlen($codeAlphabet)-1)];
}
return $token;
}
Can the code above do the trick?
Edit
Actually I borrowed ideas from this post PHP: How to generate a random, unique, alphanumeric string? to come out with the methods above but the post does not entirely address my issues. My goal is to generate a string of length say 6 to 8 (Alphanumeric and readable). This string would be use by my admin for query purposes. In my function I have mt_srand($seed) to seed the random number generator where seed is my application_id. It is possible to get duplicate $token.
Appreciate help.
You can use :
sha1(time())
Explanation: sha1 is hash function, and most important characteristic of hash function is that they never produce the same hash of different string, so as time() is always unique in theory sha1(time()) will always give you unique string with fixed width.
EDITED:
You can use you function but before giving token you can connect to database and check if token exists, if exists generate new token, if not exists give hin this token. This mechanism will give you unique tokens.
With your attempt to the problem you could apply the following to ensure a unique code:
do
{
$token = $this->getToken(6, $application_id);
$code = 'EN'. $token . substr(strftime("%Y", time()),2);
$user_code = User::where('user_code', $code)->get();
}
while(!empty($user_code));
Edit
To avoid an infinite loop in laravel, use
do
{
$token = $this->getToken(6, $application_id);
$code = 'EN'. $token . substr(strftime("%Y", time()),2);
$user_code = User::where('user_code', $code)->get();
}
while(!$user_code->isEmpty());
http://laravel.com/api/5.0/Illuminate/Support/Collection.html#method_isEmpty
or go with
do
{
$token = $this->getToken(6, $application_id);
$code = 'EN'. $token . substr(strftime("%Y", time()),2);
$user_code = User::where('user_code', $code)->first();
}
while(!empty($user_code));
Instead of get(), use first(). $user_code is probably unique so we can conveniently pull out the first result.
You could use the built in helper function:
str_random(int);
The documentation can be found: Laravel 5.1 Docs
To ensure it is unique you could always check that the name doesn't already exist and if it does rerun the function to generate a new string.
Hope that helps.
I'm trying to obfuscate the URLs to the pages where content is displayed. Content pages are displayed by getting the content id number as a GET variable in the URL. I want to obfuscate the URL (as is described by this SO post). I tried the methods in both answers but one method gave overly long codes, and the other gave overly predictable codes.
I'm working in PHP, and I'm using a MySQL table to store content; the content id is an automatically incrementing column. This means that if I didn't obfuscate my URLs users would be able to see in the URL exactly how many posts there are on the website, and could change the URL to see different posts. I want to avoid this.
I was hoping to have obfuscation similar to Imgur.com: their content ID codes are each a 5-character code containing letters, capital letters and lowercase letters.
To avoid needing to do a bunch of "encrypting" and "decrypting" you can use a unique key-pair for each page. Add another field (VARCHAR 5) to your pages table called key and then randomly generate a key for each page.
To generate the key you could crypt a random number
function random_key(){
$crypt = crypt(rand(0,9999999), 'Whatever you want to say here.');
return substr($crypt, 0, 5);
}
Which would result in a URL like ?page=55-so3ph (?page={$id}-{$key})
And then to use it you can do something like
<?php
if(empty($_GET['page']))
die('missing ?page');
$page = explode('-', $_GET['page']);
if(count($page) != 2)
die('invalid ?page');
list($page_id, $page_key) = $page;
if(!is_numeric($page_id))
die('invalid page id');
$Post = your_query_method('SELECT * FROM pages WHERE id = ' . $page_id . ' AND key = "' . your_escape_function($page_key) . '"');
if(!$Post){
header('Location: /invalid_page.html');
exit;
}
//At this point we know that they ID key pair is correct
For a super simple solution that does not really prevent people from reverse engineering your URLs but will deter 99.9999% of users you can do something like
<?php
function hash_id($id){
$crypt = crypt($id, 'Whatever you want to say here. Just SALT it!');
$md5 = md5($crypt . 'You can do another SALT here.');
return substr($md5, 0, 5);
}
if(empty($_GET['page']))
die('missing ?page');
$page = explode('-', $_GET['page']);
if(count($page) != 2)
die('invalid ?page');
list($page_id, $page_key) = $page;
if(!is_numeric($page_id))
die('invalid page id');
$Page = your_function_to_get_page_by_id($page_id);
if(!$Page || hash_id($page_id) != $page_key){
header('Location: /invalid_page.html');
exit;
}
//the URL would look like ?page=55-so3ph
Between crypt and md5 with salts, it would take somebody with a super computer a good chunk of time to start finding the collisions.
What I've ended up doing is quite simple: I cipher the number (ensuring that the output of the cipher is within a certain range) then I convert the number to base 62.
I chose base 62 because the characters in base 62 are numerics, capital alphabets, and lowercase alphabets. I ensured the output of the cipher was within a certain range so that when converted to base 62 it would have a certain number of digits (in my case I chose six digits in base 62).
To reverse the code, I convert it back to base 10 and reverse the cipher.
say if I wanted to give every user that registered on my site a unique id. It seems to me that if I wanted to do this I would have to: Create a random number for the id, check to see if that id already exists in the database, if it does exist then create another random number and send yet another query to see if that exists, and so on...
This could go on for ages. Apart from having an incrementing id, is there any decent way to do this?
The best way to do this is via the auto increment function, if you really don't want to use a function like so you could use uniqid();
Basically you it generates an unique id based on milliseconds, if you put in a kinda unique prefix in the function it will generate a very unique id.
echo uniqid('prefix');
This way you won't have to check after generating an id, if it already exists or not. You can be sure it is unique.
For more information check this url http://php.net/uniqid!
First of all, I agree with the comments. It's all overhead code, and if you're using it to make it look interesting you should really reconsider your priorities.
But, if you still need it; here's a little something:
function uid() {
mt_srand((double)microtime()*1000000);
$token = mt_rand(1, mt_getrandmax());
$uid = uniqid(md5($token), true);
if($uid != false && $uid != '' && $uid != NULL) {
$out = sha1($uid);
return $out;
} else {
return false;
}
}
Basically, it does a lot of random number generating to create a token for uniqueid, and then is sha's that. Probably overhead, but you can be sure that you never generate a double uid.
Fabian.
You can use the rand() function. It will generate a random number between two.
rand(0000,9999)
It will generate a number between 0 and 9999.
To check if it already exist:
$id = rand(0000,9999);
/* CREATE YOUR MYSQL CONNECTION */
$user_list = mysql_query("SELECT * FROM users");
while ($user = mysql_fetch_array($user_list))
{
if ($id == $user['id'])
{
echo('Already exist.');
}
else
{
/* YOUR CODE */
}
}
It's the way I did it...
If you have a string of 15 numbers you are looking at up to 999 trillion, I doubt it will run for "ages" considering there's almost 7 billion people on the planet.
Does the ID need to be numeric? By switching to alphabetic characters you will get a lot more entropy. A 6 digit number is 1,000,000 posibilities, a 6 character alphanumeric string is 2,176,782,336 possibilities. Make it mixed case alphanumeric and that jumps to 15,625,000,000.
Here's how I usually generate unique strings that are as short as possible:
$chars = 'abcdefghijklmnopqrstuvwrxyzABCDEFGHIJKLMNOPQRSTUVWRXYZ0123456789';
mt_srand((double)microtime()*1000000);
$id = '';
do {
$id .= $chars[mt_rand(0, strlen($chars) - 1)];
} while (isIdTaken($id));
var_dump($id);
You have to create a lot of items with this style of id, before you'll get to more than 3 or 4 characters.
I know it's late for this answer but the easiest solution is to generate random number and sure it will be unique 100% is
$uid = uniqid().date("Ymdhhis");
I want to create a less than or equal to 10 character unique string for an input string which could be a url
http://stackoverflow.com/questions/ask
OR an alpha numeric string
programming124
but the result should be unique for every input...Is their any function or class that you use for your projects in php... Thanks...
If you want a unique and random string, you can use the following function to create a random string:
function randString($length) {
$charset = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';
$str = '';
while ($length-- > 0) {
$str .= $charset[rand() % 62];
}
return $str;
}
After you have generated a new string, look up your database if that string already exists. If so, repeat that step until you’ve generated a unique string. Then store that new string in the database:
do {
$randString = randString(10);
// look up your database if $randString already exists and store the result in $exists
} while ($exists);
// store new random string in database
The simplest function available in php is uniqid. It is a little longer that you had mentioned, and wont work well with load balancing, but if you are doing something super simple, it should work alright.