Ir para o conteúdo

- - - - -

Reflectionclass::getmethods()...


Criado por Bruno Augusto, Jan 09 2012 17:00

3 respostas neste tópico
  • Por favor, faça o login para responder

#1 Bruno Augusto

Bruno Augusto
  • Bruno Augusto
  • Colaborador
  • 3 Revisões

Revisou 09 janeiro 2012 - 17:00

Alguns dos recursos da Reflection são bem frustrantes.

Parte dessa culpa pode ser atribuída ao Manual, que nem sempre possui documentação para os métodos das classes desse pacote ou quando tem, às vezes é incompleta.

Um bom exemplo disso é ReflectionClass::getMethods() o qual, segundo o Manual retorna um array. Beleza, mas faltou mencionar que cada elemento desse array é uma instância de ReflectionMethod.

Para os desavisados, pode ser um problema. Mas com uma ajudinha dos Iterators que a SPL provê, é possível tornar esse retorno mais amigável:

$object = new ArrayObject;

// Refletimos sobre o Objeto desejado

$reflector = new ReflectionClass( $object );

// Criamos um Iterator com os dados

$iterator = new ArrayIterator( $reflector -> getMethods() );

// Executamos uma determinada função em cada elemento do Iterator

iterator_apply(

    $iterator,

    function( Iterator $iterator ) {

        /**
         * A idéia aqui é sobrescrever o offset onde a instância de ReflectionMethod se encontra
         * com apenas o nome do método, presente na propriedade pública ReflectionMethod::$name
         */
        $iterator -> offsetSet( $iterator -> key(), $iterator -> current() -> name );

        // Retornar TRUE é obrigatório, caso contrário a rotina é interrompida

        return TRUE;
    },

    array( $iterator )
);
Analisando nosso Iterator agora temos:

ArrayIterator Object
(
    [storage:ArrayIterator:private] => Array
        (
            [0] => __construct
            [1] => offsetExists
            [2] => offsetGet
            [3] => offsetSet
            [4] => offsetUnset
            [5] => append
            [6] => getArrayCopy
            [7] => count
            [8] => getFlags
            [9] => setFlags
            [10] => asort
            [11] => ksort
            [12] => uasort
            [13] => uksort
            [14] => natsort
            [15] => natcasesort
            [16] => unserialize
            [17] => serialize
            [18] => getIterator
            [19] => exchangeArray
            [20] => setIteratorClass
            [21] => getIteratorClass
        )

)
Mas Bruno, ainda é um objeto?

Sim, todos os elementos de um ArrayIterator são armazenados na propriedade "fantasma" (ela não aparece descrita no Manual) $storage, que é privada.

Até onde sei, não é possível obter ela. Pode-se manipulá-la através de seus métodos, mas ela é uma propriedade somente leitura.

Para obter os dados do Iterator, temos de convertê-lo num array e é para isso que existe o método ArrayIterator::getArrayCopy(), que após invocado retorna:

Array
(
    [0] => __construct
    [1] => offsetExists
    [2] => offsetGet
    [3] => offsetSet
    [4] => offsetUnset
    [5] => append
    [6] => getArrayCopy
    [7] => count
    [8] => getFlags
    [9] => setFlags
    [10] => asort
    [11] => ksort
    [12] => uasort
    [13] => uksort
    [14] => natsort
    [15] => natcasesort
    [16] => unserialize
    [17] => serialize
    [18] => getIterator
    [19] => exchangeArray
    [20] => setIteratorClass
    [21] => getIteratorClass
)
O mesmo resultado poderia ser obtido por forçar o cast do Iterator para array:

$methods = (array) $iterator;


#2 Andrey Knupp

Andrey Knupp
  • Andrey Knupp
  • Colaborador
  • 13 Revisões
  • LocalizaçãoMinas Gerais - MG

Revisou 10 janeiro 2012 - 15:06

Bruno, acho que aí você complicou ..

  • Não é necessário instânciar a classe para mandar pro Reflection
  • Pra que o iterator ?

<?php
	$reflection = new ReflectionClass( 'ArrayIterator' );
	foreach ( $reflection->getMethods() as $method ) {
		$methods [ ] = $method->name;
	}
	echo '<pre>' ;
		print_r ( $methods ) ;

Array
(
    [0] => __construct
    [1] => offsetExists
    [2] => offsetGet
    [3] => offsetSet
    [4] => offsetUnset
    [5] => append
    [6] => getArrayCopy
    [7] => count
    [8] => getFlags
    [9] => setFlags
    [10] => asort
    [11] => ksort
    [12] => uasort
    [13] => uksort
    [14] => natsort
    [15] => natcasesort
    [16] => unserialize
    [17] => serialize
    [18] => rewind
    [19] => current
    [20] => key
    [21] => next
    [22] => valid
    [23] => seek
)


#3 Bruno Augusto

Bruno Augusto
  • Bruno Augusto
  • Colaborador
  • 3 Revisões

Revisou 10 janeiro 2012 - 19:32

Estranho, no PC que escrevi esse código, que é bem mais rápido desse que estou agora, a diferença de velocidade usando foreach foi brutalmente pior do que com iterator_apply().

Só por isso que eu postei. :huh:

Quanto a não precisar instanciar o objeto para refletir é verdade, dei bobeira.

#4 Andrey Knupp

Andrey Knupp
  • Andrey Knupp
  • Colaborador
  • 13 Revisões
  • LocalizaçãoMinas Gerais - MG

Revisou 30 janeiro 2012 - 13:43

Hum .. meio estranho este benchmark seu.




1 usuário(s) está(ão) lendo este código

1 membro(s), 0 visitante(s) e 0 membros anônimo(s)