Criando Extensões PHP – Criando callbacks

Em algum momento, o usuário precise fazer com que uma função chame outra função para desenvolver alguma funcionalidade. Estas funções são chamadas de Callbacks. Um exemplo disso, uma função simples, que some 2 números. Digamos que por algum motivo o resultado disso seja 3, e quando isso ocorrer, o usuário precise executar uma outra função. Esta outra função callback, será uma função PHP, ou seja, seu módulo é quem a chamará, alguma coisa assim:


A função da Zend responsável por essa mágica é a call_user_function_ex(), retornando true no caso de ter sido executada ou false no caso de falha. Esta função necessita de 8 parâmetros.

HashTable* function_table
Tabela global de funções, geralmente com argumento de CG(function_table). Quando o segundo parâmetro for usado, este deve ser NULL, e quando este é usado, o segundo deve ser NULL.

zval** object_pp
Ponteiro para um objeto. Quando este não é NULL, a tabela global de funções é populada com este objeto, e o primeiro parâmetro deve ser NULL.

zval* function_name
Nome da função ou método à ser chamado. O tipo interno deste zval deve ser do tipo string, representando o nome da função ,representando o método do objeto, ou ainda pode ser um array contendo o objeto e o método contido no código PHP.

zval* retval_ptr
Um ponteiro para armazenar o retorno da função de usuário. Assim que a função é executada, esta variável armazenará o resultado da mesma. A memória não precisa ser alocada, pois a função já faz isto automaticamente. Após o uso do retorno, esta variável precisa ser destruída utilizando zval_dtor().

zend_uint param_count
Nesta variável de valores inteiros fica armazenado o numero de parâmetros passados pela função do usuário.

zval** params[]
Um vetor contendo o valor dos parâmetros enviados pela função do usuário, na mesma ordem enviada na função.

int no_separation
Este parâmetro geralmente é 0, isso torna a função mais rápida se os argumentos não precisão de separação, mas não funcionará se os mesmos o tiverem.

HashTable* symbol_table TSRMLS_DC
Uma tabela alternativa de símbolos para ser passada para a função de usuário. Geralmente é usado o valor NULL, que faz criar uma tabela padrão de símbolo.

Quando se está criando funções que chamam callbacks, necessitamos fazer alguns testes para sabermos por exemplo, se os argumentos deste callback estão válidos, ou até mesmo para ver se a função existe no código PHP. A função da Zend responsável por isso é a zend_is_callable() retornando true ou false, em caso de estar tudo normal ou se houver falha. Esta função necessita de 3 parâmetros:

zval* callable
O nome da função callback.

uint check_flags
Flag que indica se a checagem será simples, ou uma checagem simples e a verificação se a função existe. Geralmente é usado 0, para indicar que está sendo chegado a síntese e se a função existe.

char** callable_name
Variável que armazenará o retorno da qualificação do teste. Este parâmetro é muito util quando a função falha. Não é necessário alocar a memória para esta variável, pois a função aloca automaticamente.

Um exemplo pratico de tudo que foi dito acima, pode ser visto na função abaixo. O exemplo segue o mesmo no inicio: temos umas função somadora, se o valor da soma resultar em 3, chama uma função PHP, nosso callback, caso não seja 3, nada acontece, logo, temos 3 parâmetros, o primeiro um numero, o segundo outro numero, e o terceiro uma string com o nome da nossa função callback.

PHP_FUNCTION(minha_funcao)
{
	long num1, num2;			// Parametros
	zval *retval;				// Retorno
	zval *function_name;		// Nome da função
	char *function_check;	// Nome da função
	
	// Busca os parametros
	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "llz", &num1, &num2, &function_name) == FAILURE) {
		return;
	} 
	
	// Verifica se o callback existe
	if(!zend_is_callable(function_name, 0, &function_check))
	{
		// Retorna um erro
		zend_error(E_ERROR, "Callback function problem");
	}
	
	// Verifica a conta
	if((num1 + num2) == 3)
	{
		// Chama o callback
		if(call_user_function_ex(CG(function_table), NULL, function_name, &retval, 0, NULL TSRMLS_CC, NULL, NULL) != SUCCESS)
		{
			// Retorna um erro
			zend_error(E_ERROR, "Function call failed");
		}
	}
}

O código PHP que utiliza esta função está logo abaixo. Como dito, ele somará 2 números, e se o resultado for 3, ele chamará nossa função callback. O primeiro e o segundo parâmetro são dois números, e o terceiro parâmetro o nome do nosso callback.


Faça testes, removendo parâmetros da da função, removendo nosso callback e outros testes para ver a funcionalidade de cada parte da nossa extensão.

Bem, é isso, aqui terminamos nosso capitulo de callbacks. Até mais.