Ir para conteúdo

POWERED BY:

Arquivado

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

fekz

[Resolvido] Reflection alterar visibilidade ou algo do genero

Recommended Posts

Pessoal, boa tarde.

 

Aqui no meu trabalho usamos um framework, que você declara a classe do banco de dados, com os campos da tabela, e elas são declaradas como protected.

 

Então em determinad função, você pega uma linha da tabela e pode escrever ou setar um valor assim: $usuario->nome = "fernando";

 

Mas a variável nome, foi setada como protected, portanto não deveria ser acessada por um objeto.

 

Eu desconfio que eles usam alguma coisa com a classe Reflection para poder fazer isso, seja alterando a visibilidade do campo na hora que essa função é chamada, ou sei lá de que forma.

 

Eu sei que eu declaro a variável protected e consigo imprimir ela.

 

Algm sabe algum método do reflection que faz isso?

 

Obrigado.

Compartilhar este post


Link para o post
Compartilhar em outros sites

Então, cara, obrigado pelos links e tals, eu entendi mas tenho uma dúvida. Estou fazendo isso e deu certo:

 

class Pessoa 
{
	private $teste;
	private $data = array();

	public function __set($var, $val)
	{
		$this->data[$var] = $val;
	}	
	public function __get($var)
	{
		return $this->data[$var];
	}	
}

class Fernando extends Pessoa
{
	protected $id;
	protected $nome;
}

$pessoa = new Fernando();
$pessoa->id = 10;
echo $pessoa->id;

Beleza, ele seta a variável id para 10, e depois escreve na tela 10.

 

Agora eu preciso de alguma forma de setar e recuperar o valor das variáveis da classe filha, mas na classe de cima;

 

Pq?

 

Pq eu preciso fazer isso:

 

$pessoa->id = 10;
$pessoa->nome = "fernando";
$pessoa->manageData("INSERT");

Ele tem um método na classe de cima, para pegar os valores das variávels ali, e inserir no BD.

 

Tentei por Reflaction, mas não consigo pegar os campos pq são protected.

 

$a = new ReflectionClass(get_class($this));
$b = $a->getProperties();
echo $b["nome"]->getValue();

Ele dá erro, dizendo que não posso acessar variável protected.

Como posso contornar isso?

 

Tem jeito, pq no meu trampo é usado uma estrutura de classes que faz exatamente isso, mas não entendi direito.

 

Abraços;

Compartilhar este post


Link para o post
Compartilhar em outros sites

Ele dá erro, dizendo que não posso acessar variável protected.

Como posso contornar isso?

 

@fekz,

 

Precisar violar o encapsulamento é uma indicação clara de falta de modelagem.

 

Se vale a sugestão, reveja toda a modelagem de sua aplicação, a violação do encapsulamento é só o inicio, logo você estará POGramando e as consequencias poderão ser desastrosas.

Compartilhar este post


Link para o post
Compartilhar em outros sites

Pq eu estou violando alguma coisa???

 

Eu quero o seguinte.

 

Ao fazer:

 

$this->id = 5;

$this->nome = "fer";

 

Ele está setando certinho, consigo recuperar o valor que é uma beleza.

 

Ai quando eu vou fazer manageData(); ele vai inserir no banco os valores que eu passei. O método manageData está na classe Pai, pois será extendido para todas outras funções...

 

Então preciso pegar os valores que estão nas variáveis para manipula-los, não vejo isso como um erro... Quero conseguir pegar o valor dentro da classe só isso.

 

Estou usando um framework criado pela empresa msm.;

Compartilhar este post


Link para o post
Compartilhar em outros sites

Pq eu estou violando alguma coisa???

 

@fekz,

 

Se você tem métodos ou propriedades privadas ou protegidas e você está tentando acessá-las de fora, você está sim, tentando violar o encapsulamento.

 

Procure estudar sobre modelagem, orientação a objetos e, principalmente, conhecer o que é encapsulamento.

Compartilhar este post


Link para o post
Compartilhar em outros sites

Mas eu quero acessar dentro da própria classe ué !

 

pq através do reflection eu pego as variáveis da própria classe e não consigo manipular o valor?

Compartilhar este post


Link para o post
Compartilhar em outros sites

Mas eu quero acessar dentro da própria classe ué !

 

http://br2.php.net/manual/ro/function.get-object-vars.php

 

O primeiro exemplo do link acima deverá ser o que você precisa.

Compartilhar este post


Link para o post
Compartilhar em outros sites

propriedades private não podem ser acessadas alem da class que define eles.

protected podem ser acessadas por classes estendidas.

