Ir para conteúdo

POWERED BY:

Arquivado

Este tópico foi arquivado e está fechado para novas respostas.

William Bruno

Proposta de Fluent Interface - DAO phpOO

Recommended Posts

Boas !!

 

Gostaria de 'discutir' aqui, em público, sobre esse Pattern, tão pouco divulgado, mas que é muito muito útil.

imagina a brincadeirinha de fazer o seguinte com php:

$dao = new DAO( 'categoria' );
	echo $dao->select( $vo )->where( 'id = 2' )->order( 'nome ASC' );
olha o encadeamento de métodos...

a saída:

SELECT id, nome FROM categoria WHERE id = 2 ORDER BY nome ASC

sendo a 'mágica' ali, o parâmetro (string), que passamos pro construtor do DAO, e a variável $vo

a string do construtor do DAO, é o nome da tabela.

e o $vo, por enqnto, para simplificarmos o ínicio da conversa, é apenas um array associativo:

$vo = Array(
		'id'=>'',
		'nome'=>''
	);
tá tá... mas qual a vantagem ?

 

$produtoVO = Array(
		'id'=>'',
		'nome'=>'',
		'preco'=>'',
		'descricao'=>''
	);
	$produto = new DAO( 'produto' );
	echo $produto->select( $produtoVO )->order( 'preco DESC' );
saída:

SELECT id, nome, preco, descricao FROM produto ORDER BY preco DESC

código até aqui:

 

<?php
	$vo = Array(
		'id'=>'',
		'nome'=>''
	);
	
	
	$dao = new DAO( 'categoria' );
	echo $dao->select( $vo )->where( 'id = 2' )->order( 'nome ASC' );
	
	
	echo '<br />';
	
	
	$produtoVO = Array(
		'id'=>'',
		'nome'=>'',
		'preco'=>'',
		'descricao'=>''
	);
	$produto = new DAO( 'produto' );
	echo $produto->select( $produtoVO )->order( 'preco DESC' );
	
class DAO
{
	private $table;
	private $sql;
	

	public function select( $vo )
	{
		$this->sql = 'SELECT ';
		
		$fields = array_keys( $vo );
		$this->sql .= implode( ', ', $fields );
		$this->sql .= ' FROM '.$this->table;
		
		return $this;
	}
	public function where( $str )
	{
		if( !empty( $str ) )
			$this->sql .= ' WHERE '.$str;

		return $this;
	}
	public function order( $str )
	{
		if( !empty( $str ) )
			$this->sql .= ' ORDER BY '.$str;

		return $this;
	}
	public function __construct( $table )
	{
		$this->table = $table;
	}
	private function __toString()
	{
		return $this->sql;
	}
}

:lol:

 

aguardo comentários, e sugestões...

Compartilhar este post


Link para o post
Compartilhar em outros sites

Porque ai, também é interessante poder fazer:

$produtoVO['id'] = '1';
	$produtoVO['nome'] = "'Lorem ipsum'";
	$produtoVO['preco'] = "'14.70'";
	$produtoVO['descricao'] = "'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aenean et nisi turpis.'";
	echo $produto->insert( $produtoVO );

veja, o array já existe, com as chaves que representam os campos da tabela

e agora, para cada chave, atribuo o valor da coluna

 

public function insert( $vo )
	{
		$arr = Array();
		
		
		$this->sql = 'INSERT INTO '.$this->table;
		$fields = array_keys( $vo );
		$this->sql .= ' ( '.implode( ', ', $fields ).' ) VALUES ';
		
		$this->sql .= ' ('.implode( ',', $vo ).') ';
		
		return $this;
	}
saída:

INSERT INTO produto ( id, nome, preco, descricao ) VALUES (1,'Lorem ipsum','14.70','Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aenean et nisi turpis.')

<?php	
	$produtoVO = Array(
		'id'=>'',
		'nome'=>'',
		'preco'=>'',
		'descricao'=>''
	);
	$produto = new DAO( 'produto' );
	echo $produto->select( $produtoVO )->order( 'preco DESC' );
	
	echo '<br />';
	
	
	$produtoVO['id'] = '1';
	$produtoVO['nome'] = "'Lorem ipsum'";
	$produtoVO['preco'] = "'14.70'";
	$produtoVO['descricao'] = "'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aenean et nisi turpis.'";
	echo $produto->insert( $produtoVO );
	
	
class DAO
{
	private $table;
	private $sql;
	
	public function insert( $vo )
	{
		$arr = Array();
		
		
		$this->sql = 'INSERT INTO '.$this->table;
		$fields = array_keys( $vo );
		$this->sql .= ' ( '.implode( ', ', $fields ).' ) VALUES ';
		
		$this->sql .= ' ('.implode( ',', $vo ).') ';
		
		return $this;
	}

	public function select( $vo )
	{
		$this->sql = 'SELECT ';
		
		$fields = array_keys( $vo );
		$this->sql .= implode( ', ', $fields );
		$this->sql .= ' FROM '.$this->table;
		
		return $this;
	}
	public function where( $str )
	{
		if( !empty( $str ) )
			$this->sql .= ' WHERE '.$str;

		return $this;
	}
	public function order( $str )
	{
		if( !empty( $str ) )
			$this->sql .= ' ORDER BY '.$str;

		return $this;
	}
	public function __construct( $table )
	{
		$this->table = $table;
	}
	private function __toString()
	{
		return $this->sql;
	}
}

 

 

(uso algo parecido no meu sistema atual, mas oque estou postando aqui, estou recriando na hora)

Compartilhar este post


Link para o post
Compartilhar em outros sites

Cara! É o bicho!

http://forum.imasters.com.br/public/style_emoticons/default/clap.gif

 

Só isso que tenho a dizer?

http://forum.imasters.com.br/public/style_emoticons/default/joia.gif

 

Vejam um artigo, também muito interessante aqui.

Compartilhar este post


Link para o post
Compartilhar em outros sites

eu cheguei a ler esse artigo, mas eu realmente não gosto, qndo começam a complicar as coisas sem a menor necessidade.

 

lá pra frente, ele mete uma lib do ZendFramework, que está fora do meu alcance, então sem chances de eu conseguir implementar.

Como disseram nos comentários ali, sim, aquele é o único 'artigo' sobre FluentInterface em php, que agente consegue achar pela net.

 

 

por isso, e por eu mesmo estar amadurecendo esse desenvolvimento, criei esse tópico.

