Pure PHP Point of sale system with MySQL

A few days ago I did an exercise on a sales system in PHP. It is written in pure PHP, no Javascript. Mind you, for the styles I used a Bootstrap variant.

The files don’t have a structure, but like I said, it’s an example. I also write this because it either serves someone else or it serves myself for some references.

For data persistence it uses MySQL. This POS Save products and sales. It does not handle user permissions. We store the shopping cart in the session, and well, I better explain it in parts in this post.

Obviously this POS software is free and open source.

Test finished system


This is what the finished system looks like:


To give you a little idea, you can visit this link to test the system. In the same way, watch it on YouTube:


If you like to download it and try it in your local environment, here below I leave it:


Sales system in PHP


Here I leave the SQL scheme that was used. Also keep some records so you have something to work with at the start.

And to connect to the MariaDB/MySQL database we use PDO. The code to achieve this is as follows:

Remember to change the user, password and database name.

Product management

Add product

It is a simple form that asks for the information. It only asks for the barcode, the description, the sale price, the purchase price and the existence.

We are including some files which are the header and footer. These files will be explained below.

When submitting the form, the data is received in a file called nuevo.php. This file has the following code:

As you can see, we are not doing any validation and we are inserting the data as it comes from the form. In case everything goes well, we redirect to Listar.php so that it gives the illusion that the product was saved right there and was added to the table.

List products

Speaking of listing products, here’s the code that draws the table:

Right there we include the buttons that are used to edit and delete the product, which are nothing more than links to another page. By the way, we also put a button to add a new product; It is also a link that leads to the form.

Edit product

When we click on the edit button, it redirects us to another file. In it, we read the id using $_GET. Then, we make a query to the database where the id is the one we read.

If the product does not exist, we indicate it. In case it exists, then we draw the same form but now we fill it with the value attribute of the input tag. For the textarea it is different, since the content must go between the tags, not as an attribute.

Please note that to know the id that we are editing (with which we will do the where) I am saving it in a hidden input.

There are two buttons. One of them submits the form; the other is simply a link to Listar.php. The point of all this is to provide the user with navigation buttons.

Save Changes

Above we saw the form to edit. Now let’s look at the file where we actually save the changes. Is this:

It is Very similar to the form for inserting a new one, but this one edits. If everything goes well, it takes us to Listar.php that will be in charge of displaying the products, with the changes that have been made.

Remove product

Finally let’s look at the delete one. Please note that it does not ask for confirmation, so you have to do it carefully.

And this way we finish the product management (CRUD) in this POS.

Making sells

This was the part that I liked the most. It only works with arrays and sessions, but I liked the result.

Selling interface

The interface Shows a table, which will be of the products that make up the sale. It also shows the total, which at the beginning is 0. And at the bottom 2 buttons that are to finish selling or to cancel the sale. There are also some ifs that show an alert like “Non-existent product” or things like that.

Note that it has an input, that is to read the barcode. It is actually an input within a form. When this form is sent, it goes to the file that we will see below.

Finally, if we look at the header, we will notice that it declares the cart index in the superglobal array of $_SESSION. That is where we will place the products ūüėČ

Add to shopping cart

I repeat that this is the part that I liked the most. We start by checking the existence of the product, if it does not exist, we return to vender.php and we pass the status 5 that will say that there is no longer stock of the product.

In case the product does not exist (that is, it does not exist, not that its existence is 0) we send status 4.

But assuming that everything is fine and that the product exists, we log in and go through the cart array to see if we had already added that product before. In case we have added it, then we only change the amount.

That is, if “Strawberry jam” already exists and they reread the code that belongs to that product, we will not show both products in the table. Better we show one and indicate that its quantity is 2, and so on.

If it does not exist in the cart, then we add it to the array and put its quantity, which by default is 1. Also, by default, its total will be the sale price. It is not necessary to do multiplication.

Then, if it already exists, we calculate its total, which is the result of multiplying its sale price by the quantity in the cart.

Remove from shopping cart

Now let’s see how to remove products from the cart. We simply remove the element that belongs to the index that we receive in $_GET. The code is very easy to understand:

Oh, and we go back to vender.php with status 3 which I think says was successfully removed.

Finishing sale

It is a simple file that will insert into the database the products sold, as well as the sale, its date and its total. It looks like this:

We subtract stock of products, we take the server time and save the sale. Then we clean the cart.

If you ask me for beginTransaction and commit, it is to (although it is not noticeable) speed up the process. It’s like making a lot of changes to the database but not saving them until we’re done. More information in Low performance in statements prepared with PHP and MySQL.

By the way, we go back to listing with a status anyway.

Cancel sale

To cancel the sale we simply empty the array and that’s it. We return to listing with a status.

And below I show you a picture when you cancel the sale:


To finish this great tutorial let’s look at the sales report. It consists of two things: listing sales and being able to delete them.

List sales – Sales report

Please do not blame me, but I do not know how (and if someone does, explain to me) to make a query which result contains an array. The thing is, I wanted something to show the products sold for sale. The only thing I could come up with was a group_concat. Anyway, the code looks like this:

In this way, we concatenate it in the query but “deconcatenate” it in PHP. And there is a nice result.

Delete sale

To delete a sale is like deleting a product. Note that it does not ask for confirmation either. The code looks like this:

Header and footer

As promised, here is the header and footer. They only define the container, the navigation menu, some meta tags and load the css libraries.

Header is:

And footer is:


Like I said, it has no structure. It was done quickly, but it works and that’s what counts.

By the way, if you want to see something similar to this system but in Laravel, check out this post.

I am available for hiring if you need help! I can help you with your project or homework feel free to contact me.
If you liked the post, show your appreciation by sharing it, or making a donation

2 thoughts on “Pure PHP Point of sale system with MySQL”

    1. Por supuesto, estaré encantado de ayudarle más a fondo. Ofrezco servicios de consultoría personalizados para resolver problemas específicos. Si está interesado, envíeme un mensaje a https://parzibyte.me/#contacto y podemos conversar sobre cómo puedo ayudarle.

Leave a Comment

Your email address will not be published. Required fields are marked *