lastInsertId returns 0 (zero)

Asked

Viewed 50 times

0

I need to get the ID of my last INSERT in the database, however the function lastInsertId() only returns me 0.

This is my class that connects to the bank:

<?php 
namespace App\model;

class ModelConexao{
    
    public function conecta() {
        
        try {

            $pdo = new \PDO("mysql:host=".HOST.";dbname=".DB."","".USER."","".PASS."",array(\PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES utf8"));

            $pdo->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION);

            return $pdo;
            
        } catch (Exception $e) {
            
            echo "Falha ao tentar conectar-se ao banco de dados. Erro: " . $e->getMessage();

            exit();
        }
    }
}
 ?>

This is my class that inserts the data into the database:

<?php 
namespace App\model;

use App\model\ModelConexao;

class ModelCadastro extends ModelConexao {
    
    public function insert($email, $senha){

        $sql = $this->conecta()->prepare("INSERT INTO LOGIN SET email=:email, senha=:senha");

        $sql->bindParam(":email",$email,\PDO::PARAM_STR);

        $sql->bindParam(":senha",$senha,\PDO::PARAM_STR);

        $sql->execute();

        return $this->conecta()->lastInsertId();
    }
}
 ?>
  • $this->conecta()->lastInsertId(), why opened a new connection with the bank to pick up the last id?

  • So @Woss I figured this might be wrong, but when I make $sql->lastInsertId() it’s giving the following error: "Fatal error: Uncaught Error: Call to Undefined method Pdostatement::lastInsertId() "

  • That’s because $sql is the return of prepare, nay conecta.

  • I get it. What would that make you? I tried $connected = $this->connects(); Before the prepare and at the end I made $connected->lastInsertId(); which also gave me zero.

  • @Woss now I got brother. First I took the connection: $connected = $this->connects(); Then I used this variable to do the "prepare": $connected->prepare... and finally I got the ID: $connected->lastInsertId(); TOPZER!!! Thank you very much meeeesmo. I’m trying to set your answer as valid but I’m not getting.

1 answer

1


The adopted way is that in each $this->conecta() has a new instance of the class PDO used to abstract connection to a database, after calling this method again to rescue the last id inserted is a new instance of a new connection. Quick Fix:

<?php 
    namespace App\model;

    use App\model\ModelConexao;

    class ModelCadastro extends ModelConexao {    
        public function insert($email, $senha)
        {
            $conn = $this->conecta(); //pega a instância e utiliza no decorrer do código
            $sql = $conn
               ->prepare("INSERT INTO LOGIN SET email=:email, senha=:senha");
            $sql->bindParam(":email",$email,\PDO::PARAM_STR);
            $sql->bindParam(":senha",$senha,\PDO::PARAM_STR);
            $sql->execute();
            return $conn->lastInsertId();
        }
    }
?

the solution in my ideal view is not to make inheritance because to each class that needs to use a connection to the database will be a new instance, usually the ideal is always work with only one connection in each request, improved performance and resource savings of the database.


I would use injection and not inheritance, decrease coupling and cause the connection class to be shared in all classes that so need operation with the database, example:

<?php 
    namespace App\model;

    class ModelConexao {
        private $pdo;
        public function __construct()
        {
            $this->conecta();
        }
        
        public function getConnection()
        {
            return $this->pdo;
        }
        
        private function conecta() 
        {           
            try {

                $this->pdo = new \PDO(
                    "mysql:host=".HOST.";dbname=".DB."","".USER."","".PASS."",
                    array(\PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES utf8"));
                $this->pdo->setAttribute(
                    \PDO::ATTR_ERRMODE,
                    \PDO::ERRMODE_EXCEPTION
                );
            } catch (Exception $e) {            
                throw $e;
            }
        }
    }
?>

<?php 
    namespace App\model;

    use App\model\ModelConexao;

    class ModelCadastro {
            
        private $conn;
        
        public function __construct(PDO $conn)
        {
            $this->conn = $conn;
        }
        
        public function insert($email, $senha)
        {           
            $sql = $this->conn
                ->prepare("INSERT INTO LOGIN SET email=:email,senha=:senha");
            $sql->bindParam(":email",$email,\PDO::PARAM_STR);
            $sql->bindParam(":senha",$senha,\PDO::PARAM_STR);
            $sql->execute();
            return $this->conn->lastInsertId();
        }
    }
?>

Using:

$conexao = new ModelConexao();
$cadastro = new ModelCadastro($conexao->getConnection());
$cadastro1 = new ModelCadastro1($conexao->getConnection());    
  • Got it @novic . I liked the concern with coupling, however each Controller has only one Model and all methods will be in one Model. That way you quoted, I understand that every time I instantiate that same Model i will be making a connection with the bank as well, because the request with the bank is in the constructor method of the Model. Right?

  • @Epcreation actually there is a preparation in the abstraction layer not time of the execute a connection is made. What matters is the low coupling and a single instance with the database. and if you ever have more models, which maybe you don’t have at first, it’s good to use.

  • I understand @novic, thank you so much for your attention.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.