e public, bom, ja sabe.

 

logo, no exemplo que citou acima estava usando os métodos para acessar propriedades private e retorna-los.

 

qual a visibilidade desse método manageData();

creio eu que seja public.

as propriedades que você manipula em si. é private ou protected ?

 

você citou "pegar valor dentro da classe..."?

 

isso através do método manageData();? o que ele retorna ?

 

esse framework, não fizeram uma doc ?

Compartilhar este post


Link para o post
Compartilhar em outros sites

Isso quem tá desenvolvendo sou eu, cara. Estou usando como exemplo o que eu uso, mas não vejo todo código então não posso saber.

 

O método manageData(), está na classe DatabaseManagement. Ele é público.

As variávels id e nome, estão na classe Login, e são protecteds. A classe login herda da classe databaseManagement.

 

Supondo que eu fiz um método retornando as variáveis da classe, por Reflaction, ele me retorna id e nome.

Beleza. Agora, se eu estou usando o método $login->manageData() e supondo que ele me retorna as variáveis da classe ATUAL, ele me retorna ID E NOME.

 

Então, essas variáveis são as variáveis da classe LOGIN.

Pq então, eu não posso por dentro de manageData por exemplo, por reflaction. $this->field["nome"] = "10";

Ele diz que não posso acessar uma pripriedade protected.

 

Como eu não posso, se quando dei reflaction na classe ele me trouxe esses campos. Então faz parte dessa classe.

 

Vou exemplificar o que eu quero... Não consigo saber a diferença de:

 

private $id;
    private $dados = array();

    public function __set($var,$val){
        $this->dados[$var] = $val;
    }

    public function __get($val){
        return $this->dados[$val];
    }

    public function setA(){
        $this->id = 10;
    }

    public function getA(){
        return $this->id;
    }

$pessoa = new Login();
$pessoa->setA();
echo $pessoa->getA();
$pessoa->id = 20;
echo $pessoa->id;

Ele me traz o resultado 10, 20.

Quando eu escrevo:

$pessoa->setA();
Eu só consigo retornar o ID pelo método getA();

Se eu escrever:

$pessoa->id = 20;
Só consigo retornar por echo $pessoa->id;

 

Eu queria saber qual a diferença, sendo que os 2 estão colocando valor dentro de $pessoa->id;

 

E depois da dúvida respondida, eu preciso saber como resolver isso. Quando o cara setar um valor direto pela variável, ele cai no método __set

 

E preciso usar esses valores dentro da classe.

 

Entendeu?

 

Eu pensei em quando o cara setar um valor assim: $this->id = 10;

 

No __setter eu inserir esse valor em um array.

 

Sei lá, pra poder manipular dps!

Compartilhar este post


Link para o post
Compartilhar em outros sites

Eu queria saber qual a diferença, sendo que os 2 estão colocando valor dentro de $pessoa->id;

Na verdade não... Olha os comentários da classe.

 

    private $id;
    private $dados = array();

    public function __set($var,$val){
        // o valor setado dentro da variável por aqui estará dentro do array $this->dados
        $this->dados[$var] = $val;
    }

    public function __get($val){
        // o valor retornado aqui será o de dentro do array $this->dados
        return $this->dados[$val];
    }

    public function setA(){
        // aqui você seta $this->id
        $this->id = 10;
    }

    public function getA(){
        // aqui você retorna $this->id
        return $this->id;
    }
Então, vamos olhar o código (atente-se para os comentários):

// apenas para formatar melhor a saída, melhorando a visualização
echo '<pre>';
$pessoa = new Login ();
// ao fazer isto, $pessoa->id passa a valer 10
$pessoa->setA ();
// aqui imprimimos esta mesmo variável (10)
echo $pessoa->getA (),'<br/>';
// aqui, ao fazer isto, a $pessoa->dados['id'] é setada
$pessoa->id = 20;
// aqui recuperamos a $pessoa->dados['id'], que foi setada como 20
echo $pessoa->id,'<br/>';
// visualizando o objeto completo
var_dump($pessoa);
Veja que ao executar este código, teremos o seguinte resultado:

10
20
object(Login)#1 (2) {
  ["id":"Login":private]=>
  int(10)
  ["dados":"Login":private]=>
  array(1) {
    ["id"]=>
    int(20)
  }
}
Então, perceba que isto confirma o que eu falei sobre a utilização do método __set e __get.

 

Veja se compreende o funcionamento e se tiver alguma dúvida, volte a perguntar.

 

Carlos Eduardo

Compartilhar este post


Link para o post
Compartilhar em outros sites

Sim, eu entendi isso, eu que tinha dito besteira.

 

