3. Quem é Erick Tedeschi?
Conheceu PHP em 2003
Analista de Segurança da Informação
Doctrine (extensão PECL classe Lexer)
Motociclista
Obs.: ..ñ é Takashi, Takeshi, Takeushi..É TEDESCHI
4. O que é PECL?
PHP Extension and Application Repository
5. O que é PECL?
PHP Extension and Application Repository
PHP Extension Community Library
6. O que é PECL?
← Escrito em PHP
PHP Extension and Application Repository
← Escrito em “C”
PHP Extension Community Library
8. PHP Page Life Cycle
Ciclo de vida de uma requisição de página (script) PHP originada de um WebServer:
Processo do Apache Inicia WebServer
LoadModule php5_module Carrega módulo do PHP
mysql,sockets,curl,curses,etc... PHP Carrega suas extensões (builtin e php.ini)
MINIT Carrega constantes, ini entries, resources, etc...
RINIT Inicializa autoglobals, symbol table, log, etc...
Script Execution
RSHUTDOWN Libera memória...
MSHUTDOWN Libera memória... (ini entries, resources, etc...)
10. Ambiente de Desenvolvimento (*nix)
Requisitos necessários para compilar extensões:
Ubuntu: m4 e buildessential
autoconf 2.13
(http://ftp.gnu.org/gnu/autoconf)
automake 1.4
(http://ftp.gnu.org/gnu/automake)
libtool 1.4.x+ (except 1.4.2)
(http://ftp.gnu.org/gnu/libtool)
bison 1.28
(http://ftp.gnu.org/gnu/bison)
flex 2.5.4
(http://prdownloads.sourceforge.net/flex/flex2.5.4a.tar.gz?download)
re2c 0.13.4+
(http://re2c.org)
* Caso a extensão faça uso de alguma bilioteca externa, a mesma deve ser
Instalada: Libcursesdev, libxmldev, etc...
11. Esqueleto da Extensão – Arquivos
Arquivos básicos que compõe a extensão:
Obrigatórios:
config.m4
Arquivo de configuração *unix
config.w32
Arquivo de configuração Windows
php_EXTNAME.h
Cabeçalho (includes, structs, protótipo de funções, macros, etc...)
EXTNAME.c
Esqueleto da extensão e implementação das funções/classes
Obs.: EXTNAME é o nome da extensão criada
12. Esqueleto da Extensão – Arquivos
Arquivos básicos que compõe a extensão:
Opcionais:
CREDITS
1ª linha Nome da Extensão, 2ª linha em diante nome dos colaboradores
EXPERIMENTAL
Não estável. Conteúdo: observação sobre o que está instável ou o que
pode ser alterado.
EXTNAME.php
Teste básico da extensão
tests
Diretório onde ficam os casos de teste escritos para a extensão
Obs.: EXTNAME é o nome da extensão criada
13. Script: ext_skel
O script ext_skel fica localizado dentro do diretório “ext” na raiz do source do PHP.
A extensão gerada é uma cópia dos arquivos do diretório “ext/skeleton”,
substituindo apenas o nome da extensão definida no parâmetro “extname” do
script ext_skel.
fulano@machine:/home/dev/php-5.3/ext$ ./ext_skel –extname=phpsc
fulano@machine:/home/dev/php-5.3/ext$ cd phpsc
fulano@machine:/home/dev/php-5.3/ext/phpsc$ ls -lh
-rw-r--r-- 1 kirex kirex 2,0K 2010-08-28 10:25 config.m4
-rw-r--r-- 1 kirex kirex 289 2010-08-28 10:25 config.w32
-rw-r--r-- 1 kirex kirex 5 2010-08-28 10:25 CREDITS
-rw-r--r-- 1 kirex kirex 0 2010-08-28 10:25 EXPERIMENTAL
-rw-r--r-- 1 kirex kirex 2,8K 2010-08-28 10:25 php_phpsc.h
-rw-r--r-- 1 kirex kirex 5,1K 2010-08-28 10:25 phpsc.c
-rw-r--r-- 1 kirex kirex 499 2010-08-28 10:25 phpsc.php
drwxr-xr-x 2 kirex kirex 4,0K 2010-08-28 10:25 tests
14. API – Macros e mais macros de macros!
Com macros (menor margem para erros):
zval *nome = NULL;
ALLOC_ZVAL(nome);
ZVAL_STRING(nome, “Cássia”, 0);
Sem macros (maior margem para erros):
zval *nome = NULL;
nome = (zval *)emalloc(sizeof(zval));
(*nome).value.str.len = strlen(“Cássia”);
(*nome).value.str.value = estrndup(“Cássia”, strlen(“Cássia”);
(*nome).type = 6; /* IS_STRING */
15. Esqueleto da Extensão – config.m4
PHP_ARG_ENABLE(EXTNAME, Whether to enable the EXTNAME extension,
[ --enable-EXTNAME Enable extension description ])
If test $PHP_EXTNAME != “no”; then
PHP_NEW_EXTENSION(EXTNAME, EXTNAME.c, $ext_shared)
fi
Obs.: Sempre que alterar o config.m4, executar o phpize para gerar
novamente o script “configure” e outros arquivos que são utilizados para
compilar a extensão.
16. Esqueleto da Extensão – php_EXTNAME.h
#ifndef PHP_EXTNAME_H
/* Prevent double inclusion */
#define PHP_EXTNAME_H
/* Define extension properties */
#define PHP_EXTNAME_NAME “Extension Name for Minfo”
#define PHP_EXTNAME_VER “1.0”
/* Import configure options when building outside
Of the PHP source tree */
#ifdef HAVE_CONFIG_H
#include “config.h”
#endif
/* Include PHP standard header */
#include “php.h”
/* Define the entry point symbol.
Zend will use when loading this module */
extern zend_module_entry extname_module_entry;
#define phpext_EXTNAME_ptr &extname_module_entry
#endif /* PHP_EXTNAME_H */
17. Esqueleto da Extensão - EXTNAME.c
Estrutura do arquivo “.c”:
cabeçalho Licença, Créditos, Descrição, etc...
includes API e bibliotecas externas
funções Funções existentes na extensão
MINFO Informações do módulo (phpinfo())
MINIT Tarefas a serem executadas ao carregar a extensão
MSHUTDOWN Libera memórias das tarefas executadas no MINIT
RINIT Tarefas a serem executadas na requisição do script PHP
RSUTDOWN Libera memória das tarefas executadas no RINIT
function_entry Registra as funções para a extensão
module_entry Entrada do módulo no PHP
18. Esqueleto da Extensão - Cabeçalho
/*
+----------------------------------------------------------------------+
| PHP Version 5 |
+----------------------------------------------------------------------+
| Copyright (c) 1997-2008 The PHP Group |
+----------------------------------------------------------------------+
| This source file is subject to version 3.01 of the PHP license, |
| that is bundled with this package in the file LICENSE, and is |
| available through the world-wide-web at the following url: |
| http://www.php.net/license/3_01.txt |
| If you did not receive a copy of the PHP license and are unable to |
| obtain it through the world-wide-web, please send a note to |
| license@php.net so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
| Author: Fulano de Tal < fulano at tal dot com > |
+----------------------------------------------------------------------+
*/
/* $Id: header 252479 2008-02-07 19:39:50Z iliaa $ */
20. Esqueleto da Extensão - Funções
// Exemplo de funções definidas para o “user space”.
PHP_FUNCTION(mysql_connect)
{
/* código da função */
}
PHP_FUNCTION(mysql_close)
{
/* código da função */
}
// Exemplo da implementação de classes para o “user space”.
PHP_METHOD(Cachorro, __construct)
{
/* código do construtor */
}
PHP_METHOD(Cachorro, latir)
{
/* código do método */
}
24. Esqueleto da Extensão – Function Entry
const zend_function_entry extname_functions[] = {
PHP_FE(extname_abrir, NULL)
PHP_FE(extname_colar, NULL)
PHP_FE(extname_recortar, NULL)
{NULL, NULL, NULL} /* Must be the last line in extname_functions[] */
};
25. Esqueleto da Extensão – Module Entry
zend_module_entry extname_module_entry = {
#if ZEND_MODULE_API_NO >= 20010901
STANDARD_MODULE_HEADER,
#endif
"extname",
extname_functions,
PHP_MINIT(extname),
PHP_MSHUTDOWN(extname),
PHP_RINIT(extname),
PHP_RSHUTDOWN(extname),
PHP_MINFO(extname),
#if ZEND_MODULE_API_NO >= 20010901
"0.1", /* Version number for your extension */
#endif
STANDARD_MODULE_PROPERTIES
};
26. API ZEND – Manipulação ZVAL
Macros para manipulação de ZVAL
ZVAL_RESOURCE(zval, 234)
ZVAL_NULL(zval)
ZVAL_BOOL(zval, 1)
ZVAL_LONG(zval, 1234)
ZVAL_DOUBLE(zval, 34.5);
ZVAL_STRING(zval, “Fulano”, 0)
ZVAL_EMPTY_STRING(zval)
ZVAL_FALSE(zval) // ZVAL_BOOL(zval, 0)
ZVAL_TRUE(zval) // ZVAL_BOOL(zval, 1)
Macros para manipulação do valor de retorno da função
RETVAL_RESOURCE(234) // ZVAL_RESOURCE(return_value, 234)
RETVAL_BOOL(1) // ZVAL_BOOL(return_value, 1)
RETVAL_NULL() // ZVAL_NULL(return_value)
RETVAL_LONG(1234) // ZVAL_LONG(return_value, 1234)
RETVAL_DOUBLE(34.5) // ZVAL_DOUBLE(return_value, 34.5)
RETVAL_STRING(“Fulano”, 0) // ZVAL_STRING(return_value, “Fulano”, 0)
RETVAL_FALSE
RETVAL_TRUE
etc...
27. API ZEND – Manipulação Arrays
PHP_FUNCTION(retorna_array)
{
array_init(return_value);
add_assoc_long(return_value, “Numero”, 1234);
add_assoc_bool(return_value, “Verdade”, 1);
add_assoc_double(return_value, “Peso”, 27.4);
}
<?php print_r(retorna_array()); ?>
Resultado
{
[Numero] => 1234
[Verdade] => 1
[Peso] => 27.4
}
int add_assoc_long(zval *arg, char *key, long n);
int add_assoc_null(zval *arg, char *key);
int add_assoc_bool(zval *arg, char *key, int b);
int add_assoc_resource(zval *arg, char *key, int r);
int add_assoc_double(zval *arg, char *key, double d);
int add_assoc_string(zval *arg, char *key, char *str, int dup);
int add_assoc_stringl(zval *arg, char *key, char *str, uint len, int dup);
int add_assoc_zval(zval *arg, char *key, zval *value);
28. API ZEND – Manipulação Arrays
Adiciona com um número de índice específico
int add_index_long(zval *arg, uint idx, long n);
int add_index_null(zval *arg, uint idx);
int add_index_bool(zval *arg, uint idx, int b);
int add_index_resource(zval *arg, uint idx, int r);
int add_index_double(zval *arg, uint idx, double d);
int add_index_string(zval *arg, uint idx, char *str, int duplicate);
int add_index_stringl(zval *arg, uint idx, char *str, uint length, int duplicate);
int add_index_zval(zval *arg, uint idx, zval *value);
Adiciona no próximo índice
int add_next_index_long(zval *arg, long n);
int add_next_index_null(zval *arg);
int add_next_index_bool(zval *arg, int b);
int add_next_index_resource(zval *arg, int r);
int add_next_index_double(zval *arg, double d);
int add_next_index_string(zval *arg, char *str, int duplicate);
int add_next_index_stringl(zval *arg, char *str, uint length, int duplicate);
int add_next_index_zval(zval *arg, zval *value);
29. Aceitando Parâmetros
Syntax: zend_parse_parameters(num_args, “format args”, &arg1, &arg2, ...)
l Long long *
d double double *
b Boolean zend_bool *
a array zval **
o Object zval **
O Object zval **, zend_class_Entry *
Força ser da classe/tipo determinada
s String char **, int *
Sempre recebe string e tamanho
r resource zval **
z zval zval **
Z zval-ref zval ***
| Restante (parte direita) são opcionais
! Proximo parametro retorna NULL se o tipo é IS_NULL
30. Aceitando Parâmetros – Exemplo 1
PHP_FUNCTION(exemplo1)
{
/* 1 - Definição das variáveis */
char *nome;
int nome_len;
/* 2 - Pegando os parâmetros */
if (zend_parse_parameters(1 TSRMLS_CC, “s”, &nome, &nome_len) == FAILURE)
{
return;
}
/* 3 - Implementação da função... */
php_printf(“Nome: %s”, nome);
/* 4 - Retorno de valor */
RETVAL_NULL;
}
Em PHP (User Space):
<?php exemplo1(“Cássia”); ?>
Resultado:
Nome: Cássia
31. Aceitando Parâmetros – Exemplo 2
PHP_FUNCTION(meu_gettype)
{
/* 1 - Declaração das variáveis */
zval *variavel;
/* 2 - Recebendo parâmetros */
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &variavel)
== FAILURE) {
return;
}
/* 3 - Implementação da função */
switch (Z_TYPE_P(variavel)) {
case IS_LONG:
php_printf("Inteiro");
break;
case IS_ARRAY: Em PHP (User Space):
php_printf("Matriz");
break; <?php
default: meu_gettype(array(2,2));
php_printf("Tipo desconhecido"); ?>
break;
}
/* 4 - Retorno de valor */
Resultado:
}
Matriz
32. Retornando Valor – Exemplo 3
PHP_FUNCTION(numeroCao)
{
/* 1 - Declaração das variáveis */
/* 2 - Recebendo parâmetros */
/* 3 - Implementação da função */
/* 4 - Retorno de valor */
RETVAL_LONG(666);
}
34. Definição de Classe - phpsc.c
/* Implementação dos métodos */
PHP_METHOD(phpscPessoa, __construct)
{
php_printf(“Construtor chamado! rá!rn”);
}
PHP_METHOD(phpscPessoa, getNome)
{
zval *nome = NULL;
nome = zend_read_property(phpsc_pessoa_ce, getThis(), “_nome”,
sizeof(“_nome”)-1, 0 TSRMLS_CC);
RETVAL_STRING(Z_STRVAL_P(nome), 1);
}
35. Definição de Classe - php_phpsc.h
/* Arquivo php_phpsc.h */
/* ... */
/* Declaração dos protótipos */
PHP_METHOD(phpscPessoa, __construct);
PHP_METHOD(phpscPessoa, getNome);
PHP_METHOD(phpscPessoa, getVersion);
/* ... */
36. Macros/Funcs OOP - Constantes
int zend_declare_class_constant(zend_class_entry *ce,
char *name, size_t name_len, zval *value TSRMLS_DC);
int zend_declare_class_constant_long(zend_class_entry *ce,
char *name, size_t name_len, long value TSRMLS_DC);
int zend_declare_class_constant_bool(zend_class_entry *ce,
char *name, size_t name_len, zend_bool value TSRMLS_DC);
int zend_declare_class_constant_double(zend_class_entry *ce,
char *name, size_t name_len, double value TSRMLS_DC);
int zend_declare_class_constant_stringl(zend_class_entry *ce,
char *name, size_t name_len, char *val, size_t val_len TSRMLS_DC);
int zend_declare_class_constant_string(zend_class_entry *ce,
char *name, size_t name_len, char *value TSRMLS_DC);
Obs.: Usar sizeof para passar o argumento name_len.
37. Macros/Funcs OOP - Propriedades
int zend_declare_property(zend_class_entry *ce, char *name,
int name_length, zval *property, int access_type TSRMLS_DC);
int zend_declare_property_null(zend_class_entry *ce, char *name,
int name_length, int access_type TSRMLS_DC);
int zend_declare_property_bool(zend_class_entry *ce, char *name,
int name_length, long value, int access_type TSRMLS_DC);
int zend_declare_property_long(zend_class_entry *ce, char *name,
int name_length, long value, int access_type TSRMLS_DC);
int zend_declare_property_double(zend_class_entry *ce, char *name,
int name_length, double value, int access_type TSRMLS_DC);
int zend_declare_property_string(zend_class_entry *ce, char *name,
int name_length, char *value, int access_type TSRMLS_DC);
zval *zend_read_property(zend_class_entry *scope, zval *object,
char *name, int name_length, zend_bool silent TSRMLS_DC);