0

PHP + MVC - Como resolver falha de extends

criado por Leonardo Felipe em 15/08/2012 10:26am
Bom Dia pessoal, estou reestruturando um projeto antigo para o Modelo MVC.... Comecei tudo bem, digitava o login e senha e autenticava certo e entrava no Home, então tive a necessidade de fazer umas alterações devido aos extends que necessitei então, não sei porque, começou a apresentar:
Warning: mysqli_prepare() expects parameter 1 to be mysqli, null given in...

Não entendi porque, pois estava funcionando!

PS.: O que está apresentado não é todo o código de cada arquivo... Só postei o que achei necessário para entenderem o problema.

// MainVar.class.php - Variáveis do Sistema( classe que criei para que qualquer arquivo possa usar suas variáveis )
class MainVar {
    var $DBName        = 'dbName';
    var $DBServer        = 'localhost';
    var $DBUser          = 'root';
    var $DBPassword   = '';

   { ..... }
}

// Conexao.class.php - Classe de Conexao
class Conexao extends MainVar {
   
    public function __construct(){
       
    }
   
    public function Connect(){
       
        $mysqli = mysqli_connect($this->DBServer, $this->DBUser, $this->DBPassword, $this->DBName);
                       
        if(mysqli_connect_errno()){
            trigger_error('Erro ao tentar conectar ao banco de dados! '.$mysqli->error,E_USER_ERROR);
        }
       
        $mysqli->autocommit(false);
       
        mysqli_query($mysqli, "SET NAMES 'utf8'");
        mysqli_query($mysqli, 'SET character_set_connection=utf8');
        mysqli_query($mysqli, 'SET character_set_client=utf8');
        mysqli_query($mysqli, 'SET character_set_results=utf8');
       
        return $mysqli;
    }
}

// logar.php
require_once('Config/MainVar.class.php');
require_once('Config/Conexao.class.php');
require_once('Libs/Funcoes.class.php');
require_once('Controller/LoginController.php');

if($_GET['acessar'] == 'acessar'){
       
    $LoginController = new LoginController();
    $login = $_POST['login'];
    $senha = $_POST['senha'];
   
    // Tenta logar o usuário com os dados
    if($LoginController->ValidaUsuario($login, $senha)){
       
        // Usuário logado com sucesso, redireciona ele para a página restrita
        header("Location: index.php");
        exit;
      }
}

// LoginController.php
require_once('Model/LoginModel.php');

class LoginController extends LoginModel{
   
    private $LoginModel;
    private $Funcoes;
   
    public function __construct(){
        $this->Funcoes = new Funcoes();
    }
   
    public function ValidaUsuario($login, $senha){
       
        if($senhaCodificada = $this->Funcoes->CodificaSenha($login, $senha)){
           
            // Chamo o ValidaUsuario de LoginModel
            $total = parent::ValidaUsuario($login, $senhaCodificada);
            return ($total == 1) ? true : false;
           
        }
    }
    {...}
}

// LoginModel.php
class LoginModel extends Conexao{
   
    private $mysqli;
   
    public function __construct(){
        $this->mysqli = parent::Connect();
    }
   
    public function ValidaUsuario($login, $senha){
       
        $sql = "SELECT COUNT(*) AS total
                FROM tabela_usuarios
                WHERE login = ? AND senha = ?";
       
       if($query = mysqli_prepare($this->mysqli, $sql)){

            //* O PROBLEMA É QUE AQUI NÃO ENTRA MAIS!!!!! *//
       
            /* ADICIONA OS PARÂMETROS */
            mysqli_stmt_bind_param($query, "ss",
                                   $login,
                                   $senha);
           
            /* ADICIONA OS PARAMETROS */
            if(mysqli_stmt_execute($query)){
               
                mysqli_stmt_bind_result($query,$total);
               
                if(mysqli_stmt_fetch($query)){
                    return $total;
                }
            }
        }
    }
    {...}
}

