Ir ao conteúdo
  • Cadastre-se
Mineirovsky

Php não abre múltiplos statements

Recommended Posts

Estou programando uma interação um pouco complicada com banco de dados e preciso fazer várias declarações preparadas para ler e gravar.

<?php
$email = $_POST['email'];
$mysqli = new mysqli(...);
$sql = "SELECT * FROM users WHERE email = ?";
$stmt = $mysqli->prepare($sql);
$stmt->bind_param('s', $email);
$stmt->execute();
$stmt->bind_result(...)
$stmt->close();
$sql = "UPDATE users...";
$stmt = $mysqli->prepare($sql);
[...]

Após algumas interações recebo o erro:

Fatal error: Call to a member function bind_param() on a non-object

O que pode estar causando esse problema? Como posso contorná-lo?

Compartilhar este post


Link para o post
Compartilhar em outros sites

@Mineirovsky Olá,

seria interessante você por o código todo na íntegra. Desse jeito não tem como analisar o código!

Compartilhar este post


Link para o post
Compartilhar em outros sites

Certo, lá vai:

<?php
require_once('../../config/config.php');
if(isset($_POST['id_transacao'])) {
    // Variáveis de retorno

    // Obtenha seu TOKEN entrando no menu Ferramentas do Bcash
    $token = $bcash['token'];

    /* Montando as variáveis de retorno */

    $id_transacao = $_POST['id_transacao'];
    $data_transacao = $_POST['data_transacao'];
    $data_credito = $_POST['data_credito'];
    $valor_original = $_POST['valor_original'];
    $valor_loja = $_POST['valor_loja'];
    $valor_total = $_POST['valor_total'];
    $desconto = $_POST['desconto'];
    $acrescimo = $_POST['acrescimo'];
    $tipo_pagamento = $_POST['tipo_pagamento'];
    $parcelas = $_POST['parcelas'];
    $cliente_nome = $_POST['cliente_nome'];
    $cliente_email = $_POST['cliente_email'];
    $cliente_rg = $_POST['cliente_rg'];
    $cliente_data_emissao_rg = $_POST['cliente_data_emissao_rg'];
    $cliente_orgao_emissor_rg = $_POST['cliente_orgao_emissor_rg'];
    $cliente_estado_emissor_rg = $_POST['cliente_estado_emissor_rg'];
    $cliente_cpf = $_POST['cliente_cpf'];
    $cliente_sexo = $_POST['cliente_sexo'];
    $cliente_data_nascimento = $_POST['cliente_data_nascimento'];
    $cliente_endereco = $_POST['cliente_endereco'];
    $cliente_complemento = $_POST['cliente_complemento'];
    $status = $_POST['status'];
    $cod_status = $_POST['cod_status'];
    $cliente_bairro = $_POST['cliente_bairro'];
    $cliente_cidade = $_POST['cliente_cidade'];
    $cliente_estado = $_POST['cliente_estado'];
    $cliente_cep = $_POST['cliente_cep'];
    $frete = $_POST['frete'];
    $tipo_frete = $_POST['tipo_frete'];
    $informacoes_loja = $_POST['informacoes_loja'];
    $id_pedido = $_POST['id_pedido'];
    $free = $_POST['free'];/* Essa variável indica a quantidade de produtos retornados */
    $qtde_produtos = $_POST['qtde_produtos'];
    $produto_codigo = $_POST['produto_codigo_1'];
    $autorizar = false;

    /* Verificando ID da transação */
    /* Verificando status da transação */
    /* Verificando valor original */
    /* Verificando valor da loja */

    $post = "transacao=$id_transacao".
    "&status=$status".
    "&cod_status=$cod_status".
    "&valor_original=$valor_original".
    "&valor_loja=$valor_loja".
    "&token=$token";
    $enderecoPost = "https://www.bcash.com.br/checkout/verify/";
/*
    ob_start();
    $ch = curl_init();
    curl_setopt ($ch, CURLOPT_URL, $enderecoPost);
    curl_setopt ($ch, CURLOPT_POST, 1);
    curl_setopt ($ch, CURLOPT_POSTFIELDS, $post);
    curl_exec ($ch);
    $resposta = ob_get_contents();
    ob_end_clean();
*/
    if(/*trim($resposta)=="VERIFICADO"*/true) {
        //1. Verificar se id_transacao já existe no banco de Dados
        $conn = new mysqli($database['sname'], $database['user'], $database['pass'], $database['name']);
        $sql = "SELECT status
                  FROM bcash
                 WHERE id_transacao = ?";
        $stmt = $conn->prepare($sql);
        printf("Error: 1.prepare %s.\n", $stmt->error);
        $stmt->bind_param('i', $id_transacao);
        $stmt->execute();
        printf("Error: 1.execute %s.\n", $stmt->error);
        $stmt->store_result();
        $id_exist = $stmt->num_rows;
        $stmt->bind_result($status_anterior);
        $stmt->fetch();
        $stmt->close();
        $conn->close();
        //2. Adicionar ou atualizar dados no banco de dados
        if($id_exist) {
            //Atualizar
            $conn = new mysqli($database['sname'], $database['user'], $database['pass'], $database['name']);
            $sql = "UPDATE bcash
                       SET pay_method = ?, status = ?
                     WHERE id_transacao = ?";
            $stmt = $conn->prepare($sql);
            printf("Error: 2. prepare_atualizar %s.\n", $stmt->error);
            $stmt->bind_param('ssi', $tipo_pagamento, $status, $id_transacao);
            $stmt->execute();
            printf("Error: 2.execute_atualizar %s.\n", $stmt->error);
            $stmt->close();
            $conn->close();
            printf("\$status_anterior = %s; \$status = %s; \n", $status_anterior, $status);
            if($status_anterior == "Transação em Andamento" && $status == "Transação Concluída") $autorizar = true;
        } else {
            //Adicionar
            $conn = new mysqli($database['sname'], $database['user'], $database['pass'], $database['name']);
            $sql = "INSERT INTO bcash (id_transacao, user_email, plan_id, pay_method, status, `timestamp`)
                         VALUES (?, ?, ?, ?, ?, ?)";
            $stmt = $conn->prepare($sql);
            printf("Error: 2. prepare_adicionar %s.\n", $stmt->error);
            $time = time();
            $stmt->bind_param('isissi', $id_transacao, $cliente_email, $produto_codigo, $tipo_pagamento, $status, $time);
            $stmt->execute();
            printf("Error: 2. execute_adicionar %s.\n", $stmt->error);
            $stmt->close();
            $conn->close();
            if($cod_status == 1) $autorizar = true;
        }
        //3. Autorizar usuário se pagamento for aprovado
        if($autorizar) {
            //3.1 Armazenar tempo do plano assinado
            $conn = new mysqli($database['sname'], $database['user'], $database['pass'], $database['name']);
            $sql = "SELECT duration
                      FROM planos
                     WHERE id = ?";
            $stmt = $conn->prepare($sql);
            printf("Error: 3.1.0 prepare %s.\n", $stmt->error);
            $stmt->bind_param('i', $produto_codigo);
            $stmt->execute();
            printf("Error: 3.1.0 execute %s.\n", $stmt->error);
            $stmt->bind_result($duration);
            $stmt->fetch();
            $stmt->close();
            //$conn->close();
            $duration = $duration * 3600 * 24; //converte de dias para segundos
            if(!$duration) { //Se duração = 0, i.e. plano vitalício
                $conn = new mysqli($database['sname'], $database['user'], $database['pass'], $database['name']);
                $sql = "UPDATE users
                           SET expire_date = '-1'
                         WHERE email = ?";
                $stmt = $conn->prepare($sql);
                printf("Error: 3.1.1 prepare %s.\n", $stmt->error);
                $stmt->bind_param('s', $cliente_email);
                $stmt->execute();
                printf("Error: 3.1.1 execute %s.\n", $stmt->error);
                $stmt->close();
                $conn->close();
            } else {
                //3.2 Verificar se usuário já possui plano
                $conn = new mysqli($database['sname'], $database['user'], $database['pass'], $database['name']);
                printf("Connect failed: %s\n", mysqli_connect_error());
                $sql = "SELECT expire_date
                          FROM user
                         WHERE email = ?";
                $stmt = $conn->prepare($sql);
                printf("Error: 3.2 prepare %s.\n", $stmt->errno);
                $stmt->bind_param('s', $cliente_email);
                $stmt->execute();
                printf("Error: 3.2 execute %s.\n", $stmt->error);
                $stmt->bind_result($expire_date);
                $stmt->fetch();
                $stmt->close();
                $conn->close();
                //3.3 Se plano ainda for válido (i.e. expire_date > time()), somar o tempo assinado
                if($expire_date != 0) {
                    if($expire_date == -1) {
                        //faz nada
                    } elseif($expire_date > time()) {
                        $conn = new mysqli($database['sname'], $database['user'], $database['pass'], $database['name']);
                        $sql = "UPDATE users
                                   SET expire_date = '" . ($expire_date + $duration) ."'
                                 WHERE email = ?";
                        $stmt = $conn->prepare($sql);
                        printf("Error: 3.3.1 prepare %s.\n", $stmt->error);
                        $stmt->bind_param('s', $cliente_email);
                        $stmt->execute();
                        printf("Error: 3.3.1 execute %s.\n", $stmt->error);
                        $stmt->close();
                        $conn->close();
                    } else {
                        $conn = new mysqli($database['sname'], $database['user'], $database['pass'], $database['name']);
                        $sql = "UPDATE users
                                   SET expire_date = '" . (time() + $duration) . "'
                                 WHERE email = ?";
                        $stmt = $conn->prepare($sql);
                        printf("Error: 3.3.2 prepare %s.\n", $stmt->error);
                        $stmt->bind_param('s', $cliente_email);
                        $stmt->execute();
                        printf("Error: 3.3.2 execute %s.\n", $stmt->error);
                        $stmt->close();
                        $conn->close();
                    }
                    //3.4 Senão, somar o tempo da assinatura à data atual
                } else {
                    $conn = new mysqli($database['sname'], $database['user'], $database['pass'], $database['name']);
                    $sql = "UPDATE users
                               SET expire_date = '" . (time() + $duration) . "'
                             WHERE email = ?";
                    $stmt = $conn->prepare($sql);
                    printf("Error: 3.4 prepare %s.\n", $stmt->error);
                    $stmt->bind_param('s', $cliente_email);
                    $stmt->execute();
                    printf("Error: 3.4 execute %s.\n", $stmt->error);
                    $stmt->close();
                    $conn->close();
                }
            }
        }
    }
} else {}
?>

No caso aqui abri e fechei várias vezes a conexão, porque foi a forma que consegui contornar esse problema antes, mas nessa página especificamente há muito mais interações que nas outras que fiz. Só abrir e fechar os $stmt, ao invés de fechar os $conn também, não fez absolutamente nenhuma diferença.

Editado por Mineirovsky

Compartilhar este post


Link para o post
Compartilhar em outros sites

Como ninguém contribuiu e tenho prazo a ser cumprido, adaptei todo o código para PDO e resolvi o problema.

  • Curtir 1

Compartilhar este post


Link para o post
Compartilhar em outros sites

Crie uma conta ou entre para comentar

Você precisar ser um membro para fazer um comentário

Criar uma conta

Crie uma nova conta em nossa comunidade. É fácil!

Crie uma nova conta

Entrar

Já tem uma conta? Faça o login.

Entrar agora





Sobre o Clube do Hardware

No ar desde 1996, o Clube do Hardware é uma das maiores, mais antigas e mais respeitadas publicações sobre tecnologia do Brasil. Leia mais

Direitos autorais

Não permitimos a cópia ou reprodução do conteúdo do nosso site, fórum, newsletters e redes sociais, mesmo citando-se a fonte. Leia mais

×