Ir para conteúdo

POWERED BY:

Arquivado

Este tópico foi arquivado e está fechado para novas respostas.

Matheus Gelinski

PHP recusando mais de uma chamada no MySQL

Recommended Posts

Olá, pessoal!

Estou tentando fazer duas ou mais requisições no banco de dados MySQL via PHP, mas somente a primeira requisição está aceitando utilizar os comandos "mysql_alguma_coisa". Por exemplo: Uso um trecho em PHP que faz a requisição de uma lista para imprimir no começo da página. Os comandos requeridos são "mysql_query", "mysql_num_rows","mysql_fetch_row", etc. A primeira vez funciona redondo. Só que, mesmo depois de já ter usado e ao solicitar uma segunda requisição, os comandos estão retornando false, por exemplo:"Warning: mysql_num_rows() expects parameter 1 to be resource, boolean given in caminho_do_arquivo.php".

Já experimentei fazer dentro de classes e retornar o array com os objetos, já tentei inclusive abrir conexão dentro da página, coisa que é inaceitável, mas mesmo assim continua dando problemas. Alguém pode me auxiliar, por favor?
Página principal:

<html> 
<?php include "../shared/head.php"; ?> 
<body>
 <!--Corpo da página-->
 <div class="corpo">
 <?php include "../shared/topMenu.php"; ?> 
 <div class="inner"> 
 <!--Cabeçalho-->
 <?php include "../shared/header.php"; ?> 
 <div class="conteudo"> 
 <div id="containerCenter">
 <div id="menuNoticias"> 
 <?php include "menuCategorias.php";?>
 </div> 
 <?php include "containerCenter.php"; ?>
 </div> 
 </div> 
 </div> 
</div> 
<body>
 </html>

Arquivo Header.php chama o listaMenus.php, que faz o uso da primeira requisição ao banco de dados:

<?php
        include("/../../models/menus.php");
        $menuLista = new Menu();
        $arrayMenu = array();
        $arrayMenu = $menuLista->listaMenus();
        
        for($i=0; $i<=sizeof($arrayMenu); $i++)
        {
            if(isset($arrayMenu[$i]))
            {
                $menu = new Menu();
                $menu = $arrayMenu[$i];
                echo "<li><a href=\"$menu->link\">$menu->nome</a></li>";
            }
        }
?>

Arquivo menuCategorias, que deveria trazer outro menu (de categorias), mas que está retornando "Warning: mysql_num_rows() expects parameter 1 to be resource, boolean given in C:\xampp\www\models\noticias.php on line 120":

<div id="menuCategorias">
<ul id="menuCategorias">
<?php
include_once("../../models/noticias.php");
$_categoria = new CategoriaNoticia();
$arrayCategorias = $_categoria->listarCategoriasMenu();


for($i=0; $i<=sizeof($arrayCategorias); $i++)
{
    if(isset($arrayCategorias[$i]))
    {
        $_categoria2 = new CategoriaNoticia();
        $_categoria2 = $arrayCategorias[$i];
        echo "<li><a href=\"scriptNoticias.php?acao=verNoticias&idCategoria=$_categoria2->idCategoriaNoticia\">$_categoria2->categoria</a></li>";
    }
}
?>
</ul>
<div>

Função listaMenus utilizada:

        public function listaMenus()
        {
            $query = "CALL sp_menusSelectActive();";
            $resultado = mysql_query($query);
            mysql_close();
            $linhas = mysql_num_rows($resultado);
            $arrayMenu = array();
            for($i=0; $i<$linhas; $i++)
            {
                $_menu = new Menu();
                $registro = mysql_fetch_row($resultado);
                $_menu->nome = $registro[0];
                $_menu->link = $registro[1];
                $arrayMenu[$i] = $_menu;
            }
            return $arrayMenu;
        }

Função listarCategoriasMenu utilizada:

        public function listarCategoriasMenu()
        {
            $query = "CALL sp_categoriasNoticiasSelectAll();";
            $resultado = mysql_query($query);
            mysql_close();
            $linhas = mysql_num_rows($resultado);
            $arrayCategorias = array();
            for($i=0; $i<$linhas; $i++)
            {
                $_categoria = new CategoriaNoticia();
                $registro = mysql_num_rows($resultado);
                $_categoria->idCategoriaNoticia = mysql_result($resultado,$i,'idCategoriaNoticia');
                $_categoria->categoria = mysql_result($resultado,$i,'categoria');
                $arrayCategorias[$i] = $_categoria;
            }
            return $arrayCategorias;
        }

