begin; update users set balance = balance - :amount where balance >= amount and id=:user_id;
If from the last request affected_rows = 1, then we register the order, do what else is needed in the database, then we commit .
If affected_rows was 0, it means either there is no such client or he does not have enough money on the balance sheet. We make rollback and tell the client that there is no money.
You can make a select ... for update and calculate the balance on the client, then make an update but why? Especially on php, the calculation will most likely be done in a float with the corresponding errors, and the DBMS will normally calculate its numeric.