Последният път, когато проверих, не беше възможно да се подготви изявление, където засегнатите колони бяха неизвестни по време на подготовката - но това нещо изглежда работи - може би вашата система от база данни е по-прощаваща от тези, които използвам (главно postgres)
Това, което е очевидно неправилно, е изразът implode(), тъй като всяка променлива трябва да се обработва сама, вие също се нуждаете от скоби около списъка с полета в инструкцията за вмъкване.
За да вмъкнете потребителски дефинирани полета, мисля, че трябва да направите нещо подобно (поне така го правя аз);
$fields=array_keys($a); // here you have to trust your field names!
$values=array_values($a);
$fieldlist=implode(',',$fields);
$qs=str_repeat("?,",count($fields)-1);
$sql="insert into user($fieldlist) values(${qs}?)";
$q=$DBH->prepare($sql);
$q->execute($values);
Ако не можете да се доверите на имената на полетата в $a, трябва да направите нещо като
foreach($a as $f=>$v){
if(validfield($f)){
$fields[]=$f;
$values[]=$v;
}
}
Където validfields е функция, която пишете, която тества всяко име на поле и проверява дали е валидно (бързо и мръсно чрез създаване на асоциативен масив $valfields=array('name'=>1,'email'=>1, 'phone'=>1 ... и след това проверка за стойността на $valfields[$f] или (както бих предпочел) чрез извличане на имената на полетата от сървъра)