Make unique ID using Laravel - php

I want to generate a unique id in Laravel.
EX: PO-12010001
PO = product,
12 = the month,
01 = the year,
0001 = ID of product.
I have tried googling and the answer is using UUID but could not understand.

Your ID will always be 4 digits at the end, so we can pluck those last four characters using substr(). When you increment that by one, it will lose its padding. So 0001+1=2. We therefor pad it back using str_pad() with a length of four.
$string = 'PO-12010001';
$id = substr($string, -4, 4);
$newID = $id+1;
$newID = str_pad($newID, 4, '0', STR_PAD_LEFT);
echo "PO-1201".$newID;
Live demo at https://3v4l.org/55RTL

Since it is not clear where the last 4 characters (ID of product) come from, there are 2 different outcomes based on their origin, I am assuming that "PO" is a constant in all your products:
1.If you're auto-generating the Product ID:
$id = "PO-".date('my') . substr(uniqid(), 9, 12);
date('my') will return a two-digits form of the current month and a two-digits form of the current year.
uniqid() returns a unique identifier based on the current time in microseconds, the identifier is usually a mix of letters and digits, and it is usually 13 characters long, so we use substr() to only return the last 4 characters of the string.
NOTE: we are using the last characters of uniqid() because they change every millisecond.
2.If you already have a Product ID:
$id = "PO-".date('my') . $product_id;

When like this situation first how you want to make your ID
Item Type
Month
Year
Product ID
Get product type in your controller
if Product = PO /
Service = SE
Create a New Date using PHP
$date2 = date('Y-m-d');
and get date substring with your requirement and get the last id of the product table and concat all the variable and use as Unique ID.

First, I dopn't know. So maybe it has a similar concept. But anyway, user defined+designed unique are most likely not unique.
My recommendation is to let the database create an unique id with the autoincrement feature. This is usually the only way to guarantee unique ideas in a multi tasking environment.
The, in an second step, you can create an human readable id and use it for displaying it at the suer interface. Such query can be something like:
update table set nice_id = concat("prefix-",main_id)
where main_id = $last_inserted_id
... or any other calculation based on counting the the number of same entries since beginning of month.
There are other solutions based on try to create an nice_id, insert it into the database, and if this fails, create the next one .. and loop until successful. But simple integers created by autoincrement are more performant on queries and for keys.

it's called Human code which can be unique identify beside an Id column in db table.
$idColumn = 1;
$dateCode = date('ym');
$newHumanCode = 'PO-'.$dateCode.substr('0000'.$idColumn, -4);
return $newHumanCode;
also you can use randome number instead of use $idColumn,
for example:
$idColumn = mt_rand();

You can use the Laravel ID generator.
First Install it:
composer require haruncpi/laravel-id-generator
Import the class in your controller.
use Haruncpi\LaravelIdGenerator\IdGenerator;
Now simply use it
$prefix = "PO-".date("my");
$id = IdGenerator::generate(['table' => 'your_table_name', 'length' => 11, 'prefix' =>$prefix]);
Output
PO-12010001
PO-12010002
PO-12010003
...

Related

Ranking based on users placement instead of score

I have a issue that I cannot wrap my head around.
I am using the Laravel Framework.
I am trying to make a ranking table based on placement (Meaning the user does not have any SCORE, they just have placements)
How I want it to work is the following way:
User A = Placement: 1
User B = Placement: 10
User B wins over User A, then User B gets placed as number 1 and User A gets placed as number 2, and then I want it to update all the other users accordingly.
I can't seem to find a reliable way of doing this.
I don't think this is a Laravel challenge but an SQL one. And it may be simple to solve: basically, you will ask for the actual position of the defeated person, if the position is greater than the winner, you do nothing, otherwise you will assign the position of the loser to the new winner and update the rest of the table with a +1 in the position column.
In code it would be something like this:
$winner_player = User::where('id', userA->id)->first();
$loser_player = User::where('id', userB->id)->first();
if($winner_player->position < $loser_player->position) {
//Update the rest of the users.
//We add 2 because we need space for the new winner and for
//the loser that is still above of the rest of the players.
DB::table('users')
->where('position', '>', $loser_player->position)
->update(DB::raw('position+2'));
//Set the winner with the actual position of the loser.
$winner_player->position = $loser_player->position;
$winner_player->save();
//Set the looser with the new position (+1 of his actual).
$loser_player->position = $loser_player->position + 1;
$loser_player->save();
}
UPDATED LOGIC
As Classified pointed out, it moves the rows around but doesn't do it correctly, so I'm updating the logic to make it work as it is supposed to, and it will be a little simpler too.
$winner_player = User::where('id', userA->id)->first();
$loser_player = User::where('id', userB->id)->first();
if($winner_player->position < $loser_player->position) {
//Set the winner with the actual position of the loser.
$winner_player->position = $loser_player->position;
//Update the users between the swap. There is no need to update
//the whole table, we only update the records between the swap.
DB::table('users')
->where([['position', '<', $winner_player->position],
['position', '>=', $loser_player->position]])
->update(DB::raw('position+1'));
//Save the value of the winner AFTER updating the positions
//between winner and loser.
$winner_player->save();
}

