TheNight 1 Denunciar post Postado Maio 22, 2015 Bom guys, eu tinha feito uma conexão com MySQLi e então resolvi mudar. Obs: não me venham falar de PDO, pq até agora não me familiarizei com PDO ainda... class Connect extends mysqli { public $db_connection, $db_hostname, $db_username, $db_password, $db_database; public function __construct() { $this->db_hostname = DB_HOSTNAME; $this->db_username = DB_USERNAME; $this->db_password = DB_PASSWORD; $this->db_database = DB_DATABASE; $this->connectMe(); } private function connectMe() { $this->db_connection = @$this->connect($this->db_hostname, $this->db_username, $this->db_password, $this->db_database); if($this->connect_error) { die("Falha na tentativa de se conectar com o servidor: " . $this->connect_error); } } } Compartilhar este post Link para o post Compartilhar em outros sites
Williams Duarte 431 Denunciar post Postado Maio 22, 2015 Obs: não me venham falar de PDO, pq até agora não me familiarizei com PDO ainda... :D Passe estes dados de acesso dentro de uma instancia, ao invés do construtor. Tendo um instancia da Classe de conexão, você evita conexões simultâneas dentro de outros objetos. Compartilhar este post Link para o post Compartilhar em outros sites
TheNight 1 Denunciar post Postado Maio 22, 2015 como por exemplo ? : public static function getInstance() { if(!isset($_instance)) { self::$_instance = new self(); } return self::$_instance; } ??? ou passar private static $db_connection; etc... ? Compartilhar este post Link para o post Compartilhar em outros sites
Williams Duarte 431 Denunciar post Postado Maio 22, 2015 De uma estudada e ve onde possa melhorar e otimizar os scripts abaixo, pois é bem antigo, mas lá pelo meados de 2008 e como fazíamos pra usar mysqli em Oo, hoje a maioria usa PDO, acredito que você ira utilizar mais a frente. :P <?php class DB { private static $db; private static $_config = null; private $_connection = null; private function __construct() { } public static function getInstance() { if (func_num_args() == 4) { self::$_config = func_get_args(); } else { self::$_config[0] = defined("SERVER") ? SERVER : ''; self::$_config[1] = defined("USER") ? USER : ''; self::$_config[2] = defined("PASS") ? PASS : ''; self::$_config[3] = defined("DB") ? DB : ''; } if (!(self::$db instanceof DB)) { $class = __CLASS__; self::$db = new $class; } return self::$db; } protected function _connect() { if ($this->_connection) { return; } if (!extension_loaded('mysqli')) { throw new Exception('É necessario a extension Mysqli.'); } if (is_array(self::$_config)) { $this->_connection = mysqli_init(); if (!$this->_connection) { throw new Exception('mysqli_init failed'); } $_isConnected = @mysqli_real_connect( $this->_connection, self::$_config[0], self::$_config[1], self::$_config[2], self::$_config[3] ); if ($_isConnected === false || mysqli_connect_errno()) { throw new Exception(mysqli_connect_error()); } } } public function getConnection() { $this->_connect(); return $this->_connection; } public function isConnected() { return ((bool) ($this->_connection instanceof mysqli)); } public function closeConnection() { if ($this->isConnected()) { $this->_connection->close(); } $this->_connection = null; } public function query($sql = '') { if ($sql != '') { $this->_connect(); return $this->_connection->query($sql); } } public function prepare($sql = '') { if ($sql !== '') { $this->_connect(); return $this->_connection->prepare($sql); } } public function fetchOne($sql = '') { if ($sql != '') { $this->_connect(); $rs = $this->_connection->query($sql); $re = $rs->fetch_array(); return $re[0]; } } public function lastInsertId() { $mysqli = $this->_connection; return (string) $mysqli->insert_id; } public function __clone() { trigger_error('Clone is not allowed.', E_USER_ERROR); } } Depois é só estanciar a Conexão $db = DB::getInstance(); //forçando a conexao $db->getConnection(); Uso $db->query('...') //Fecha conexão com o banco $db->closeConnection(); Pega o ID do insert $db->lastInsertId(); Esta faz um count, mas existe forma mais simples fetchOne Com Construtor <?php /* * Mysqli database class - only one connection */ class Database{ private $_connection; private static $_instance; //The single instance private $_host = 'localhost'; private $_username = 'root'; private $_password = ''; private $_database = 'blogwebsite'; public static function getInstance(){ if(!self::$_instance){ // If no instance make one self::$_instance = new self(); } return self::$_instance; } /* * Constructor */ public function __construct(){ $this->_connection = new mysqli($this->_host, $this->_username, $this->_password, $this->_database); // Error handling if(mysqli_connect_error()){ trigger_error("Failed to connect to MySQL: " . mysqli_connect_errno(), E_USER_ERROR); }else{ echo "You are connected to " . $this->_database; } } // Magic method clone is empty to prevent duplication of connection public function __clone(){ } // Get mysqli connection public function getConnection(){ return $this->_connection; } } ?> Bons estudos Compartilhar este post Link para o post Compartilhar em outros sites
Gabriel Heming 766 Denunciar post Postado Maio 22, 2015 Alguns pontos a considerar: - Uma conexão não deve ser estendida, ela deve ser apenas utilizada. Você pode utilizar injeção de dependencia. Caso queira utilizar mais de uma conexão a SGBDs diferentes, adapter ou facade pode ser útil; - Injete, também, as propriedades (dados de conexão). Você não quer limitar seu sistema a uma só conexão; - Perpetue a instância da forma correta através da sua aplicação. Seja por injeção de dependência ou Registry, mas evite singleton para conexões com Banco de Dados. Singleton possui sua utilidade sim, mas deve ser evitado ao máximo, pois normalmente é utilizado de forma errada; - Não utilize supressão de erros. Se a conexão falhou, seu sistema não funcionará. Ao invés de suprimir o erro, trate o erro e avise ao usuário; - O mesmo vale para o die. Ao invés, lance uma exception. Compartilhar este post Link para o post Compartilhar em outros sites
Williams Duarte 431 Denunciar post Postado Maio 22, 2015 Me tire uma dúvida Gabriel, que o assunto OPP sempre me interessa, e estou aqui também para aprender, apesar que uso em meus sistemas injeção de dependência e Registry, alguns falam em posts "evite Singleton" e recomenda "Registry", este que tem em sua base o Singleton. Até ai tudo bem, você explanou e tirou minhas dúvidas tempo atrás aquiCom PDO tem este exemplo e fica fácil a compreensão, o qual sempre recomendo, e quando lembro é claro! Mas como seria utilização de Registry com mysqli ? Compartilhar este post Link para o post Compartilhar em outros sites
Gabriel Heming 766 Denunciar post Postado Maio 22, 2015 A utilização seria da mesma forma. Sendo o Registry um repositório de objetos, MySQLi permite a utilização orientada a objetos. $registry = Registry::getInstance(); $mysqli = new mysqli(/** dados **/); $registry->set('mysqli' , $mysqli); Ou quando necessito de mais de uma conexão: $registry = Registry::getInstance(); $conexao1 = new mysqli(/** dados **/); $registry->set('mysqli-conexao1' , $conexao1); $conexao2 = new mysqli(/** dados **/); $registry->set('mysqli-conexao2' , $conexao2); Isso depende da forma que seu sistema foi modelado. Entretanto, se, de alguma forma, não for utilizado uma conexão orientada a objetos, deve-se, então, encapsular a conexão em um objeto. Como antigamente era feito com as mysql_*, mssql_* pg_* ou com o seu exemplo, onde a conexão mysqli foi encapsulada ao objeto DB. Remove-se a restrição do singleton e utiliza-se normalmente: $registry = Registry::getInstance(); $database = new Database(); $registry->set('database' , $database); Compartilhar este post Link para o post Compartilhar em outros sites
Williams Duarte 431 Denunciar post Postado Maio 22, 2015 Show!!! Sanou minhas dúvidas, até porque com as novas versões do PHP, não é mais necessário $mysqli->close(). $thread = $mysqli->thread_id; $mysqli->close(); $mysqli->kill($thread); Para efetuar as limpezas, daqui pra frente não recomendarei mais Singleton com DB nas postagens! :thumbsup: Valeu!! :worship: Obrigado. Compartilhar este post Link para o post Compartilhar em outros sites
Aderson Designer 3 Denunciar post Postado Maio 22, 2015 Olá Pessoal o que é PDO ? Compartilhar este post Link para o post Compartilhar em outros sites
Gabriel Heming 766 Denunciar post Postado Maio 22, 2015 PHP Data Objects Compartilhar este post Link para o post Compartilhar em outros sites
TheNight 1 Denunciar post Postado Maio 23, 2015 Bom, dei uma estudada mais profunda neste assunto, e cheguei a seguinte conclusão: Não preciso fazer o que eu fiz sendo que uma única class faria o mesmo ou até melhor!!! assim: class Connect { // MySQLi object instance public $mysqli = null; // Class constructor override public function __construct() { $this->mysqli = @new mysqli(DB_HOSTNAME, DB_USERNAME, DB_PASSWORD, DB_DATABASE); if ($this->mysqli->connect_error) { echo "Error MySQLi: " . $this->mysqli->connect_error; exit(); } } } Gabriel, Williams, eu estou impaciente, estou tentando escolher entre MySQLi e PDO, porém não consigo me familiarizar de jeito maneira... Vale lembrar que sou iniciante, e qualquer fonte sobre o assunto é bem vinda, sendo que eu li e relei o que vocês mandaram e eu entendi muito pouco :( Haa! e também gostaria de saber como tratar estes erro, ouvi falar que se colocar um "@" resolve igual eu fiz ali mas o sistema fica vulnerável a invasões... Compartilhar este post Link para o post Compartilhar em outros sites
Williams Duarte 431 Denunciar post Postado Maio 23, 2015 Então como foi mencionado, você fica engessado ao passar os dados de conexão por constantes de valor único, ou seja vai utilizar um único banco de dados, e não vários Bancos. Seu caso: $this->mysqli = @new mysqli(DB_HOSTNAME, DB_USERNAME, DB_PASSWORD, DB_DATABASE); O mais simples é passar estes dados via o método __construct, como foi dito pelo Gabriel, "Injete os dados" public function __construct($hostname, $username, $password, $database) { No construtor do mysqli $this->mysqli = new mysqli($this->hostname, $this->username, $this->password, $this->database); class Connect { public function __construct() { $this->mysqli = @new mysqli(DB_HOSTNAME, DB_USERNAME, DB_PASSWORD, DB_DATABASE); if ($this->mysqli->connect_error) { echo "Error MySQLi: " . $this->mysqli->connect_error; exit(); } } } E como já foi falado, evite supressão de erros e falhe elegantemente, use Exeções Exemplo de captura do erro: throw new Exception("Error MySQLi: " . $this->mysqli->connect_error); A Classe inteira, ficaria assim//Connect.php <?php class Connect { // MySQLi object instance private $mysqli; // Class constructor override public function __construct($hostname, $username, $password, $database) { $this->mysqli = new mysqli($hostname, $username, $password, $database); if ($this->mysqli->connect_errno) { throw new Exception("Error MySQLi: " . $this->mysqli->connect_error); } return $this->mysqli; } } Ou assim <?php class Connect { // MySQLi object instance private $mysqli; private $hostname; private $username; private $password; private $database; // Class constructor override public function __construct($hostname, $username, $password, $database) { $this->hostname = $hostname; $this->username = $username; $this->password = $password; $this->database = $database; $this->mysqli = new mysqli($this->hostname, $this->username, $this->password, $this->database); if ($this->mysqli->connect_errno) { throw new Exception("Error MySQLi: " . $this->mysqli->connect_error); } return $this->mysqli; } } Ai amigo,você pode encapsular quantas conexões quiser, ou seja, sua conexão fica ilimitada a qualquer banco do MySQL, mas restrito a somente e exclusivo SGBD "MySQL", diferente da PDO. Veja um exemplo de como passar os dados de acesso, para o construtor da classe: $connect1 = new Connect('localhost', 'root', '123456', 'banco1'); Para usar de uma forma mais simples os dados de conexão, passe por parâmetro através do objeto. $class1 = new Data1(); $class1->insert($connect1); No exemplo acima use normalmente as constantes DB_HOSTNAME, DB_USERNAME, DB_PASSWORD, DB_DATABASE Mas a mágica e usar de diversas conexões e simultânea: $connect1 = new Connect('localhost', 'root', '123456', 'test'); $connect2 = new Connect('localhost', 'root', '123456', 'banco2'); $connect3 = new Connect('other', 'root', '123456', 'banco'); $connect4 = new Connect('216.58.222.3', 'root', '123456', 'banco'); $class1 = new Data1(); $class1->insert($connect1); $class2 = new Data2(); $class2->update($connect2); $class3 = new Data3(); $class3->delete($connect3); $class4 = new Data4(); $class4->seletc($connect4); Voltando a classe de conexão, após lançar o erro na Exception throw new Exception("Error MySQLi: " . $this->mysqli->connect_error); Coloque os códigos dentro do bloco try/catch, caso tenha algum erro, será lançada uma exceção no bloco catch, dentro deste bloco, você manipula as informações retornadas das classes. try { } catch (Exception $e) { } <?php ini_set('display_errors', FALSE); include_once 'Connect.php'; try{ $connect1 = new Connect('localhost', 'root', '123456', 'test'); $connect2 = new Connect('localhost', 'root', '123456', 'banco2'); $connect3 = new Connect('outro', 'root', '123456', 'banco'); $connect4 = new Connect('216.58.222.3', 'root', '123456', 'banco'); $class1 = new Data1(); $class1->insert($connect1); $class2 = new Data2(); $class2->update($connect2); $class3 = new Data3(); $class3->delete($connect3); $class4 = new Data4(); $class4->seletc($connect4); } catch (Exception $e){ echo "Um erro ocorreu.<br />"; echo "Número da linha: ".$e->getLine()."<br />"; echo "Nome Do Arquivo: ".$e->getFile()."<br />"; echo "Descrição do erro: ".$e->getMessage(); } Haa! e também gostaria de saber como tratar estes erro, ouvi falar que se colocar um "@" resolve igual eu fiz ali mas o sistema fica vulnerável a invasões... Isso é jogar sujeira para debaixo do tapete. :assobiando: Você pode esconder do usuário, casso esteja habilitado para mostrar os erros em tela. ini_set('display_errors', FALSE); Aqui algumas formas de criar logs de erros para saber oque esta ocorrendo em backgroud Outra Dica é criar suas próprias classes de validação, estendendo a classe Exception, para tratar devidamente cada erro. class FileException extends Exception { // Exceptions para erros com o sistema de arquivos } class ValidateException extends Exception { // Exceptions para erros com a validação } class SQLException extends Exception { // Exceptions para erros com a conexão de banco de dados } exemplo utilizando suas próprias ExceptionsNa Connect throw new SQLException("Error MySQLi: " . $this->mysqli->connect_error); No bloco try/catch try { } catch (SqlException $e) { } catch (ValidateException $e) { } //etc.... Você pode também utilizar as Exceptions nativas da biblioteca para padronizar seu código, até mesmo para facilitar futuras manutenções por outros desenvolvedores. Saiba mais sobre cada uma delas aqui Gabriel, Williams, eu estou impaciente, estou tentando escolher entre MySQLi e PDO, porém não consigo me familiarizar de jeito maneira... Bom não sei se é seu caso, mas para quem vem de programação estrutural para OPP, sofre um um pouco para aprender no inicio, e não é da noite para o dia, por isso poucos se arriscam. B) Ps.: Este cara fala que qualquer um aprende qualquer coisa em 20 horas, acredito que sim, mas com foco, ai vai embora. Mas para que vai em frente, e encare ela, acaba vendo que os ganhos é muito maior que a dor. :) E sobre MyQLI OO e PDO, não há muita diferença entre as formas de uso, e até mesmo os nomes das funções são bem parecidas.Chega por aqui, fica para a próxima. :thumbsup: Compartilhar este post Link para o post Compartilhar em outros sites
TheNight 1 Denunciar post Postado Maio 24, 2015 Opa, Williams Duarte, muito obrigado, acho que você consegui responder todas minhas dúvidas até este ponto, vou marcar sua resposta como resolvido, da próxima dúvida abro outro tópico, grato... Compartilhar este post Link para o post Compartilhar em outros sites