You can write an equation that, when generating a page with forms, would insert into the forms not the real data of record identifiers from the database, but some conditional strings \ figures. Whenever data came from a user, the same equation would calculate everything in reverse order. It is important to add some kind of "salt" that would guarantee that the decoded data belong to a record. For example, the date of creation of the record in the database. But it is easier to use encryption . Or use password hashing logic (easiest).
For example, we take from the base the identifier of the record and the date-time of the creation of this record (as a "salt"). We connect them together, we bring, for example, to the form 174_2017-23-02_23-00 (it’s best to write the record ID is not expected at the beginning, but somewhere else, between date and time. Users don’t know what and how here twist).
Further we use password_hash() ( documentation ). We $2y$10$3KYZHiFhKHNB7.yJUGXJf.zR6Z8uc4.pdPsKbTTMDoApsp8CBY5qe hash of the form $2y$10$3KYZHiFhKHNB7.yJUGXJf.zR6Z8uc4.pdPsKbTTMDoApsp8CBY5qe , which we use to output to the user in a hidden field.
When receiving data from the user, we verify what is received, what should be. For example, using password_verify() ( documentation )
If the user wants to correct something on his page, he will not be able to find out what the data is and he will not be able to do anything. The meaning, I hope, is clear.