ene1 0 Denunciar post Postado Setembro 10, 2016 Estou aprendendo PHP OO + PDO + MVC. Classe conexão: <?php class Conexao { public function conectar() { try { $conexao = new PDO("mysql:host=localhost;dbname=teste", "root", ""); $conexao->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); } catch (PDOException $e) { echo "Erro: " . $e->getMessage(); } return $conexao; } } Porém quando vou instanciar na classe a seguir, eu preciso colocar o método de conectar para que o preparedStatement seja reconhecido. include_once './Conexao.class.php'; class UsuarioDAO { public function inserir($nome, $cpf){ $j = new Conexao; $c = $j->conectar(); $sql = $c->prepare("insert into usuarios (nome, cpf) values (:nome, :cpf)"); $sql->bindParam("nome", $nome, PDO::PARAM_STR); $sql->bindParam("cpf", $cpf, PDO::PARAM_STR); $sql->execute(); } } Existe alguma forma/boa prática de já deixar instanciado para todos os métodos que eu tiver dentro de uma classe? Como podem ver, se eu tivesse um método de update/delete/read, eu teria que realizar a mesma coisa, o "$c = $j->conectar();" para que funcione. Compartilhar este post Link para o post Compartilhar em outros sites
Éverson da Luz 6 Denunciar post Postado Setembro 11, 2016 Se você fizesse isso de conectar várias vezes você teria o erro do MySQL de ter muitas conexões, eu tive esse problema também quando estava desenvolvendo meu framework, a solução é usar o Singleton, que é um Design Pattern, esse padrão diz que só pode haver uma instancia de uma classe no ciclo de vida da aplicação, altere sua classe para o seguinte: class Conexao { private static $instance = null; private function __construct() {} private function __clone() {} public static function conectar() { if (!isset(self::$instance)) { try { self::$instance = new PDO("mysql:host=localhost;dbname=teste", "root", ""); self::$instance->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); } catch (PDOException $e) { echo "Erro: " . $e->getMessage(); } } return self::$instance; } } agora para chamar use $db = Conexao::conectar(); Compartilhar este post Link para o post Compartilhar em outros sites
Williams Duarte 431 Denunciar post Postado Setembro 11, 2016 a solução é usar o Singleton, que é um Design Pattern, esse padrão diz que só pode haver uma instancia de uma classe no ciclo de vida da aplicação, altere sua classe para o seguinte: Singleton é péssimo e causa um alto acoplamento e difícil de testar, mas se for usar, antes Registry que ainda é usada por "alguns" Frameworks, pelo menos este ainda não te limita, claro que implementa no escopo o pattern singleton. Mas o melhor mesmo é utilizar Injeção de Dependência com interface da Conexão. Assim não interessa quem fez a conexão, se foi a ZEND, você, eu ou PQP, sua DAO só aceitara um tipo de Conexão, a que esta na assinatura, desacoplando seu código de todo o resto. Um exemplo mas simples e aproveitando seu código de Conexão seria assim, mas sua conexão poderia ficar dinâmica também, passando os dados da DNS, via D.I. ;) interface ConexaoInterface interface ConexaoInterface { public function conectar(); } Sua Interface forçando a sua classe de Conexão ter o método conectar, que sera usada na DAO class Conexao implements ConexaoInterface{ private $pdo; public function conectar() { try { $options = array( PDO::ATTR_PERSISTENT => true, PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES UTF8; SET CHARACTER SET UTF8; SET character_set_connection=UTF8; SET character_set_client=UTF8;', PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION ); $this->pdo = new \PDO( "mysql:host=localhost;dbname=teste" , "root", "" , $options); return $this->pdo; } catch (PDOException $e) { exit( "Erro: " . $e->getMessage() ); } } } UsuarioDAO class UsuarioDAO { private $db; public function __construct(ConexaoInterface $conexao) { $this->db = $conexao->conectar(); } public function inserir($nome, $cpf){ $sql = $this->db->prepare("insert into usuarios (nome, cpf) values (:nome, :cpf)"); $sql->bindParam("nome", $nome, PDO::PARAM_STR); $sql->bindParam("cpf", $cpf, PDO::PARAM_STR); $sql->execute(); } //outras public function excluir($id){ $sql = $this->db->prepare("delete ..."); $sql->execute(); } } Repare que forço o tipo da Conexão no construtor B) public function __construct(ConexaoInterface $conexao) { $this->db = $conexao->conectar(); } Forma de Uso $conexao = new Conexao(); $dao = new UsuarioDAO($conexao); $dao->inserir('William', '576.482.864-32'); $dao2 = new OutraClasse($conexao); $dao2->inserir('string', true); desta forma você pode ter quantos métodos quiser dentro da classe, só usar a @var $this->db que nela foi atribuída os objetos da PDO de forma encapsulada ou seja estamos nos acoplando a a uma abstração que naturalmente é mais estáveis e segura. $this->db->prepare("query .....") Se quiser usar uma outra Conexão, por exemplo para logs dentro da mesma classe, só criar outro objeto de conexão ao banco de dados, dentro da Classe de Conexao, declarar na interface e pronto, teria mais uma conexão distinta. public function __construct(ConexaoInterface $conexao) { $this->db = $conexao->conectar(); $this->dblog = $conexao->conectarLog(); } Enfim estude sobre injeção de dependência. Compartilhar este post Link para o post Compartilhar em outros sites
ene1 0 Denunciar post Postado Setembro 12, 2016 Olá pessoal, agradeço a ajuda. Mas nenhuma forma que vocês mostraram funcionou :( O método prepare do PDO não foi reconhecido. Alterei algumas coisas do seu codigo para ficar mais parecido com o meu Williams. class UsuarioDAO { private $db; public function __construct(ConexaoInterface $con) { $this->db = $con->conectar(); } public function inserir($nome, $cpf){ $sq = $this->db->prepare("insert into usuarios (nome, cpf) values (:nome, :cpf)"); $sq->bindParam("nome", $nome, PDO::PARAM_STR); $sq->bindParam("cpf", $cpf, PDO::PARAM_STR); $sq->execute(); } } class Conexao implements ConexaoInterface { private $conexao; public function conectar() { try { $this->$conexao = new PDO("mysql:host=localhost;dbname=teste", "root", ""); $this->$conexao->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); return $this->$conexao; } catch (PDOException $e) { echo "Erro: " . $e->getMessage(); } } } Há algo errado? Compartilhar este post Link para o post Compartilhar em outros sites
Gabriel Heming 766 Denunciar post Postado Setembro 12, 2016 A variável abaixo não existe, entretanto, o PHP cria para o escopo, por isso pode não dar erro. $this->$conexao O correto é: $this->conexao O que você quer dizer com: O método prepare do PDO não foi reconhecido. Qual foi o erro apresentado? Compartilhar este post Link para o post Compartilhar em outros sites
ene1 0 Denunciar post Postado Setembro 12, 2016 A variável abaixo não existe, entretanto, o PHP cria para o escopo, por isso pode não dar erro. $this->$conexao O correto é: $this->conexao O que você quer dizer com:[quote name="ene1" post="2 O método prepare do PDO não foi reconhecido.Qual foi o erro apresentado? Puts pessoal, eu estou utilizando Netbeans para desenvolver. E quando dou Ctrl + Espaço, aparece o autocompletar. Mas do codigo que vocês estavam colocando, ele não auto completava, ai achei que tinha algo de errado com o acesso a classe e sendo assim, nao iria funcionar. Vejam aqui: Acho que o desenvolvimento em java fez isso, sempre me acostumava ao auto completar, e se não aparecesse o que eu queria, algo estava de errado. Testei um outro método que achei no google e ignorei o prepared não estar aparecendo, e funcionou normalmente. Quando der vou testar o método do Williams e do Everson novamente. Há alguma forma de voltar a aparecer os métodos do PDO no netbeans utilizando essas formas de acesso a classe de Conexão? Compartilhar este post Link para o post Compartilhar em outros sites
Gabriel Heming 766 Denunciar post Postado Setembro 12, 2016 Veja se não tem que atualizar o manual. Não costumo utilizar intellisense nesses casos Compartilhar este post Link para o post Compartilhar em outros sites