Como instanciar uma consulta no banco ?


(Gabriel) #1

Sou iniciante em PHP e gostaria de deixar meu código mais limpo, acredito que deixar uma query no meio do meu HTML não é muito correto, como resolver isso? Posso criar uma função que chama essa query? ou tenho que fazer includes ?


(Maykel Esser) #2

Trabalhar com classes e DAOs pode ser uma saída interessante.

Basicamente, trabalho com uma classe que monta as querys (Query.php), uma classe para conexão ao banco (Conexao.php), e uma classe para cada tabela do banco (ex: Usuario.php).

Vou mostrar os arquivos que eu uso, e como faço uma chamada simples ao banco.

Query.php

<?php

	/**
	* @author Maykel Esser
	* @copyright (C)2016, Maykel Esser.
	* @version 2.0.0
	* @since 1.0.0
	*/
	 
	class Query extends Conexao
	{
		/**
		* Armazena a query em construção
		* @access private
		* @var String
		*/
		private $sqlQuery;

		/**
		* Formata os campos colocando apostrofo
		* em cada nome, evitando problemas futuros no sql
		* @param String $fields
		* @access protected
		* @return String
		*/
		protected function quotedFields($fields){
			if(!is_array($fields)){
				foreach(explode(',', $fields) as $fields){
				   $field[] = sprintf('`%s`', $fields);
				}
			}elseif(is_array($fields)){
				foreach($fields as $index => $data){
					$field[] = sprintf('`%s`', $index);
				}
			}
			return implode(',', $field);
		}

		/**
		* Recupera o nome tabela da classe 
		* que está chamando o método 
		* @access protected
		* @return String
		*/
		protected function getTable(){
			return sprintf('%s', strtolower(array_pop(explode('\\', get_class($this)))));
		}

		/**
		* Monta uma instrução SELECT
		* @param String $fields
		* @access protected
		* @return Query 
		*/
		public function select($fields = '*'){
			if($fields != '*' && !empty($fields)){
				
				if(is_array($fields)){
					$fields = implode(",", $fields);
				}
				else{
					$fields = $fields;
				}
			}
			else{
				$fields = '*';
			}
			
			$this->sqlQuery = sprintf('SELECT %s', $fields);
			return $this;
		}

		/**
		* Verifica se existe uma cláusula from no sql 
		* @access public
		* @return Boolean
		*/
		public function hasFrom(){
			if(!preg_match('/^(?!UPDATE)(.*)FROM(.*)$/', $this->sqlQuery)){
				return false;
			}else{
				return true;
			}
		}

		/**
		* Verifica se existe uma cláusula has no sql 
		* @access public
		* @return Boolean
		*/
		public function hasSelect(){
			if(!preg_match('/SELECT(.*)|SELECT DISTINCT(.*)/', $this->sqlQuery)){
				return false;
			}else{
				return true;
			}
		}

		/**
		* Adiciona uma claúsula FROM no SQL atual
		* @param String $table
		* @access public
		* @return Query 
		*/
		public function from($table = null){
			$from = !is_null($table) ? sprintf('%s', $table) : $this->getTable();
			$this->sqlQuery = sprintf('%s FROM %s', $this->sqlQuery, $from);
			return $this;
		}

		/**
		* Adiciona uma ordenação nos resultados
		* @param String $order
		* @access public
		* @return Query 
		*/
		public function order($order){
			if(!is_null($order)){
				!$this->hasFrom() ? $this->from() : '';
				$this->sqlQuery = sprintf('%s ORDER BY %s', $this->sqlQuery, $order);
			}
			return $this;
		}

		/**
		* Adiciona um limite aos resultados retornados
		* @param Integer $start
		* @param Integer $end
		* @access public
		* @return Query 
		*/
		public function limit($start, $end){
			if(!is_null($start) || !is_null($end)){
				!$this->hasFrom() ? $this->from() : '';
				$this->sqlQuery = sprintf('%s LIMIT %d,%d', $this->sqlQuery, $start, $end);
			}
			return $this;
		}

		/**
		* Adiciona uma claúsula WHERE no sql
		* @param String $where
		* @access public
		* @return Query 
		*/
		public function where($where){
			if(!is_null($where)){
				$this->sqlQuery = sprintf('%s WHERE %s', $this->sqlQuery, $where);
			}
			return $this;
		}

		/**
		* Adiciona um 'AND' no sql
		* @param String $andWhere
		* @access public
		* @return Query 
		*/
		public function andWhere($andWhere){
			if(!is_null($andWhere)){
				!$this->hasFrom() ? $this->from() : '';
				$this->sqlQuery = sprintf('%s AND %s', $this->sqlQuery, $andWhere);
			}
			return $this;
		}

		/**
		* Adiciona um 'OR' no sql
		* @param String $orWhere
		* @access public
		* @return Query 
		*/
		public function orWhere($orWhere){
			if(!is_null($orWhere)){
				!$this->hasFrom() ? $this->from() : '';
				$this->sqlQuery = sprintf('%s OR %s', $this->sqlQuery, $orWhere);
			}
			return $this;
		}

		/**
		* Controla o Having
		* @param String $orWhere
		* @access public
		* @return Query 
		*/
		public function having($having){
			if(!is_null($having)){
				$this->sqlQuery = sprintf('%s HAVING %s', $this->sqlQuery, $having);
			}
			return $this;
		}

		/**
		* Cria uma instrução INSERT
		* @param Array $fields
		* @param String $table
		* @access public
		* @return Query 
		*/
		public function insert(Array $fields, $table = null){
			if(!is_null($fields) || count($fields) != false){
				$table = is_null($table) ? $this->getTable() : '`'.$table.'`';
				$this->sqlQuery = sprintf('INSERT INTO %s (%s)', $table, $this->quotedFields($fields));
			}
			return $this;
		}

		/**
		* Adiciona os valores no SQL, fazendo o cast
		* dos itens no array, string ou integer
		* @param Array  $values
		* @access public
		* @return Query 
		*/
		public function values(Array $values){
			if(!is_null($values) || count($values) != false){
				foreach($values as $index => $data){
					$value[] = "'{$data}'";
				}
				$this->sqlQuery = sprintf('%s VALUES(%s)', $this->sqlQuery, implode(',', $value));
			}
			return $this;
		}

		/**
		* Adiciona uma seleção sem repetição nos resultados
		* nos campos passados no primeiro parâmetro
		* @param String $fields
		* @access public
		* @return Query 
		*/
		public function distinct($fields){
			if(!is_null($fields)){
				$this->sqlQuery = sprintf('SELECT DISTINCT %s', $this->quotedFields($fields));
			}
			return $this;
		}

		/**
		* Cria um group no SQL
		* @param String $group
		* @access public
		* @return Query 
		*/
		public function group($group){
			if(!is_null($group)){
				!$this->hasFrom() ? $this->from() : '';
				$this->sqlQuery = sprintf('%s GROUP BY %s', $this->sqlQuery, $group);
			}
			return $this;
		}

		/**
		* Cria um relacionamento de tabelas
		* Primeiro parâmetro: tipo do join { inner, left, right, natural, cross }
		* Segundo parâmetro: o relacionamento com a claúsula ON
		* Terceiro parâmetro: a tabela a ser relacionada
		* @param String $joinType
		* @param String $join
		* @param String $table
		* @access public
		* @return Query 
		*/
		public function join($joinType = null, $join = null, $table = null){
			$table = is_null($table) ? $this->getTable() : $table;
			$Join = Array('INNER', 'FULL', 'LEFT', 'RIGHT', 'CROSS', 'NATURAL', 'JOIN');
			if(!in_array($joinType, $Join) && !is_null($joinType)){
				throw new InvalidArgumentException('Tipo de join não reconhecido');
			}
			!$this->hasFrom() ? $this->from() : '';
			if(!is_null($join)){
				$this->sqlQuery = sprintf('%s %s JOIN %s ON %s', $this->sqlQuery, $joinType, $table, $join);
			}else{
				$this->sqlQuery = sprintf('%s %s JOIN %s', $this->sqlQuery, $joinType, $table);
			}
			return $this;
		}

		/**
		* Cria uma instrução delete
		* @return Query
		* @access public
		*/
		public function delete(){
			$this->sqlQuery = 'DELETE';
			return $this;
		}

		/**
		* Cria uma instrução update
		* @return Query
		* @access public
		*/
		public function update($table = null, $values){
			$table = is_null($table) ? $this->getTable() : '`'.$table.'`';
			$this->sqlQuery = sprintf('UPDATE %s SET', $table);
			$arrCondition = array();
			if(!is_null($values) || count($values) != false){
				foreach($values as $index => $data){
					$value = "'{$data}'";
					$arrCondition[] = $index." = ".$value;
				}
				$this->sqlQuery = sprintf('%s %s', $this->sqlQuery, implode(", ",$arrCondition));
			}

			return $this;
		}
		 
		/**
		* Recupera o sql como string
		* @return String
		* @access public
		*/
		public function __toString(){
			!$this->hasFrom() && $this->hasSelect() ? $this->from() : '';
			return $this->sqlQuery;
		}
	}
