Preciso definir uma sequência de ordem personalizada para categorias ao adicionar novas e alterar as existentes. Acredito que o código e a consulta sql serão os mesmos nos dois cenários. Na minha webshop_categories
-table eu tenho uma so
-column (ordem de classificação INT) que eu uso para determinar em qual ordem as categorias devem ser enviadas para o visualizador.
Aqui está um exemplo simplificado de como minha tabela de categorias se parece (so = sorting_order):
id | name | so
--------------------
1 | Shoes | 1
2 | Hats | 2
3 | Bags | 3
4 | Coats | 4
5 | Rings | 5
Ao adicionar uma nova categoria, sem definir a ordem de classificação, eu apenas enviaria um formulário e executaria uma consulta assim:
$so = $dbh->query('SELECT (MAX(so)+1) FROM webshop_categories WHERE so != 0')->fetchColumn();
$ins = $dbh->prepare('INSERT INTO webshop_categories (name, so)')->execute([$_POST['name'], $so]);
(Isto irá adicionar uma nova categoria, e apenas colocá-la no final. Neste caso so
, seria definido como 6)
Essa é a maneira básica de apenas adicionar uma nova categoria. Funciona bem. Mas na maioria dos casos, ao lidar com categorias, é preciso colocá-lo em uma ordem específica de apresentação.
Mas geralmente ao adicionar uma nova categoria, deve-se especificar onde essa nova categoria deve ser colocada em relação às existentes. E é aí que atualizar a so
coluna - se torna um quebra-cabeças para mim ...
Meu formulário simplificado para adicionar uma nova categoria:
<form>
<input type="text" name="name">
<select name="so">
<option value="0" selected>At the end</option>
<option value="1">At the top</option>
<!-- php foreach loop through exising categories -->
<option value="<?=so?>">after <?=category_name?></option>
<select>
<input type="submit" name="submit_add" value="Add">
</form>
<?php
if($_POST['submit_add']){
if($_POST['so']==0){ // put new category at the end
$so = $dbh->query('SELECT (MAX(so)+1) FROM webshop_categories WHERE so != 0')->fetchColumn();
} else {
$so = $_POST['so'];
}
$ins = $dbh->prepare('INSERT INTO webshop_categories (name, so)')->execute([$_POST['name'], $so]);
}
?>
Já passei pelo primeiro cenário: Não especificar uma ordem de classificação.
Mas quando se trata de usar esse recurso, preciso atualizar o so
para as categorias afetadas.
Se eu adicionar uma nova categoria entre Shoes e Hats, eu usaria depois de Shoes na lista de seleção - o que significa que essa nova categoria deve obter o so
-valor de 2 . Isso significa que será necessário fazer um +1
para so
Chapéus e todas as categorias acima.
Qual seria uma boa maneira de fazer isso?
Uma situação bastante igual a esta seria ao mover uma categoria de um número mais alto para um so
número mais baixo. Seria necessário abrir espaço para a categoria movida e aumentar o resto (faça um +1
para o so
). Mas apenas os que estão entre as duas posições, é claro.
E deve ser bastante semelhante ao fazer o contrário - Mover uma categoria de um número mais baixo para um número mais alto. A única diferença é que agora precisamos fechar a lacuna que criamos entre essas duas poções.
Se eu mudasse os chapéus para after Coats
- os chapéus se tornariam 4, e o resto precisaria ser empurrado para baixo (faça um -1
ao seu so
).
Eu tentei fazer isso buscando as categorias afetadas ao usar esse recurso e atualizando cada uma em um loop foreach. Mas eu não consegui fazê-lo funcionar como esperado para todos os cenários.
Fazer uma cópia de todas as linhas (em um array PHP), excluí-las, criar uma nova lista atualizada, então inseri-las de volta também foi uma solução, mas não acho que deva ser necessário apenas fazer essas alterações. . Mas essa é uma maneira que eu descobri que funcionou...
Alguma sugestão?