How to set sequence data with existing random data?

I have a table entity named it as uniqueId where the entry generate randomly.Such as
$customer->uniqueId = $request->Input(['uniqueId']) ?: mt_rand(1000, 9999);
means if there is existing uniqueId it will store the existing one otherwise it will be set to the random number. Now instead of setting the random number i want to set it as sequentially . means from 1, 2, 3 like that.. as i can't delete the existing uniqueId which has already created how do I create new entry sequentially with the existing one?
If you simply set column to auto increment you will achieve this automatically you dont even need to call it.
In laravel you can achieve this in your migrations by
$table->increments('uniqueId');
OR
You can achieve this by
lets assume you have a customer Model
// find the last entry in you table
$oldCustomer = Customer::orderBy('uniqueId','DESC')->first();
$customer->uniqueId = ++($olderCustomer->uniqueId);
I hope this helps
**EDIT **
$customers = Customer::all();
$index = 1;
#foreach($customers as $customer)
{
$customer->uniqueID = $index++;
$customer->update();
}

ORDER BY random() with seed in SQLITE

I would like to implement paging for a random set
Select * from Animals ORDER BY random(SEED) LIMIT 100 OFFSET 50
I tried to set int to some integer and to some fracture. Doesn't work.
How do I seed random in sqlite?
I known that a similar question already exists, Seeding SQLite RANDOM(), but I don't understand the PHP solution.
Short answer:
You can't. SQLite's random() function does not support a seed value.
Not so short answer:
Checking SQLite's func.c shows that random() is defined without any parameters..
VFUNCTION(random, 0, 0, 0, randomFunc ),
..and this randomFunc() just calls sqlite3_randomness() (again without any explicit seed value) to obtain a random value of sizeof(sqlite_int64) bytes.
Internally, the implementation of sqlite3_randomness() (see random.c) will set up the RC4 pseudo-random number generator the first time it is used with random seed values obtained from the OS:
/* Initialize the state of the random number generator once,
** the first time this routine is called. The seed value does
** not need to contain a lot of randomness since we are not
** trying to do secure encryption or anything like that...
**
** [..]
*/
if( !wsdPrng.isInit ){
[..]
sqlite3OsRandomness(sqlite3_vfs_find(0), 256, k);
[..]
wsdPrng.isInit = 1;
}
Actually, SQLite's unit test functions themselves just use memcpy() on the global sqlite3Prng struct to save or restore the state of the PRNG during test runs.
So, unless you're willing to do something weird (like create a temporary table of consecutive numbers (1..max(Animals)), shuffle those around and use them to select 'random-seeded' RowIds from your Animals table) I suppose you're out of luck.
I would not usually copy an existing answer, but I can see that you have left a comment asking the author of this answer to explain how it works already a few weeks ago and no explanation has been given. I will therefore copy the relevant part and try to explain whats going on. If this explanation is good, do go and vote on the original answer.
$seed = md5(mt_rand());
$prng = ('0.' . str_replace(array('0', 'a', 'b', 'c', 'd', 'e', 'f'), array('7', '3', '1', '5', '9', '8', '4'), $seed )) * 1;
$query = 'SELECT id, name FROM table ORDER BY (substr(id * ' . $prng . ', length(id) + 2)';
The first two rows are just about creating a seed of a sort. The result is a decimal number with lots of decimals like:
0.54534238371923827955579364758491
Then the sql select uses this number to multiply with the numeric row id of every row in the SQLite table. And then the rows are sorted according to the decimal part of the resulting product. Using fewer decimals, the sort order would look something like this:
row id row id * seed sort order
1 0.545342384 545342384
2 1.090684767 090684767
3 1.636027151 636027151
4 2.181369535 181369535
5 2.726711919 726711919
6 3.272054302 272054302
7 3.817396686 817396686
8 4.362739070 362739070
After sorting this would be the result:
row id row id * seed sort order
2 1.090684767 090684767
4 2.181369535 181369535
6 3.272054302 272054302
8 4.362739070 362739070
1 0.545342384 545342384
3 1.636027151 636027151
5 2.726711919 726711919
7 3.817396686 817396686
In this sample I used only eight rows so the result is not very random looking. With more rows the result will appear more random.
This solution will give you the same order repeatedly as long as:
You use the same seed
No new rows have appeared in the table and no rows have been deleted from the table
I don't know if you're wanting a PHP and iOS solution, but if you are only interested in iOS and dont care much about using the built-in sqlite random() function, you could declare a custom function to use in your queries, one that does take a seed parameter.
sqlite3_create_function(database, "CUSTOM_RANDOM", 1, SQLITE_UTF8, NULL, &CustomRandomSQLite, NULL, NULL);
.
void CustomRandomSQLite(sqlite3_context* context, int argc, sqlite3_value** argv)
{
if(argc == 1 && sqlite3_value_type(argv[0]) == SQLITE_INTEGER)
{
const int seed = sqlite3_value_int(argv[0]);
const int result = ...;
sqlite3_result_int(context, result);
}
else
{
sqlite3_result_error(context, "Invalid", 0);
}
}
.
Select * from Animals ORDER BY CUSTOM_RANDOM(SEED) LIMIT 100 OFFSET 50
I use this for random from seed in my javascript game i am sure you can quite easily convert it to sql
seed: function(max) {
if(typeof this._random === 'undefined') this._random = max; // init on first run
this._random = (this._random * 9301 + 49297) % 233280;
return Math.floor(this._random / (233280.0) * max);
}

