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

,

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();
        }
        
        
    }
1 curtida

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.

2 curtidas

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 ?

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.

1 curtida

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

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;
}
1 curtida

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.

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.