Herança no PHP em classe de conexão e DAO

7 respostas
phppdo
Y

Tenho uma classe abstrata BaseDAO, está classe está sendo herdade na classe DissertativaDAO, na BaseDAO tem um construtor que inicia a conexão com o banco de dados, eu posso acessar essa conexão pela classe DissertativaDAO ?

Pois quando tento usar esse método ele da um erro dizendo que a conexão está null.

<?php

namespace App\Models\DAO;

use App\Lib\Conexao;

abstract class BaseDAO{
    
    private $conexao;
    
    public function __construct()
    {
        $this->conexao = Conexao::getConnection();
    }


<?php
namespace App\Models\DAO;

use PDOException;

class TipoDissertativaDAO extends BaseDAO{
    
    public function Salvar($dissertativaObj){
        
        try {
        
        $this->conexao->beginTransaction();
        
        $stmt = $this->conexao->prepare("INSERT INTO questoes (id, titulo, questao, respostaPersonalizada, resposta, idAtividadeAcademica,
                                        idProfessor, idRevisor, idRevisorLinguistico, anoProva, situacao, tipo, dificuldade, dataCriacao,
                                        validade, numeroLinhas, linhasVisiveis, obrigatoria, nomeGrupo, tempo_estimado) 
                                        VALUES (:ID, :TITULO, :QUESTAO, :RESPOSTAPERSO, :RESPOSTA, :IDATIVIDADEACADEMICA, :IDPROFESSOR,
                                        :IDREVISOR, :IDREVISORLINGUISTICO, :ANOPROVA, :SITUACAO, :TIPO, :DIFICULDADE, :DATACRIACAO, :VALIDADE,
                                        :NUMLINHAS, :LINHASVISIVEIS, :OBRIGATORIA, :NOMEGRUPO, :TEMPOESTIMADO)");
        $stmt->execute(array(
            ':ID'=>NULL,
            ':TITULO'=>$dissertativaObj->getTitulo(),
            ':QUESTAO'=>$dissertativaObj->getEnunciado(),
            ':RESPOSTAPERSO'=>$dissertativaObj->getRespostaPersonalizada(),
            ':RESPOSTA'=>$dissertativaObj->getGabarito(),
            ':IDATIVIDADEACADEMICA'=>$dissertativaObj->getAtividadeAcademica()->getId(),
            ':IDPROFESSOR'=>$dissertativaObj->getProfessor()->getId(),
            ':IDREVISOR'=>$dissertativaObj->getRevisorArea()->getId(),
            ':IDRESIVORLINGUISTICO'=>$dissertativaObj->getRevisorLinguistico()->getId(),
            ':ANOPROVA'=>$dissertativaObj->getAnoProva(),
            ':SITUACAO'=>1,
            ':TIPO'=> 'dissertativa',
            ':DIFICULDADE'=>$dissertativaObj->getDificuldade(),
            ':DATACRIACAO'=>$dissertativaObj->getValidade(),
            ':NUMLINHAS'=>$dissertativaObj->getNumeroLinhas(),
            ':LINHASVISIVEIS'=>$dissertativaObj->getLinhasVisiveis(),
            ':OBRIGATORIA'=>$dissertativaObj->getIsObrigatorio(),
            ':NOMEGRUPO'=>$dissertativaObj->getGrupoQuestao(),
            ':TEMPOESTIMADO'=>$dissertativaObj->getTempo_estimado()
                                ));
        
        $idAtual = $this->conexao->lastInsertId();
        
        $stmt2 = $this->conexao->prepare("INSERT INTO questao_competencia (idQuestao , idcompetencia)
                                          VALUES (:IDQUESTAO, :IDCOMPETENCIA)");
        
        foreach ($dissertativaObj as $competencia){
            $stmt2->execute(array(':IDQUESTAO'=>$idAtual, ':IDCOMPETENCIA'=>$competencia->getId()));
        }
        
        $stmt3 = $this->conexao->prepare('INSERT INTO questao_conhecimento (idQuestao, idConhecimento),
                                          VALUES (:IDQUESTAO, :IDCONHECIMENTO)');
        foreach ($dissertativaObj->getConhecimentos() as $conhecimento){
            $stmt3->execute(array(':IDQUESTAO'=>$idAtual, ':IDCONHECIMENTO'=>$conhecimento->getId()));
        }
        
        $this->conexao->commit();
        
        }catch (PDOException $e){
            $e->getMessage();
            $this->conexao->rollBack();
        }
        
        
    }

7 Respostas

T

Palpite: declare $conexao como protected, pois senão a classe filha não conseguirá acessá-la (atributos private não são acessíveis por classes filhas).

abstract class BaseDAO{
    
    protected $conexao;
    
    public function __construct()
    {
        $this->conexao = Conexao::getConnection();
    }

Verifique também se conexao está sendo devidamente criado:

public function __construct()
    {
        $this->conexao = Conexao::getConnection();
       if ($this->conexao === null){
          // alguma mensagem de erro ou exception
       }
    }

Abraço.

Y

Bah não sabia dessa. Pelo menos em java não é assim.

Então para a classe filha herdar os atributos da classe pai tem que declarar o atributo protected ?

T

Em java também funciona assim. Se o atributo for private, a classe filha não consegue acessá-lo diretamente. Tem que ser protected. Exemplo: https://ideone.com/tt2cwI

Tem alguns detalhes específicos como packages e namespaces, mas a regra geral é que, se uma classe filha precisa acessar um atributo da classe pai diretamente, o atributo não pode ser private. É basicamente a razão do protected exibir pois, sem ele, o atributo teria de ser public, o que raramente é desejável.

Abraço.

Y

haaa verdade. Nem me liguei da regra de encapsulamento. :man_facepalming: :sweat_smile:

G

na teoria sim mas seria melhor vc deixar a conexao como private e criar um method getConnection() ou getConexao() com o modificador protected exemplo

protected function getConexao() 
{
    return $this->conexao;
}
D

Não é somente teoria é assim que funciona, concordo com o método, mas, ai eu me pergunto é mais código desnecessário ou não, é somente uma padronização que eu gosto ou não, cuidado em escrever também códigos sem necessidade.

D

Eu não faria uma herança de uma classe conexão, eu injetaria essa classe em todos as minhas classes DAO, sendo no caso uma interface em seu construtor, porque a minha DAO não precisa conhecer e cuidado com múltiplas instâncias de um classe onde você precisa somente de uma.

Exemplo:

Connection

interface IConection 
{
}

class Conection implements IConnection
{
}

Dao

class DaoItem 
{
    private $connection;
    public function __construct(IConnection $connection)
    {
        $this->connection = $connection;
    }
}

class DaoSaldo
{
    private $connection;
    public function __construct(IConnection $connection)
    {
        $this->connection = $connection;
    }
}

Como proceder:

$connection = new Connection();
$daoItem = new DaoItem($connection);
$daoSaldo = new DaoSaldo($connection);

Da outra maneira, são criadas instâncias desnecessárias e em vez de ter um reaproveitamento de código, há repetição.

Observação: o exemplo não tem corpo (body), é realmente bem básico.

Criado 19 de dezembro de 2018
Ultima resposta 20 de jan. de 2019
Respostas 7
Participantes 4