Se alguém puder me dar uma dica do que pode estar errado, agradeço muito. Mas não vale mandar abrir conexão de banco fora da classe, cujo qual já está incluída na mesma!

Compartilhar este post


Link para o post
Compartilhar em outros sites

A mensagem de erro mostra que o erro está no arquivo noticias.php. Teste este arquivo diretamente no navegador.

Não é não. Se testar separadamente, todos os métodos funcionam normalmente. Mas ao invocar mais de um na mesma página, ele retorna o erro. Esse erro está dando justo no browser. E esse arquivo noticias.php é um arquivo que contém classes e métodos, não pode ser usada diretamente no browser. Considere que estou usando como arquitetura de desenvolvimento em MVC, e não outra.

 

Eu já testei método por método, por partes, fazendo individualmente funciona. Mas da forma que está, só o primeiro método retorna certo, os demais retornam errado. Tipo, "você já usou o mysql uma vez, não pode usar mais aqui", é mais ou menos isso que estou vendo que está acontecendo...

Compartilhar este post


Link para o post
Compartilhar em outros sites

imprima a consulta para ver se os paramentros não estão em branco, veja tbm se a conexao n esta morrendo tbm.

Compartilhar este post


Link para o post
Compartilhar em outros sites

imprima a consulta para ver se os paramentros não estão em branco, veja tbm se a conexao n esta morrendo tbm.

Não é, como já disse, separados todos os métodos estão funcionando. Mas juntos, estão dando esse problema. Tentei inclusive usar a mesma conexão para executar duas queries e fazer duas variáveis diferentes receberem o retorno das mesmas, a primeira consulta é bem sucedida, mas a segunda retorna o erro, por exemplo:

$query = "CALL sp_AlgumaCoisa1();";
$resultado1 = mysql_query($query);
echo mysql_num_rows($resultado1);

$query2 = "CALL sp_AlgumaCoisa2();";
$resultado2 = mysql_query($query2);
echo mysql_num_rows($resultado2);
mysql_close();

Isso tudo dentro de um mesmo trecho. O primeiro echo retorna o número de linhas, o segundo retorna "Warning: mysql_num_rows() expects parameter 1 to be resource, boolean given in arquivo_com_o_metodo.php on line x". Deu pra entender?

 

Se mando dar echo nas queries, elas estão aparecendo corretamente, tanto que se selecionar o que tem no echo e disparar diretamente no SGBD, o comando é processado.

 

Abaixo mostrarei um teste que realizei, e seu respectivo resultado:

 

Arquivo: teste.php

<?php
		include "s/conexao.inc";
		$query = "CALL infraatlas.sp_categoriasNoticiasSelectAll();";
		$resultado = mysql_query($query);
		$linhas = mysql_num_rows($resultado);
		echo $linhas . "\n";
		$query2 = "CALL infraatlas.sp_categoriasNoticiasSelect('2');";
		$resultado2 = mysql_query($query2);
		$linhas2 = mysql_num_rows($resultado2);
		echo $linhas2 . "\n";
		mysql_close();
?>

Resultado no Browser:

 

8

Warning: mysql_num_rows() expects parameter 1 to be resource, boolean given in C:\xampp\www\teste.php on line 9

 

Invertendo o teste.php:

<?php
		include "s/conexao.inc";
		$query2 = "CALL infraatlas.sp_categoriasNoticiasSelect('2');";
		$resultado2 = mysql_query($query2);
		$linhas2 = mysql_num_rows($resultado2);
		echo $linhas2 . "\n";
		$query = "CALL infraatlas.sp_categoriasNoticiasSelectAll();";
		$resultado = mysql_query($query);
		$linhas = mysql_num_rows($resultado);
		echo $linhas . "\n";
		mysql_close();
?>

Resultado:

 

1

Warning: mysql_num_rows() expects parameter 1 to be resource, boolean given in C:\xampp\www\teste.php on line 9

 

Ou seja, somente a primeira requisição do PHP ao MySQL está sendo aceita. Mesmo se dar um mysql_close() entre as duas requisições, o retorno é exatamente o mesmo.

 

Espero que isso explique melhor minha situação.

Compartilhar este post


Link para o post
Compartilhar em outros sites

o cara do link tem um problema parecido com seu, so q no caso ele usa mysqli

 

http://mike-hostetler.com/blog/2007/04/09/php-5-and-mysql-5-stored-procedures-error-and-solution-qcodo/

Parece que a partir daí começou a dar uma luz. O problema agora vai ser alterar uma aplicação inteira que foi escrita usando o mysql em vez do mysqli, por pura falta de conhecimento minha... Fiz o teste abaixo e já começou a clarear a situação:

