requesting unique id every page load - php

I'm creating a page that needs to select a Unique ID for every page load. It's basically a purchase order system, but the PO will be just the UID, so it's important that no user can get the same ID. I tried doing just calling upon last ID, then adding 1 and submitting, but that could create conflict if two or more users are entering at the same time. What's the best way to pull a UID for each page load? Any solutions?
Thanks
Lloyd

UniqId() is one way, but results in large numbers. As V Patel says, there's also "Auto Increment" and this is probably the option you want.
In MySQL set up a table (say "PurchaseOrders") with a field "po_id" and set that to be the primary key and auto increment. Add another field "po_status" (TinyInt*1) and another "po_lastused" (Date*1). Status will be 0=draft, 1=final, 2=shipped etc. LastUsed is the last time the user accessed the details.
When you want to create a new purchase order, INSERT INTO PurchaseOrders(po_status, po_lastused) VALUES(0, NOW()); Note: you've not specified the actual purchase order
You can get the po_id through asking for the "last insert id" (http://php.net/manual/en/mysqli.insert-id.php, http://php.net/manual/en/function.mysql-insert-id.php, http://www.php.net/manual/en/pdo.lastinsertid.php, depending on your coding library)
Store the po_id in a session variable so that when the user returns, you know their po_id(*2)
Each time a user access a purchase order, if "last updated" was more then 5 minutes ago, update the timer.
Periodically deleted all purchase orders that are draft and where last updated is older than your session (e.g. after a day)
This way, you'll end up with nice purchase order numbers that are easily quotable.
*1 For the purists, You can also use Enum for the status, and int for dates - depends on your preference. You can also set the date to be automatically updated. But I'm keeping it simple.)
*2 Again, for the purists, there is more security you could implement here to ensure the "other" users can't access someone else's purchase order, but this is enough to start.

You can use the uniqid function to get a unique key. Run it through hexdec if you need an integer.

PHP has one:
http://php.net/manual/en/function.uniqid.php

Use auto increment feature of the database in use, especially if you like it to be a number and don't need it till you want to persist it.

Related

How to create a ticket reference number in PHP and mySQL

I'm working on a ticketing system in PHP and mySQL.
I have a table support with id as my primary key and AI.
I want to add ticket_number, so that when a ticket is submitted each ticket is assigned a unique number. I can't use mySQL to AI a second field, right?
If I give the first ticket a number, then write a query to lookup the last ticket_number in the DB, then I was thinking of doing something like:
$ticket = 1;
$next = $ticket+1;
echo "ticket number: #".$next;
would this work or is there a better way?
As advised by MonkeyZeus, you need to take a step back and rethink your schema.
You want to have multiple rows (replies) that are linked together by a single ID (the ticket number).
You definitely want this ID to be the ID of a row in another table.
So you should have two tables:
one for tickets
another for replies
The first one will be able to hold data that is ticket-specific, including the state of the ticket (open, closed...), who it is assigned to (the id of the user), who created the ticket (again, an id), and possibly when it was opened and closed (though this could be inferred through other means).
The second one will hold data specific to each entry in your ticket (the initial message, and subsequent replies going back and forth).
You may also have other tables (or it could be the same as replies) for other types of actions (ticket status changed, sub-ticket created, etc.).
tickets will have a unique ID which you can use as is as the ticket number (probably with some sort of prefix, possibly reformatted somehow).
replies will have a unique ID (which will be useful when you want to attach files to the reply, or edit it) as well as the ID of the ticket it is associated with.
Let Mysql create IDs. Use you favorite language's API to get the ID of the last inserted row.
DO NOT increment IDs client-side based on the max id returned by the server. Race condition looms.
DO NOT use IDs that are generated client-side and are not guaranteed to be unique
You can achieve by below code. It will generate unique ticket number every time
$brand = '#ref';
$cur_date = date('d').date('m').date('y');
$invoice = $brand.$cur_date;
$customer_id = rand(00000 , 99999);
$uRefNo = $invoice.'-'.$customer_id;
echo $uRefNo;
For a good and unique ID you have much better solutions :
You can use a md5 hash based on the microtime (same as uniqid from PHP but more secure)
You can use an extra column with unique = true functionnality and a request to get the max of this column and increment in your code before a new insert
You can use your support ID as unique entry, it's perfectly doable by inserting first the other field and then get back the ID inserted to update your ticket ID (if its a other component of your table) or show it alone to your users if you consider it as you ticket id..
#jcaron I've designed a schema - would this work?
I decided to adapt #Himanshu kumar's answer as follows (as it resolves my orgional question) to use the user's id and the timestamp (both of which I'm using already) as the ticket number:
$user_id = 7; //example from session variable
$cur_date = date('dmyHis'); //timestamp ticket submitted
$ticket = '#'.$user_id.'-'. $cur_date;
This will create create a unique variable that has the user's id and the date and time. I've used seconds to make it more unique. I will then use a query to find all messages/tickets with this ticket.

Multiple DB users updating at the same time

I am curious what path I should take to accomplish the following. I want multiple computers at one location to be able to view and make changes to data inside a mysql DB with a web browser. I dont have extensive knowledge in this area, but from what I do remember this was very difficult if not impossible.
Example: Lets say I have a record for John and I want 2 computers to be able to edit Johns record. Please note that the computers will not be editing the same portion of Johns record. Lets say one record is changing a status from need to be called to called and the other computer is changing the status of need to be ordered to ordered.
I want a solution that could natively handle this.
My current knowledge is building web interfaces with PHP and SQL. I would like to use these languages as I have some prior knowledge.
So my question: Is this possible? If, so exactly how would it work(flow of info)?
There are several ways that you can accomplish this. There's already some great PHP database editing software packages out there (phpMyAdmin).
To handle this in code though you can either use Transactions (depending on what flavor of SQL you're using this would be done differently)
One of the easier ways to ensure that you don't have people's data clashing with one another is just by adding additional where clauses to your statement.
Lets say you have a user record and you want to update the last name from Smith to Bill, and the user ID is 4.
Instead of writing
UPDATE users SET lastName='Bill' WHERE id='4'
You would add in:
UPDATE users SET lastName='Bill' WHERE id='4' AND lastName='Smith'
That way if someone else updates the last name field while you're working on it, your query will fail and you'll have to re-enter the data, thus faking a transaction
Use Transactions. Updating a single record at the exact same time isn't really supported, but applying one transaction followed immediately by another certainly is. This is native to MySQL.
START TRANSACTION;
SELECT #A:=SUM(salary) FROM table1 WHERE type=1;
UPDATE table2 SET summary=#A WHERE type=1;
COMMIT;
One other thing to do is the old desktop approach. Wich is almost mannualy control the flow of modifications. I will show:
Say that you have a client table with the fields id, firstname, lastname, age. In order to control multiple users updates you will add the version integer default 0 field to this table.
When you populate the object on the form to an user you will also store the actual version that the user has selected.
So lets assume that your client table is like this:
id firstname lastname age version
1 Tomas Luv 20 0
2 Lucas Duh 22 0
3 Christian Bah 30 0
When the user select the client with the id=1 the version of this row is, in this moment, 0. Then the user update the lastname of this client to Bob and submit it.
Here comes the magic:
Create a trigger (before update) that will check the current version of that registry with the version that the user previously selected, something like this (this is just pseudo code, as I'm doing it from my head):
create trigger check_client_version on client before update as
begin
if new.version != old.version then
throw some error saying that a modification already was done;
else
new.version = old.version + 1;
end if;
end;
On the application you check if the update has this error and inform to user that someone else made change on the registry he try to change.
So with the given example it would be like:
1 - The user A selected the row 1 and start editing it
2 - At the same time the user B selected the row 1 and save it before the user A
3 - The user A try to save his modifications and get the error from the application
On this context the user A has the version field pointed to 0 also is the user B but when the user B save the registry it now is 1 and when the user A try to save it it will fail because of the check trigger.
The problem with this approch is that you will have to have a before update trigger to every table in your model or at least the one you are concerned with.

Using $this->db->insert_id() with multiple users on Codeigniter

I'm building an eCommerce site with Codeigniter which will allow users to register, buy products and then track the orders.
I'm using the following in several places around the site, mainly when a user is submitting an order:
$this->db->insert_id();
Basically when a user submits an order, it will add the order to one table, and then, within the same segment of code (immediately after the insert query), add each order item to another table using the ID created when the order is inserted into the first table.
My question is: Out of the following, what does $this->db->insert_id(); do:
1) Does it get the ID that has just been inserted in (and only from) insert query just run?
2) Does it get the last inserted ID from the latest entry in the database regardless of what query its come from?
Basically I'm trying to avoid orders being mixed up, say for example if several customers were submitting orders at the same time, I don't want one customer's order items to be added to the incorrect order.
I think the answer is 1, and that there's no problem, but I wanted to be sure.
Thanks!
It gets the ID that last inserted by the last query. So what you said in #1
Just a suggestion - but another way to do this is to generate a random string - and use that to associate the cart items and order together - instead of by order id. you would still use the order id as the "order number".
this gives you the option of generating that random string when the shopping session first begins and using it to tie the cart items, shipping, billing etc together as the purchase is proceeding. so in that way you are starting the order immediately, but you haven't had to commit a space in the final order table until the transaction verifies.
Your question exposes a potential bug in the codeigniter environment. If two inserts are done in rapid succession, how do you have confidence that the ID returned from insert_id is the proper ID?
Codeigniter documentation does not answer this question
http://ellislab.com/codeigniter/user-guide/database/helpers.html
A relevant blog entry from ellis lab does not resolve the question. It concludes that the appropriate resolution is to take your chances.
http://ellislab.com/forums/viewthread/63052/
If this function is a wrapper function for mysqli_insert_id, the documentation at php.net is unclarified.
http://www.php.net/manual/en/mysqli.insert-id.php
It states the ID is from "the last query". It does not say whose last query.
Two successive inserts, and the return of a wrong ID will compromise the integrity of your data. The way to be sure is lock the database.
$this->db->query('LOCK TABLE (your table name) WRITE');
$this->db->insert('(your table name');
$int_id = $this->db->insert_id();
$this->db->query('UNLOCK TABLES');
This has a negative impact on execution time, but depending on your server's capacity is likely preferable to data corruption.

How to limit number of searches per user in PHP

I am trying to develop an application where a guest user can see search results only 10 times after which he should be directed to payment page. I can use sessions on the search results page, but how can i put a counter on that. Can any please help me on that.
Every time a search request is created you just do
$_SESSION['counter']++
Altough he can just get rid of the limit by deleting cookies. An other approach would be, to store the number of search requests in a database table including the IP address, but this can also be bypassed, while it takes more work to do so.
If you should put search limit on current running session than you can use $_SESSION['count']++.
And if you should put search limit per day than you can use 'UPDATE users SET search_count = search_count+1'
It depends whether you would allow him to search again when he comes to your website or just those 10 times even after he visits after a year.
For temporary bases, you can use cookies (see setcookie function) but if you want to restrict him once and for all, you will have to ssave that information in database.
You would code something like:
<?php
session_start();
$_SESSION['counter'] += 1;
// more logic/code
Now you will have to save the value of $_SESSION['counter'].
If your users can search only while logged in, then I see no problem - you definitely have db table with users, so just add another column to it, say 'search_count' and increase it by one each time user attemps a search.
For example:
UPDATE `users` SET search_count = search_count+1
You can also use a counter in the table user of your db and call a function everytime the user looks for the result, that increments the value by one, so a simple UPDATE.
I think maintaining database will be much better then maintaining SESSION because may be due to some reason session removed or erased.
add a field within users table name for example visit with default value 0 and update this field on every visit of search result page..
"update usertablename set visitfield = visitfield + 1 where user_id = ".$current_user_id
thanks

script to tell me who, and how many users, are online

In my research to find a way to make PHP tell me how many people are 'online' on my site I've discovered that there are ways to 'estimate' this.
I've chosen to log everything that happens on the site, also for error-management sake, but now i'm stuck at writing my SQL query.
Basicly I have a database with 'IP', 'userid' and 'datetime' and I figured that a query like this would do the trick:
SELECT distinct(IP), datetime
FROM `bigBrother`
WHERE datetime BETWEEN DATE_SUB(NOW(), INTERVAL 3 MINUTE) AND NOW()
The problem is that my site is mostly viewed and used by students on the school network, and well... they all have the same IP.
So the question is, am I doing this right, and can I select two distinct rows from my database, so that I can sort out the registered users (who will have a 'userid' - others will have userid = 0)?
Just use the session id instead of the IP.
Use cookies instead of IP addresses.
PHP makes it very easy with it’s session mechanism. On each you first do a session_start() and then you use the value returned by session_id() as a identifier of the visitor that you can put in your database.
I created a system for a school site that asked for this feature as well and here's how i did it.
I had a table of users, in that table there was a field called "online_time"
On every page a function was called if the user was logged in that updated the "online_time" to the current time of that user. (unixtime)
Then i had an "Who is online" function that looked at the "online_time" and displayed all the users with the online time of the last 5 minutes.
EDIT to the comment:
You could make the same function save the session id in another table and the time it was saved. The session id is unique to that user browsing, so you could get the number of session id's active within the last 5 minutes.
session_id()

Categories