tô reconstruindo a cada post, chega de coisas prontas, e de códigos que já são apresentados num nível em que nem todos conseguem acompanhar com facilidade.

Compartilhar este post


Link para o post
Compartilhar em outros sites

Concordo contigo. Eu postei o link para o artigo apenas para mostrar mais um pouco, além do que você começou a apresentar-nos aqui.

Eu também não gostei do Zend que foi utilizado no artigo dele.

 

Bom, parabéns pela excelente iniciativa William! :)

 

(Comecei a utilizar aqui já! Valeu pela contribuição!)

Compartilhar este post


Link para o post
Compartilhar em outros sites

Bom..hora de amadurecer o conceito...

 

ValueObject

 

é mais 'amigável', fazer:

	$produtoVO = new ProdutoVO();

	$produtoVO->set_id( '1' );
	$produtoVO->set_nome( 'Lorem ipsum' );
	$produtoVO->set_preco( '14.70' );
	$produtoVO->set_descricao( 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aenean et nisi turpis.' );
doque:

        $produtoVO = Array(
                'id'=>'',
                'nome'=>'',
                'preco'=>'',
                'descricao'=>''
        );

        $produtoVO['id'] = '1';
        $produtoVO['nome'] = "'Lorem ipsum'";
        $produtoVO['preco'] = "'14.70'";
        $produtoVO['descricao'] = "'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aenean et nisi turpis.'";
pois tendo agora um objeto(especialista), não manipulamos diretamente o array(operação que será repetitiva), e não precisamos nos preocupar 'tão de cara', com as aspas(ou não aspas, caso campos numéricos).

 

uso:

<?php
	$produto = new DAO( 'produto' );
	$produtoVO = new ProdutoVO();
	
	
	echo $produto->select( $produtoVO )->order( 'preco DESC' );
	echo '<br />';
	
	$produtoVO->set_id( '1' );
	$produtoVO->set_nome( 'Lorem ipsum' );
	$produtoVO->set_preco( '14.70' );
	$produtoVO->set_descricao( 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aenean et nisi turpis.' );
	
	
	echo $produto->insert( $produtoVO );
saída:

SELECT id, nome, preco, descricao FROM produto ORDER BY preco DESC

INSERT INTO produto ( id, nome, preco, descricao ) VALUES (NULL,'Lorem ipsum','14.70','Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aenean et nisi turpis.')

 

abstract class ValueObject
{
	private $fields;
	
	public function get_names()
	{
        if ( !$this->fields )
			return array_keys( $this->get_fields() );
        else 
			return array_keys( $this->fields );
	}
	public function get_fields()
	{		
		$this->fields = Array();
		foreach( $this AS $name=>$value )
		{
			if ( $value instanceOf Field )
				$this->fields[ $name ] = $value->__toString();
		}
		return $this->fields;
	}
}
class ProdutoVO extends ValueObject
{
	protected $id, $nome, $preco, $descricao;

	public function __construct()
	{
		$this->id 				= new Field( 'id', Field::IDENTITY );
		$this->nome 			= new Field( 'nome' );
		$this->preco 			= new Field( 'preco' );
		$this->descricao 		= new Field( 'descricao' );
	}
	
	public function set_id( $id ){ $this->id->value = (int)$id; }
	public function set_nome( $nome ){ $this->nome->value = $nome; }
	public function set_preco( $preco ){ $this->preco->value = $preco; }
	public function set_descricao( $descricao ){ $this->descricao->value = $descricao; }
	
	public function get_id(){ return $this->id->value; }
	public function get_nome(){ return $this->nome->value; }
	public function get_preco(){ return $this->preco->value; }
	public function get_descricao(){ return $this->descricao->value; }
}
class Field
{
	const NORMAL = 1;
	const IDENTITY = 2;
	
    public function __construct( $name , $type = self::NORMAL, $value = null )
	{
        $this->name 		= $name;
        $this->type 		= $type;
        $this->value 		= $value;
    }
    public function __toString()
	{		
        switch ( $this->type )
		{
			case 1: return sprintf( "'%s'" , $this->value ); break;
			case 2: return 'NULL'; break;			

			default : return (string)$this->value;
        }
    }
}
class DAO
{
	private $table;
	private $sql;
	
	public function insert( ValueObject $vo )
	{	
		$values = $vo->get_fields();
		$fields = $vo->get_names();		
		
		$this->sql = 'INSERT INTO '.$this->table;
		$this->sql .= ' ( '.implode( ', ', $fields ).' ) VALUES ';
		$this->sql .= ' ('.implode( ',', $values ).') ';
		
		return $this;
	}

	public function select( $vo )
	{
		$fields = $vo->get_names();
		
		
		$this->sql = 'SELECT ';
		$this->sql .= implode( ', ', $fields );
		$this->sql .= ' FROM '.$this->table;
		
		return $this;
	}
	public function where( $str )
	{
		if( !empty( $str ) )
			$this->sql .= ' WHERE '.$str;

		return $this;
	}
	public function order( $str )
	{
		if( !empty( $str ) )
			$this->sql .= ' ORDER BY '.$str;

		return $this;
	}
	public function __construct( $table )
	{
		$this->table = $table;
	}
	private function __toString()
	{
		return $this->sql;
	}
}

 

 

ah é.. uma coisa que tinha me esquecido.. agora que estamos definindo bem a interface da nossa aplicação, podemos fazer algo como:

public function insert( ValueObject $vo )
para fazer uma espécie de 'casting' do tipo.. assim, fica bem claro oque queremos.

Compartilhar este post


Link para o post
Compartilhar em outros sites

Muito legal a ideia desse framework!

 

É semelhante ao Linq To SQL do .NET, onde a idéia é não escrever select nenhum na aplicação e trabalhar apenas com queries em formato de código. Bem interessante! Dá pra desenvolver muita coisa boa em cima disso.

Um overview do que estou falando: http://www.hookedonlinq.com/LINQtoSQL5MinuteOverview.ashx

 

Apostem no William, ele manja demais hehe

 

Abraços!

Compartilhar este post


Link para o post
Compartilhar em outros sites

a idéia e a intenção são boas, mas como toda solução para consultas dinâmicas acaba sendo limitado a queries simples

no final, é impossível depender somente disso

Compartilhar este post


Link para o post
Compartilhar em outros sites

Eu só estranhei essa parte:

public function get_fields()
 { 
 $this->fields = Array();
 foreach( $this AS $name=>$value )
 {
 if ( $value instanceOf Field )
 $this->fields[ $name ] = $value->__toString();
 }
 return $this->fields;
 }

Note que na classe filha, temos:

protected $id, $nome, $preco, $descricao;

O método get_fields [da classe mãe] só vai funcionar se as propriedades da classe filha forem protected. Se forem private, não funciona [testem!!!!!]

Em linguagens como o C++, quando se utiliza de herança, o ponteiro this passa a referenciar a classe DERIVADA, ou seja, se fosse do mesmo jeito em PHP,

não teria porquê o método get_fields não conseguir acessar as propriedades armazenadas em $this, mas isso não ocorre.

 

Mais estranho ainda é o fato de funcionar com as propriedades definidas como protected.

Uma propriedade ou método protected só pode ser acessada pela classe e suas filhas [tree down], NUNCA pela classe mãe.

Se o ponteiro $this não aponta para o objeto da classe derivada, como ele pode acessar suas propriedades protegidas num nível mais elevado da árvore de classes?

Seria isso uma falha do PHP?

 

Ficou bem confuso isso, eu realmente não consigo entender.

Fiz alguns testes em C++ aqui e utilizando esse tipo de polimorfismo ('inserção'), verifiquei que o ponteiro this em C++ aponta de fato para a classe DERIVADA, não a classe base.

Como o PHP é escrito em C++, imaginei que o mesmo deveria ocorrer, mas não ocorre.

 

O.o

Compartilhar este post


Link para o post
Compartilhar em outros sites

Rick, a herança em PHP acontece da maneira inversa à qual você trabalha em C++.

 

Quando você usa classes herdeiras, na verdade você trabalha na classe ancestral, agregando funcionalidades à ela.

 

Lendo literalmente a expressão:

class AA extends A {}

Podemos concluir que AA é uma extensão de A, um complemento, um conjunto de funcionalidades que foram agregadas para completar A. Percebeu a ordem de relacionamento? Percebeu quem é nosso elemento principal? AA aponta para A.

 

Quando trabalharmos com métodos e propriedades, há que se ter em mente que (a menos que haja sobreposição - mais adiante) estamos trabalhando no escopo do maior ancestral.

 

Suponhamos que eu tenha 5 heranças, de A até AAAAA.

 

Se eu chamo um método que está presente em AAAAA, o compilador busca, em ordem de prioridade de AAAAA até A, apenas para evitar conflitos com sobreposição de métodos. Você perceberá pelo exemplo dado adiante, que o compilador vai alterar o escopo de execução quando executar o método.

 

Ao passo que para propriedades, não há a necessidade de viajar da descendente até a herdeira, pois podemos simplesmente sobrescrever seu valor no caso de um eventual conflito. A ordem de prioridade nesse caso se dá de A até AAAAA.

 

Para tentar exemplificar, vamos tomar o seguinte par:

 

class ancestral {
	private $a = 'ancestral A';
	protected $b = 'ancestral B';
	public $c = 'ancestral C';
	
	public function showAll(){
		echo $this->a . ' / ' . $this->b . ' / ' . $this->c . PHP_EOL;
	}
	
	public function overloadedShowall(){
		echo $this->a . ' / ' . $this->b . ' / ' . $this->c . PHP_EOL;
	}
	
	public function showVar($id){
		if(isset($this->$id)) echo $this->$id . PHP_EOL;
	}
}

class descendant extends ancestral {
	private $a = 'descendant A';
	protected $b = 'descendant B';
	public $c = 'descendant C';
	private $d = 'descendant D';
	protected $e = 'descendant E';
	public $f = 'descendant F';
	
	public function showDescendant(){
		$this->showAll();
		parent::showAll();
	}
	
	public function overloadedShowAll(){
		echo $this->a . ' / ' . $this->b . ' / ' . $this->c . PHP_EOL;
	}
	
	public function ancientShowAll(){
		echo parent::overloadedShowall();
	}
}

$a = new ancestral();
$b = new descendant();

Acredito que o trabalho com $a não tenha mistério algum ou dúvidas, certo? Então vamos nos focar em $b;

 

Chamando $b->showAll, o compilador viaja de Descendant até Ancestral em busca do método showAll(), o encontra em Ancestral e parte de Ancestral até Descendant em busca das propriedades $a, $b e $c. O modificador $this indica que ESTE objeto é o ponto inicial e, caso não seja encontrado, procuraremos por eventuais definições da propriedade na árvore de herança (do ancestral até descendente).

 

Perceba que se invocarmos $b->showAll(), uma das respostas será ANCESTRAL A. O método showAll() foi executado dentro do escopo de Ancestral, por isso foi possível acessar esta propriedade privada.

 

A diferença que deve estar gerando confusão, provavelmente reside no modo como as visibilidades são tratadas/processadas pelo compilador.

 

Já foi dito que, quando extendemos uma classe, apenas agregamos funcionalidades ao ancestral maior. Não existe a idéia de TreeDown, uma vez que todos os descendentes se tornam um com o ancestral.

 

PRIVATE -> visível apenas dentro do escopo da classe.

PROTECTED -> visível apenas dentro do escopo de HERANÇA, seja ancestral ou descendente.

PUBLIC -> visível publicamente.

 

Vamos partir para o segundo método de testes, para tentar exemplificar o que foi dito:

 

$b->showVar(); // Para $c, $d, $e e $f

 

Partindo do princípio que você já compreendeu que a busca por métodos se dá do descendente ao ancestral e a busca por propriedades se dá do ancestral ao descendente, entendemos que:

O compilador não encontra showVar() em Descendant e parte para Ancestral. Encontra e executa. Inicia a busca NO ESCOPO ATUAL e então busca sobreposições desde o maior ancestral até o último descendente.

 

Para abreviar, chamaremos Ancestral de A:: e Descendant de D::.

 

Para C, temos o encontro em A::C mas a sobreposição em D::C, resultado da saída é 'descendant C'

 

Para D, não encontramos nada em A::D e, como D::D é privado (só vale dentro do escopo D::), não está visível para o método, que foi chamado fora do escopo de D::. Resultado: Não há saída de informações.

 

Para E e F, a saída é como esperada. Perceba que o método foi chamado dentro do escopo do objeto, o que torna possível a leitura de D::E que é visível para todas as chamadas a partir do objeto, ao passo que D::F também é visível para chamadas de fora do objeto ($obj->F).

 

O método showDescendant() em conjunto com overloadedShowAll() explicará o uso do modificador parent::

 

Perceba que showDescendant chama showAll() no escopo atual e no escopo do ancestral.

Perceba também que a saída é idêntica porque, para o compilador, as chamadas são idênticas. Uma vez que não existe showAll() no escopo de D::, partimos para o seus ancestrais (efeito parent::showAll()) até encontrarmos uma declaração do método.

 

Os métodos overloadedShowAll() e ancientShowAll() ilustram a sobreposição de métodos.

 

Se chamamos overloadedShowAll() dentro do escopo de D::, esta existe, é executada e exibe o até então desconhecido 'descendant A'. Veja que as sintaxes de showAll e overloadedShowAll são idênticas, e foram criados dois métodos apenas para explicar como acontece a sobreposição.

 

A partir do momento que chamamos o modificador de escopo parent::, saímos do escopo de D:: e vamos ao escopo de A:: que então exibe 'ancestral A'.

 

Leitura complementar:

http://www.php.net/manual/en/language.oop5.overloading.php

http://php.net/manual/en/language.oop5.late-static-bindings.php

Compartilhar este post


Link para o post
Compartilhar em outros sites

Podemos concluir que AA é uma extensão de A, um complemento, um conjunto de funcionalidades que foram agregadas para completar A. Percebeu a ordem de relacionamento? Percebeu quem é nosso elemento principal? AA aponta para A.

Acho que esse é o conceito de herança em todas as linguagens orientadas a objeto. A direfença é que o PHP não permite overloading de métodos como no Java e no C++.

 

Se eu chamo um método que está presente em AAAAA, o compilador busca, em ordem de prioridade de AAAAA até A, apenas para evitar conflitos com sobreposição de métodos. Você perceberá pelo exemplo dado adiante, que o compilador vai alterar o escopo de execução quando executar o método.

De maneira 'natural', é o que ocorre no C++ também. Existe uma PILHA com a ordem das funções que o compilador deve procurar.

O elemento do topo da pilha é o método, no caso, de A. Se tal método existe, é executado e não permite que nenhum outro seja executado também, senão, o compilador segue para a próxima classe da árvore de herança.

 

Em certas ocasiões isso não é interessante e por isso há a palavra chave virtual que permite a inversão da pilha, ou seja, o compilador vai primeiro na classe derivada, procurando por um método.

Se acha, executa, senão, segue 'subindo' a arvore, que é justamente o que o PHP faz por padrão -.-'.

 

Ao passo que para propriedades, não há a necessidade de viajar da descendente até a herdeira, pois podemos simplesmente sobrescrever seu valor no caso de um eventual conflito. A ordem de prioridade nesse caso se dá de A até AAAAA.

Sim, concordo. Afinal, instanciamos um objeto da classe derivada, naturalmente, estamos querendo os valores das propriedades da mesma.

 

 

O problema é que, como as propriedades vão 'descendo' a árvore e os métodos vão 'subindo', não funciona o exemplo que eu dei, mas eu realmente acredito que deveria funcionar, afinal, o objeto estanciado foi o da classe derivada.

 

Esse processo diminui um pouco a 'magia' dos métodos mágicos.

Por exemplo, queremos configurar o método mágico __get geral ao invés de criar gettes para todas propriedades:

 

public function __get($var){
 		if(isset($this->$var))
 			return $this->$var;
}

Colocando isso na sua classe exemplo Ancestral, se tentarmos:

 

$b = new Descendant();
$b->f; //funciona pois f é public, nem se quer chama o método mágico
$b->e; //não funciona, pois o método é executado a partir do escopo de Ancestral e A::$e não existe -.-'
$b->a; //mostra Ancestral A pela mesma razão

Se funcionasse, poderia ser bastante útil em classes VO, apenas para fins de facilitamento na criação do código:

//Ao invés de:
$obj->get('valor');
//Teríamos:
$obj->valor;

Pode parecer pouca coisa olhando assim, mas pense na quantidade de caracteres digitados a mais e tempo gasto em um sistema grande.

Ajudaria a evitar a LER e a ganhar mais dinheiro http://forum.imasters.com.br/public/style_emoticons/default/thumbsup.gif

 

Além disso, diminuiria a duplicação de código, pois isso só funciona se tivermos o método __get explícito em TODAS as classes VO, ou seja, CTRL+C + CTRL+V 'n' vezes, o que não se faz, mas acaba se tornando inevitável às vezes =/.

 

Bom, é minha opinião. Talvez os desenvolvedores já tenham pensado na mesma coisa e considerado que não é uma boa idéia fazer como sugeri.

 

Mas, de novo: minha opinião, a Orientação a Objetos do PHP tem algumas falhas e nem sei se serão corrigidas no tão esperado PHP6.

 

Comecemos já pelo fato de todas as propriedades e métodos serem públicos por padrão, um verdadeiro assassinato do conceito de OO.

Meu professor de Programação de Computadores (aprendíamos C++) dava ZERO na prova intera do infeliz que se utiliza-se de 1 só propriedade pública.

 

Acho que mudanças como essa facilitariam nossa vida em vários dos problemas que enfrentamos no cotidiano, quando temos aquela sensação de estarmos fazendo alguma gambiarra que não deveríamos.

Como no exemplo do William Bruno, colocar as propriedades como protected faz o código funcionar.

 

Porém, conforme aprendi, protected deve ser usado somente em último caso, pois gera um certo acoplamento e tem um outro problema:

- 'Jamais confie em outro programador' (algum dos fodões da computação cujo nome eu não lembro).

 

Em PHP não sofremos tanto com isso, pois normalmente é um trabalho 'solitário', ou seja, só você vai mexer naquilo e ponto final.

A coisa muda de figura quando se desenvolve em grupo.

Usando protected, nada impede de o infeliz extender sua classe e foder com o funcionamento do método ou com o conteúdo de uma propriedade.

Se essa nova classe made in China for utilizada no sistema (normalmente grande, pois há um grupo por trás dele), um belo dia, daqui uns 5 anos aquela classe pode receber um valor 'diferente' do usual e, sei lá, causar uma pane no sistema.

 

Se for um sistema controlador de ogivas nucleares, fudeu O_o.

Se for um simples site, bom, os usuários vão ver e reclamar, alguém da equipe vai lá tentar achar o problema e corrigir.

 

Enfim, já estou divagando... Sei lá...

Compartilhar este post


Link para o post
Compartilhar em outros sites

Acho que esse é o conceito de herança em todas as linguagens orientadas a objeto. A direfença é que o PHP não permite overloading de métodos como no Java e no C++.

 

Dois equívocos. Primeiro, vamos à definição de herança:

 

Aurélio

s.f. Bem, direito ou obrigação transmitidos por disposição testamentária ou por via de sucessão.

 

Michaelis

Inform Em programação orientada a objetos, ação de passar as características de uma classe ou tipo de dado para outro, chamada de descendente.

 

Veja a força que a palavra herança nos passa. Praticamente implica que a classe ancestral não existe mais, todo o seu legado - métodos e propriedades herdáveis - foi repassado à classe descendente que passa a ser o nosso escopo principal. É assim que linguagens realmente orientadas a objetos trabalham.

 

Segundo que você disse que PHP não permite overload. Talvez não da maneira que você está acostumado mas, tanto permite que criei um método sendo sobrescrito no exemplo (overloadedShowAll) e citei o link que trata de overload no manual.

 

Em certas ocasiões isso não é interessante e por isso há a palavra chave virtual que permite a inversão da pilha, ou seja, o compilador vai primeiro na classe derivada, procurando por um método.

Se acha, executa, senão, segue 'subindo' a arvore, que é justamente o que o PHP faz por padrão -.-'.

 

Questão de performance. Subentende-se que se eu estou trabalhando num escopo descendente, queira utilizar os métodos presentes em tal. Para utilizar os ancestrais eu não precisaria instanciar um objeto descendente como você mesmo disse:

Sim, concordo. Afinal, instanciamos um objeto da classe derivada, naturalmente, estamos querendo os valores das propriedades da mesma.

 

Sim, concordo. Afinal, instanciamos um objeto da classe derivada,

Esse processo diminui um pouco a 'magia' dos métodos mágicos.

Por exemplo, queremos configurar o método mágico __get geral ao invés de criar gettes para todas propriedades:

 

public function __get($var){
 		if(isset($this->$var))
 			return $this->$var;
}

 

Rick, não me leve a mal, eu também pensava assim até entender o real conceito de encapsulamento mas, magical getters/setters é coisa de preguiçoso. Sério.

 

Imagine que tivéssemos typecasting forte em PHP, onde uma variável/propriedade, desde o momento de sua criação, tem seu tipo definido e assim será até que seja excluída, assim como acontece em C/Java. Não haveria muito sentido em definir uma propriedade como privada, se você define a leitura dela como pública. As duas utilidades em se bloquear a alteração de uma propriedade de maneira direta e mover essa funcionalidade para os métodos são que:

1- definindo uma propriedade, não precisamos conhecer como o objeto é construído, apenas o que eu posso fazer com ele através de sua interface.

2- não haveria filtro/tratamento de dados.

 

Se você define a alteração do valor de uma propriedade via método, você DEVE permitir sua leitura SOMENTE via método, quando necessário.

 

Aliás, existem até umas certas normas, posso citar como por exemplo, que se seu método inicia com 'in','has' ou 'is', ele deve sempre retornar um Booleano. O que lhe permite que não se crie algumas propriedades à toa, e seu mágico get permita que esse controle seja visto.

 

Se funcionasse, poderia ser bastante útil em classes VO, apenas para fins de facilitamento na criação do código:

//Ao invés de:
$obj->get('valor');
//Teríamos:
$obj->valor;

 

Para isso, você deve definir que o escopo Descendant permita o acesso mágico. É CTRL + C / CTRL + V não porque PHP não foi preparado para OO, e sim porque métodos mágicos são gambiarra SIM! Um crime contra a performance e outro contra a manutenção de código. Se eu precisar de algo de algum objeto, devo estudar sua interface e verificar o que ela me oferece para que eu utilize o objeto.

 

Pode parecer pouca coisa olhando assim, mas pense na quantidade de caracteres digitados a mais e tempo gasto em um sistema grande.

Ajudaria a evitar a LER e a ganhar mais dinheiro http://forum.imasters.com.br/public/style_emoticons/default/thumbsup.gif

 

Pelo contrário. Se quando você desenvolve sozinho já é um parto encontrar aonde está o problema, imagina quando um membro da equipe se utiliza de um método GENÉRICO, que pode estar em qualquer lugar da aplicação provocando o problema? Já pensou por esse lado?

 

Mas, de novo: minha opinião, a Orientação a Objetos do PHP tem algumas falhas e nem sei se serão corrigidas no tão esperado PHP6.

 

Perfeitamente.

 

Comecemos já pelo fato de todas as propriedades e métodos serem públicos por padrão, um verdadeiro assassinato do conceito de OO.

 

Isso se deve ao fato de que, como o PHP não nasceu como linguagem orientada a objetos e integrou o conceito de maneira parcial, até hoje circulam vários scripts pela web baseados na famigerada construtora var que impreterivelmente seria pública. O nome disso é compatibilidade retroativa ou retrocompatibilidade.

 

Porém, conforme aprendi, protected deve ser usado somente em último caso, pois gera um certo acoplamento e tem um outro problema:

- 'Jamais confie em outro programador' (algum dos fodões da computação cujo nome eu não lembro).

 

Protected nos conceitos de PHP serve para quando você quiser tornar uma propriedade pública sem permitir que ela seja modificada arbitrariamente de fora do objeto.

 

Usando protected, nada impede de o infeliz extender sua classe e foder com o funcionamento do método ou com o conteúdo de uma propriedade.

Se essa nova classe made in China for utilizada no sistema (normalmente grande, pois há um grupo por trás dele), um belo dia, daqui uns 5 anos aquela classe pode receber um valor 'diferente' do usual e, sei lá, causar uma pane no sistema.

 

Ninguém melhor que o manual para responder essa:

http://www.php.net/manual/en/language.oop5.final.php

 

Acho que nos extendemos demais e saímos do foco do tópico hehehe. Vou resgatar um histórico que tenho com o William e postar as idéias importantes aqui para tentar retomar o foco, mais tarde. Não hesite em me procurar ou abrir um tópico no fórum sobre sua dúvida. Creio que teremos mais membros que terão prazer em opinar sobre.

Compartilhar este post


Link para o post
Compartilhar em outros sites

Algum moderador da área poderia dividir o tópico...

 

Rick, não me leve a mal, eu também pensava assim até entender o real conceito de encapsulamento mas, magical getters/setters é coisa de preguiçoso. Sério.

Preguiça? Sim, talvez, mas como engenheiro, sempre levo o lema: 'O mais simples que funcione bem'.

 

Na realidade eu compreendo bem sim esse conceito. A idéia é proteger os dados do programa da ação de algum agente externo, garantir a procedência dos mesmos.

Nos métodos mágicos você faz um 'meio termo': acessa a propriedade como se fosse pública, mas na hora se alterar seu valor, é possível sim fazer o controle da entrada de dados.

 

Não sou fã de gambiarras, os quase 5 anos como programador me ensinaram isso, mas infelizmente em certos casos é 'melhor'.

 

Imagine uma tabela com 20 campos. Quando for trazê-la para o mundo PHP, através de um objeto VO serão 40 métodos (20 setters e 20 getters)...

Pelo menos de acordo com as estratégias de VO que vejo por aí.

Pensando justamente nisso, e tentando me livrar mesmo dos métodos mágicos, estava até agora trabalhando numa implementação, se funcionar beleza eu compartilharei aqui.

 

Protected nos conceitos de PHP...

À princípio pode-se pensar que o conceito de OO é o mesmo para qualquer linguagem, mas aí você pega o exemplo do Javascript...

 

Eu comecei com PHP bem antes do C++, mas devido à falta de tempo, os conceitos de OO só vieram depois, na faculdade, com C++ e ao mesmo tempo tentando aplicar ao PHP.

Eu acreditei que fossem quase idênticas pois o próprio PHP é escrito em C, maaaaas o buraco é mais embaixo...

 

Como o PHP é uma linguagem mais 'aberta', com tipagem fraca, etc, etc, etc, fica estranho mesmo e acaba confundindo alguém que venha do Java, do C++, do Delphi e outras linguagens historicamente mais 'sérias'.

Mas esse tipo de discussão vai loooonge.

E esse tipo de discussão 'alto nível' é o que interessa o pessoal mais experiente nessa área, pois, convenhamos, responder às dúvidas básicas que aparecem todos os dias é entediante...

Compartilhar este post


Link para o post
Compartilhar em outros sites

Ok gente, +/- assim ?

<?php
     use \DataObject\Users;
     $Users = new Users();
     $Users->login = 123;
     $Users->senha = hash( 'sha256', 'teste' );
     $Users->save();

Users.php

<?php   
       /**
        * Namespace para os objetos 
        * que acessam é realizam transações
        * com o banco de dados
        */
       namespace DataObject;
       /**
        * @author Andrey Knupp Vital
        * @filesource Users.php
        * @copyright (C)2011-2012
        * @version 1.0.0
        * @since 1.0.0
        */
       class Users extends \DataGateway\TableDataGateway{
             /**
              * 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 ];
                  }
             }
             /**
              * Salva os dados guardados 
              * na caixa no banco de dados
              */
             public function save(){
                  /**
                   * Monta o sql e executa com Objeto,Resource
                   */
             }

       }

Exemplos da fluent interface proposta para montar o SQL

$this->insert( $this->storage )->values( $this->storage );
/** 
* Saída:
* INSERT INTO `users` ( `login`,`senha` ) VALUES ( 123,'46070d4bf934fb0d4b06d9e2c46e346944e322444900a435d7d9a95e6d7435f5' )
*/
$this->select();
/**
* Saída:
* SELECT * FROM `users`
*/
$this->select()->from( 'tabela' );
/**
* Saída:
* SELECT * FROM `tabela`
*/
$this->select()->from( 'tabela' )->where( 'id = 10' );
/**
* Saída:
* SELECT * FROM `tabela` WHERE id = 10
*/
$this->select()->from( 'tabela' )->where( 'id = 10' )->where( 'nome = Teste' );
/**
* Saída:
* SELECT * FROM `tabela` WHERE id = 10 AND nome = Teste
*/
$this->select()->from( 'tabela' )->where( 'id = 10' )->order( 'nome DESC' );
/**
* Saída:
* SELECT * FROM `tabela` WHERE id = 10 ORDER BY nome DESC
*/
$this->select()->from( 'tabela' )->where( 'id = 10' )->order( 'nome DESC' )->limit( 0, 10 );
/**
* Saída:
* SELECT * FROM `tabela` WHERE id = 10 ORDER BY nome DESC LIMIT 0, 10
*/
$this->select()->from( 'tabela' )->innerJOIN( 'clientes.id = pagamentos.id' )->where( 'id = 10' );
/**
* Saída:
* SELECT * FROM `tabela` INNER JOIN `users` ON clientes.id = pagamentos.id WHERE id = 10
*/
$this->select()->from( 'tabela' )->rightJOIN( 'clientes.id = pagamentos.id' )->where( 'id = 10' );
/**
* Saída:
* SELECT * FROM `tabela` RIGHT JOIN `users` ON clientes.id = pagamentos.id WHERE id = 10
*/
$this->select()->from( 'tabela' )->leftJOIN( 'clientes.id = pagamentos.id' )->where( 'id = 10' );
/**
* Saída:
* SELECT * FROM `tabela` LEFT JOIN `users` ON clientes.id = pagamentos.id WHERE id = 10
*/
$this->select()->distinct( Array( 'nome', 'sobrenome' ) );
/**
* Saída:
* SELECT DISTINCT `nome`,`sobrenome` FROM `users`
*/
$this->select()->where( 'id = 5' )->group( 'nome' );
/**
* Saída:
* SELECT * FROM `users` WHERE id = 5 GROUP BY `nome`
*/

TableDataGateway.php

<?php
       /**
        * Registra o namespace para os gateways
        * de dados, controle de SQL
        */
       namespace DataGateway;
       /**
        * @author Andrey Knupp Vital
        * @filesource TableDataGateway.php
        * @copyright (C)2011-2012
        * @version 1.0.0
        * @since 1.0.0
        */
       abstract class TableDataGateway{
               /**
                * Armazena uma SQL Pronta para ser executada
                */
               public $sqlQuery;
               /**
                * Monta uma declaração SELECT
                * para ser executada no banco de dados
                * é possivel especificar os campos que deseja selecionar
                * na tabela, enviando um array como parametro para esse método
                * @param Array $Fields
                * @return TableDataGateway 
                */
               public function select( Array $Fields = NULL ){
                      if( !is_null( $Fields ) ){
                          foreach( $Fields as $index ){
                              $Field[] = sprintf( '`%s`', $index );
                          }
                          $this->sqlQuery = sprintf( 'SELECT %s', implode( ',', $Field ) );
                      }else{
                         $this->sqlQuery = 'SELECT *';
                      }
                      return $this;
               }
               /**
                * Monta um SQL Insert, os nomes dos campos a serem
                * inseridos na tabela devem ser passados como um array
                * pelo primeiro parametro do método.
                * @param Array $Fields
                * @param String $Table
                * @return TableDataGateway 
                */
               public function insert( Array $Fields = NULL, $Table = NULL ){
                      if( $Table == null ){
                          $Table = sprintf( '`%s`', addslashes( strtolower( array_pop( explode( '\\', get_class( $this ) ) ) ) ) );
                      }else{
                          $Table = sprintf( '`%s`', addslashes( $Table ) );
                      }
                      if( !is_null( $Fields ) ){
                          foreach( $Fields as $index => $data ){
                              $Field[] = sprintf( '`%s`', $index );
                          }
                          $this->sqlQuery = sprintf( 'INSERT INTO %s ( %s )', $Table, implode( ',', $Field ) );
                      }else{
                          $this->sqlQuery = sprintf( 'INSERT INTO %s', $Table );
                      }
                      return $this;
               }
               /**
                * Adiciona os valores para o insert atual
                * @param Array $Values
                * @return TableDataGateway 
                */
               public function values( Array $Values ){
                      $Value = Array();
                      foreach( $Values as $index => $data ){
                          !is_numeric( $data ) ? $Value[] = "'{$data}'" : $Value[] = $data;
                      }
                      $this->sqlQuery = sprintf( '%s VALUES ( %s )', $this->sqlQuery, implode( ',', $Value ) );
                      return $this;
               }
               /**
                * Adiciona um FROM no SQL atual, o mesmo deve ser um SELECT
                * @param String $Table
                * @return TableDataGateway 
                */
               public function from( $Table = Null ){
                      if( $Table == null ){
                          $Table = sprintf( '`%s`', addslashes( strtolower( array_pop( explode( '\\', get_class( $this ) ) ) ) ) );
                      }else{
                          $Table = sprintf( '`%s`', addslashes( $Table ) );
                      }
                      if( preg_match( '/SELECT(.*)|SELECT DISTINCT(.*)/', $this->sqlQuery ) == true ){
                          $this->sqlQuery = sprintf( '%s FROM %s', $this->sqlQuery, $Table );
                      }else{
                          throw new \InvalidArgumentException( 'Esperavamos uma declaração SELECT');
                      }
                      return $this;
               }
               /**
                * Adiciona uma claúsula WHERE no sql atual
                * se o where já existir no sql, adiciona um AND
                * com a condição passada no parâmetro
                * @param String $cond
                * @return TableDataGateway 
                */
               public function where( $cond ){
                      if( !is_null( $cond ) ){
                          if( !preg_match( '/(.*)FROM(.*)/', $this->sqlQuery ) ){
                              $this->from();
                          }
                          if( !preg_match( '/(.*)WHERE(.*)/', $this->sqlQuery ) ){
                              $this->sqlQuery = sprintf( '%s WHERE %s', $this->sqlQuery, $cond );
                          }else{
                              $this->sqlQuery = sprintf( '%s AND %s', $this->sqlQuery, $cond );
                          }
                      }
                      return $this;
               }
               /**
                * Monta um SELECT Distinct com os campos passados
                * por array no primeiro parâmetro
                * @param Array $Fields
                * @return TableDataGateway 
                */
               public function distinct( Array $Fields ){
                      if( !is_null( $Fields ) ){
                          foreach( $Fields as $index ){
                              $Field[] = sprintf( '`%s`', $index );
                          }
                          $this->sqlQuery = sprintf( '%s DISTINCT %s', str_replace( '*', null, $this->sqlQuery ), implode( ',', $Field ) );
                      }
                      return $this;
               }
               /**
                * Cria uma ordenação dos resultados
                * @param String $order
                * @return TableDataGateway 
                */
               public function order( $order ){
                      if( !is_null( $order ) ){
                          $this->sqlQuery = sprintf( '%s ORDER BY %s', $this->sqlQuery, $order );
                      }
                      return $this;
               }
               /**
                * Cria um INNER JOIN, permitindo a claúsula on
                * quando passado o primeiro parâmetro 
                * @param String $join
                * @param String $Table
                * @return TableDataGateway 
                */
               public function innerJoin( $join = null, $Table = null ){
                      if( $Table == null ){
                          $Table = sprintf( '`%s`', addslashes( strtolower( array_pop( explode( '\\', get_class( $this ) ) ) ) ) );
                      }else{
                          $Table = sprintf( '`%s`', addslashes( $Table ) );
                      }
                      if( !preg_match( '/(.*)FROM(.*)/', $this->sqlQuery ) ){
                              $this->from();
                      }
                      if( !is_null( $join ) ){
                          $this->sqlQuery = sprintf( '%s INNER JOIN %s ON %s', $this->sqlQuery, $Table, $join );
                      }else{
                          $this->sqlQuery = sprintf( '%s INNER JOIN %s', $this->sqlQuery, $Table );
                      }
                      return $this;
               }
               /**
                * Cria um LEFT JOIN, também pode ser passado
                * a claúsula ON como primeiro parâmetro do método
                * @param String $join
                * @param String $table
                * @return TableDataGateway 
                */
               public function leftJoin( $join, $table = null ){
                      if( $Table == null ){
                          $Table = sprintf( '`%s`', addslashes( strtolower( array_pop( explode( '\\', get_class( $this ) ) ) ) ) );
                      }else{
                          $Table = sprintf( '`%s`', addslashes( $Table ) );
                      }
                      if( !preg_match( '/(.*)FROM(.*)/', $this->sqlQuery ) ){
                              $this->from();
                      }
                      if( !is_null( $join ) ){
                          $this->sqlQuery = sprintf( '%s LEFT JOIN %s ON %s', $this->sqlQuery, $Table, $join );
                      }else{
                          $this->sqlQuery = sprintf( '%s LEFT JOIN %s', $this->sqlQuery, $Table );
                      }
                      return $this;
               }
               /**
                * Cria um RIGHT JOIN, também pode ser passado
                * como primeiro parâmetro a claúsula ON
                * @param String $join
                * @param String $table
                * @return TableDataGateway 
                */
               public function rightJoin( $join, $table = null ){
                      if( $Table == null ){
                          $Table = sprintf( '`%s`', addslashes( strtolower( array_pop( explode( '\\', get_class( $this ) ) ) ) ) );
                      }else{
                          $Table = sprintf( '`%s`', addslashes( $Table ) );
                      }
                      if( !preg_match( '/(.*)FROM(.*)/', $this->sqlQuery ) ){
                              $this->from();
                      }
                      if( !is_null( $join ) ){
                          $this->sqlQuery = sprintf( '%s RIGHT JOIN %s ON %s', $this->sqlQuery, $Table, $join );
                      }else{
                          $this->sqlQuery = sprintf( '%s RIGHT JOIN %s', $this->sqlQuery, $Table );
                      }
                      return $this;
               }
               /**
                * Cria um grupo no SQL Atual
                * @param String $group
                * @return TableDataGateway 
                */
               public function group( $group ){
                      if( !is_null( $group ) ){
                          if( !preg_match( '/(.*)FROM(.*)/', $this->sqlQuery ) ){
                              $this->from();
                          }
                          $this->sqlQuery = sprintf( '%s GROUP BY `%s`', $this->sqlQuery, $group );
                      }
                      return $this;
               }
               /**
                * Adiciona um Limite aos resultados
                * @param Integer $start
                * @param Integer $end
                * @return TableDataGateway 
                */
               public function limit( $start, $end ){
                      $this->sqlQuery = sprintf( '%s LIMIT %d, %d', $this->sqlQuery, $start, $end );
                      return $this;
               }
               /**
                * Retorna o SQL Atual como String
                * @return String
                */
               public function __toString(){
                      if( preg_match( '/SELECT/', $this->sqlQuery ) ){
                          if( !preg_match( '/(.*)FROM(.*)/', $this->sqlQuery ) ){
                              $this->from();
                          }
                      }
                      return $this->sqlQuery;
               }


       }

Compartilhar este post


Link para o post
Compartilhar em outros sites

tem muito código repetido ai entre leftJoin, rightJoin e innerJoin.

 

DRY

Compartilhar este post


Link para o post
Compartilhar em outros sites

Pode ser implicância minha, mas a minha Table (é, tava sem inspiração pra um nome bacana :P) não ofereço métodos para JOIN, de nenhum tipo pois acho uma coisa meio delicada que deveria ser feita, até mesmo por questões de performance não mão.

Compartilhar este post


Link para o post
Compartilhar em outros sites

tem muito código repetido ai entre leftJoin, rightJoin e innerJoin.

 

DRY

Tens razão :lol:

 

Que tal assim então ?

 

 

<?php
       /**
        * @author Andrey Knupp Vital
        * @filesource TableDataGateway.php
        * @copyright (C)2011-2012
        * @version 1.0.0
        * @since 1.0.0
        */
       abstract class TableDataGateway{
                /**
                 * Armazena a query em construção
                 * @var String
                 */
                private $sqlQuery;
                /**
                 * Formata os campos colocando apostrofo
                 * em cada nome, evitando problemas futuros no sql
                 * @param String $fields
                 * @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 
                 * @return String
                 */
                protected function getTable(){
                       return sprintf( '`%s`', strtolower( array_pop( explode( '\\', get_class( $this ) ) ) ) );
                }
                /**
                 * Monta uma instrução SELECT
                 * @param String $fields
                 * @return TableDataGateway 
                 */
                public function select( $fields = '*' ){
                       $fields = $fields != '*' && !empty( $fields ) ? $this->quotedFields( $fields ) : '*';
                       $this->sqlQuery = sprintf( 'SELECT %s', $fields );
                       return $this;
                }
                /**
                 * Verifica se existe uma cláusula from no sql 
                 * @return Boolean
                 */
                protected function hasFrom(){
                       if( !preg_match( '/(.*)FROM(.*)/', $this->sqlQuery ) ){
                           return false;
                       }else{
                           return true;
                       }
                }
                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
                 * @return TableDataGateway 
                 */
                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
                 * @return TableDataGateway 
                 */
                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
                 * @return TableDataGateway 
                 */
                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
                 * @return TableDataGateway 
                 */
                public function where( $where ){
                       if( !is_null( $where ) ){
                           !$this->hasFrom() ? $this->from() : '';
                           $this->sqlQuery = sprintf( '%s WHERE %s', $this->sqlQuery, $where );
                       }
                       return $this;
                }
                /**
                 * Adiciona um 'AND' no sql
                 * @param String $orWhere
                 * @return TableDataGateway 
                 */
                public function orWhere( $orWhere ){
                       if( !is_null( $orWhere ) ){
                           !$this->hasFrom() ? $this->from() : '';
                           $this->sqlQuery = sprintf( '%s AND %s', $this->sqlQuery, $orWhere );
                       }
                       return $this;
                }
                /**
                 * Cria uma instrução INSERT
                 * @param Array $fields
                 * @param String $table
                 * @return TableDataGateway 
                 */
                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
                 * @return TableDataGateway 
                 */
                public function values( Array $values ){
                       if( !is_null( $values ) || count( $values ) != false ){
                           foreach( $values as $index => $data ){
                               if( !is_numeric( $data ) ){
                                   $value[] = "'{$data}'";
                               }else{
                                   $value[] = (integer)$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
                 * @return TableDataGateway 
                 */
                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
                 * @return TableDataGateway 
                 */
                public function group( $group ){
                       if( !is_null( $group ) ){
                           !$this->hasFrom() ? $this->from() : '';
                           $this->sqlQuery = sprintf( '%s GROUP BY %s', $this->sqlQuery, $this->quotedFields( $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
                 * @return TableDataGateway 
                 */
                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 TableDataGateway
                 */
                public function delete(){
                       $this->sqlQuery = 'DELETE';
                       return $this;
                }
                /**
                 * Recupera o sql como string
                 * @return String
                 */
                public function __toString(){
                       !$this->hasFrom() && $this->hasSelect() ? $this->from() : '';
                       return $this->sqlQuery;
                }

       }

 

 

 

^_^

Compartilhar este post


Link para o post
Compartilhar em outros sites

O que eu queria Aqui é exatamente isso daí.

Compartilhar este post


Link para o post
Compartilhar em outros sites

×

Informação importante

Ao usar o fórum, você concorda com nossos Termos e condições.