Dúvida sobre CRUD PHP/MySQL
Estou desenvolvendo um CRUD com PHP e cheguei na parte de fazer as ligações das tabelas de estado, cidade, bairro e rua. Para pegar esses dados eu implementei uma API de CEP, que quando o user digita seu CEP as informações carregam automaticamente. Estou com um pequeno problema, os estados eu ja pre inseri dentro do banco, por nao ser tratar de algo tão grande, mas o que está me incomodando, é o fato de os dados cidades, bairros, ruas serem duplicados quando houver um novo cadastro, tem alguma maneira de corrigir isto?
Pritn da tabela cidades: https://prnt.sc/RH_-w40ujFWx
Preciso que não ocorra um mesmo cadastro se o mesmo ja existir, é possivel?
No Laravel há um método que atende a tua dúvida e tu pode transportar.
Há uma função firstOrCreate
que recebe dois parâmetros: attributes
e values
, ambos arrays. O que ela tenta fazer é encontrar no banco algo que satisfaça as condições do que você passar no primeiro parâmetro, caso exista, retornará o próprio objeto, caso contrário, criará um novo registro.
Ela é mais ou menos assim:
public function firstOrCreate(array $attributes = [], array $values = [])
{
if (!is_null($instance = $this->where($attributes)->first())) {
return $instance;
}
return tap($this->newModelInstance(array_merge($attributes, $values)), function ($instance) {
$instance->save();
});
}
Como funciona:
Nesse trecho da função, ele está fazendo uma consulta no banco com tudo o que foi passado como primeiro parâmetro da função firstOrCreate
.
if (!is_null($instance = $this->where($attributes)->first())) {
return $instance;
}
Por exemplo:
User::firstOrCreate(['email' => 'dummymail@mail.com'], []);
A função irá realizar uma consulta no banco, verificando o seguinte: se, na tabela users
, existe um usuário com email
tendo o valor dummymail@mail.com
, então me retorne esse usuário. Caso contrário, siga o seu curso.
Para o seu caso: ['nome_cidade' => 'value_that_you_want', 'fk_estado' => 'value_that_you_want']
.
No segundo trecho da função, ele vai apenas criar uma nova instância do modelo, tendo como atributos os dois arrays mergeados que foram passados e salvará no banco. Por exemplo:
User::firstOrCreate(['email' => 'dummymail@mail.com'], ['name' => 'Dummy User']);
Caso o email não exista, o resultado será um novo registro no banco com esse email e esse nome de usuário.
Talvez tenha ficado um pouco mais complexo do que deveria por se tratar do framework, mas a ideia central é: realize uma consulta no banco na hora de criar o registro. Se existir um registro com as condições que satisfaçam o que você deseja, retorne o que for adequado para ti. Se não existir, insira o novo registro.
@meira você consegue exemplificar quais são as ligações entre essas tabelas? Se eu consegui entender bem, o que está acontecendo é que para cada novo cadastro que contém essas informações está duplicando as informações dentro do banco de dados correto?
Essa tabela do seu print seria uma tabela para armazenar as cidades?
Aparentemente você possui uma tabela para cada um desses modelos que você citou. Seria isso mesmo? Uma tabela para cidade, uma para estado e outra para endereço. Correto?
Se for isso mesmo, você poderia ter uma tabela extra que armazenaria todas as referências de chave estrangeira das outras tabelas que citei acima:
endereco_usuario
id | endereco_fk |
onde essa tabela faz referencia ao endereço em formato de chave estrangeira, que por sua vez faz referência à cidade
endereco
id | cidade_fk
onde essa tabela faz referência à cidade em formato de chave estrangeira e por fim, a cidade faz referênca ao estado
cidade
id | estado_fk
Perceba que aqui você terá uma tabela de estado
contendo todos os estados do Brasil por exemplo, uma tabela de cidade
que faz referência aos estados (onde você terá várias cidades para um mesmo estado por exemplo), uma tabela de endereços
que faz referência a uma cidade (também podendo conter várias cidades para a mesma cidade) e a última, caso seja realmente isso, poderia ser uma tabela de endereco_usuario
onde vc faz referência somente a primary key de um endereço.
Acho que ficaria algo assim
1 estado ----------> N cidades
1 cidade ----------> N enderecos
No final, se vc souber o ID de um endereço, você saberá a FK de uma cidade e na cidade vc sabe a FK do estado.
Se precisar, existe DB Diagram, que te ajuda no mapeamento de relações entre as tabelas
O exemplo abaixo simula um contador de visualização que não cadastra uma nova data se ela já existir no banco de dados, da pra pegar a mesma lógica para o seu problema.
include('Database/database.php');
$date_now = date('Y-m-d');
$query = "SELECT * FROM hit_counter_product WHERE `data` = '$date_now'";
$query = $pdo->query($query);
if ($query->rowCount() > 0) {
$query = "UPDATE hit_counter_product SET `counter` = `counter` + 1 WHERE `data` = '$date_now'";
$query = $pdo->query($query);
} else {
$query = "INSERT INTO hit_counter_product (`data`, `counter`) VALUES ('$date_now', 1)";
$query = $pdo->query($query);
}
Qualquer dúvida, só perguntar.