Tacno 2 Denunciar post Postado Novembro 15, 2012 Olá! Faço Ciência da Computação e estudei o diagrama de classes. Criei o diagrama e gostaria de utilizar um ORM junto, porém já utilizei o doctrine e não gostei muito não então resolvi criar minhas classes e adicionar metodos para facilitar minha vida. No banco de dados resolvi utilizar um PDO, porém estou tendo um problema. Quando faço um ->save(), verifico se o id existe, caso exista, então update, caso contrário, inclua. O update funciona perfeitamente agora toda vez que chamo o insert, ele insere dois valores e isso não faz sentido oO o código é esse: function Save() { $sql = "SELECT COUNT(id) FROM modulo WHERE id = " . $this->id; $rows = $this->con->prepare($sql); $rows->execute(); //count the rows $count = $rows->fetchColumn(); if ($count > 0) { $this->con->query("update `modulo` set `curso`='".$this->curso."', `nome`='".$this->nome."', `ordem`='".$this->ordem."' where `id`='".$this->id."'"); } else { $new = "insert into `modulo` (`curso`, `nome`, `ordem` ) values ('".$this->curso."','".$this->nome."','".$this->ordem."' )"; $this->con->query($new); // Aqui está inserindo duas vezes!!!!! } $insertId = $this->con->lastInsertId(); if ($this->id == "") { $this->id = $insertId; } return $this->id; } Por que isso acontece? estou chamando esse método apenas uma vez. e não existe nenhuma estrutura de repetição. Por que está incluindo duas vezes ? oO Bem desde já agradeço Compartilhar este post Link para o post Compartilhar em outros sites
Bruno Augusto 417 Denunciar post Postado Novembro 15, 2012 De acordo com o manual, PDOStatement::fetchColumn() retorna uma string e sempre que você conta uma string, sempre retorna 1 (um), mesmo que seja uma string vazia. Sendo assim, experimente substituir a condição por PDOStatement::rowCount() Compartilhar este post Link para o post Compartilhar em outros sites
Tacno 2 Denunciar post Postado Novembro 16, 2012 beleza, alterei lá. Eu já li bastante coisa do manual referente ao PDO, porém em qualquer parte do código que eu coloco um insert, ele insere duas vezes. $this->con->exec("insert into `curso` (`nome` ) values ('".$this->nome."' )"); Ele insere: id: 1 Nome: <nome> id:2 Nome: <nome2> alguém faz alguma ideia pq isso ta acontecendo? Inclusive passei pro mysqli e continua dando o mesmo problema. Compartilhar este post Link para o post Compartilhar em outros sites
Bruno Augusto 417 Denunciar post Postado Novembro 16, 2012 Você fez a modificação que eu falei? Além dela, posta o fragmento de código que invoca essa sua função save() Pode ser que a lógica do invocador esteja produzindo a duplicidade. Compartilhar este post Link para o post Compartilhar em outros sites
Tacno 2 Denunciar post Postado Novembro 16, 2012 Poo eu descobri o por que está ocasionando o erro. Porém não sei como resolver. O meu .htaccess que está fazendo isso aparentemente ele está executando a página duas vezes. Segue o código do meu .htaccess Options +FollowSymlinks RewriteEngine On RewriteBase / #verifica se existe um arquivo com o nome do parametro vindo após a / RewriteCond %{REQUEST_FILENAME} !-f #verifica se existe uma pasta com o nome do parametro vindo após a / RewriteCond %{REQUEST_FILENAME} !-d #Direciona a url para a página index.php RewriteRule .(/)?$ index.php # Aqui está o erro!! Eu testei com o mysql normal (mysql_connect...) e deu o mesmo erro. Então resolvi testar meu .htaccess Todas as páginas devem ir para index em meu sistema, e ele determinará o que deve ser executado de acordo com a URL. Isso está acontecendo normalmente, porém se eu tiro a regra RewriteRule do .htaccess e executo nomedomeusite.com/index.php a inclusão acontece normalmente. Sabe me dizer o por que isso pode estar acontecendo? Compartilhar este post Link para o post Compartilhar em outros sites
Bruno Augusto 417 Denunciar post Postado Novembro 16, 2012 Se você detectou o problema partindo do htaccess, ele está relacionado ao roteamento das suas URL's, então, você tem de dizer como que seu index.php determina quem será invocado com base na requisição recebida. Porém, nem sempre o problema está no roteamento e sim naquilo que está sendo invocado (Controller) que é quem, de fato, está invocando o método save(), o qual eu já havia pedido para que você postasse. Para termos uma solução, precisamos conhecer o problema inteiro e não apenas parte dele. Compartilhar este post Link para o post Compartilhar em outros sites
Tacno 2 Denunciar post Postado Novembro 16, 2012 Eu peguei no index.php e coloquei isso no início de tudo para testar session_start(); header('Content-Type: text/html; charset=utf-8'); $con = new mysqli('<host>','<usuario>','<senha>','<database>'); #conectando $cmd = $con->query('INSERT INTO curso VALUES (null,"TESTE")'); #inserindo die(); A página está apenas executando esse script. Fiz isso apenas para testar. Como pode ver só é executado uma vez, e depois a página fecha. porém ela é executada duas vezes. Então quando eu comento a linha do .htaccess funciona perfeitamente. Porém só funciona se eu digitar index.php na barra de endereço. se eu descomentar, então funciona, porém inserindo valores duplicados. Obs: Estou utilizando o mysqli nesse caso apenas para teste. Logo o problema não está no PDO nem na execução do código, está no .htaccess que por algum motivo chama index.php duas vezes Compartilhar este post Link para o post Compartilhar em outros sites
Evandro Oliveira 331 Denunciar post Postado Novembro 16, 2012 Adicione a flag last ao final do seu redirect #Direciona a url para a página index.php RewriteRule .(/)?$ index.php [L]# Aqui está o erro!! Se você tiver mais regras de reescrita, poste-as. Compartilhar este post Link para o post Compartilhar em outros sites
Tacno 2 Denunciar post Postado Novembro 16, 2012 Coloquei essa regra e o erro persiste =( Compartilhar este post Link para o post Compartilhar em outros sites
Bruno Augusto 417 Denunciar post Postado Novembro 16, 2012 Você não está entrando num consenso. Você diz que está usando a PDO, mas postou um exemplo usando MySQLi, o que me leva a crer que você criou esse cenário agora e, se funcionou como deseja, pode caracterizar que o problema não seja como htaccess, tendo você recebido um falso positivo. Com essa posição você acaba forçando àqueles que tem condição de ajudar a não fazê-lo pois você demonstra recusa ao fornecer informações contundentes à solução do problema. Compartilhar este post Link para o post Compartilhar em outros sites
Tacno 2 Denunciar post Postado Novembro 16, 2012 Olha só bruno augusto eu comentei no código acima que estou realizando teste com o mysqli, pois o mesmo também está trazendo problemas. Sendo assim o problema não é com o PDO, pois o mesmo acontece com os comandos básicos do mysql e do mysqli. Na página index.php (como citei acima), eu coloquei no início de tudo um código onde só é incluido um dado na tabela curso e logo em seguida a página fecha. Consequentemente não é necessário mostrar o método ->save(), não é nele que está acontecendo o problema. Descobri que o problema é no .htaccess, pois primeiramente renomeei para .htaccess2 para que ele não executasse nada no servidor e o script funcionou corretamente. Após descobrir isso, fui comentando linha a linha até descobrir que o redirect do htaccess se comentado, o mysqli não retorna problema, porém com ele descomentado retorna. porém preciso dele descomentado, pois o único arquivo php existente na raiz é ele. Os outros arquivos php estão em uma pasta chamada protected, onde ficam a pasta config,model e controller. O erro esta acontecendo pela execução da página duas vezes seguidas ocasionada pelo .htaccess. Concordo que o título que postei é Meu PDO ta inserindo valores duplicados, porque acreditava que fosse erro do PDO, mas já chegamos ao consenso de que não é. Compartilhar este post Link para o post Compartilhar em outros sites
Bruno Augusto 417 Denunciar post Postado Novembro 16, 2012 Tudo bem, vamos nos ater, então, ao roteamento que está sendo feito. Todas as requisições são enviadas ao htaccess que faz o roteamento de alguma forma. Como que você faz isso? Explode pelas barras da URL, ordena, inverte, complementa... Como que você faz para que aquilo que o usuário solicitou seja determinada a ser tratado por um Controller específico? Um exemplo estendido: Imagina que seu sistema seja um cinemateca digital, tipo o IMDB. Nesse sistema teríamos avisualização dos filmes cadastrados e um formulário para adicionar novos filmes, acessíveis pelas seguintes URL's: site.com/admin/movies site.com/admin/movies/add Tenhamos em mente que a forma de roteamento que você adotou se baseia em expressões regulares as quais você executa com preg_match(). Essa função é preguiçosa e pára no primeiro casamento válido, sendo assim, a segunda rota jamais deveria alcançada pois como ambas possuem o termo site.com/admin/movies, a análise parará na primeira. Ela até poderia ser, mas como após executada uma ação você deveria interromper o fluxo para que nada mais seja executado (até mesmo para não se ter dois HTML's), ela não seria. Agora pense comigo: E se o seu sistema que não sei como funciona faz exatamente isso, mas não interrompe o fluxo? Vai executar as duas ações, das duas rotas. É só um caso hipotético, mas ilustra o porquê de eu estar batendo na mesma tecla da falta de código. De repete o seu sistema nem é essa piração toda que eu demonstrei e seja, de fato, uma coisa bem mais simples. E pode ser aí que mora o perigo, a simplicidade extrema, não previu essa ação em particular e, como não sabe como ou qual fazer, faz os dois. Enfim... Essa RewriteRule que você usa, tem certeza de que ela está correta? Você diz que um único caractere qualquer (ponto) seguindo de uma barra, sendo lido de trás pra frente (cifrão) será enviado ao index.php. Eu costumo fazer diferente. Já que meu sistema é mais automatizado eu delego que seja simplesmente: RewriteRule .*?$ index.php [L] Não seria esse seu caso? Uma ER mal formada? Compartilhar este post Link para o post Compartilhar em outros sites
Tacno 2 Denunciar post Postado Novembro 16, 2012 Bem o jeito que eu faço funciona da seguinte maneira Eu faço algo parecido com o cakephp. Crio uma pasta chamada protected (baseado no Yii) e lá fica o MVC. Além do MVC crio uma pasta para as configurações necessárias (como a conexão do banco de dados e alguns defines que irei precisar). o sistema todo é rodado em classes. Antes de tudo crio uma classe abstrata na qual não poderei instancia-la. Essa classe terá as variáveis criadas no config e será utilizada como extend para todas as outras classes. Tudo passará pelo index porque? no index.php, primeiramente chamo o config, logo após isso pego os parâmetros da url e transformo em um array. Ex: meusite.com/noticias/nome-da-materia, então o arquivo que irei chamar será o segundo parâmetro (no caso noticias.inc.php em controller). Se não existir a página, chamo o 404. A página notícias.php será uma classe, na qual, se for apenas notícias/ então eu chamo o método index, caso contrário, chamo um método correspondente a cada tipo de página. Em cada método defino variáveis que posteriormente será enviado para um template do smarty, assim criando a página. Variáveis pequenas (como title) e variáveis grandes como as de conteúdo. para as variáveis de conteúdo, utilizo a função ob_start(). Dessa forma que eu crio as páginas, pode não ser o jeito mais eficiente, mas me baseei no cakephp para me organizar dessa maneira. Segundo o site woorank.com, meus sites tem um desempenho bom. =D Veja um por exemplo: http://errandoeaprendendo.com (sem intenção de fazer merchandagem) eu fiz esse site dessa maneira. Porém utilizei o doctrine. Resolvi dessa vez criar meu ORM, pois ae poderei seguir de fato o meu diagrama de classes. E foi aí que tive problemas. Porém posso postar meu código sem problemas, só não tinha achado conveniente, pois o erro está no .htaccess e como eu não entendo muito de htaccess estou aqui depois de saber qual é o problema de fato. function Save() { $sql = "SELECT COUNT(id) FROM modulo WHERE id = " . $this->id; $rows = $this->con->prepare($sql); $rows->execute(); //count the rows $count = $rows->fetchColumn(); if ($count > 0) { // Aqui funciona, até pq se fizer isso duas vezes dará o mesmo resultado. haha $this->con->query("update `modulo` set `curso`='".$this->curso."', `nome`='".$this->nome."', `ordem`='".$this->ordem."' where `id`='".$this->id."'"); } else { $new = "insert into `modulo` (`curso`, `nome`, `ordem` ) values ('".$this->curso."','".$this->nome."','".$this->ordem."' )"; $this->con->query($new); } $insertId = $this->con->lastInsertId(); if ($this->id == "") { $this->id = $insertId; } return $this->id; } Logo para definir um novo módulo de curso $modulo = new Modulo(); $modulo->curso = 2; $modulo->nome = 'Intermediário II'; $modulo->ordem = 4; $modulo->save(); Compartilhar este post Link para o post Compartilhar em outros sites
Bruno Augusto 417 Denunciar post Postado Novembro 16, 2012 Perfeito! Com o perdão da brincadeira, viu como não doeu? Agora me diz, você tentou alterar a linha do htaccess para uma ER que faça um pouco mais de sentido? Porque se sem aquela RewriteRule funciona, a ER pode estar errada. Compartilhar este post Link para o post Compartilhar em outros sites
Tacno 2 Denunciar post Postado Novembro 16, 2012 ahuahuahuahu, doeu não!! haha o RewriteRule está sim mandando para index.php, porém parece q ele executa a página duas vezes. Ex: (com o código descomentado(indo para index)) nomedomeusite.com/qualquercoisa Insere dois registros (com código comentado(agora tenho que abrir index.php)) nomedomeusite.com/index.php Insere somente 1 a expressão regular está certa, porém não sei por que cargas d'agua insere duas vezes. e acho q só uma pessoa q passou por isso, encontrei um erro desse em um grupo do google, porém ninguem resolveu também. haha acho q só acontece comigo essas coisas Compartilhar este post Link para o post Compartilhar em outros sites
Bruno Augusto 417 Denunciar post Postado Novembro 16, 2012 A gente até poderia cavar a fundo seu problema, mas envolveria expor muito do seu código e horas de análise. Uma coisa que você pode tentar é depois da invocação do save() exibir o resultado de debug_backtrace(). De repente mostra quem é um culpado por invocar esse método duas vezes. Compartilhar este post Link para o post Compartilhar em outros sites