Então, aí está a dificuldade:
if($query = mysqli_prepare($this->mysqli, $sql)){
$this->mysqli deve(acho) está vazia como informa o Warning.


Achando isso, em LoginModel fiz:

class LoginModel extends Conexao{
   
    private $mysqli;
   
    public function __construct(){
        $this->mysqli = parent::Connect();
        var_dump($this->mysqli); // ADICIONEI ESTE VAR_DUMP();
    }
    { ... }
}

Mas não retornou nada na tela. Tô achando que a classe de Conexão não esteja realizando corretamente o extends da classe MainVar OU nã está conseguindo trazer os valores de DBServer, DBUser, DBUser e DBName para a function Connect() da classe Conexao:

$mysqli = mysqli_connect($this->DBServer, $this->DBUser, $this->DBPassword, $this->DBName);

ACHO que está vindo assim, tudo vazio:

$mysqli = mysqli_connect(, , ,);

Mas não to sabendo como confirmar isto...

Será este o problema msm? Como posso testar e consequentemente resolver... Como faço??? Estou perdido, OMG!!!

Agradeço antecipadamente pelas dicas!!!

Lista de Respostas:

0
15/08/2012 2:38pm
(~11 anos atrás)
Leonardo Felipe respondeu:
Boa tarde pessoal,

=================
Wilson Tamarozzi Jr.

Obrigado pela resposta Wilson... Mas não uso PDO, uso uma extensão do PHP * MySQLi - feita para aproveitar os recursos mais avançados do MySQL *.
Mas não foi este o problema não.... Explicação abaixo!

=================

Bem, consegui filtrar o problema. Em LoginModel.php na function __construct() conectava ao banco usando parent::Connect(), desta forma:

LoginModel.php
class LoginModel extends Conexao{
  
    private $mysqli;
  
    public function __construct(){
        $this->mysqli = parent::Connect();
    }
  
    public function ValidaUsuario($login, $senha){
      
        $sql = "SELECT COUNT(*) AS total
                FROM tabela_usuarios
                WHERE login = ? AND senha = ?";
      
       if($query = mysqli_prepare($this->mysqli, $sql)){

            O PROBLEMA É QUE AQUI NÃO ENTRA MAIS!!!!!
      
            /* ADICIONA OS PARÂMETROS */
            mysqli_stmt_bind_param($query, "ss",
                                   $login,
                                   $senha);
          
            /* ADICIONA OS PARAMETROS */
            if(mysqli_stmt_execute($query)){
              
                mysqli_stmt_bind_result($query,$total);
              
                if(mysqli_stmt_fetch($query)){
                    return $total;
                }
            }
        }
    }
    
    {...}
}


Mas o problema é que não está entrando no método __construct(). Para testar fiz o seguinte:

LoginModel.php
class LoginModel extends Conexao{
  
    private $mysqli;
  
    public function __construct(){
        //$this->mysqli = parent::Connect(); VOU UTILIZAR ESTE MÉTODO NA FUNCTION VALIDAUSUARIO()
    }
  
    public function ValidaUsuario($login, $senha){
      
        $sql = "SELECT COUNT(*) AS total
                FROM tabela_usuarios
                WHERE login = ? AND senha = ?";

       $this->mysqli = parent::Connect(); // COLOQUEI AQUI A CHAMADA DO MÉTODO DE CONEXÃO
      
       if($query = mysqli_prepare($this->mysqli, $sql)){

            O PROBLEMA É QUE AQUI NÃO ENTRA MAIS!!!!!
      
            /* ADICIONA OS PARÂMETROS */
            mysqli_stmt_bind_param($query, "ss",
                                   $login,
                                   $senha);
          
            /* ADICIONA OS PARAMETROS */
            if(mysqli_stmt_execute($query)){
              
                mysqli_stmt_bind_result($query,$total);
              
                if(mysqli_stmt_fetch($query)){
                    return $total;
                }
            }
        }
    }
    
    {...}
}

A testar funcionou perfeitamente, autenticou e acessou minha home.php.

O estranho é que em LoginController.php eu uso o método __construct() da seguinte forma:

LoginController.php
require_once('Model/LoginModel.php');

class LoginController extends LoginModel{
  
    private $LoginModel;
    private $Funcoes;
  
    public function __construct(){
        $this->Funcoes = new Funcoes(); // INSTANCIO A CLASSE FUNÇÕES
    }
  
    public function ValidaUsuario($login, $senha){
      
        if($senhaCodificada = $this->Funcoes->CodificaSenha($login, $senha)){ // CHAMO O MÉTODO DE CRIPTOGRAFAR SENHA
          
            // Chamo o ValidaUsuario de LoginModel
            $total = parent::ValidaUsuario($login, $senhaCodificada);
            return ($total == 1) ? true : false;
          
        }
    }
    
    { ... }
}

E consegue entrar no __construct() instanciar a classe Funcoes e utilizar seus métodos.

Só não entendi o porque.... Alguém poderia me explicar para que eu consigar utilizar do __construct() de LoginModel.php para fazer a Conexão!!???

Agradeço antecipadamente...

0
16/08/2012 11:44am
(~11 anos atrás)
Marcos Regis respondeu:
Fiz o seguinte teste aqui e tudo ocorreu como o esperado

<?php
class MainVar {
    public $DBName        = 'dbName';
    public $DBServer      = 'localhost';
    public $DBUser        = 'root';
    public $DBPassword    = '';
}

// Conexao.class.php - Classe de Conexao
class Conexao extends MainVar {
   
    public function __construct(){
       echo 'Chamou o construtor de Conexao <br />';
    }
   
    public function Connect(){
       
        $mysqli = "mysqli_connect($this->DBServer, $this->DBUser, $this->DBPassword, $this->DBName)";
                              
        return $mysqli;
    }
}

// LoginModel.php
class LoginModel extends Conexao{
   
    private $mysqli;
   
    public function __construct(){
        echo 'Chamou o construtor de LoginModel <br />';
        $this->mysqli = parent::Connect();
    }
   
    public function ValidaUsuario($login, $senha){
       
        $sql = "SELECT COUNT(*) AS total
                FROM tabela_usuarios
                WHERE login = ? AND senha = ?";
       
       if($this->mysqli!=null){

            echo 'ENTROU<br />'. time() . '<br />' . $this->mysqli;
           
            
        }
    }
    
}


$a = new LoginModel;

$a->ValidaUsuario('A',"B");

Qual a versão do PHP que está usando???

Nova Resposta:

(Você pode usar tags como <b>, <i> ou <code>. URLs serão convertidas para links automaticamente.)