?>

Conexao.php

<?php

	/**
	* @author Maykel Esser
	* @copyright (C)2016, Maykel Esser.
	* @version 2.0.0
	* @since 1.0.0
	*/
	 
	class Conexao
	{
		/**
		* connect()
		* Usada para conectar  ao banco de dados.
		* @author Maykel Esser
		* @return Object
		*/
 		function connect(){
			try{
				$obj = new PDO(
					"mysql:host=".DATABASE_HOST.";port=".DATABASE_PORT.";dbname=".DATABASE_NAME, 
					DATABASE_LOGIN, 
					DATABASE_PASS, 
					array(
						PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
						PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES utf8"
					)
				);
			}
			catch (PDOException $e){
				die("Erro na conexão ao banco: (".$e->getMessage().")");
			}
			return $obj;
		}
	}
		
?>

Usuario.php

<?php

	/**
	* @author Maykel Esser
	* @copyright (C)2016, Maykel Esser.
	* @version 2.0.0
	* @since 1.0.0
	*/
	 
	class Usuario extends Query
	{
		/**
		* Armazena um array com as informações
		* enviadas pelo usuário, atraves do método __set
		* @var String
		*/
		public $storage;

		/**
		* Guarda uma propiedade na caixa
		* @param String $index
		* @param String|Integer $value
		* @return String 
		*/
		public function __set($index, $value){
			$this->storage[ $index ] = addslashes($value);
			return $this->storage[ $index ];
		}

		/**
		* Recupera uma propiedade na caixa
		* @param String $index
		* @return String|Integer
		*/
		public function __get($index){
			if(array_key_exists($index, $this->storage)){
				return $this->storage[ $index ];
			}
		}

		/**
		* Carregam os dados guardados de uma única tabela
		* no banco de dados
		* @return Array com registros
		*/
		public function load($debug = false, $order = null, $limit = null){
			$object = "";
			$arrayTabela = array("tbl_usuario");
			$query = $this->select()->from(implode(",", $arrayTabela));
			if(!empty($this->storage)){
				if(!is_null($this->storage) || count($this->storage) != false){
					$i = 0;
					foreach($this->storage as $index => $data){
						if(!is_numeric($data)){
							$value = "'".$data."'";
						}else{
							$value = (integer)$data;
						}
						if($i == 0){
							$query->where($index." = ".$value);
						}
						else{
							$query->andWhere($index." = ".$value);
						}
						$i++;
					}
				}
			}
			if(!empty($order)){
				$query->order($order);
			}
			if(!empty($limit)){
				$limit = explode(",", $limit);
				$query->limit($limit[0], $limit[1]);
			}
			if($debug){
				echo $query."<br />";	
			}
			try {
				$objConnect = Conexao::connect();
				$objResult = $objConnect->query($query);
				$object = $objResult->fetchAll(PDO::FETCH_ASSOC);
			}
			catch (Exception $e){
				$object = null;
			}
			return $object;
		}
    }

Com isso, temos as classes definidas para uma chamada no banco de dados.

Crie um index.php (ou qualquer outro arquivo), inclua estas classes chamando estas classes, e para fazer uma consulta ao banco, só fazer isso:

<?php

	$objUsuario = new Usuario();
	$resultado = $objUsuario->load();

	if(!empty($resultado)){
		foreach($resultado as $usuario){
			echo "Nome: ".$usuario['Nome'];
		}
	}

?>

(Jonatan Santana) #3

O DAO que o colega acima mencionou por si só não explica nada. É um monstro para algo simples que só vai atrapalhar seu entendimento agora.

Se quer trabalhar com orientação a objetos para realizar consultas no banco procure pela Biblioteca PDO PHP ou MYSQLI PHP.