Attraverso lo Zend Engine è possibile effettuare svariate operazioni di routine che risultano molto utili quando si sviluppano estensioni. In questo paragrafo mi occuperò di descriverle brevemente, lasciando al lettore il compito di sperimentare.
La funzione zend_printf si occupa di stampare del testo indirizzandolo all'output stream di PHP. La funzione è sintatticamente identica a printf.
La funzione zend_error (che funziona allo stesso modo della funzione php_error) genera dei messaggi di errore e li indirizza al motore di PHP. Accetta due parametri:
- il primo parametro è la tipologia di errore, che può essere una tra le seguenti costanti: E_ERROR, E_WARNING, E_PARSE, E_NOTICE, E_CORE_ERROR, E_COMPILE_ERROR, E_COMPILE_WARNING. In base alla costante utilizzata PHP gestirà l'errore in modo differente;
- il secondo è una stringa che rappresenta testualmente l'errore generato;
Per aggiungere delle informazioni relative all'estensione all'output generato dalla funzione phpinfo, è possibile definire una funzione utilizzando la macro PHP_MINFO_FUNCTION. Questa funzione può utilizzare le API per aggiungere all'output di phpinfo informazioni relative all'estensione. Un breve esempio:
PHP_MINFO_FUNCTION(test_info)
{
php_info_print_table_start();
php_info_print_table_header(2, "Estensione di prova", "supportata");
php_info_print_table_end();
DISPLAY_INI_ENTRIES();
}
le funzioni php_info_print_table_* vengono utilizzate per la costruzione della tabella da aggiungere all'output di phpinfo:
- php_info_print_table_start() e php_info_print_table_end() si occupano di stampare rispettivamente l'inizio e la fine di una tabella;
- php_info_print_table_header accetta un numero variabile di argomenti (il numero di colonne ed il valore di ogni colonna) e stampa l'header della tablla;
- php_info_print_table_row funziona come la funzione precedente ma stampa una normale riga.
Utilizzano zend_get_executed_filename() è possibile recuperare il nome del file in cui una funzione definita nella nostra estensione è richiamata, mentre utilizzando zend_get_executed_lineno() è possibile recuperare il numero della linea in cui la funzione è stata richiamata.
Lo Zend Engine fornisce anche un sistema che permette di esporre delle costanti allo script PHP che utilizza la nostra estensione. La creazione di costanti viene effettuata tramite le seguenti macro:
- REGISTER_LONG_CONSTANT(name, value, flags);
- REGISTER_DOUBLE_CONSTANT(name, value, flags);
- REGISTER_STRING_CONSTANT(name, value, flags);
- REGISTER_STRINGL_CONSTANT(name, value, length, flags);
Il parametro flgs può essere una combinazione di una delle seguenti costanti:
- CONST_CS, che obbliga lo Zend Engine a trattare il nome della costante in modo case sensitive;
- CONST_PERSISTENT che mantiene la costante in memoria anche dopo che il processo che l'ha creata viene terminato;
L'engine PHP ci permette di definire ed utilizzare variabili globali in modo thread safe. Le variabili generate e gestite utilizzando le API ora descritte saranno locali per ogni thread che utilizza un'estensione.
Le macro ZEND_BEGIN_MODULE_GLOBALS e ZEND_END_MODULE_GLOBALS si occupano di generare una struttura contenente le variabili globali. La definizione delle variabili globali viene eseguita solitamente in un file header, seguendo la seguente struttura:
ZEND_BEGIN_MODULE_GLOBALS(nome_modulo)
tipo variabile;
tipo variabile2;
// ....
ZEND_END_MODULE_GLOBALS(nome_modulo)
Le macro generano una struttura zend_(nome_modulo)_globals e definisce una variabile (nome_modulo)_globals che può essere utilizzata per accedere alle variabili globali. Solitamente si opta per definire una macro per l'accesso agli elementi della struttura.
#define VAR_G(v) (nome_modulo_globals.v)
In caso si stia compilando l'estensione per un sistema multithread, è necessario accedere alla variabile recuperandola dalla pool delle variabili di thread:
#define VAR_G(v) TSRMG(nome_modulo_globals_id, zend_nome_modulo_globals *, v)
L'inizializzazione delle variabili avviene utilizzando un'apposita macro che richiama una funzione definita dall'utente:
static void nome_modulo_init_globals(zend_nome_modulo_globals *nome_modulo_globals)
{
// codice per inizializzare le variabili globali
}
PHP_MINIT_FUNCTION(nome_modulo)
{
ZEND_INIT_MODULE_GLOBALS(nome_modulo, test_nome_modulo_globals, NULL);
return SUCCESS;
}
La macro in questione è ZEND_INIT_MODULE_GLOBALS, che richiama il metodo passato come secondo argomento al fine di popolare correttamente la struttura delle variabili globali.
Un'altra funzionalità importante fornitaci dallo Zend Engine è quella di definire funzioni speciali da richiamare nel momento in cui un modulo viene caricato in memoria, inizializzato, distrutto e scaricato. Per poter definire queste funzioni è necessario operare sulla struttura che definisce la nostra estensione e sfruttare delle macro apposite:
zend_module_entry nome_modulo_module_entry = {
#if ZEND_MODULE_API_NO >= 20010901
STANDARD_MODULE_HEADER,
#endif
"nome_modulo",
nome_modulo_functions,
PHP_MINIT(nome_modulo),
PHP_MSHUTDOWN(nome_modulo),
PHP_RINIT(nome_modulo),
PHP_RSHUTDOWN(nome_modulo),
PHP_MINFO(nome_modulo),
#if ZEND_MODULE_API_NO >= 20010901
"0.1",
#endif
STANDARD_MODULE_PROPERTIES
};
Come possiamo notare le righe dalla sette alla undici permettono aggiungere al modulo delle funzioni da richiamare in casi particolari. In caso non siano presenti delle funzioni speciali, è necessario specificare il parametro della struttura zend_module_entry come NULL.
Le seguenti macro possono essere utilizzate per dichiarare funzioni speciali:
- PHP_MINIT_FUNCTION(nome_modulo), che permette di definire la funzione richiamata all'inizializzazione del modulo;
- PHP_MSHUTDOWN_FUNCTION(nome_modulo), che permette di definire la funzione richiamata quando il modulo viene scaricato;
- PHP_RINIT_FUNCTION(nome_modulo), che permette di definire la funzione richiamata quando viene effettuata una richiesta;
- PHP_RSHUTDOWN_FUNCTION(nome_modulo), che permette di definire la funzione richiamata quando viene terminata una richiesta;
- PHP_MINFO_FUNCTION(nome_modulo), che permette di definire la funzione richiamata per aggiungere all'output della funzione phpinfo informazioni sull'estensione.