Mas eu preciso que ao a pessoa setar a variável por $objeto->id = 10, eu consiga recuperar isso na classe, entende?

 

Aí eu pensei no __set colocar o valor em um array, mas não sei se é a melhor forma.

 

O que acha?

 

Ou tem outra solução?

Compartilhar este post


Link para o post
Compartilhar em outros sites

Olha... não entendi muito bem o que você quer, mas olha só, de uma maneira bem simplória...

 

<?php
class Login {
	
	private $id;
	/**
	 * @return the $id
	 */
	public function getId() {
		return $this->id;
	}

	/**
	 * @param $id the $id to set
	 */
	public function setId($id) {
		$this->id = (int)$id;
	}

	
}

class ManageData{
	public function getDados(Login $login){
		echo $login->getId();
	}
}

$pessoa = new Login ();
$pessoa->setId(20);
$manage = new ManageData();
$manage->getDados($pessoa);

Vai imprimir o valor definido em $pessoa->id, que foi definido no $pessoa->setId(20). Assim, não precisa utilizar os métodos __set e __get para isto.

 

O que eu quis demonstrar é que você pode passar um objeto inteiro para outra classe, e utilizar os métodos deste objeto dentro da classe que recebe o objeto. Para isto, é interessante entender e utilizar type hinting e interfaces. Então, vale a pena dar uma olhada no curso de PHP orientado a objetos.

 

Carlos Eduardo

Compartilhar este post


Link para o post
Compartilhar em outros sites

Fekz, existe também o nível de execução em tempo de execução

 

Se você prever a um método que ele irá trabalhar em uma propriedade já existente, ele sempre apontará para a propriedade existente. Contudo, há um porém:

 

class a {}
$a = new a;
$a->b = 'c';
echo $a->b;

 

Instanciamos uma classe a, que nos retorna uma instância de classe vazia.

 

Definimos uma nova propriedade pública em tempo de execução, chamada b, com o valor c. A partir de agora, nossa instância de a tem a seguinte estrutura:

 

class a {
   public $b = 'c';
}

 

Digo nossa instância de a, porque se você criar uma nova instância de a, ela será vazia, como prevista na declaração da classe.

 

Note que não é possível alterar a estrutura de uma classe em tempo de execução:

 

class teste {
   private $testando = 'testado';
}

$teste = new teste;
$teste->testando = 0;

 

Isso gera um erro, pois a visibilidade de $testando é privada, não pode ser acessada de fora da classe.

 

ReflectionClass é uma estrutura criada para obter informações da classe, e não seus valores. Para obter valores, a classe precisa prever os métodos (através de interfaces) que nos permitirão trabalhar com elas

 

interface iManipuladorDeBancosDeDados {
   public function adiciona($tabela, array $campos, array $valores);

   public function deleta($tabela, $condicao);

   public function altera($tabela, array $campos, array $valores, $condicao);

   public function consulta($tabela, $condicao);

 

Assim sabemos que sempre que precisarmos de um objeto que implemente um iManipuladorDeBancosDeDados, teremos estes 4 métodos disponíveis para trabalhar com o objeto.

Como o João Batista disse, é uma questão de trabalhar a modelagem das classes para não precisar fazer isso em tempo de execução.

Compartilhar este post


Link para o post
Compartilhar em outros sites

Carlos,

 

Por essa forma, eu sei fazer.

 

Eu uso um set e um get, e beleza. Isso, tudo bem! Eu até posso fazer assim, mas pra ser mais simples, eu gostaria de usar

$this->id = 10; e nao this->setId(10) entende??

 

Como eu falei, talvez a solução seja utilizar o array $dados, que é onde está sendo guardado as informações do __set e __get...

 

tipo

 

__set($nome, $valor){ $this->dados[$nome] = $valor}

 

Ta tudo guardado dentro de daods, então eu posso usar, não é mta gambiarra eu acho, ou é??

 

Foi a solução que achei...

Compartilhar este post


Link para o post
Compartilhar em outros sites

Olha, desta forma funciona, mas você não tem controle sobre os dados que são passados e aí o encapsulamento fica sem sentido. Veja um trecho do meu código:

 

        public function setId($id) {
                $this->id = (int)$id;
        }
Veja que eu faço o cast para inteiro. Ou seja, eu garanto que $this->id será, SEMPRE um inteiro. Se você fizer com o __set, é melhor então definir as propriedades como públicas e acessar diretamente, sem precisar de __set e __get, porque não tem sentido utilizar setter e getter se você não validar os dados gravados ali.

 

Carlos Eduardo

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.