Проблемът тук е, че свързвате параметри с bindParam , който използва обвързване чрез препратка. Във вашия случай трябва да използвате bindValue вместо това:
foreach( $binders as $key => $value ) {
$sql->bindValue( $key, $value );
}
Или можете да предадете своя масив директно на execute() метод:
$sql->execute( $binders );
Както е описано в ръководството:
the variable is bound as a reference and will only be evaluated at the time that PDOStatement::execute() is called.
Така че, когато вашият foreach цикъл приключи $value има стойност на последния елемент от масива Apple . Така че, когато execute изпълнява и двете :ctid и :p1 стойностите стават равни на Apple . Разбира се, това не е това, което искате)