Saltious, there's different ways of skinning this cat but mine is generally:
Javascript validation in the form, as a quickie pre-check that e.g. req'd fields are there. If all OK, the JS calls a form handler php. (The handler is called anyway, if JS is turned off).
The handler does validation (don't rely on the JS) - checks not only that the fields are supplied but whether they have malicious content, e.g. attempts to use as a spam relay, etc etc.
If there are errors, the handler displays a page saying so and showing what's wrong/missing, with a form with the user's input as hidden fields. The form button takes them back to the original form, and so posting these hidden fields.
The orig form checks for posted fields, and if present, echoes them to the fields.
The validation stuff lives in a separate file(s), for re-use, and one form handler can process all forms, if there's not too many.