Recordset paging based on a secondary field rather than key.

Bit stuck on how to achieve this.....
I have a PHP page which shows information for one record in a table. These records include a unique key (image_id) AND a name (image_name).
In order to display the correct record, I am using a search function on a previous page which results in a URL parameter (imageinfo.php?image_id=1 etc).
My problem is that I wish to add forward and back arrows to the table to cycle through different records, BUT based on the alphabetical order of 'image_name' rather than the numerical order of 'image_id.
I'm really not sure how to achieve this, so any help would be appreciated.
Something like this: (I hope the comments will explain)
<?php
$data = array(
123 => "B",
321 => "C",
124 => "A"
);
$id = 123; // This is the current image id
asort($data); // Sort the array based on values (names)
// Advance the internal pointer until it points to the current image
while(current($data) != $data[$id])
next($data);
// TODO: Also check whether next is past end here
echo next($data); // Should be C

How do I check and unset/set SESSION by element?

I have a session var for a shopping cart that reads: 'cart_b_1_1'.
The letter in the string indicates a category, the ints represent user id & product id.
How can I check the category of an already set SESSION var to see if it matches the category of a new selection?
I am trying to make sure that if an item is added to the SESSION array and there is a var that already exists with the same category letter, then it is unset and effectively replaced with the new selection. This is to limit selections by category to one.
Thanks for the help in advance.
You should consider taking advantange of the awesomeness of what associative arrays let you do:
$_SESSION['categories'][$mycat] = array($user_id, $product_id);
That way whenever you set a new category it overrides the last one. Not sure why you need the user_id at that level, assuming the whole cart belongs to one user, my Session would look like:
array(
'user' => $user_id,
'cart' => array('catid' => 'prodid', 'catid2', 'prodid2'))
);
You should use 3 variables instead of 1.
$_SESSION['category'] = 'cart_b';
$_SESSION['user_id'] = 1;
$_SESSION['product_id'] = 1;
But just in general - you can convert string to a array with '_' separator.
$varArray = explode('_', $_SESSION['var']);
explode the session variable using _ and check the first element to find the category.
$myarray=explode("_",$_SESSION['yourvariablename']);
then you the $myarray[1] is the category so you can compare and do other stuff.
Is this what you wanted?

Categories