La mejor forma es usando sesiones.
Yo tuve el mismo problema y lo solvente con una sesión.
En mi sesión defino un array para guardar lo que el formulario envía por POST.
Código PHP:
$_SESSION['formulario']
En el formulario, para cada campo le defino como valor por defecto el que tenga la sesión.
Código PHP:
echo "<input type='text' name='nombre' value='".$_SESSION['formulario']['nombre']."'>";
La primera vez que entras en el formulario, como al array $_SESSION['formulario'] NO le has definido ningún valor, los valores por defecto de cada campo estará vacio.
Luego en la página que recibe el formulario asignas los valores al array ...
Código PHP:
$_SESSION['formulario']=$_POST;
Ahora solo queda saber si todos los campos están cumplimentados, y en caso de que alguno no lo este, redireccionar a la página anterior manteniendo los campos...
Lógicamente el script que recibe el formulario SOLO conoce los campos que se le han enviado, y NO conoce los campos que habian en el formulario.
Por ello si en el formulario tienes 20 campos y solo seleccionar 12 el script recibirá 13 (los 12 campos seleccionados + el botón submit).
Por ello debería verificar campo a campo para saber si lo has recibido o no.
Código PHP:
if ( !isset($_POST['nombre]) )
... lo que sea
if ( !isset($_POST['apellido]) )
... lo que sea
Otra solución sería poner en el formulario un campo oculto cuyo valor por defecto sea el total de campos que debe recibir el script ...
Código PHP:
echo "<input type='hidden' name='totalCampos' value='20'>";
... y en el script verificas si el total de campos recibidos es igual al valor de totalCampos.
Saludos.