Como trabalhar com array de checkboxes opcionais 2
Dando continuidade ao artigo anterior:
http://wbruno.com.br/sql/como-trabalhar-com-array-de-checkboxes-opcionais/
Iremos escrever enfim, os códigos para fazer esse CRUD com checkboxes.
Lembrando que o intuito do artigo não é ensinar programação orientada a objetos. Então irei deixar o script php o mais simples possível, para que você possa extrair e então montar o seu dentro da sua estrutura/framework.
Listando os opcionais do banco
A listagem dos itens é super trivial:
<?php
$query = $mysqli->query('SELECT id, name FROM optional');
while($row = $query->fetch_object()) {
?>
<label>
<input type="checkbox" name="optional[]" value="<?php echo $row->id; ?>" />
<?php echo $row->name; ?></label>
<?php
}
?>
Apenas conecto no MySQL com a lib mysqli e imprimo um checkbox para cada registro da tabela.
DESCRIBE TABLE optional_vehicle
Ainda não estamos preocupados com trazer os checkboxes marcados, pois precisamos entender como utilizar a tabela optional_vehicle.
Ela faz um relacionamento N:N (um veículo para N opcionais, e 1 opcional para N veículos).
Para inserir nessa tabela, precisamos mais ou menos da seguinte string sql:
INSERT INTO vehicle_optional (id_vehicle, id_optional) VALUES (42, 1),(42 2)
Nessa query acima, estamos inserindo o opcional 1 e 2 para o veículo 42.
Se quisessemos inserir mais o opcional 5, bastaria:
INSERT INTO vehicle_optional (id_vehicle, id_optional) VALUES (42, 1),(42, 2),(42, 5)
Okay ?
Fazer essa string é uma simples maniplação de array. Lembra que o name do checkbox é name=”optional[]” então, no php irá chegar um array:
_POST['optional'][0], $_POST['optional'][1], $_POST['optional'][2]
Visto isso, vamos montar o INSERT:
//optional insert
$values = [];
foreach($optionals AS $id_optional) {
$values[] = "({$id}, {$id_optional})";
}
$values = implode(',', $values);
$sql = "INSERT INTO vehicle_optional (id_vehicle, id_optional) VALUES {$values}";
echo $sql;
$query = $mysqli->query($sql)or die($mysqli->error);
Simples, não ? a saída do echo $sql, será a string que escrevi acima.
Comecei pelos opcionais para matar logo a sua curiosidade, mas para deixar registrado o INSERT simples do veículo tem apenas as colunas que são atributos da entidade veículo:
sql = "INSERT INTO vehicles (id, name, year, model) VALUES(NULL, '{$name}', '{$year}', '{$model}')";
echo $sql, '<br /><br />';
$query = $mysqli->query($sql)or die($mysqli->error);
$id = $mysqli->insert_id;//ultimo id inserido no banco
Os truques
As duas queries acima são bem triviais e você já está mais do que acostumado com elas no seu dia a dia. Só existem 2 truques no server-side para essa modelagem.
O primeiro é:
Delete tudo, depois insira novamente
O comportamento do input type=”checkbox” do html é enviar para o server-side apenas os checkboxes marcados. Então aqueles que não estiverem no estado checked.
Tente imaginar a lógica de atualizar os opcionais de um carro. Ele já possui alguns cadastrados no banco. No submit do formulário você precisa remover os que não foram marcados, inserir os novos e com os que não alteraram não fazer nada. Complexo, não?
Um truque muito mais simples é remover tudo e depois inserir tudo o que vier.
DELETE FROM vehicle_optional WHERE id_vehicle = 42;
INSERT INTO vehicle_optional (id_vehicle, id_optional) VALUES (42, 1),(42, 2),(42, 5);
Marque os checkboxes
Agora precisamos marcar os checkboxes na listagem durante a edição de um registro.
O truque aqui é puramente SQL e se baseia em uma subquery.
SELECT `id`, `name`, (SELECT 'checked' FROM vehicle_optional WHERE id_vehicle = 1 AND id_optional = optional.id) AS `checked` FROM `optional`;
Pense no seguinte:
-> Temos que listar todos os opcionais
Fácil, já tinhamos feito isso.
-> E dizer quem está marcado ou não.
Aqui que entra a subquery.
(SELECT 'checked' FROM vehicle_optional WHERE id_vehicle = 1 AND id_optional = optional.id)
ela vai trazer a string ‘checked’ apelidada como a coluna `checked` AS `checked` apenas nos registros do veiculo id = 1 que tiverem marcados. o/
mysql>SELECT `id`, `name`, (SELECT 'checked' FROM vehicle_optional WHERE id_vehicle = 1 AND id_optional = optional.id) AS `checked` FROM `optional`;
+----+------------------+---------+
| id | name | checked |
+----+------------------+---------+
| 1 | air_con | checked |
| 2 | bluetooth | checked |
| 3 | parking_sensors | NULL |
| 4 | escape_motorcyle | NULL |
| 5 | plasma_cannon | NULL |
| 6 | cruise_control | checked |
| 7 | leather | NULL |
| 8 | metallic_paint | NULL |
| 9 | electric_locks | NULL |
| 10 | xenon_lights | NULL |
| 11 | nitro | NULL |
| 12 | wings | NULL |
+----+------------------+---------+
12 rows in set (0.00 sec)
E então vamos simplesmente imprimir isso no nosso input:
<input type="checkbox" name="optional[]" value="<?php echo $row->id; ?>" <?php echo $row->checked; ?>/>
Mágica.
Código no GitHub
https://github.com/wbruno/examples/tree/gh-pages/checkboxes-opcionais