<?php
	include "s/conexao2.inc";

	if($mysqli->multi_query("CALL sp_categoriasNoticiasSelectAll();"))
	{
		if($resultado = $mysqli->store_result())
		{
			print $resultado->num_rows;
			printf(" linhas de categorias\n");
		}
		$mysqli->next_result();
	}
	print "\n";
	
	if($mysqli->multi_query("CALL sp_menusSelectActive();"))
	{
		if($resultado = $mysqli->store_result())
		{
			print $resultado->num_rows;
			printf(" linhas de categorias\n");
		}
		$mysqli->next_result();
	}
?>

 

Pelo que vi também, não é necessário encerrar a conexão, ao contrário do que eu imaginei. Pelo que nosso amigo aqui disse, o PHP destrói implicitamente a conexão assim que não for mais usada. Bem mais cômodo pra mim, já que vou precisar usar várias conexões para montar uma página que faz várias solicitações. Por que se der um $mysqli->close() no meio do código e tentar usar de novo, ele não vai conseguir mais. Vou testar mais aqui para ver se me atenderá efetivamente.

Compartilhar este post


Link para o post
Compartilhar em outros sites

então o problema é no retorno da sp?

Compartilhar este post


Link para o post
Compartilhar em outros sites

o cara do link tem um problema parecido com seu, so q no caso ele usa mysqli

 

http://mike-hostetler.com/blog/2007/04/09/php-5-and-mysql-5-stored-procedures-error-and-solution-qcodo/

 

O link que você forneceu resolveu o meu problema, parece que da forma que estava sendo feito, o PHP somente aceita uma única vez a requisição com o comando usado. O lance do mysqli foi a peça fundamental que precisava para resolver esse impasse, mas que eu não o conhecia.

 

então o problema é no retorno da sp?

 

Não, pois, como dito antes, tudo funciona, mas usando os mesmos comandos mysql_alguma_coisa mais de uma vez por página só processa a primeira vez, nas demais vai recusar. A solução encontrada foi utilizar com os comandos do mysqli.

 

Pode ser alguma configuração do SGBD

 

Não é. Se fosse, as SP's mesmo já dariam problema mesmo testando dentro do SGBD.

Compartilhar este post


Link para o post
Compartilhar em outros sites

esse negocio do mysql_query não suportar multiplas query esta no manual, ainda n tinha visto esse problema.

 

http://php.net/manual/en/function.mysql-query.php

 

mysql_query() sends a unique query (multiple queries are not supported)

 

 

 

Outra solução esta nos comentarios é essa rs de 4 anos atras....

 

For all you programmers out there getting the 'Command out of synch' errors when executing a stored procedure call:

There are known bugs related to this issue, and the best workaround for avoiding this error seems to be switching to mysqli.

Still, I needed mysql to also handle these calls correctly.
The error is normally related to wrong function call sequences, though the bug report at http://bugs.php.net/bug.php?id=39727 shows otherwise.

For me, after commenting out hundreds of lines and several introspection calls to parse the procedure information (using information_schema and 'SHOW' extensions), I still got the same error.
The first result is returned, because I initiated my connection using the MYSQL_MULTI_RESULTS value of 131072 (forget this and you will never get any output, but an error message stating mysql cannot return results in this context)

After testing with this code (sproc2 simply calls 'SELECT * FROM sometable'), I found the error must be in the mysql library/extension. Somehow, mysql does not handle multiple resultsets correctly, or is at least missing some functionality related to handling multiple results.

<?php
//...
$rs = mysql_query('CALL sproc2(500)');
while (($row=mysql_fetch_assoc($rs))!==false) {
print_r($row);
}
mysql_free_result($rs);

$rs = mysql_query('CALL sproc2(500)');
print mysql_error(); //the notorious 'command out of synch' message :(
while (($row=mysql_fetch_assoc($rs))!==false) {
print_r($row);
}
mysql_free_result($rs);
?>

After spending hours debugging my code (the full library is already over the MB), the only solution seemed to be to CLOSE the connection after the first call, and reopening it before the second.

So if you ever make a uniform database accessing interface and implement stored procedures/prepared statements (or classes for it), this could be a solution if you really wish to enable stored procedures.

Still, be aware that this is really a serious flaw in your design (and IMHO, the mysql extension)

Also see the documentation for mysqli on mysqli_query, which seems to be working fine.

 

 

Matheus Gelinski, se tiver intresse existe outro metodo para conectar em banco de dados é o PDO.

Compartilhar este post


Link para o post
Compartilhar em outros sites

×

Informação importante

Ao usar o fórum, você concorda com nossos Termos e condições.