PHP Manuál | ||
---|---|---|
Predchádzajúci | Nasledujúci |
Táto sekcia je už dosť zastaralá a demonštruje ako rozšíriť PHP 3. Ak sa zaujímate o PHP 4, prosím, prečítajte si sekciu na Zend API. Tiež si môžete prečítať rôzne súbory nachádzajúce sa v PHP zdroji, súbory ako sú README.SELF-CONTAINED-EXTENSIONS a README.EXT_SKEL.
Všetky funkcie vyzerajú takto:
void php3_foo(INTERNAL_FUNCTION_PARAMETERS) { } |
Argumenty sú vždy typu pval. Tento typ obsahuje zväz, ktorý má aktuálny typ argumentu. Takže ak má vaša funkcia dva argumenty, mali by ste na začiatku funkcie urobiť niečo podobné tomuto:
Keď meníte hocijaký prešlý parameter, či už je poslaný odkazom alebo hodnotou, môžete buď začať odznova zavolaním pval_destructor, alebo ak je to POLE, ktoré chcete pridať, môžete použiť funkcie podobné tým v internal_funcions.h, ktoré manipulujú s return_value ako s POĽOM.
Rovnako, ak meníte parameter na IS_STRING, uistite sa, že najprv priradíte nový estrdup()'ovaný reťazec a dĺžku reťazca, a až potom zmeňte typ na IS_STRING. Ak zmeníte reťazec parametra, ktorý je už IS_STRING alebo IS_ARRAY, mali by ste na neho najprv použiť pval_destructor.
Funkcia môže nadobudnúť pohyblivé množstvo argumentov. Ak vaša funkcia môže nadobudnúť buď argument 2 alebo 3, použite následovné:
Typ každého argumentu sa ukladá do typového poľa pval. Tento typ môže byť jeden z následujúcich:
Tabuľka F-1. Interné typy PHP
IS_STRING | Reťazec |
IS_DOUBLE | Pohyblivá čiarka s dvojitou presnosťou |
IS_LONG | Dlhý integer |
IS_ARRAY | Pole |
IS_EMPTY | Nič |
IS_USER_FUNCTION | ?? |
IS_INTERNAL_FUNCTION | ?? (ak niektoré z týchto nemôžu byť vložené do funkcie - delete) |
IS_CLASS | ?? |
IS_OBJECT | ?? |
Ak dostanete argument jedného typu a chceli by ste ho použiť ako iný, alebo ak chcete prinútiť argument, aby bol príslušného typu, môžete použiť následujúce konverzné funkcie:
convert_to_long(arg1); convert_to_double(arg1); convert_to_string(arg1); convert_to_boolean_long(arg1); /* Ak je retazec "" alebo "0", bude 0, inak 1 */ convert_string_to_number(arg1); /* Konvertuje retazec bud na LONG alebo DOUBLE zavisiac na retazci */ |
Tieto funkcie robia konverziu na mieste. Nevracajú nič.
Aktuálny argument je uložený v zväzku; členmi sú:
IS_STRING: arg1->value.str.val
IS_LONG: arg1->value.lval
IS_DOUBLE: arg1->value.dval
Všetka pamäť, ktorú funkcia potrebuje by sa mala vyhradiť buď s emalloc() alebo estrdup(). Toto sú abstraktné funkcie manipulujúce s pamäťou, ktoré vyzerajú ako normálne funkcie malloc() a strdup(). Pamäť by sa mala uvoľniť s efree().
V tomto programe sú dva druhy pamätí: pamäť, ktorá je vrátená do parsera v premennej a pamäť, ktorú potrebujete pre dočasné uloženie vo vašej internej funkcii. Keď priraďujete reťazec k premennej, ktorá sa vracia do parsera, musíte sa uistiť, že pamäť najprv vyhradíte buď s emalloc() alebo estrdup(). Túto pamäť by ste NIKDY nemali uvoľniť vy, pokiaľ neskôr v tej istej funkcii neprepíšete svoje pôvodné priradenie (avšak tento typ programovacej techiky nie je dobrý).
Pre hocijakú dočasnú/trvalú pamäť, ktorú potrebujete vo svojich funkciách/knižnici, by ste mali použiť tri funkcie emalloc(), estrdup() a efree(). Správajú sa PRESNE ako ich opačné funkcie. Všetko, čo emalloc()'ujete alebo estrdup()'ujete, musíte na niektorých miestach efree()'ovať, pokiaľ kód do konca neuviazne; inak pamäť pretečie. Významom "funkcie sa správajú presne ako ich opačné funkcie" je: ak efree()'ujete niečo, čo nebolo emalloc()'ované alebo estrdup()'ované, môže sa objaviť zlyhanie segmentácie. Takže sa prosím o to postarajte a uvoľnite celú zbytočnú pamäť.
Ak kompilujete s "-DDEBUG", tak po dokončení špecifického skriptu, PHP vypíše zoznam všetkej pamäte, ktorá bola vyhradená použitím emalloc() a estrdup(), ale ktorá nebola nikdy uvoľnená s efree().
Existuje množstvo makier, ktoré uľahčujú nastavenie premennej v tabuľke symbolov:
SET_VAR_STRING(name,value)
SET_VAR_DOUBLE(name,value)
SET_VAR_LONG(name,value)
Varovanie |
Buďte opatrný s SET_VAR_STRING. Časť hodnoty musí byť malloc'ovaná manuálne, pretože kód pamäťového manažmentu sa neskôr pokúsi tento ukazovateľ uvoľniť. Nepresúvajte staticky vyhradenú pamäť do SET_VAR_STRING. |
Tabuľky symbolov v PHP sú implementované ako tabuľky hash. V hocakom danom čase je &symbol_table ukazovateľom 'hlavnej' tabuľky symbolov a active_symbol_table ukazuje na teraz aktívnu tabuľku symbolov (tieto môžu byť identické ako pri štarte, alebo rôzne, ak ste vo vnútri funkcie).
Následujúce príklady používajú 'active_symbol_table'. Mali by ste ju nahradiť s &symbol_table, ak chcete špecificky pracovať s 'hlavnou' tabuľkou symbolov. Rovnako aj rovnaké funkcie sa môžu použiť na polia, ako je vysvetlené nižšie.
Ak chcete definovať nové pole v tabuľke symbolov, mali by ste urobiť následujúce.
Najprv by ste mali zistiť, či existuje a vhodne ju zrušiť, a to použitím hash_exists() alebo hash_find().
Ďalej, inicializujte pole:
Tu je uvedené ako sa do neho pridávajú položky:
hash_next_index_insert() používa viac-menej tú istú logiku ako "$foo[] = bar;" v PHP 2.0.
Ak budujete pole na vrátenie z funkcie, môžete inicializovať pole práve tak ako sa to urobilo vyššie:
if (array_init(return_value) == FAILURE) { zlyhal...; } |
...a potom pridaním hodnôt s pomocníkom funkcií:
add_next_index_long(return_value,long_value); add_next_index_double(return_value,double_value); add_next_index_string(return_value,estrdup(string_value)); |
Samozrejme, ak sa pridanie neurobí hneď po inicializácii poľa, pravdepodobne sa budete musieť najprv postarať o pole:
pval *arr; if (hash_find(active_symbol_table,"foo",sizeof("foo"),(void **)&arr)==FAILURE) { nemoze najst... } else { pouzi arr->value.ht... } |
Všimnite si, že hash_find zachytáva ukazovateľ do pval ukazovateľ, a nie pval ukazovateľ.
Vlastne akákoľvek hash funkcia vracia SUCCESS alebo FAILURE (okrem hash_exists(), ktorá vracia pravdivú hodnotu booleanu).
Je k dispozícií veľa makier, aby sa vrátenie hodnôt z funkcie uľahčilo.
Všetky makra RETURN_* nastavujú vrátenú hodnotu a vrátia ju z funkcie:
RETURN
RETURN_FALSE
RETURN_TRUE
RETURN_LONG(l)
RETURN_STRING(s,dup) Ak je dup TRUE, reťazec sa reprodukuje
RETURN_STRINGL(s,l,dup) Vráti reťazec (-ce) stanovenej dĺžky (l).
RETURN_DOUBLE(d)
Makra RETVAL_* nastavujú vrátenú hodnotu, ale nevrátia ju.
RETVAL_FALSE
RETVAL_TRUE
RETVAL_LONG(l)
RETVAL_STRING(s,dup) Ak je dup TRUE, reťazec sa reprodukuje
RETVAL_STRINGL(s,l,dup) Vráti reťazec (-ce) stanovenej dĺžky (l).
RETVAL_DOUBLE(d)
Tieto horeuvedené reťazcové makra estrdup()'ujú vložený argument 's', takže môžete bezpečne uvoľniť argument po volaní makra, alebo po prípade použiť staticky vyhradenú pamäť.
Ak vaša funkcia vracia odozvy v podobe úspech/chyba, vždy použite RETURN_TRUE a RETURN_FALSE jednotlivo.
Vaša funkcia môže tiež vrátiť komplexný dátový typ ako je objekt alebo pole.
Vrátenie objektu:
Zavolajte funkciu object_init(return_value).
Doplňte hodnoty. Funkcie slúžiace na tento účel sú vypísané nižšie
Prípadne, pre tento objekt zaregistrujte funkcie. Aby ste získali hodnoty objektu, funkcia by "ich" mala vybrať z active_symbol_table. Jej typ by mal byť IS_OBJECT, a je to pôvodne platná hash tabuľka (t.j., môžete použiť platné hash funkcie na .value.ht). Registrácia funkcie sa dá urobiť použitím:
add_method( return_value, function_name, function_ptr ); |
Funkcie používané na obsadenie objektu sú:
add_property_long( return_value, property_name, l ) - Pridá vlastnosť nazvanú 'property_name', typu long, rovnú 'l'
add_property_double( return_value, property_name, d ) - To isté, len pridá double
add_property_string( return_value, property_name, str ) - To isté, len pridá reťazec
add_property_stringl( return_value, property_name, str, l ) - To isté, len pridá reťazec dĺžky 'l'
Vrátenie poľa:
Zavolajte array_init(return_value).
Doplňte hodnoty. Funkcie slúžiace na tento účel sú uvedené nižšie.
Funkcie používané na obsadenie poľa sú:
add_assoc_long(return_value,key,l) - pridá associatívnu položku s kľúčom 'key' a hodnotou long 'l'
add_assoc_double(return_value,key,d)
add_assoc_string(return_value,key,str,duplicate)
add_assoc_stringl(return_value,key,str,length,duplicate) - špecifikuje dĺžku reťazca
add_index_long(return_value,index,l) - pridá položku indexu 'index' s hodnotou long 'l'
add_index_double(return_value,index,d)
add_index_string(return_value,index,str)
add_index_stringl(return_value,index,str,length) - špecifikuje dĺžku reťazca
add_next_index_long(return_value,l) - pridá položku poľa do ďalšieho voľného offsetu s hodnotou long 'l'
add_next_index_double(return_value,d)
add_next_index_string(return_value,str)
add_next_index_stringl(return_value,str,length) - špecifikuje dĺžku reťazca
PHP má štandardný spôsob zaobchádzania s rôznymi typmi zdrojov. Toto nahrádza všetky miestne linkované zoznamy v PHP 2.0.
Dostupné funkcie:
php3_list_insert(ptr, type) - vracia 'id' novo vloženého zdroja
php3_list_delete(id) - odstráni zdroj s určeným id
php3_list_find(id,*type) - vracia ukazovateľ zdroja s určeným id, aktualizuje 'type' na typ zdroja
Typický zoznam kódu by vyzeral takto:
Príklad F-8. Použitie existujúceho zdroja
|
PHP má štandardný spôsob ukladania trvalých zdrojov (t.j, zdroje, ktoré sa uchovávajú medzi zásahmi). Prvý modul, ktorý mal používať túto vlastnosť bol modul MySQL, a následne mSQL, takže pri čítaní mysql.c môžete nadobudnúť dojem, aký trvalý zdroj by sa mal použiť. Funkcie, na ktoré by ste sa mali pozrieť sú:
php3_mysql_do_connect |
php3_mysql_connect() |
php3_mysql_pconnect() |
Všeobecný význam trvalých modulov je tento:
Nakódujte celý svoj modul tak, aby pracoval so zoznamom platných zdrojov, ako bolo spomenuté v sekcii (9).
Nakódujte extra prepojenia na funkcie, ktoré zistia, či už zdroj existuje v zozname trvalých zdrojov. Ak áno, zaregistrujte ho tak ako v zozname platných zdrojov ako ukazovateľ na zoznam trvalých zdrojov (pretože zvyšok kódu by mal pracovať okamžite). Ak nie, tak ho vytvorte, pridajte ho do zoznamu trvalých zdrojov A pridajte naň ukazovateľ zo zoznamu platných zdrojov, takže by celý kód fungoval, pretože je v zozname platných zdrojov, ale na druhom prepojení by sa zdroj našiel v zozname trvalých zdrojov a používal by sa bez potreby znovuobnovenia. Tieto zdroje by ste mali zaregistrovať ako rozličné typy (t.j. LE_MYSQL_LINK pre dočasný odkaz a LE_MYSQL_PLINK pre trvalý odkaz).
Ak si prečítate mysql.c, zistíte, že okrem komplexnejších funkcií spojenia, sa nič, čo zostalo v module, nesmie zmeniť.
Úplne také isté rozhranie existuje pre zoznam platných zdrojov a zoznam trvalých zdrojov, iba 'list' sa nahradil s 'plist':
php3_plist_insert(ptr, type) - vracia 'id' novo vloženého zdroja
php3_plist_delete(id) - odstraňuje zdroj so špecifickým id
php3_plist_find(id,*type) - vracia ukazovateľ zdroja so špecifickým id, aktualizuje 'type' na typ zdroja
Ale je viac ako pravdepodobné, že tieto funkcie by sa pre vas preukázali ako zbytočné, keď by ste sa pokúšali implementovať trvalý modul. Niekto by typicky chcel využiť fakt, že zoznam trvalých zdrojov je v skutočnosti hash tabuľka. Napríklad, v moduloch MySQL/mSQL, keď sa volá pconnect() (trvalé prepojenie), funkcia vybuduje reťazce z host/user/passwd, ktoré sa funkcii predali, a hashuje SQL odkaz s týmto reťazcom ako kľúč. Ďalej, niekto zavolá pconnect() s rovnakým host/user/passwd, vygeneruje sa rovnaký kľúč a funkcia vyhľadá SQL odkaz v trvalom zozname.
Kým sa pozriete na ďalej zdokumentované, mali by ste sa pozrieť na mysql.c alebo msql.c, aby ste videli, ako by sa schopnosti hash tabuľky plistu mali použiť.
Jedna dôležitá poznámka: zdroje, ktoré idú do zoznamu trvalých zdrojov, sa *NESMÚ* vyhradiť s pamäťovým manažérom PHP, t.j., NEMALI by sa vytvárať s emalloc(), estrdup(), atď. Radšej by sa mali použiť regulérne malloc(), strdup(), atď. Dôvod je jednoduchý - na konci požiadavky (konci zásahu), sa každá pamäťová informácia, ktorá bola vyhradená pomocou pamäťového manažéra PHP, vymaže. Nakoľko trvalý zoznam nie je na to, aby sa na konci požiadavky vymazal, manažér pamäte PHP sa nesmie používať na vyhradenie zdrojov, ktoré do neho idú..
Keď registrujete zdroj, ktorý bude v trvalom zozname, mali by ste k nemu pridať deštruktorov v dočasnom aj v trvalom zozname. Deštruktor by nemal v dočasnom zozname deštruktora urobiť nič. Ten v trvalom zozname deštruktora by mal vhodne uvoľniť akékoľvek zdroje získané tým typom (t.j. pamäť, SQL odkazy, atď). Práve tak ako s dočasnými zdrojmi, *MUSÍTE* ku každému zdroju pridať deštruktora, aj keď nevyžaduje žiaden a keby bol aj prázdny. Pamätajte, nakoľko emalloc() a 'spol.' sa nemajú používať spoločne s trvalým zoznamom, ani tu nesmiete použiť efree().
Mnoho vlastností PHP sa môže konfigurovať v runtime. Tieto konfiguračné direktívy sa môžu zjaviť buď v určenom php3.ini súbore alebo, v prípade Apache modulu, v Apache .conf. súboroch. Ich výhodou v Apache .conf súboroch je, že sa dajú konfigurovať na pre-adresárovom základe. To znamená, že jeden adresár môže mať napríklad jasný safemodeexecdir, zatiaľ čo druhy môže mať iný. Táto konfiguračná diskrétnosť je užitočná, hlavne keď sever podporuje členité virtuálne hosty.
Kroky nutné na pridanie novej direktívy:
Pridajte štruktúru do php3_ini_structure v mod_php3.h.
V main.c, editujte funkciu php3_module_startup a vhodne pridajte cfg_get_string() alebo cfg_get_long() volanie.
Pridajte direktívu, vymedzenie a komentár do štruktúry php3_commands v mod_php3.c. Všimnite si časť vymedzení. RSRC_CONF sú direktívy, ktoré môžu byť prítomné len v Apache .conf súboroch. Direkívy OR_OPTIONS môžu byť prítomné všade, vrátane normálnych .htaccess súborov. files.
Buď v php3take1handler() alebo php3flaghandler(), pridajte vhodnú položku pre vašu direktívu.
V konfiguračnej sekcii funkcie _php3_info() v functions/info.c, musíte pridať svoju novú direktívu.
A nakoniec, samozrejme musíte niekde svoju novú direktívu použiť. Bude adresovateľná ako php3_ini.directive.
Predchádzajúci | Domov | Nasledujúci |
Debugger Protokol | Hore | Volanie užívateľských funkcií |