Programming | PHP » Fábián Zoltán - Tanuljunk PHP-ül

Datasheet

Year, pagecount:2005, 149 page(s)

Language:Hungarian

Downloads:2007

Uploaded:October 16, 2007

Size:711 KB

Institution:
-

Comments:

Attachment:-

Download in PDF:Please log in!



Comments

No comments yet. You can be the first!

Content extract

Tanuljunk PHP-ül (Fejlesztés alatt) Fábián Zoltán 2001-2004 v0.8 1 Tartalomjegyzék 1 BEVEZETÉS.5 MIRE JÓ EZ A JEGYZET?.5 1. 2 A PHP RÖVID TÖRTÉNETE 5 MI A PHP? .6 2 MILYEN RENDSZEREN HASZNÁLHATÓ? .8 2.11 2.12 3 Milyen operációs rendszer? .8 Milyen WEB szervert? .8 A PHP4 TELEPÍTÉSE (WIN32 VÁLTOZAT) .9 3.1 KÖNYVTÁRAK .9 3.2 TELEPÍTÉS .10 3.21 Apache WEB szerver 1.3xx vagy 20xx 10 3.22 Internet Information Server 4 vagy 5.10 3.23 Personal Web Server 4 vagy újabb (Win98) .11 3.24 Szerver nélküli használat: .11 4 ESZKÖZÖK A PHP HASZNÁLATÁHOZ.12 5 EGY HTML ÉS EGY PHP OLDAL SZERKEZETE .13 6 A PHP SZINTAKTIKÁJA.14 7 VÁLTOZÓK, ADATTÍPUSOK.15 7.1 7.2 7.3 7.4 7.41 7.42 7.43 7.5 8 ALAPVETŐ UTASÍTÁSOK .19 8.1 8.2 8.3 9 STRINGEK KÖZÖTTI MŰVELETEK.22 ARITMETIKAI MŰVELETEK .22 HOZZÁRENDELÉS, ÉRTÉKADÁS .22 NÖVELŐ/CSÖKKENTŐ OPERÁTOROK.22 LOGIKAI OPERÁTOROK .23 ÖSSZEHASONLÍTÓ OPERÁTOROK .23 BITORIENTÁLT OPERÁTOROK.23

HIBAKEZELŐ OPERÁTOROK .24 VÉGREHAJTÓ OPERÁTOROK .24 GYAKORLÓ FELADATOK.24 VEZÉRLÉSI SZERKEZETEK .25 10.1 10.2 10.3 10.4 10.5 10.6 11 ECHO .19 FORMÁZOTT KIÍRÁS .20 A KIIRATÁS GYAKORLÁSA .21 OPERÁTOROK (MŰVELETEK).22 9.1 9.2 9.3 9.4 9.5 9.6 9.7 9.8 9.9 9.10 10 A VÁLTOZÓ NEVE .15 A VÁLTOZÓ ÉRTÉKE .15 A VÁLTOZÓK ÉS KIFEJEZÉSEK TÍPUSAI .15 ELŐRE DEFINIÁLT VÁLTOZÓK .17 PHP Core – A PHP rendszer alapvető változóinak a listája.17 Environment .17 PHP Variables - A PHP változók listája.17 KONSTANSOK .18 ELÁGAZÁSOK .25 CIKLUSOK .27 ELÁGAZÁSOK ÉS CIKLUSOK HASZNÁLATA HTML KÓDDAL KEVERVE .29 PHP LAPOK BESZÚRÁSA, ”MAKRO”-K HASZNÁLATA. 30 TÁVOLI FILE-OK HÍVÁSA .31 PÉLDAPROGRAMOK FELTÉTELEKKEL, CIKLUSOKKAL .31 SAJÁT FÜGGVÉNYEK, VÁLTOZÓK ÉLETTARTAMA ÉS LÁTHATÓSÁGA.32 11.1 11.2 11.3 FÜGGVÉNYEK .32 PARAMÉTERÁTADÁS .32 FÜGGVÉNYEK VISSZATÉRÉSI ÉRTÉKE .34 2 11.4 VÁLTOZÓK ÉLETTARTALMA ÉS LÁTHATÓSÁGA .34 11.5

VÁLTOZÓK ÁTADÁSA LAPOK KÖZÖTT .36 11.51 Header utasítás.36 11.52 GET metódus .36 11.53 POST metódus .37 11.54 $ SESSION változók .40 Egy session kezelő működése - példa.45 11.55 COOKIE-k (sütik) .48 12 KONVERZIÓ ADATTÍPUSOK KÖZÖTT.50 13 TÖMBÖK.51 14 SZTRINGEK, SZÖVEGEK MANIPULÁCIÓJA.55 15 FORMOK /ŰRLAPOK – INTERAKTÍV PROGRAMOK ÍRÁSA .59 15.11 Önmagukat meghívó űrlapok.59 16 FORMOK ADATAINAK FELDOLGOZÁSA – SZERVER- ÉS KLIENS OLDALON.61 17 LEVÉLKÜLDÉS, PLAIN TEXT, HTML LEVÉL, ATTACHEMENT.63 18 ADATBÁZISOK .65 18.1 MYSQL .66 18.2 POSTGRES SQL .66 18.3 ADATBÁZIS-KEZELÉS NATÍV MÓDON .68 18.4 TIPIKUS FELADATOK ADATBÁZIS-KEZELÉSNÉL .70 18.5 HIBAKEZELÉS .73 18.6 ADATBÁZISKEZELÉS MÁSKÉPPEN – ABSZTRAKCIÓS RÉTEGEK, ADODB, ODBC .73 18.61 Az absztrakciós réteg.73 18.62 ODBC programcsomag.73 18.63 Az ADODB rétegezés .74 Example 3: Inserting .79 Example 4: Debugging .79 Example 5: MySQL and Menus.80 Example 6: Connecting

to 2 Databases At Once.80 Example 7: Generating Update and Insert SQL .80 Example 8: Implementing Scrolling with Next and Previous.82 Example 9: Exporting in CSV or Tab-Delimited Format.83 Example 10: Recordset Filters.83 Example 11: Smart Transactions .83 18.7 USING CUSTOM ERROR HANDLERS AND PEAR ERROR.85 18.8 DATA SOURCE NAMES .87 18.9 CACHING OF RECORDSETS .87 18.10 PIVOT TABLES .87 19 CLASS REFERENCE.91 19.1 GLOBAL VARIABLES.91 $ADODB COUNTRECS.91 $ADODB CACHE DIR.91 $ADODB FETCH MODE.91 19.2 ADOCONNECTION .93 ADOConnection Fields.93 ADOConnection Main Functions.94 ADOConnection Utility Functions .105 19.3 ADORECORDSET .107 ADORecordSet Fields .107 ADORecordSet Functions.107 function rs2html($adorecordset,[$tableheader attributes], [$col titles]).112 Differences between this ADOdb library and Microsoft ADO.113 20 20.1 20.2 DATABASE DRIVER GUIDE.114 IDŐ KEZELÉSE PHP – MYSQL ESETÉN .115 SOKÁIG FUTÓ PROGRAMOK .116 3 21 FILE-OK, KÖNYVTÁRAK KEZELÉSE A SZERVEREN ÉS

TÁVOLI URL-EKEN .117 LÁTOGATÓK SZÁMA:<BR> <?PHP .120 22 GRAFIKA .122 23 A KÖRNYEZET FELDOLGOZÁSA, AZONOSÍTÁS .131 24 BELÉPTETÉS, JELSZAVAK ALKALMAZÁSA, TITKOSÍTÁS.132 24.1 TITKOSÍTOTT ÁTVITELE A KLIENS ÉS A SZERVER KÖZÖTT: MD5().136 25 BIZTONSÁG, TIPPEK ÉS TRÜKKÖK .143 26 A PHP.INI FILE PARAMÉTEREZÉSE145 SABLONOK – TEMPLATE-EK, LIB-EK.148 26.1 26.2 27 TEMPLATE-EK, SMARTY .148 PEAR CSOMAG .148 PHP CACHE PROGRAMOK .149 4 1 Bevezetés Mire jó ez a jegyzet? A jegyzetnek az a célja, hogy bevezesse az olvasót a ma robbanásszerűen terjedő PHP nyelv világába, megtanítsa az alapvető eljárásokat, fogalmakat és képessé tegye az olvasót saját PHP scriptek írására. Használjuk továbbá a Szily Kálmán Műszaki Középiskola ötödéves számítástechnikai programozó szakán is. Nem teljes PHP dokumentáció! Nem is lehet az, hiszen mialatt a jegyzetet megírtam legalább két új verzió jelent meg a PHP-ből és

folyamatosan bővül a PHP-ben használható szolgáltatások köre. Igyekeztem arra koncentrálni, hogy egy kezdő viszonylag gyorsan elsajátíthassa a nyelv alapjait, gyorsan tudjon hatásos programokat írni, és ha valamilyen gyakran előforduló probléma megoldására keres választ, akkor azt viszonylag hamar meg tudja oldani. Teljes dokumentációt az Internetről lehet beszerezni, részben magyar nyelven az alábbi címekről, http://www.phpnet dokumentáció angolul vagy a http://hu.phpnet/docsphp oldal magyarul A php 423 verziójától próbálkozva írom ezt a jegyzetet A jegyzetben található példaprogramokat, ötleteket, részben az alábbi forrásokból szemezgettem és ezúton köszönetet mondok nekik : http://hu.phpnet A PHP site magyar oldalai php-lista@Gimli.externethu Magyar PHP lista http://php4.x3hu, Korsós István (KI), kefa@maildatanethu PHP-s cikksorozata a PC-World-ből, resource-ok PHP és egyéb témákban

http://phpbuilder.com/columns/ying20000602php3?page=1 sessionok, Ying Zhang cikke http://phpmailer.sourceforgenet Emailküldés http://php.weblogscom/ADODB ADODB – adatbáziskezelés Molnár László A Postgres SQL telepítése Smarty felhasználói kézikönyv http://Smarty.phpnet Smarty template rendszer És a diákjaim is. 1. 2 A PHP rövid története A PHP története 1994 őszére nyúlik vissza, amikor a munkát kereső Rasmus Lerdorf egy Perl CGI szkriptet használt a Web odalát felkeresők regisztrálására. A látogatókat naplózó kódot "PHP-tools for Personal Home Page"-nek nevezte el. Az első nyilvános változat úgy 1995 táján látott napvilágot Ez még csak néhány egyszerűbb feladatra volt használható, többek között számlálót, vendégkönyvet tartalmazott. A PHP fejlesztése a Torontói Egyetemen folytatódott, ahol Rasmus Lerdorf olyan interfészt fejlesztett ki, aminek segítségével a HTML kódba ágyazott speciális utasítások

közvetlenül érték el az egyetemi adatbázisokat. A rendszert Rasmus "Form Interpreter"-nek, FI-nek nevezte el Az FI-ben használt elv már megegyezett a PHP alapelvével, miszerint a HTML kódba beágyazott utasításokat értelmezte és 5 hajtotta végre az FI értelmezője. Később a PHP és az FI összeházasításából született meg az első széles körben használt parancsértelmező a PHP/FI. Ez tartalmazta a PHP és az FI addigi szolgáltatásait, sőt az mSQL adatbázisok elérését is támogatta. Rasmus eleinte eljátszadozott a gondolattal, hogy a PHP-t kereskedelmi termékké teszi, de olyan komoly mennyiségű visszajelzést kapott más programozóktól, különböző kiegészítéseket és hibajavításokat küldve a PHP-hez, hogy letett ebbéli szándékáról. A PHP fejlődéséhez és sokrétűségéhez nagymértékben hozzájárult külső programozók szabad és ingyenes részvétele a rendszer fejlesztésében. A PHP a mai napig is ingyenes

termék, és ez valóban nagyon jó dolog. Az első verzió megjelenésétől kezdve a PHP felhasználói tábora töretlenül növekedett. 1996-ban közel 15.000 Web oldalon használták a PHP/FI-t, 1997-ben már több mint 50000 Web oldalon Ebben az évben kezdődött el a PHP sokkal jobban szervezett továbbfejlesztése. A PHP/FI-t értelmezőjét szinte az alapoktól kezdve újraírták, átemelve a PHP/FI-ben alkalmazott technikákat és kódot, de számos újat is hozzátéve. Így alakult ki a PHP 3-as változata, ami gyakorlatilag rendelkezett mindazokkal a képességekkel, amik a PHP népszerűségét megalapozták. A PHP fejlődése azonban nem áll meg Jelenleg a 4.06 változatnál tart a fejlesztés, de köszönhetően a "szabad szoftver" filozófiának nem valószínű, hogy itt megreked. A magyar PHP lista az elmúlt évben indult, napi 2-3 levéllel, egy év alatt napi 30-50 levélre duzzadt a forgalma. Mi a PHP? Egy programozási nyelv. A PHP majdnem

általános célú programozási nyelv, amely mára sokféle területen alkalmazható, amit a Weben keresztül meg lehet oldani. Dinamikus oldalak, adatbázis-kezelés, akár ügyviteli alkalmazások, levelezés, portálok, grafikai alkalmazások, file-kezelés, távoli adminisztráció, stb. Mielőtt a PHP működését részleteznénk, meg kell ismerkedni egy kicsit a Web-en lévő alkalmazások lelkivilágával. Amikor a böngészőben beírjuk egy olyan oldal nevét, és letöltjük azt, akkor az Interneten lévő WEB szerver küldi el a böngészőnknek a kívánt oldalt. Ez az oldal egy HTML oldal, egy ASCII szöveg állomány, amely megérkezve a böngészőnkre azt a böngésző értelmezi, és a tartalmát megjeleníti. Az ilyen oldalakat statikus oldalaknak hívjuk, mivel a következő és az utána következő kérésekkor mindig pontosan ugyanazt az oldalt fogjuk újra meg újra megkapni, hiszen a szerveren ez egy file. Abban az esetben, ha azt szeretnénk, hogy az oldal

tartalma változzon, azaz dinamikus oldalt szeretnénk, valamilyen módon az oldalt a szerveren létre kell hozni, módosítani kell. Ennek érdekében ki kell egészíteni a WEB-szervert olyan alkalmazásokkal, amelyek az oldal kérésekor futáskor állítják elő az oldalt, majd odaadják a szervernek, amely az eredményt továbbítja a böngésző felé. Ezeket a programokat összefoglaló néven CGI programoknak hívjuk, ami a Common Gateway Interface kifejezés rövidítése. Ezek a programok tehát új funkcionalitással bővítik ki a WEB szervereket A legfontosabb ebben az, hogy ez által a böngészők interaktív módon tudnak kapcsolatot teremteni a WEB szerverrel, adatokat tudnak bevinni neki, a bevitt információ alapján változik a visszaadott érték. Az ilyen rendszer működése olyan, hogy a böngészőben beírt információt megkapja a WEB szerver, átadja a CGI programnak, ami az információ birtokában feldolgozza és visszaküldi a WEB szervernek, amely

továbbítja a böngésző felé HTML kód formájában. A CGI programok vagy a szerver operációs rendszerén futni képes programok, amelyeket valamilyen nyelven, pl. C-ben írtak meg és fordítottak le, vagy úgynevezett scriptek, amelyek egy értelmező program közreműködésével futnak. A PHP programokat egy ilyen értelmező futtatja a szerveren akkor, ha a böngésző PHP, PHP3, PHP4, vagy hasonló kiterjesztésű file-okra hivatkozik. Ekkor a WEB szerver meghívja a PHP értelmező programot (interpretert), amely értelmezi a kérdéses oldalt, majd az eredményt Web oldal formájában visszaadja a WEB szervernek, amely továbbítja a böngészőnek. 6 Tehát a PHP program egy WEB szerveren futó script, amelynek az eredménye egy WEB böngészőn keresztül jelenik meg. Ha valaki már találkozott HTML oldalakon Javascriptekkel, vagy Vbscriptekkel, akkor lehet fogalma arról, hogy miről is van szó, ugyanakkor lényeges különbség van a kétféle megoldás

között. Míg a Javascriptek és a Vbscriptek a böngészőn hajtódnak végre, addig a PHP scriptek a szerveren. Ennek több előnye van, például sokkal bonyolultabbak lehetnek, el lehet rejteni a tartalmukat a kíváncsi tekintetek elől, nincsenek a böngésző képességeihez kötve. A PHP script a böngészőn soha nem jelenik meg (ha megjelenik, akkor baj J), csak az a HTML vagy egyéb kód, amelyet előállít. A böngésző kérése nyomán a PHP értelmező megkapja az oldal helyét, nevét és az esetleges bemenő paramétereket valami.php ⇒ Böngésző valami.php WEB szerver ⇒ PHP értelmező A kívánt oldalt betölti az értelmező, feldolgozza, és az eredményt visszaküldi HTML kód Böngésző ⇐ HTML kód WEB szerver ⇐ PHP értelmező ⇐ valami.php A PHP értelmező a fejlődése során egyszerű script futtató programocskából komoly fejlesztőeszköz lett. 7 2 Milyen rendszeren használható? 2.11 Milyen operációs rendszer?

Gyakorlatilag létezik az összes elterjedt operációs rendszeren, Win32, Linux, Solaris, BSD, hogy csak a legismertebbeket írják le. Ezeken a rendszereken futó sok-sok WEB szerver segítségével lehet futtatni Gondolva a tanulásra és az általában meglévő számítástechnikai környezetre a Windows 98, ME, NT, W2000 operációs rendszert ajánljuk. Magyarázat: Miért nem LINUX? Azok részére, akik most tanulják a nyelvet nem célszerű olyan rendszert használni, amelynek nem ismerik eléggé a tulajdonságait. Az oktatásban elsősorban Windowsos rendszereket használnak. 2.12 Milyen WEB szervert? A PHP telepítése előtt mindenképpen szükségünk lesz egy működő WEB szerverre. Nyilván most nem az a feladatunk, hogy egy WEB szerver telepítését bemutassuk, de ha a Windows NT-t használjuk és a Service Pack 5-öt feltelepítettük, akkor lesz IIS4-ünk. A Windows 2000 alatt eleve a rendszer része, Win9x alatt pedig a Personal WEB Servert használhatjuk

alapértelmezetten. Ennek ellenére mi az Apache WEB szervert ajánljuk, annak egyszerű telepítése, egyszerű beállítása miatt. Megjegyezzük, hogy az Apache beállítása majdnem ugyanaz LINUX alatt és Win32 alatt is, tehát ennek a rendszernek a használatakor nagyon kis különbségek kellenek a LINUX-os verzióra való átálláshoz. A későbbiek során bemutatunk egy olyan összeállítást is, amellyel egyszerűbb PHP programokat tudunk futtatni WEB szerver nélkül is, Win9x, ME, NT, W2000, XP rendszeren! Én Windows 2000 és Apache 1.3xx valamint Windows XP és Apache 20xx rendszerrel is használom Hol találok szolgáltatót, aki futtat PHP scripteket, esetleg adatbázist? Az utóbbi időben többen is vállalkoznak erre a szolgáltatásra. Jelenleg tudomásom szerint a következő szolgáltatók hajlandók futtatni ingyen php-t: http://www.f2scom ingyen PHP, MySQL, PostGres SQL http://www.swihu pénzes szolgáltató 8 3 A PHP4 telepítése (Win32 változat) A

PHP telepítése operációs rendszerenként és WEB szerverenként más és más. A telepítésről további információ a http://hu.phpnet és a http://wwwphp4winde oldalakon található A PHP csomagot letöltve kapunk egy tömörített állományt, amelyet kibontva az alábbi könyvtárstruktúrát kapjuk. 3.1 Könyvtárak browscap: A browscap.ini file-t tartalmazza Ez a file az egyes böngészőtípusok adatait, tulajdonságait tartalmazza. dlls: Itt olyan dll-ek vannak, amelyekre a php-nek és néhány kiterjesztésnek van szüksége. Ezeket másold be a windows/system (Win9.x) vagy a winnt/system32 (Windows NT, Win2000) könyvtárba. Ha ezek léteznek már az adott helyen, csak akkor írd felül a régieket, ha a rendszer nem működik. extensions: A php kiterjesztéseit tartalmazó könyvtár. keys: Az mcrypt-hez kulcsok. Az mcrypt még nem működik licenses: Több licence-et tartalmaz. mibs: Az SNMP használata esetén szükséges. pdf-related:Az itt lévő fontok a PDF

kiterjesztés használatához kellenek. Olvasd el az ezzel kapcsolatos licence-t. pear: The pear archive captured at the build date. readme: Readme file-ok különböző témákban sapi: Natív server api-kat tartalmaz. Az ajánlott a CGI verzió Ezen kívül választhatod még ezeket: - php4-module a win32 Apache szerver sapi-ja, - ISAPI - az IIS4/5 sapi-ja, - NAPI - a netscape enterprise server és a php4 servlet verziója tests: A PHP működésének teszteléséhez használható program van itt. A PHP értelmező általában a C:PHPPHP.EXE program, amelynek manapság Windows NT/W2000/XP környezetben a WINNTSYSTEM32PHPPHP.EXE helyet ajánlják, de én nem ide teszem Szerintem az utólagos frissítések miatt célszerű valamelyik meghajtó gyökeréből nyíló könyvtárba tenni, például C:PHP. A PHP konfigurálásához szükség van egy PHP.INI nevű file-ra, amelynek a Windows könyvtárba kell kerülnie. Ennek a file-nak a mintája phpini-dist néven a PHP

könyvtárban található telepítéskor A megfelelő sorokat átírva van egy működő konfigurációnk. A későbbiek során megnézzük, hogy milyen változtatások szükségesek a PHP.INI-ben, a gyorsabb működés érdekében. 9 3.2 Telepítés Mindenekelőtt csomagold ki a PHP-t a C:PHP könyvtárba, majd másold a php4ts.dll-t a C:WINDOWSSYSTEM vagy a C:WINNTSYSTEM32 könyvtárba! Másold a php.ini-dist file-t a rendszer gyökérkönyvtárba, ahol a Windows van, majd nevezd át PHPINIre Szerkeszd át a PHPINI-t, szükség szerint (a későbbiekben bemutatjuk, hogy mit érdemes átszerkeszteni). 3.21 Apache WEB szerver 1.3xx vagy 20xx 1. Telepítsd az Apache szervert Ez a telepítőt tartalmazó MSI file vagy az EXE kiterjesztésű file esetén az önkicsomagoló file futtatását jelenti. 2. Állítsd le az Apache Webszervert 3. Az Apache szerver konfigurációs állománya például az C:Apacheconfhttpdconf file Szerkeszd meg ezt a file-t, az alábbi módon: Apache

modul esetén: # Apache modul esetén LoadModule php4 module c:/php/sapi/php4apache.dll AddType application/x-httpd-php .php4 Másold be a Winntsystem32 vagy a windowssystem könyvtárba a php4ts.dll file-t CGI modul esetén: #for the cgi bináris esetben ScriptAlias /php4/ "C:/php/" Action application/x-httpd-php4 "/php4/php.exe" AddType application/x-httpd-php4 .php Sajnos jelenleg az Apache modul nem fut a 2.0xx-es verzióban 4. Keresd meg a DirectoryIndex parancsot a konfigurációs állományban és egészítsd ki az alábbi módon DirectoryIndex index.html indexphp indexphp3 indexphp4 5. Indítsd újra az Apache szervert, 6. Írd meg a kedvenc ASCII editorod segítségével az alábbi tartalmú scriptet, mentsd el a szervered gyökérkönyvtárába, majd hívd meg a böngészőben az alábbi módon: <?php echo phpinfo(); ?> 7. Próbáld ki az alábbi programocskát a Böngésződdel a szervered root könyvtárából: http://localhost/proba.php Ennek

hatására lefut a script és kiírja a böngésződbe az éppen használt php rendszer rengeteg paraméterét. 3.22 Internet Information Server 4 vagy 5 Indítsd el a Microsoft Management Console-t vagy az Internet Services Manager-t, a Control Panelről. Kattints a Webszerverre és válaszd a properties-t. Ha nem akarsz HTTP Authentication-t használni a PHP-vel, akkor átlépheted ezt a lépést. Az ISAPI Filters (ISAPI szűrők) alatt add hozzá az új ISAPI szűrőt. Használd a PHP nevet a szűrő nevének, majd keresd meg az php4isapi.dll-t, a C:PHPsapiphp4isapidll útvonalon 10 A Home Directory alatt, kattints a Configuration (Konfiguráció) gombra. Új bejegyzést kell felvenni, az Application Mapping-be (Alkalmazások Hozzárendelése). Használd a C:phpsapiphp4isapidll-t és állítsd Executable-re (Futtatható), .php legyen a kiterjesztés, Method exclusions-nál állítsd be az engine checkbox-ot. Állítsd le az IIS-t. Indítsd újra. az IIS-t Írd meg a kedvenc

ASCII editorod segítségével az alábbi tartalmú scriptet, mentsd el a szervered gyökérkönyvtárába, majd hívd meg a böngészőben az alábbi módon: <?php phpinfo(); ?> localhost/és próbáld ki az alábbi programocskát a Böngésződdel a szervered root könyvtárából: http://localhost/proba.php Ennek hatására lefut a script és kiírja a böngésződbe az éppen használt php rendszer rengeteg paraméterét. 3.23 Personal Web Server 4 vagy újabb (Win98) Szerkeszd meg a csomagban lévő PWS-php4isapi.reg (ISAPI interface) file-t vagy a PWSphp4cgireg (CGI interface) file-t, hogy arra könyvtárra mutasson, ahol a php4isapidll / phpexe található. Pl [HKEY LOCAL MACHINESYSTEMCurrentControlSetServicesw3svcparametersScriptMap]".php"="C:\PHP php4isapi.dll" A PWS Manager-ben jobb egérrel kattintva, a megfelelő könyvtárhoz add hozzá a PHP support-ot (támogatás), válaszd a Properties-t (Tulajdonságok). Állítsd be az Execute

’végrehajtható’ tulajdonságot. 3.24 Szerver nélküli használat: Bontsd ki a C:PHP könyvtárba a csomagot. Az alábbi batch file-t készítsd el, a megfelelő útvonalakkal C:phpphp.exe %1 >%Temp%phptemphtm C:Progra~1Intern~1iexplore %Temp%phptemp.htm A batch file-t paramétere a php file legyen. A második sorba az általad használt böngésző elérését kell beírni Írd meg a kedvenc ASCII editorod segítségével az alábbi tartalmú scriptet, mentsd el a szervered gyökérkönyvtárába, majd hívd meg a böngészőben az alábbi módon: <?php phpinfo(); ?> Hívd meg a megírt batch file-t az alábbi módon: Test.bat probaphp Ennek hatására lefut a script és kiírja a böngésződbe az éppen használt php rendszer rengeteg paraméterét. A CGI verzió stabilabb a Windows rendszerekben, az ISAPI verziók alkalmanként összedönthetik a rendszert. 11 4 Eszközök a PHP használatához Felmerül a kérdés, hogy mi kellhet a PHP használatához a

fentieken kívül. A várakozással ellentétben nem sok, de azért itt összefoglalom a lehetőségeket: Kell egy ASCII szövegszerkesztő, kezdetben jó a NOTEPAD.EXE a Windowsból is Ha ennél komolyabbra vágysz, akkor válaszd mondjuk az EditPlus nevű editort, amely a http://www.editpluscom címről tölthető le. Számozza az oldalakat, és még a szintaktikát is színezi Ezen kívül sok más hasonló editor van forgalomban. A nagyok közül tudnám ajánlani a Macromedia Dreamweaver Ultradev 4 vagy a Dreamweaver MX csomagot is. Nem árt, ha van egy jó HTML editorod, mert a php oldalak jelentős részben azért HTML kódból is állnak. A freeware vagy shareware programok között jelentős választék van, pl CoffeCup Kell egy böngésző, ami adott az újabb Windows-okban Internet Explorer 4/5/6. Használhatod a Netscape Navigator-t (www.netscapecom), illetve az Opera legújabb változatát is Talán ez utolsó a legkisebb és leggyorsabb. Az opera letölthető a

wwwoperacom -ról Szükséged lesz egy jó Help-re. Én a http://huphpnet/docsphp oldaláról a CHM (Windows-os Help file) változatot javaslom, de használhatod a HTML verziókat is, és ha gyors Internet kapcsolatod van, akkor a Internetről is lehet online módon használni őket. Nem árt, ha a HTTP-ről is van egy jó Help-ed. A http://wwwhtmlhelpcom/ -ról letölthető többféle formában, köztük Windows-os Help formájában a HTML nyelv szintaktikája. Nem ide tartozik, de gyakori, hogy a php scripteket vegyítjük Javascriptekkel is. Erre a célra több forrás létezik, de sajnos magyar nyelven és Windows-os Help formájában nem tudok róla: Talán célszerű a következőt Web oldalt használni http://weblabor.hu/leiras/javascr/ vagy megnézni az alábbi oldalt: http://www.szilysulinethu/jegyzetek Letölthető állapotú változat az ftp://ftp.szilysulinethu/jegyzetek/Javascript/ könyvtárban található Szükség lehet egy jó HTML/ Javascript könyvre, például Bócz

Péter – Szász Péter: A világháló lehetőségei 12 5 Egy HTML és egy PHP oldal szerkezete Mielőtt továbbmennénk nézzük, mit akarunk programozni? Hogyan is néz ki egy HTML oldal: <HTML> <head> <TITLE>Proba web oldal</TITLE> </head> <BODY> <P> Hello World!!! </P> </BODY> </HTML> Na ez nagy durranás volt. A bekezdéses írásmódot az áttekinthetőségért használok, de mint látjuk később, ez rendkívül fontos! A böngészők a sor vége jelet, a szóközöket és a tabulátor jeleket kihagyják, ezért akár az egészet egy sorba is írhatnánk. A fenti HTML oldalt az alábbi php scripttel tudjuk előállíttatni: <HTML> <head> <TITLE>Proba web oldal</TITLE> </head> <BODY> <P> <?php echo ”Hello World!!!”; ?> </P> </BODY> </HTML> Tisztán látszik, hogy a program szerkezete nagy vonalakban ugyanaz, de azért vannak különbségek. A

PHP értelmező a kód első sorait változatlanul továbbítja a Web szervernek, de amikor a <?php taghez ér, értelmezi az ott lévő sorokat, és az echo paranccsal kiírja a Web szerver felé az echo utáni szöveget. A következő sorban lévő ?> tag jelzi az értelmezőnek a PHP script végét. Egy oldalon többször is megnyithatjuk a scriptet és bezárhatjuk, azaz keverhetjük a php és a HTML kódot, sőt ha van merszünk, akkor beiktathatunk javascriptes részeket is. Az alábbi lehetőségeink vannak arra, hogy php scriptet helyezzünk el egy oldalon: <?php .php kód ?> <script language=”PHP”> . php kód </script> Ha beírjuk a PHP.INI-ben, a short open tag= on sort, akkor ez a megoldás is lehetséges: <?. php kód ?> Ha beírjuk a PHP.INI-be az asp tags = on sort, akkor használható az alábbi szintaktika is: <% . php kód %> Speciális lehetőség. Ha egy változó értékét szeretnénk csak kiiratni és a short open tag =

on sor be van írva, akkor egy változó értékét így adhatjuk át a web oldalnak legegyszerűbben: <?=$valtozo ?> 13 6 A PHP szintaktikája A PHP nyelv szintaktikája nagyon hasonlít a C nyelvére, ezért sokak számára nem lesz túlságosan idegen. A php scriptben lévő utasítások mindegyike után kötelezően ki kell tenni a ; elválasztójelet Megjegyzés: Bár a dokumentáció azt mondja, hogy egy záró tag előtt nem kell kitenni, azért azt tanácsolom, hogy megszokás céljából mindenhol alkalmazzuk A Megjegyzéseinket szintén C jellegű szintaktikával kétféleképpen tehetjük ki: // Az egysoros kommentek, a sor végéig tarthatnak, mint a C-ben # jellel, mint a Unixos shell programoknál /*.*/ A több soros kommentek <?php echo "Ez egy teszt"; // Ez egy egysoros c++ szerű komment /* Ez egy többsoros komment Még egy sor komment */ echo "Ez egy másik teszt"; echo "Ez az utolsó teszt"; # Ez egy shell-szerű

komment ?> Amint látjuk a fentiek alapján a kiírandó szöveget ”” jelek közé tehetjük, de a jelpáros lehet ’.’ is A továbbiakban nézzük meg, hogy milyen típusú értékekkel dolgozhatunk. 14 7 Változók, adattípusok A PHP-ben használhatunk változókat is. A változó neve előtt mindig $ jel található 7.1 A változó neve A változó neve betűvel vagy aláhúzás jellel kezdődik és bármilyen alfanumerikus karakterrel, illetve 127.255 ASCII kódú karakterrel folytatódhat A kis és nagybetűk különböznek! 7.2 A változó értéke Amikor először adunk értéket egy változónak, akkor jön létre a változó. $a = 5; $todo = ”szöveg”; Ha egy változó értékét azelőtt vizsgáljuk meg, mielőtt értéket adunk neki, az értéke NULL lesz. Egy változó típusát többféleképpen lehet meghatározni. - Értéket adunk neki, az érték alapján létrejött változónak a típusa is egyértelművé válik. Beállítjuk a

típusát a settype (“változónév”, “típus”) paranccsal, ahol a típus az alábbiak közül választható: "integer", "double", "string", "array", "object" - Típuskonverziót alkalmazunk. Az alkalmazható típusok ugyanazok, mint a fenti példában, hozzávéve, hogy az ”integer” lehet ”int” is, a ”double” lehet ”float” és ”real” is. $a = (int) $b $c = (string) $d A változók értékadásakor használhatunk hasonló trükköket, mint a C-ben: $a = $b = 5 A fenti kifejezést úgy kell értelmezni, mintha az alábbiakat írtuk volna le: $b = 5; $a = b; A későbbiekben foglalkozunk részletesen az operátorokkal, amelyek egy változó értékét meghatározzák. A változónak bármilyen módon értéket adtunk, akkor a típusát is meghatároztuk. 7.3 A változók és kifejezések típusai A különböző programozási nyelveken megszokott típusok a PHP-ban is megtalálhatók: Numerikus típusok:

int, integer - egész típus – értéke –32768-32767-ig tart Float, double, real – Lebegőpontos String A C-ben használt string fogalomhoz hasonló, ”.” vagy ’’ jelek közé írt ASCII karaktersorozat. Array Tömb típus. A tömb elemi tetszőlegesen vegyesek lehetnek Egy tömb lehet egy, két és több dimenziós tömb is. A tömb indexelése történhet hagyományosan 0-tól kezdődő indexeléssel, vagy lehet úgynevezett asszociatív tömböt is létrehozni, amikor a tömbindex valamiféle string, vagy egyéb érték. Ebben a példában egy dimenziós tömböt hozunk létre. $array = array (1, "hello", 1, "world", "hello"); 15 Az alábbi példában kétdimenziós asszociatív hozunk létre. $fruits = array ( "fruits" => array ("a"=>"orange", "b"=>"banana", "c"=>"apple"), "numbers" => array (1, 2, 3, 4, 5, 6), "holes" => array

("first", 5 => "second", "third") ); Object - Objektum. A típus hasonlít a C++ objektumaira, de vannak lényeges különbségek is Egy objektum típusú változó létrehozásához először definiálni kell magát az osztályt a class kulcsszóval, hasonlóképpen, mint C++ -ban, majd a definíció után a new() operátorral létre lehet hozni a megfelelő változót. A class részét képezik változók és a classhoz tartozó függvények is A későbbiekben részletesen is szólunk az objektumokról. Az alábbiakban egy példát látunk <?php class Kosar { var $dolgok; // A kosárban levő dolgok function berak ($sorsz, $db) { // berak a kosárba $db darabot az $sorsz indexű dologból $this->dolgok[$sorsz] += $db; } function kivesz ($sorsz, $db) { // kivesz a kosárból $db darabot az $sorsz indexű dologból if ($this->items[$sorsz] > $db) { $this->items[$sorsz] -= $db; return true; } else { return false; } } } $a = new Kosar;

?> boolean – Logikai értékek. Két érték előre definiált, a TRUE és a FALSE null - Olyan változók, amelyeknek nincsen beállított értékük Resource – Erőforrások, mint például file vagy adatbáziskezelő mutatója. Valójában ezek a memória egyes helyére mutató pointerek! Unknown type - Ismeretlen típusok Változók és kifejezések visszatérési értékének típusát le lehet kérdezni az alábbi függvényekkel: int empty ($a) Megadja, hogy a változó üres volt-e vagy nem. string gettype ($a) Visszaadja a változó típusát. A lehetséges típusok az alábbiak: "integer", "double", "string", "array", "object", "unknown type" void settype($var,$type) Beállítja egy változó típusát. A lehetséges típusok ($type) lehet: "integer", "double", "string", "array", "object" int intval($a,[$alap]) Visszaadja a változó értékét

egésszé konvertálva a megadott alapú számrendszerben. Az alap default értéke 10 int is array($a) Megadja, hogy a változó tömb vagy sem int is bool($a) Megadja, hogy a változó logikai típusú vagy sem int is float ($a) int is double ($a) Megadja, hogy a változó lebegőpontos-e, vagy sem. 16 int is real ($a) int is long ($a) int is integer ($a) int is int ($a) Megadja, hogy a változó egész vagy sem. int is numeric ($a) Megadja, hogy a változó numerikus, numerikus szöveg vagy sem. int is object ($a) Megadja, hogy a változó objektum vagy sem int is resource ($a) Megadja, hogy a változó erőforrás azonosító vagy sem (pl. file handler) int is string ($a) Megadja, hogy a változó string vagy sem. int isset (változó) Megadja, hogy be van-e állítva a változó. A visszatérési értéke hamis, ha nem és Igaz, ha van értéke a változónak void print r(kifejezés) Ember számára olvasható információt ad egy változóról. <?php $a

= array (1, 2, array ("a", "b", "c")); print r ($a); ?> 7.4 Előre definiált változók A változók között vannak olyanok, amelyek a rendszerben előre definiáltak. Ezeknek a változóknak a nevét és pillanatnyi értékét a phpinfo() függvény segítségével lehet kiíratni. A változókra hivatkozva természetesen az értékeket fel tudjuk használni, és azt tudjuk manipulálni. Ezen változóknak az értékét a PHP.INI file-ban lehet beállítani, néhány érték a használt WEB szervertől függ, további értékek pedig a futtató operációs rendszertől függnek. A változók másik nagy csoportjai a rendszerben alkalmazott modulok értékei. Néhány fontosabb változó csoport 7.41 PHP Core – A PHP rendszer alapvető változóinak a listája A rendszer beállításait, és alapértelmezett paramétereit tartalmazó változólista. 7.42 Environment Az operációs rendszerről, a környezeti beállításokról, a WEB

szerverről, a böngészőről, az aktuálisan meghívott lapról és a kliensről minden lényeges adatot felsorol, beleértve az IP címeket is. 7.43 PHP Variables - A PHP változók listája További gyakran használt változók tömbjei a szerver által szolgáltatott tömb és a $ SERVER[”PATH”] A környezeti változók $HTTP ENV VARS vagy $ ENV[”valtnev”] Formok kezelésénél használható változók listája a GET metódussal elküldött változók listája és értékei $ GET[”valtnev”] Post metódussal elküldött változók listája és értékei $ POST[”valtnev”] 17 Sessionokben használt változók listája és értékei $ SESSION[”valtnev”] $GLOBALS[”valtnev ”] a szuperglobális változók. Bárhol elérhetők az értékei $ COOKIE[”valtnev”] A PHP 4.10-tól ez a szuperglobális tömb is létezik A HTTP protokollban definiált további változók. Ezek közül a változók közül néhány megtalálható a környezeti változók

között is. A szerver IP címe Echo $REMOTE ADDR a szerver neve $REMOTE HOST a lekért oldal azonosítója $HTTP REFERER a szerverhez kapcsolódó böngésző fajtája, az operációs rendszer fajtája $HTTP USER AGENT a WEB oldalnak átadott paramétersztring (a.php?A=proba) $QUERY STRING Az aktuálisan futtatott PHP oldal azonosítója: $ SERVER["PATH TRANSLATED"] A szerveren lévő WEB szerver gyökérkönyvtára $ SERVER["DOCUMENT ROOT"] Az alábbiakban egy példát mutatok be a fenti változók használatából: A pár sort beszúrva egy script elejére előűllítja konstans formában az aktuálisan futó script elérési útvonalát, továbbá a WEB szerver dokumentumainak elérési útvonalát. $path=dirname($ SERVER["PATH TRANSLATED"]); DEFINE("PATH",$path); DEFINE("DOCROOT", $ SERVER["DOCUMENT ROOT"]); 7.5 Konstansok A PHP-ben vannak előre definiált konstansok, továbbá mi is definiálhatunk a

define(nev, érték) parancs segítségével. Az előre definiált konstansok közül néhány: FILE az éppen futtatott file neve LINE az éppen futó programsor PHP VERSION a futtatott rendszer verziószáma PHP OS a futtató operációs rendszer TRUE, FALSE logikai értékek 18 8 Alapvető utasítások Aki a Pascal nyelven nevelkedett megszokta, hogy a definiciós és a végrehajtható utasításoknak kötött sorrendje van. A C nyelv és többek között a PHP tartalmaz előírásokat az utasítások sorrendjére, de azok nem annyira kötöttek, ezért aztán nagyon könnyű áttekinthetetlen és rosszul működő programot írni bennük. Ahhoz, hogy gyorsan tudjunk egy programot írni, ismertetünk néhány utasítást 8.1 Echo A PHP egyik leggyakrabban használt utasítása az echo. Segítségével a böngészőbe ki lehet írni a program futásának eredményét. A kiíratás során gondolnunk kell arra, hogy az eredmény egy HTML kód mindig, amit majd a

böngésző tovább értelmez. Az egymás után ír echo parancsok az eredményt egymás után írják ki a kimenetre, pozicionálás, visszalépés a szövegben nem lehetséges. Ha a kiírás után új sorban szeretnénk kezdeni a kiírást, akkor a HTML szerint egy <BR> tag-et (soremelés) vagy kell kiírni. Az alábbiakban több soros kiírást alkalmazunk: <?PHP echo ”Szevasz tavasz<BR>”; echo ”Mit sütsz kis szücs?<BR>”; ?> A numerikus eredmények kiírására is használhatjuk ezt az utasítást, azonban formátumozni nem tudjuk a kimenetet így. <?PHP $a = $b = echo echo ?> 5; 6; $a + $b; ”Mit sütsz kis szücs?<BR>”; További probléma, hogy mi van akkor, ha numerikus információt és string-et akarunk egy szövegben kiírni. A feladat megoldáshoz ugyanazt kell használnunk, mint amikor két string-et akarunk összefűzve kiírni. <?PHP $a = 5; $b = 6; echo ”Az eredmény: ”.$a + $b; $sz = ”Tán sós húst sütsz kis

szűcs?”; echo ”Mit sütsz kis szücs?”.$sz”<BR>”; ?> A fenti példában az echo parancs az összeadás műveletét string-gé konvertálta és így íratta ki. A konverzió teljesen automatikus. További érdekes lehetőség, amikor egy string-ben szeretnénk kiíratni egy változó értékét: <?php $o = 5 + 6; Echo ”Az eredmény: $o<BR>”; ?> Amint látjuk, a korábbi megfontolások alapján a soremelést a HTML szerint kell használnunk. Az alábbiakban néhány gyakran használt tag-et írunk le. A használható tag-ek tárát egy HTML kódolással foglalkozó könyvből, jegyzetből vagy Internet helyről meg lehet tudni. A képernyőn való soremelésre a <BR> tag szolgál. Vízszintes vonal írására <HR> Paragrafus eleje, vége: <P> .</P> Vastag betű <B> .</B> 19 Dőlt betű <I> .</I> Táblázat létrehozásáraLaz alábbi példa egy soros, két oszlopos táblázatot hoz létre)

<table> <tr> <td> <td> </tr> </table> <P> első oszlop</p> </td> <P> masodik oszlop</p> </td> Stb. Mivel a fenti TAG-ek sztringek, ezért célszerűen az echo paranccsal kell kiiratnunk őket. Az echo egy nyelvi elem és nem függvény, azaz valami olyasmi, mintha C-ben egy függvénymakrót hoznánk létre. Éppen ezért bonyolultabb kifejezések kiiratásához alkalmatlan! Ha az adatokat formázottan szeretnénk kiírni, akkor a printf parancsot kell használni 8.2 print() Formázott kiírás – Ugyanaz, mint az Echo, csak a szintaktika kissé más. printf() – kiiratás formázottan sprintf() – formázott sztringet ad vissza az alábbi szintaktika szerint: string sprintf (string formátum [, mixed paraméterek.]) A fromátum szerint megadott karaktersorozattal tér vissza. A formátumkarakterek lényegében a C-ben megszokott formátumkarakterek. A formátumstring több direktívát tartalmazhat. A

% string vezeti be a direktívákat, majd utána következnek a formázó karakterek. Ezeken kívül minden karakter megjelenik a kimeneten A kimenet konverziós parancsait a printf() és az sprintf() parancsban ugyanúgy lehet használni. A konverziós parancssorozat az alábbi parancsokat tartalmazza: Opcionális kitöltő karakter. Ezzel lehet a stringet megfelelő méretre kitölteni Default értéke a szóköz Ezen kívül lehet a 0, vagy egyéb karakter. Igazítás karakter. Az eredmény balra vagy jobbra igazított lesz A default a jobbraigazítás; a – karakter igazítja balra. Szélesség meghatározó. Megmondja, hogy minimum hány karakter legyen az eredményben A tizedes jegyek száma. Csak a double formátum esetén hatásos (A számformátumokat number format() függvénnyel tudjuk még jól kezelni.) A típusmeghatározó megmondja, hogy milyen típusú adatokat kell kezelnie. Lehetőségek: % - a % jel. b – az argmentum integer, és bináris számként jelenítjük

meg c – az argumentum integer, ASCII kódként jelenítjük meg. d – az argumentum integer, decimális számként jelenítjük meg. f - the argumentum double és lebegőpontos számként jelenítjük meg. o - az argumentum integer, és oktális számként jelenítjük meg. s – az argumentum string és így is jelenítjük meg. 20 x - az argumentum integer és hexadecimális számként jelenítjük meg (kisbetűvel) X - az argumentum integer és hexadecimális számként jelenítjük meg (nagybetűvel) $isodate = sprintf ("%04d-%02d-%02d", $ev, $ho, $nap); $money1 = 68.75; $money2 = 54.35; $money = $money1 + $money2; // Az echo $money kimenete "123.1" lesz $formatted = sprintf ("%01.2f", $money); // Az echo $formatted kimenete "12310" echo $money; echo $formatted; 8.3 A kiiratás gyakorlása 1. Írasd ki PHP programmal egy általad ismert tetszőleges vers első négy sorát, soronként! 2. Írasd ki egy tetszőleges dalszöveget

egy táblázatba, versszakonként egy- egy oszlopba! 3. Írasd ki egymás után a 1-től 20-ig a négyzetszámokat jobbra igazítval! 21 9 Operátorok (műveletek) A következőkben megismerjük, hogy milyen műveleteket végezhetünk a különböző adattípusokkal. 9.1 Stringek közötti műveletek Stringek összefűzése: . $a = ”alma”.”körte” ; echo $a; //eredménye ”almakörte” lesz Stringek hozzáadása meglévő sztringhez: .= $a = ”meleg”; $a .= ”víz”; $echo $a; // eredmény: melegvíz 9.2 Aritmetikai műveletek A numerikus értékek összeadására ugyanolyan operátorokat használunk, mint más nyelvekben. echo echo echo echo echo 9.3 $a $a $a $a $a + * / % $b; $b; $b; $b; $b; //$a és $b összege //$a és $b különbsége //$a és $b szorzata //$a és $b hányadosa (egész, ha $a és $b egészek és a hányados egész) //Modulus $a / $b maradéka Hozzárendelés, értékadás Az operátor az "=". Ez ugyanazt jelenti, mint

Pascalban a := vagy C-ben az = A bal oldal értéke legyen az, ami a jobb oldalé. A hozzárendelő kifejezésnek az értéke a bal oldalhoz rendelt érték $a = ($b = 4) + 5; // $a most 9, és $b 4 9.4 Növelő/csökkentő operátorok A PHP támogatja a C-ben megismert inkrementáló és dekrementáló operátorokat. Az alábbiakban megismerjük azokat, majd példát látunk rájuk: Amikor az operátor a változó előtt van, akkor a kiértékelés során először növekszik a változó értéke, majd értékeli ki a rendszer, míg a változó mögötti operátor esetén először kiértékeli a változót a rendszer, majd növeli vagy csökkenti az értékét! <?php $a = 33; echo ++$a; echo $a++; echo --$a; echo $a--; ?> // // // // Növeli $a-t eggyel, majd visszaadja $a értékét Visszaadja $a értékét, majd növeli $a-t eggyel Csökkenti $a-t eggyel, majd visszaadja $a értékét Visszaadja $a értékét, majd csökkenti $a-t eggyel Itt egy másik példaprogram:

<?php echo "<h3>Postinkrementálás</h3>"; $a = 5; echo "5-nek kell lennie: " . $a++ "<br> "; echo "6-nak kell lennie: " . $a "<br> "; echo $a = echo echo "<h3>Preinkrementálás</h3>"; 5; "6-nak kell lennie: " . ++$a "<br> "; "6-nak kell lennie: " . $a "<br> "; echo $a = echo echo "<h3>Postdekrementálás</h3>"; 5; "5-nek kell lennie: " . $a-- "<br> "; "4-nek kell lennie: " . $a "<br> "; 22 echo $a = echo echo ?> 9.5 "<h3>Predekrementálás</h3>"; 5; "4-nek kell lennie: " . --$a "<br> "; "4-nek kell lennie: " . $a "<br> "; Logikai operátorok A logikai műveletek minden programozási nyelvben hasonlóan néznek ki. Az alábbi lehetőségek vannak. A PHP-ben az igaz

értéket mindig az 1 és a hamis értéket a 0 hordozza Ennek a tudásnak a birtokában ugyanakkor nem célszerű a 0 és 1 értékeket numerikusan használni. <?php $a = TRUE; $b = FALSE; echo $a and $b; echo $a or $b; echo $a xor $b; echo ! $a; echo $a && $b; echo $a || $b; ?> 9.6 //És //Vagy //Kizáró vagy //Tagadás //És //Vagy Csak akkor igaz, ha mind $a mind $b igazak Akkor igaz, ha $a és $b között van igaz Akkor igaz, ha $a és $b közül pontosan egy igaz Igaz, ha $a nem igaz Csak akkor igaz, ha mind $a mind $b igazak Akkor igaz, ha $a és $b között van igaz Összehasonlító operátorok Az összehasonlító operátorok, mint nevük is sugallja, két érték összehasonlítására szolgálnak. Az eredmény igaz, vagy hamis lehet! Echo $a == $b; //Egyenlő Igaz, ha $a és $b értéke egyenlő <?php $a = ”alma”; $b = ”körte”; echo $a === $b; //Azonos Igaz, ha $a és $b értéke egyenlő, és azonos típusúak // (csak PHP 4) echo $a != $b;

//Nem egyenlő Igaz, ha $a és $b értékei különbözők echo $a !== $b; //Nem azonos Igaz, ha $a és $b értékei vagy típusai különbözők // (csak PHP 4) echo $a < $b; //Kisebb mint Igaz, ha $a szigorúan kisebb, mint $b echo $a > $b; //Nagyobb mint Igaz, ha $a szigorúan nagyobb, mint $b echo $a <= $b; //Kisebb, vagy egyenlő Igaz, ha $a kisebb, vagy egyenlő, mint $b echo $a >= $b; //Nagyobb, vagy egyenlő Igaz, ha $a nagyobb, vagy egyenlő, mint $b ?> Van egy feltételes operátor is, a "?:" (ternális) operátor, ami úgy muködik, mint a C-ben és sok más nyelvben. (kif1) ? (kif2) : (kif3); A kifejezés kif2-t értékeli ki, ha kif1 igaznak bizonyul, és kif3-at, ha kif1 hamis. 9.7 Bitorientált operátorok A bitorientált operátorok teszik lehetővé, hogy egy egész érték bizonyos bitjeit beállítsuk, vagy kimaszkoljuk. <?php $a = 126; $b = 3 ; echo $a & $b; // echo $a | $b; echo $a ^ $b; // echo ~ $a; echo $a << $b; // //

echo $a >> $b //És Azon helyeken, ahol mind $a-ban, mind $b-ben 1 volt, az eredményben 1 lesz, egyébként 0. //Vagy Ott lesz 1 az eredmény, ahol vagy $a-ban, vagy $b-ben 1 állt. //Kizáró vagy Ott lesz 1, ahol vagy $a-ban, vagy $b-ben 1 áll, de csak az egyikben. //Nem $a összes bitjét invertálja //Eltolás balra $a bitjeit $b-vel balra tolja (minden tolás 2-vel való szorzást jelent [amíg el nem fogynak a bitek. A legfelső helyiérték az előjelbit.) //Eltolás jobbra $a bitjeit $b-vel jobbra tolja (minden tolás 2-vel való 23 // // [egész!]osztást jelent. Mivel a legfelső bit az előjelbit, negatív szám jobbra tolása fura eredményre vezet!) ?> 9.8 Hibakezelő operátorok A PHP egy hibakezelő operátort támogat, az at (kukac) jelet (@). Ha egy PHP kifejezés elé írod, a kifejezés által esetlegesen generált hibaüzenete(ke)t figyelmen kívül hagyja a rendszer. Ha a track errors szolgáltatás be van kapcsolva, bármilyen a kifejezés

által generált hibaüzenet a $php errormsg globális változóba kerül tárolásra. Ez a változó minden hiba esetén felülíródik, ezért ellenőrizd minél hamarabb a kifejezést követően ha használható információt szeretnél kapni. <?php /* Szándékos SQL hiba (plusz idézőjel a táblanévnél): / $res = @mysql query ("select nev, kod from nevlista") or die ("A lekérés sikertelen volt. A hiba: $php errormsg"); ?> Lásd még: error reporting(). 9.9 Végrehajtó operátorok A PHP-segítségével utasításokat hajthatok végre az operációs rendszeren. A jel a visszaidézőjel `` Ha közéjük írok egy parancsot az operációs rendszer részére, akkor az megpróbálja végrehajtani és egy változónak átadni az eredményt. [Az alábbi kis példa az aktuális könyvtár tartalmát (hosszú lista, rejtett fájlok is) formázva írja ki (illetve fix szélességű betűket használva, entereket tiszteletben tartva)] <?php $output =

`dir C:`; echo "<pre>$output</pre>"; ?> Ebben a témában az alábbi függvényeket érdemes még megtekinteni a doksiból: system(), passthru(), exec(), popen(), és escapeshellcmd(). 9.10 Gyakorló feladatok 1. Irasd ki két változónak az összegét különbségét, szorzatát és hányadosukat, továbbá a maradékot úgy, hogy minden sorba egy érték kerül, továbbá kiiratjuk az operandusokat is! 2. Irasd ki áttekinthető formában egy ember különböző címen megkapott jövedelmeit, a befizetendő adóját és összesaítését! 3. Írd ki az alábbi logikai kifejezés igazságtáblázatát: (A and B ) or not C! 4. Mutasd meg, hogy mi történik akkor, ha negatív számnak a két, három, négy bittel eltolod az értékeit jobbra és balra is! 5. Hívd meg a futtató operációs rendszeren a könyvtár listázó parancsot és irasd ki az eredményét! 24 10 Vezérlési szerkezetek A PHP-ben ugyanúgy, mint más programozási nyelvekben az

utasítások végrehajtásának sorrendje alapvetően fentről lefelé. Ily módon csak szekvenciális programokat lehet írni, azonban rövid tanukás után szükségessé válik elágazásokat és ciklusokat tartalmazó programok írása is. A vezérlési szerkezetek, mint mindig itt is a C-hez hasonlóak. A program a különböző irányokba való továbbhaladását általában egy kifejezés határozza meg. Ennek a kifejezésnek az értéke logikai alapvetően, azonban a PHP hasonlóképpen, mint a C nem különböztet meg külön logikai értékeket, hanem a 0 és a nem 0 értékek jelentik azt. Ily módon, ha egy numerikus kifejezés 0, akkor hamis, és ha nem 0, akkor igaznak tekinthető. Ha egy string kifejezés üres, akkor hamis, ha van értéke, akkor igaz. Az olyan változók, amelyeket még azelőtt értékelünk ki, hogy értéket kaptak volna (ez nem helyes), a NULL értékkel bírnak. 10.1 Elágazások Az első fontos lehetőség a feltételhez kötött végrehajtás.

Ha bármelyik ágon több utasítást akarunk végrehajtatni, akkor szintén a C szintaktika szerint { .} jelpárost kell használnunk If( utasítás) . if(kifejezés) utasítás; if(kifejezés) { utasítás1; utasitas2; . } If . else Ha a kifejezés igaz, akkor az utasítás1 különben az utsítás2 hajtódik végre. if( kifejezés ) else utasítás1; utasítás2; Ha a kifejezés igaz, akkor az utasítás1 ág hajtódik végre, különben a másik if( kifejezés ) { utasítás1; utasitas2; . }else{ utasítás3; utasitas4; . } If . elseif else Ha kettőnél több elégazást szeretnénk, akkor az alábbi szintaktikával tudjuk a kérdést megoldani: if( kifejezés1 ) elseif(kifejezés2) else utasítás1; utasítás2; utasítás3; vagy if( kifejezés1 ) { utasítás1; utasitas2; . 25 }elseif( kifejezés2 ){ utasítás3; utasitas4; . }else { utasítás5; utasítás6; . } Switch(kifejezés) A fenti esetben az if és az elseif utasításnál lévő kifejezések

tetszőlegesek lehetnek, és az így felírt vezérlési szerkezettel meglehetősen bonyolult elágazásokat lehet létrehozni. Ezzel szemben általánosabb eset, amikor egy változ értékétől függően akarunk több féle műveletet is végrehajtani. Erre a célra alkalmas a C-ből jól ismert switch() függvény, amely több irányú elágazást hajt végre. Az ágak meghatározásakor csak konstansokat használhatunk, és az ágra akkor adódik át a vezérlés, ha a switch függvényben lévő változó értéke pontosan a konstans értékével egyezik meg. Amennyiben egy ágra ráadtuk vezérlést, majd végrehajtottuk az ott definiált utasításokat, a switch szerkezet végére kell ugranunk a break utasítás segítségével, mivel különben rácsorognánk a következő case feltételvizsgálatokra. Nézzük a szintaktikáját: switch ($i) { case 0: print "i break; case 1: print "i break; case 2: print "i break; default: print "i most 0"; most

1"; most 2"; se nem 0, se nem 1, se nem 2"; } A fenti példában az $i változó értékétől függően léptünk valamelyik irányba. Ha a változó értéke nem vette fel sem a 0, 1 vagy 2 értékeket, akkor a default utáni parancs hajtódik végre. Gyakori eset, hogy amikor több különböző eseményt egyetlen változó különböző értékei alapján akarsz végrehajtatni, akkor használod a switch utasítást. Előfordulhat, hogy ugyanazt az eseményt több érték is jelölheti, illetve több különböző esemény van. Az alábbi példában a $jelző változó 0, 1, 2 értéke esetén az fv1() függvény fut le, a 3-as értékre az fv2() függvény, egyéb esetekben az fv3(). switch ($i) { case 0: case 1: case 2: fv1($jelzo); break; case 3: fv2($jelzo); break; default: fv3($jelzo); } A fenti példában az fv1, fv2, fv3 függvények lehetnek akármik! 26 10.2 Ciklusok Mint a C-ben, itt is hasonló ciklusszerkezetek léteznek. While (kifejezés) Itt a

kifejezés a ciklus előtt értékelődik ki, azaz a ciklus magja nem biztos, hogy végrehajtódik. While (kifejezés) utasítás; While (kifejezés) { Utasítás1; Utasítás2; . } Példa: <?php $i = 1; while ($i <= 10) { print $i++; } $i = 1; while ($i <= 10) { print $i; $i++; } ?> // a kiírt érték $i, a kiírás után nő $i értéke // Az előző ciklus másképpen, de ugyanazzal az eremdénnyel // a kiírt érték $i, a kiírás után nő $i értéke Do . While(kifejezés) A kifejezés a ciklus végén értékelődik ki, azaz a ciklus magja egyszer mindenképpen lefut. Do Do{ utasítás while(kifejezés); Utasítás1; Utasítás2; . }while(kifejezés); Példa: <?php $i = 0; do { print $i; } while ($i>0); ?> For(inicializáló kifejezés; Benntmaradás kifejezése; iteráló kifejezés) A ciklus elején egyszer fut le az inicializáló kifejezés. Általában ez egy változónak ad egy kezdőértéket. Az ilyen változót ciklusváltozónak hívjuk

A Benntmaradás kifejezése mindannyiszor a ciklus magjának lefutása előtt értékeli ki a rendszer. Ha a kifejezés igaz értéket ad vissza, akkor lefut a ciklus magja, ha hamis értéket, akkor a ciklus utáni első utasításon folytatódik a futás. Ha a kifejezés helyére üres értéket írunk, akkor végtelen ciklusba kerülhetünk, hacsak a ciklus belsejéből nem ugrunk ki a break utasítással. Az Iteráló kifejezés felelős azért, hogy a ciklus valamikor befejeződjön. Általában a ciklusváltozó értékét növeljük vagy csökkentjük eggyel. For (init;bentmaradás;iterácio) utasítás; For (init;bentmaradás;iterácio){ Utasítás1; Utasítás2 . } Példa: 27 <?php // Írassuk ki az egész számokat visszafelé 100-tól 1-ig for ($i = 100; $i >0; $i--) { print $i; } //Írassuk ki egy két dimenziós tömb elemit soronként $a= array( array(3,5,4,6),array(12,234,12,12),array(3,6,5,77)); for ($i =1; $i<= 0; $i--) { for (j=1;j<=4;j++){ print

$a[$i][$j].” ”; } print ”<BR>”; } ?> Foreach ( tömb kifejezés as $érték) vagy Foreach ( tömb kifejezés as $kulcs => $érték) Ez a fajta ciklus a Perl nyelvből került át a PHP-be. Ezt a ciklust arra használhatjuk, hogy egy ciklussal végigmenjünk egy tömb minden egyes elemén. Rendkívül jól használható adatbázis lekérdezések vagy egyéb tömbben visszaadott adatok feldolgozása során. Kétféle Foreach ($tömbváltozó as $ertek) utasítás; Foreach ($tömbváltozó as $ertek){ Utasítás1; Utasítás2 . } Példa: $tomb = array (1, 2, 3, 17); foreach ($tomb as $ertek) { print "Az aktuális értéke $tomb-nek: $ertek. "; } A második formában a $kulcs változó megkapja a tömb éppen aktuális indexét, ezáltal egyes esetekben könnyebb a feldolgozása Foreach($tömbváltozó as $kulcs => $ertek) utasítás; Foreach ($tömbváltozó as $kulcs => $ertek){ Utasítás1; Utasítás2 . } Példa: * harmadik foreach példa:

kulcs és érték / $tomb = array ( "egy" => 1, "kettő" => 2, "három" => 3, "tizenhét" => 17 ); foreach ($tomb as $kulcs => $ertek) { print "$tomb[$kulcs] => $ertek. "; } break vagy break n A break utasítás arra szolgál, hogy segítségével egy struktúrából az adott helyen ki tudjunk ugrani. Ha utána írunk egy számot, akkor annak alapján több egymásba ágyazott struktúrából is ki tud ugrani: Példának okáért korábban a switch utasításnál mutattunk egy példát a break használatára, az opcionális módra pedig itt van egy példa: $i = 0; while ($i++) { switch ($i) { case 5: echo "5 esetén<br> "; 28 break 1; /* csak a switch-ből lép ki / case 10: echo "10 esetén kilépés<br> "; break 2; /* a switch és a while befejezése / default: break; } } continue vagy continue n Bár programozási módszertanok kerülik a ciklusokból való kiugrálást és a

ciklusmagon belüli iterációt, azért minden általános nyelvben benne van a lehetőség, beleértve a Pascalt és a C-t is. Ez az utasítás akkor használható, ha a ciklus belsejében már eldőlnek a további iterációra vonatkozó feltételek és nem akarjuk, hogy a ciklus magjának többi részét feleslegesen futtassuk. Ha a continue n formát használjuk, akkor több egymásba ágyazott struktúrát tudunk folytatni. Az alábbi példában 100 db véletlenszámot hozunk létre a 0.4 egész tartományból és az eloszlásukat vizsgáljuk A continue utasítások hatására ha megvan az érték, további feltételeket nem értékel ki a program, hanem rögtön iterálja a for ciklust. <?php $n = 100; srand (double) microtime() * 1000000); $a1=$a2=$a3=$a4=$a5=0; for($i=1;$i < $n;$i++){ $veletlen= rand(0,4); switch($veletlen){ case 0: $a1++; continue; case 1: $a2++; continue; case 2: $a3++; continue; case 3: $a4++; continue; default: $a5++; } } ?> 10.3 Elágazások és

ciklusok használata HTML kóddal keverve Gyakori, hogy a HTML oldalon két különböző kódot szeretnénk megjeleníteni, attól függően, hogy éppen melyik feltétel igaz, ugyanakkor a kiírandó HTML részt túl bonyolultan állíthatjuk csak elő PHPben. Ebben az esetben alkalmazni lehet az alábbi példához hasonlót: <?php if ( kifejezés) { echo ”elso ág”; ?> <table> <tr> <td> <P> Szevasz tavasz, a kifejezés igaz</p> </td> <td> <P> valamit visz a víz</p> </td> </tr> . </table> <?php } else { echo ”Másik oldal”; ?> <p> Ez a rész itt egyszerűbb lett!</p> <?php } ?> Az igaz kifejezés esetén az igaz ágban létrejövő egy soros táblának két oszlopa lesz, míg a hamis érték esetén csak a második szakaszban lévő kiírás jelenik meg, mivel a PHP amikor megszakad a PHP kód – itt többször is megszakad -, akkor a szervernek változatlanul adja vissza

a HTML kódot. Sajnos az így megírt program kissé áttekinthetetlen. 29 10.4 PHP lapok beszúrása, ”makro”-k használata Gyakran megfogalmazott feladat, hogy egy több lapból álló PHP programban minden PHP oldal elején fussanak le ugyanazok a beállítások, ugyanazok az inicializáló paraméterek, illetve ugyanazokat a függvényeket és lehetőségeket használjuk minden PHP scriptben. Valami olyasmire gondolok itt, mint Pascal-ban a unit fogalma vagy C-ben a header file-ok fogalma. Erre a célra két parancs áll rendelkezésre, amelyeknek a működése nem pontosan ugyanaz, de nagyon hasonló. Mind a két esetben arról van szó, hogy a PHP script egy adott pontján behívunk egy file-t, amelynek a kódja futásidőben bekerül a PHP scriptbe, a szerver kiértékeli, és annak megfelelően jár el. A file tartalma tehát a futás idejére úgy válik a PHP script részévé, mintha eleve abba beírtuk volna. Mivel a Webszerver kezdi a kérdéses include file-t

feldolgozni, ezért ilyenkor HTML módba kerül a szerver, így a PHP kód feldolgozásához az include file elején PHP nyitó tag-et kell elhelyezni és a végén zárótag-et. (<?php ?>) Include () Az include használata esetén a megadott file mindannyiszor kiértékelődik, ahányszor a vezérlés az include-ra kerül. Ennek eredményeként, ha egy ciklus belsejében megfelelően helyezzük el a file-t, akkor a ciklus értékétől függően mindig más és más file-t szerkesztünk be, mint az alábbi példában láthatjuk: $fileok = array (elso.php, masodikphp, harmadikphp); for ($i = 0; $i < count($fileok); $i++) { include $files[$i]; } require() A require parancs akkor is beolvassa a célfile-t, ha soha nem hajtódik végre a kérdéses sor a fő file-ban, és ha ciklusban helyezzük el a kérdéses sort, akkor is csak egyszer kerül be. A fentiek miatt require parancsot csak konstans file-nevekkel szabad használni. <?php require ("file.php"); ?>

include once() Az utasítás hasonlít az include() utasításra, azzal a különbséggel, hogy csak egyszer kerül bele a futáskor a kérdéses file. Ez azért fontos, mert ha az include() utasítással többször is meghívjuk futás közben ugyanazt a file-t, akkor a benne lévő globális változók és függvények többször kerülnek a kódba, ami miatt a futás hibaüzenettel leáll, hiszen ugyanaz az azonosító más és mást jelöl. Az include once() segítségével ezt a hibaforrást kiküszöbölhetjük. require once() Az utasítás hasonlóan az include once() utasításhoz csak egyszer hívja be a kérdéses file-t futás közben, így a függvények és globálisváltozók újradefiniálása körüli problémák kiküszöbölhetők. Egyébként a require() utasítással megegyező a szerepe és működése. 30 10.5 Távoli file-ok hívása A fenti két utasítás – include és require – alkalmas arra, hogy a PHP megfelelő konfigurálása esetén távoli

file-okat is elérjünk, akár másik Web szerveren is. Ehhez az "URL fopen wrapper"-eket kell bekapcsolni, a PHP4.03-tól kezdődően az allow url fopen phpini beállításával Ez a lehetőség Windows rendszereken nem működik. Ennek a tulajdonságnak persze vannak veszélyei is. Ha egy ilyen távoli hívás során olyan lapot hívunk meg, aminek a tartalmára nincsen hatásunk, akkor az include-olt file tartalma lehet olyan, hogy a mi rendszerünkre veszélyeket hordoz. A távoli helyen megfelelően elkészített lap email-ben elküldheti az azonosítókat és egyéb olyan adatokat, amelyeket nem szeretnénk nyilvánosságra hozni, ezért ezzel a lehetőséggel óvatosan kell bánni. 10.6 Példaprogramok feltételekkel, ciklusokkal 1. Írj programot, amely kiírja az öttel és a héttel osztható számokat és ezen számok összegét! 2. Írj egy programot, amely az eraszthotenészi szita vagy más módszer segítségével kiírja a prímszámokat 1-től n-ig! 3.

Készíts programot, amely összefésüli $a, $b rendezett tömbök tartalmát, majd az tetszetős formában kiírja a képernyőre! 4. Írj programokat, az include és require parancsok segítségével, amely teszteli egy rendezési algoritmus sebességét, mivel ugyanazokat az include-olt tömböket rendezi sorba. Az alábbi feladatok a Programozási tételek és Adatszerkezetek című jegyzetemből származnak Feladatok: Egy repülő indul az egyik kontinensről a másikra, és repülés közben rendszeresen méri az alatta lévő felszín tengerszint feletti magasságát. A mért érték nulla – ekkor tenger felett repül – vagy pozitív – ekkor szárazföld felett repül. Készítsünk olyan programot, amelyik a következőkre képes: Szimulálja a méréseket véletlenszerűen, figyelve arra, hogy az első és az utolsó mérés szárazföld felett történt. Az eredményeket fájlba menti Kiírja a képernyőre az alábbi kérdésekre a válaszokat: 1. 2. 3. 4. 5. 6. 7.

8. 9. 10. Milyen távol van egymástól a két kontinens? Hol vannak a szigetek partjai (előtte tenger, utána szárazföld vagy fordítva)? Hány sziget van a két kontinens között? Hány hegycsúcsot talált (A hegycsúcs az a hely, ami előtt és mögött kisebb a tengerszint feletti magasság)? Át tud-e menni a két kontinens között egy kajakos, ha egyszerre csak egy adott távolságot tud evezni, mert ha többet evez, akkor elpusztul? Mekkora a szigetek átlagos távolsága? Van-e leszállópálya valamelyik szigeten (olyan rész, amely vízszintes legalább két mérés távolságig) Hány darab apró sziget van (maximum 3 méréshosszúságú)? Szeretünk alföldön élni. Van-e olyan rész, amely sík vidék, elég nagy és alföld? Keressük meg ezt a helyet! Hol található a leghosszabb sziget kezdőpontja? - A fenti kérdésekre választ ad úgyis, hogy véletlen-szél gátolja, vagy segíti a repülőgép útját - Töltsünk fel adatokkal egy két-dimenziós

tömböt! Írjunk programot, amely kiírja a legnagyobb elemet tartalmazó sor számát! 31 11 Saját függvények, változók élettartama és láthatósága Eddig sok szó esett a változókról és esetenként a függvényekről is, azonban az eddigiek alapján azt gondolná az ember, hogy csak ilyen egyszerű programok írhatók PHP-ben. Az igazság az, hogy PHPben csak a futási idő és a futtató rendszer memóriája szab határt az alkalmazott program bonyolultságának. 11.1 Függvények A PHP-ban is használhatunk programstruktúrákat, programszegmenseket. Már Pascal-ból vagy C-ből is jól ismerhetjük az alapvető két eljárástípust, amit Pascalban Procedure illetve Function névvel illetünk, C-ben pedig típus nélküli illetve típusos function-nak mondunk. Mind a két nyelven a különbség az, hogy ad-e vissza a kérdéses eljárástípus értéket, vagy nem. A PHP-ben csakúgy, mint a C-ben kétféle eljárástípust használhatunk. A szintaktika a

következő: Ez az eljárástípus nem ad vissza értéket. function függvény név(paraméterlista) { A függvény törzse; } Ez az eljárástípus a definiáltnak megfelelő típusú értéket ad vissza: function függvény név(paraméterlista) { A függvény törzse; return érték; } Látható, hogy a visszatérési érték léte vagy nem léte a programozótól függ, ezért egyes esetekben célszerű a visszatérési érték típusát megállapítani ahhoz, hogy van-e egyáltalán visszatérési érték. PHP3-ban a definiált függvénynek mindig a függvény hívása előtti ponton kell lennie, vagyis azokat a függvényeket, amelyeket használni akarunk a PHP program elejére kell tennünk. A PHP4–ben ez a megszorítás megszűnt, ugyanakkor célszerű magadat ehhez a szokáshoz tartani. A PHP nem támogatja a függvények polimorfizmusát, a függvényeket nem tudod undefiniálni vagy újradefiniálni a már definiált függvényeket. Az objektum orientáltság ennek

megfelelően nem teljes a PHP-ben. A függvény meghívása esetén paramétereket adhatunk át a hívott függvénynek. Ennek részleteit a következő szakaszban fogjuk tárgyalni. Rekurzió lehetséges a függvényhívásoknál, de természetesen arra kell vigyázni, hogy a rekurzió véget érjen. Az alábbi kis példa az N faktoriális kiszámítását végzi rekurzív módon <?php function nfakt($n){ if ($n>1) $nf = $n*nfakt($n-1); else $nf = 1; echo $n." => "$nf"<BR>"; return $nf; } nfakt(200); ?> 11.2 Paraméterátadás Egy függvény definiálásakor meg kell határozni, hogy milyen paramétereket vegyen át. Ezt a paraméterlistával tudjuk megtenni, amelyben az átvevő változók neveit vesszővel elválasztva fel kell sorolni. 32 A híváskor nem kell minden paramétert átadni. Ebben az esetben a kérdéses paramétereknek a függvényen belül nem lesz értéke. Az empty() függvénnyel lehet megvizsgálni, hogy egy paraméter

kapott-e értéket vagy sem. A PHP-ben kétféle paraméterátadás, létezik Érték szerinti A hívó kifejezés értéke behelyettesítődik a meghívott függvény paraméterlistájában szereplő változóba és a függvényen belül a paraméter használható. Ez az alapértelmezés Cím szerinti Ez azt jelenti, hogy a változó memóriacímét adjuk át a függvénynek, amely a cím ismeretében tudja azt módosítani és a függvényből való visszatéréskor a változások megmaradnak. Ez utóbbi esetben, ha cím szerint akarunk átvenni értéket egy függvénnyel, akkor használnunk kell a & operátort. <?php function fgv(&$n) { $n *= 2; } $n=100; echo ”$n<BR>”; fgv($n); echo ”$n<BR>”; ?> Még akkor is átadhatjuk cím szerint a változót, ha a fogadó függvényt nem készítettük fel a cím szerinti paraméterátvételre, az átadásnál használjuk a & operátort. Ez utóbbi nem túlságosan szép mód, mivel egy függvényt

valószínűleg nem azért használunk érték szerinti paraméter átvételre, hogy majd máshol módosítsunk a dolgon. <?php function fgv($n) { $n *= 2; } $n=100; echo ”$n<BR>”; fgv(&$n); echo ”$n<BR>”; ?> A függvények paramétereinek átvétele még egy módon megtörténhet. A PHP támogatja a paraméterek kezdőértékadását. Ennek akkor van értelme, ha a függvény hívásakor nem adtunk át értéket a függvénynek. Ilyenkor alapértelmezett értéket kap az a paraméter, amelyet a hívó nem adott át Természetesen az át nem adott paramétereknek a helye az átadottak után helyezkedjen el! <?php function joghurtot keszit ($flavour, $type = "acidophilus") { return "Készítek egy köcsög $flavour ízű $type-ot. "; } echo joghurtot keszit ("eper"); ?> Ha azt szeretnénk, hogy egy függvény változó számú paramétert vegyen át és a függvényben meg akarjuk állapítani, hogy éppen most hány

paraméter van, akkor a következő függvényeket használni: func get args() Egy tömbben visszaadja az átadott paraméterek listáját. Func num arg() Megadja a kapott függvények számát 33 func get arg(sorszám) Visszaadja a sorszám paraméterrel megadott paramétert. Ha a sorszám nagyobb, mint a paraméterlista utolsó elemének indexe, akkor hibaüzenet jön (warning). A paraméterlista indexe 0-val kezdődik Az alábbi példa ezeket példázza. <?php function foo() { $numargs = func num args(); echo "paraméterek száma: $numargs<br> "; if ($numargs >= 2) { echo "A második paraméter: " . func get arg (1) "<br> "; } $arg list = func get args(); for ($i = 0; $i < $numargs; $i++) { echo "$i-ik paraméter: " . $arg list[$i] "<br> "; } } foo (1, 2, 3); ?> 11.3 Függvények visszatérési értéke Egy függvény tetszőleges típust, még tömböt, vagy változóreferenciát is vissza tud

adni. Több érték visszaadására a tömböt használhatjuk. Ha nem használjuk a return utasítást, akkor az utolsó végrehajtott kifejezés lesz a visszatérési érték. 11.4 Változók élettartalma és láthatósága A PHP-ban nagyon egyszerű szabályok vannak a változók láthatóságára és élettartamára vonatkozólag. Élettartam A változó akkor jön létre, amikor létrehozzuk, értéket adunk neki. Egy változó megsemmisül, ha az unset(változónév) paranccsal felszabadítjuk a változó nevét (memóriaterületét is), vagy véget ér az adott PHP script oldal. Ez alól kivétel, ha a változókat átadjuk egy másik PHP oldalnak a POST, GET metódussal, a cookie-k vagy sessionok használatával. Egy PHP oldal elején használhatók a HTTP és az Environment változók, amikről korábban esett szó. Használhatók azok a változók, amelyeket egy másik php oldal, vagy más HTML oldal küldött, POST vagy GET metódussal. Használhatók a Cookie-k és a

Sessionok segítségével átvitt változók is. Létezik az úgynevezett a $GLOBALS tömb, amelynek tartalma a PHP oldal minden helyéről látható. 34 Létezik-e a változó Azt, hogy egy változó létezik-e az isset() függvénnyel kérdezhetjük le. Igazat ad vissza, ha a változó létezik, az empty() függvény pedig igazat ad vissza, ha a változó értéke 0, üres, vagy nem létezik! <?PHP if (!isset($ SESSION[”logged in”])) print(”Beléptél!”); ?> die(”Jelentkezz be!”); Láthatóság A PHP oldalon létrejött és a különböző módokon átvett változók globálisak, azaz attól a helytől kezdve láthatók mindenhonnan, azonban ha meghívunk egy függvényt, akkor abban a függvényben csak azok a változók láthatók, amelyeket a függvényben hoztunk létre, vagy paraméterként adtunk át. Ha a függvényből kilépünk, akkor ezek a változók megsemmisülnek kivéve, ha nem cím szerinti paraméterátadás során jöttek létre. Azaz ezek

a változók lokálisak lesznek a függvényre nézve Ha egy függvényből új függvényt hívunk, akkor abban nem lehet látni a hívó függvény változóit. A fentiek alól az egyetlen kivétel, ha a függvényben használjuk a global parancsot, aminek segítségével importálhatjuk a script globális változóit a függvénybe. <?php $a = 1; $b = 2; Function Osszead () { global $a, $b; $b = $a + $b; } Ossszead (); echo $b; ?> A másik lehetőség az, hogy használjuk a $GLOBALS[] asszociatív tömb értékeit, amelyben minden bejegyzett globális változó megtalálható. <?php $b = 1; $a = 10; $GLOBALS["b"] = $GLOBALS["a"] + $GLOBALS["b"]; echo $b; ?> Létrehozhatunk statikus változókat is, amelyek a Clipperben és más hasonló nyelveken léteznek. Statikus változó egy függvényben jöhet létre. Amikor kilépünk a függvényből már nem használhatjuk ennek a változónak az értékét, de ha újra meghívjuk a függvényt,

nini még megvan az előző értéke. J ott folytathatjuk, ahol abbahagytuk. Ennek néha van értelme Mindenesetre a használatához a függvényben a static kulcsszót kell használni. Az alábbi kis szösszenet egy ciklusból meghívja újra meg újra a Test() függvényt és ennek során az $a változó tartalma folyamatosan nő, noha mindig kilépünk a függvényből. Na ja, statikusnak deklaráltuk! A statikus változónak kezdőértéket adva, az csak egyszer fut le, amikor először meghívjuk a függvényt. Function Test () { static $a = 0; echo $a; $a++; } for ($i =0; $i< 10;$i++) { 35 Test(); Echo ”blablabla” } 11.5 Változók átadása lapok között Gyakori kérdés a PHP-ben programozók között, hogyan tudnak értékeket átadni a PHP lapok között, hiszen ha egy lap lefut, akkor eddig úgy tudtuk, hogy a lapon keletkezet változók is megszűnnek. Amikor először szembekerültem a problémával, akkor azt hittem, hogy a globális változók oldják meg a

problémát. Sajnos a dolog nem ennyire egyszerű, de nem is túlságosan bonyolult Átadhatunk egyedi változókat és egy dimenziós tömböket is. Négy lehetőségünk van erre 11.51 Header utasítás A Header utasítást csak akkor használhatjuk, ha az adott oldalon még semmiféle képernyőre írás nem volt, azaz a keletkező HTML oldalnak még nem kezdtük írni a BODY részét. A header segítségével bármilyen header TAG-et kiírathatunk a HTML oldalra. Az alábbi példában egy teljes header sorozatot írunk ki a HTML oldalra header header header header ("Expires: Mon, 26 Jul 1997 05:00:00 GMT"); // Date in the past ("Last-Modified: " . gmdate("D, d M Y H:i:s") " GMT"); // always modified ("Cache-Control: no-cache, must-revalidate"); // HTTP/1.1 ("Pragma: no-cache"); // HTTP/1.0 header ("HTTP/1.0 404 Not Found"); Itt egy hibakezelést írunk ki, az URL nem található. Akkor lehet ilyet tenni, ha

például az Apache szerverünk hibaüzeneteit átirányítjuk a saját oldalainkra. header ("HTTP/1.0 404 Not Found"); Böngésző átirányítása. Itt adhatjuk meg az új oldalt Ez a parancs nem csak a böngészőt vágja át az új oldalra, hanem a szervernek is visszaküld egy átirányítás státusz üzenetet is. header ("Location: http://www.phpnet"); /* Átirányítja a böngészőt a PHP web oldalra / exit; /* Ha nem megy az átirányítás, akkor az exit parancs biztosan kilép / 11.52 GET metódus A GET metódust úgy használhatjuk, hogy meghívunk egy lapot az oldalunkról egy másik lapot és az URL végére paraméterként átadjuk a változókat, valahogy így, ahogy a következő példákban látjuk: Az első példában igazából nem is PHP a megoldás, egyszerűen a <BODY> TAG-ben megadjuk, hogy melyik oldalt és menyi idő múlva hívja meg az oldal. Ennek a megoldásnak hibája, hogy tulajdonképpen itt egy Javascriptet használunk. A

példában 3 másodpercig vár a betöltődés után a böngésző, majd a szerver átdobja az új oldallal és meghívja a lapot a user, pwd és a level változókkal. <BODY OnLoad=timerID=setTimeout(location="index.php?user=anonym&pwd=anonymous&level=1",30000)> A következő példában hasonlót teszünk, de itt a HTML oldal fejlécében dolgozunk. Felhasználjuk a HTML meta tag-ját. Itt is 3 másodperc múlve hívja be a következő oldalt és az előző oldalról átadjuk az előző példában látott 3 változó pillanatnyi értékét. <meta http-equiv="refresh" content="3; URL=<index.php?<?php echo ’user=$user&pwd=$pwd&level=$level’ ?>"> A harmadik példában a PHP header utasítását használjuk. A példában egy POST metódussal egy űrlapon bevitt adatokat vizsgálunk meg, és amennyiben hiányzik az adat, akkor egy hibakezelő 36 függvénybe irányítom át, ahol a header segítségével

átirányítom egy másik oldalra, átadva neki a megfelelő változókat. function sorry($msg,$from=1,$glob="") { header("Location: sorryuser.php?from=$from&msg=$msg&glob=$glob"); } if(empty($name)) sorry("Hiányzik a név adat! Kötelező kitölteni",1); if(empty($loginname)) sorry("Hiányzó login név! Kötelező kitölteni",1); if(empty($email)) sorry("Hiányó E-mail cím! Kötelező kitölteni. Itt kapod meg a jelszót!",1); A fenti három lehetőség közös hibája az, hogy az átirányított lapok URL-je megjelenik a böngészőben, azaz titkos információt nem tudunk átadni, továbbá azok a böngészők, amelyek nem tűrik az átirányítást, nem fognak továbbmenni. 11.53 POST metódus A POST adatátviteli metódust az űrlapokkal kapcsolatban használhatjuk legtermészetesebben. Itt egyelőre csak annyit mondunk, hogy az ürlapok olyan HTML kódok, amelyen keresztül a böngésző előtt ülő felhasználó

beírhat adatokat a HTML oldalon, az űrlap SUBMIT gombjának megnyomására pedig az űrlapon definiált mezők tartalmát, mint változóneveket és változó tartalmakat elküldi a cél oldalnak a böngésző. Az űrlap fejlécében meg kell adni a cél oldalt (kinek küldjük) és a megfdelelő oldal, ha az olyan oldal, amit a szerver meg tud jeleníteni betöltődik a böngészőbe. A PHP esetén a módszer az, hogy az űrlap kitöltése után a submit gomb megnyomásával elküldjük az eredményeket egy PHP oldalnak, amely betöltődéskor megkapja az elküldött változókat, esetleg elvégzi azokat a ferladatokat, amelyekre rendeltetett, majd megjelenít valami választ. Ennél a módszernél, az elküldött értékek nem látható módon kerülnek el a meghívott oldalhoz, tehát ezzel a módszerrel viszonylag könnyű változóértékeket átadni. Vigyázni kell azonban arra, hogy az adatbevitel alapvetően string és ha nem úgy használjuk fel azokat a bevitt stringeket,

hogy előtte kiszűrjük a .//etc/ stb jellegű adatrokatés nem figyelünk arra, hogy az eredményeket a lehető legtöbb szempont szerint ellenőrizzük, akkor a web site-unk feltörhető lehet. Az alábbi példában egy olyan HTML oldalt mutatok be, amely egy űrlapot tartalmaz, a submit gomb megnyomásának hatására az oldal önmagának (!) küldi el a változókat, majd a submit változó értéke alapján egy elágazásra kerül a végrehajtás és az eredményt elküldi e-mailben egy megadott címre. A lapon van egy kis Javascript betét is, amely az aktuális időpont beszúrására szolgál. Az űrlapon található olyan mező is, amelynek a tartalma hidden, azaz az űrlapon nem jelenik meg. <html> <head> <meta http-equiv="Content-Language" content="hu"> <meta http-equiv="Content-Type" content="text/html; charset=windows-1250"> <title>Munkalap</title> <script language="JavaScript">

function Kitolt() { var x=0; for (x=0;x<document.munkalaplistalength;x++) if (document.munkalaplistaoptions[x]selected) document.munkalapcegvalue = documentmunkalaplistaoptions[x]value; Alert (document.munkalaplistaoptions[x]value); } </script> </head> <body bgcolor="#efefef" text="#00000000" link="#6666CC" vlink="#FF9900"> <script language="php"> $datum = date(Y.Md H:i); //aktuális dátum 37 $mikor= date (Y.Md); if (!empty($pswd)) $jls = " ".$pswd" "; else $jls = " "; // // egyszerű (primitiv) password ellenőrzés // Lehetne biztonsáégosabban is, de itt most ez nem szempont // A munkalap elküldéséhez ki kell tölteni a partnercég nevét is. if(!empty($ceg)) { $jel= (strpos($jls, "xxxx") == 0) | empty($munkavegzo); if(!$jel) { // Itt állítjuk össze az Email-t az átküldött változók értékéből. $uze =""; $uze= $uze ."Cég $ceg

"; $uze= $uze ."Bejelentő $bejelento "; $uze= $uze ."Bejelentés időpontja $mikor "; $uze= $uze ."Hibajelenség $hibajelenség "; $uze= $uze ."A hiba oka $hibaok "; $uze= $uze ."Az elvégzett munka $elvegzett munka "; $uze= $uze ."A munkavégzés alapja "; $uze= $uze ."- Garanciális $granciális "; $uze= $uze ."- Rendszergazdai $rendszergazda "; $uze= $uze ."- Fizetős $fizetos "; $uze= $uze ."- Kiszállás $kiszallas "; $uze= $uze ."- Műhelyben $muhely "; $uze= $uze ."- Rendszergazdai $rendszergazda "; $uze= $uze ."A szükséges munkaidő $munkaido "; if (!empty($munkadij)) { $uze= $uze ."Számlázott munkadíj $munkadij Ft + 25% ÁFA "; } if (!empty($alkatreszek)) { $uze= $uze ."Beépített alkatrészek $alkatreszek "; $uze= $uze ."Alkatrészek ára $alkatreszar Ft + 25% ÁFA "; } $uze= $uze ." "; $uze=

$uze ."Munkavégző $munkavegzo "; $uze= $uze ."Dátum $datum "; $uze= $uze ."Igazolás $igazolas "; $uze= $uze ."A munkalapot küldő gép adatai "; $uze= $uze ."A gép IP címe ".$HTTP ENV VARS[HTTP HOST]" "; $uze= $uze ."A gép neve ".$HTTP ENV VARS[REMOTE HOST]" "; $uze= $uze ."A gépen futó böngésző "$HTTP USER AGENT" "; mail("europr@matavnet.hu","munkalap",$uze); if( Die("Az munkalapot elküldtük!")); } if ($jel) </script> <script language="javascript"> Alert ("Hiányosan töltötte ki a munkalapot"); </script> <script language="php"> } </script> <table width="77%" border="0"> <tr> <td><font size="6" color="#6666CC"><b><img src="./jozsi logopng" width="100"

height="93"></b></font></td> <td><font size="6" color="#6666CC"><b>Józsi Cégének munkalapja</b></font></td> </tr> </table> <form name="munkalap" method="post" enctype="multipart/form-data" action="index.php"> <table width="76%" border="0"> <tr> <td width="21%" valign="top">A partnercég:</td> <td width="79%" valign="top"> <input type="text" name="ceg" size="60"> <select name="lista" onclick="Kitolt()"> <option value="Nincs a listában"> </option> <option value="Emulátor KFT ">EKFT</option> <option value="Géza KFT">GKFT</option> <option value="Magyar-Uránusz Ujságírók Baráti

Társasága">MUÚBNT</option> <option value="Magyar Tudományos Akadémia Ördögűző Intézete">MTAÖI</option> <option value="Alladin BT">ABT</option> <option value="Balogh Aladár SZKI">BA.KI</option> 38 <option value="Kiss Piroska Irodalmi Múzeum">KPIM</option> </select> </td> </tr> <tr> <td width="21%" valign="top">A bejelentő neve:</td> <td width="79%" valign="top"> <table border="0"> <tr> <td width="131"> <input type="text" name="bejelento" cols ="60% "> </td> <td width="310"> A bejelentés időpontja: <input type="text" name="mikor" value="<?php echo $mikor; ?>" > </td> </tr> </table> </td> </tr> <tr> <td

width="21%" valign="top">A hibajelenség:</td> <td width="79%" valign="top"> <textarea name="hibajelenseg" rows=4 cols =60 ></textarea> </td> </tr> <tr> <td width="21%" valign="top">A megállapított hiba</td> <td width="79%" valign="top"> <textarea name="hibaok" rows=5 cols =60 ></textarea> </td> </tr> <tr> <td width="21%" valign="top">Az elvégzett munka leírása</td> <td width="79%" valign="top"> <textarea name="elvegzett munka" rows="6" cols =60 > </textarea> </td> </tr> <tr> <td width="21%" valign="top"> <table width="75%" border="0"> <tr> <td>Garanciális?</td> <td> <input type="checkbox"

name="garancialis" > </td> </tr> <tr> <td>Rendszergazdai?</td> <td> <input type="checkbox" name="rendszergazda" > </td> </tr> <tr> <td>Fizetős?</td> <td> <input type="checkbox" name="fizetos" > </td> </tr> <tr> <td>Kiszállás</td> <td> <b> <input type="checkbox" name="kiszallas" > </b></td> </tr> <tr> <td>Műhely</td> <td> <input type="checkbox" name="muhely" > </td> </tr> </table> 39 </td> <td width="79%"> <p align="left">Beépített alkatrészek<br> <textarea name="alkatreszek" rows=2 cols =60 ></textarea> </p> <p align="left">Alkatrészek ára (nettó) <input type="text"

name="alkatreszar" size="40"> +25% ÁFA</p> </td> </tr> <tr> <td width="21%" valign="top"><br> A munkát végző(k): <input type="text" name="munkavegzo" size="30"> </td> <td width="79%">Munkaórák <input type="text" name="munkaido" > <br>Munkadíj (netto) <input type="text" name="munkadij">+25% ÁFA </td> </tr> <tr> <td width="21%" valign="top"> <p>Dátum: <?php echo "$datum"; ?> </p> </td> <td width="79%"> Digitális aláírás: <input type="password" name="pswd" value="titok" size=20> </td> </tr> <tr> <td width="21%"> <p> <input type="submit" name="Submit" value="Elküldés"> <input

type="submit" name="Reset" value="Mégsem"> </p> </td> <td width="79%"> <font face="Times New Roman, Times, serif">Igazolás:<br> <textarea name="Igazolas" rows=2 cols =60 ></textarea> </font></td> </tr> </table> </form> <p><A HREF="index.html" onMouseOver="documentvisszasrc=/visszaanimgif;" onMouseOut="document.visszasrc=/visszagif"> <IMG SRC="./visszagif" NAME="vissza" ALT="Vissza a főoldalra" BORDER=0 height="25"> </A> </p> <p>Utolsó módosítás: 2011. március 12</p> </body> </html> 11.54 $ SESSION változók A session változók olyan változók, amelyek megtartják értékeiket miközben a felhasználó egyik oldalról átlép a másikra anélkül, hogy a korábban ismertetett módszerek valamelyikével direkt át kellene

adnunk az értékeket a lapok között. Ez a lehetőség igazi globális változókat enged meg és sokkal összetettebb WEB-es programok készítését teszi lehetővé. Több lapból álló site fejlesztése gyakorlatilag session változók nélkül nem megy. Amikor egy felhasználó belép egy WEB oldalra, akkor egy egyedi azonosító keletkezik, az úgynevezett session id (SID), amelyet vagy a böngészőben tárolunk úgynevezett cookie (süti) formájában, vagy a szerver oldalon tartunk nyilván. A sessionok támogatják korlátlan mennyiségű változó regisztrálását és a tartalmuk megtartását. Amikor a felhasználó eléri a web oldalt, akkor a PHP automatikusan leellenőrzi, hogy a megfelelő session id vajon már létezik-e a szerveren. Ha létezik a session id, akkor a session-höz tartozó elmentett értékeket hozzárendeli a lekért oldalhoz. A session id-t két módon lehet aktivizálni. 1. Vagy a PHPINI-ben beállítjuk a sessionauto start =1 értéket 40

2. Minden oldal elején használjuk a session start() függvényt, vagy implicit módon a session register() függvényt. Amikor a látogató elindít egy PHP-s lekérést, a PHP motor megnézi, hogy a fenti esetekben van-e a kéréshez hozzárendelve egy session id. Ha van, akkor a korábban elmentett környezetet hozzárendeli ehhez a kéréshez, azaz visszaállítja a megfelelő változókat. Minden regisztrált változót elment a rendszer a kérés befejeződésekor. Azok a regisztrált változók, amelyek nem kaptak értéket, azaz nem definiáltuk őket, a nem definiáltak közé kerülnek. Ezek a változók csak akkor kerülnek a definiáltak közé később is, ha a user értéket ad neki. A track vars és a register globals konfigurációs paraméterek (PHP.INI-ben) befolyásolják a session változók tárolásának és visszaállításának módját. Ha a track vars engedélyezve van és a register globals tiltva, akkor csak a $HTTP SESSION VARS globális asszociatív

tömböt lehet session változóknak beállítani. A visszaállított változók is csak ebben a tömbben lesznek elérhetők. (Ebben az esetben egy visszaálított változó értékét az alábbi módon tudjuk elérni: <?php session register("valtozonev"); $HTTP SESSION VARS["valtozonev"]++; ?> Ha a register globals engedélyezett, akkor minden globális változót session változónak tudunk elmenteni, és a session változók a következő kérés során automatikusan globális változókká válnak. <?php session register("valtozonev"); $valtozonev++; ?> Ha a track vars és a register globals is engedélyezettek a PHP.INI-ben, akkor mind a két fenti módszert használhatjuk, azaz a $HTTP SESSION VARS elemei és a globális változók ugyanazokat az értékeket tartalmazzák majd. Hogyan kezelhetjük a session id-ket? Cookie - sütikkel URL parameterekkel A session modul mind a két változatot támogatja. A cooki-k az optimálisak,

viszont vannak olyan kliensek, akik nem támogatják a cooki-k elhelyezését a gépükön biztonsági okokból, ráadásul ilyenkor a böngésző és a szerver között vándorolnak adatok is. Ez biztonsági problémákat vet fel A második módszer esetén a session id az URL része. A PHP képes hajlékonyan kezelni a kérdést, ha megfelelően fordítottuk (--enable-trans-sid kapcsolóval) Ebben az esetben a relatív URI-k megváltoznak automatikusan és tartalmazni fogják a session ID-t (=SID). Más esetben használhatjuk a SID konstanst, amely a session name=session ID vagy egy üres stringet tartalmaz (pl. PHPSESSID=8e1f5ff69434aea7ecab51da33314b53&PHPSESSID=8e1f5ff69434aea7ecab51da33314b53 ) Az alábbi példában bemutatjuk, hogyan lehet regisztrálni egy változót és egy URI-hoz hozzárendelni a session ID-t, felhasználva a SID-et. Példa 3. Egy user bejelentkezéseit számolja le ez a példa <?php session register ("count"); $count++; ?> Hello

visitor, you have seen this page <? echo $count; ?> times.<p> <php? 41 # the <?=SID?> is necessary to preserve the session id # in the case that the user has disabled cookies ?> To continue, <A HREF="nextpage.php?<?=SID?>">click here</A> Ha a fenti kódot lefuttatjuk és megnézzük a PHP.INI-ben megadott könyvtárban lévő file-okat, akkor látni fogjuk, hogy a session indulása után létrejön egy file (pl. C: emp-ben) valami hasonló névvel, sess 8e1f5ff69434aea7ecab51da33314b53. Ez tartalmazza a session változók nevét és értékét Ez felveti azt a problémát, hogy az ilyen típusú file-ok a szerveren lévő temp könyvtárban csak gyűlnek és korrekt lekezelésük idővel nagyon nehézzé válik. Azt is figyelembe kell venni, hogy egyes sessionok elévülnek, másokat nem lehet még törölni, mert éppen futó alkalmazás használja. A PHP.INI session részében vannak azok a beállítások, amelyek a session

file-ok elévülését, a szemétszedést és egyebeket szabályoznak. A szerver automatikusan gondoskodik egy idő múlva a session file-ok törléséről. Másfelől a fejlesztőket gondoltak arra is, hogy a programozók a saját kezükbe akarják venni a session kezelésének lehetőségét. Erre a célra a fejlesztők megadták a session set save handler() függvényt, aminek paramétereivel megadhatjuk a teljes session kezelő függvénycsomagunkat. A paraméterek tehát azoknak a függvényeknek a nevei, amelyek az egyes műveleteket végzik. session set save handler ("ss open", "ss close", "ss read", "ss write", "ss destroy", "ss gc"); Az egyes függvények feladatai a következők: ss open ($save path, $session name) a két megadott paraméter tartalmazza a PHP.INI-ben megadott helyet session.save path, és változónevet, sessionsession name, ami a keletkezett file-t is megjelöli sess session name alakban (lásd

fenti példa) ss close() Ezzel bezárjuk a session kezelőt, nem lelőjük, mintha a sess destroy()-t alkalmaznánk! ss read($id) Ez a függvény olvassa be a megfelelő változókba a kulcs által meghatározott sessionokhoz tartozó értékeket. ss write($id, $változonév érték) Ez írja bele a megfelelő kulccal azonosított sessionba a változónév érték párokat. ss destroy($id) Ezt hívjuk meg, amikor törölni akarjuk egy session adatait és be akarjuk zárni a boltot. ss gc($maxlifetime) Garbage collection algoritmus. Ha egy session lejárt, akkor az időnként elindított függvénnyel letöröljük a feleslegessé vált sessionok adatait. Ez például azért is szükséges, mert az egyes userek nem biztos, hogy megvárják egy php oldal lefutását, hanem időnként csak egyszerűen kilépnek, megszakad a kapcsolat, vagy egyéb okok is lehetnek. Ha túllépi egy session a neki szánt időt, illetve sokáig nem nyúltak hozzá a session adataihoz, akkor azt

könyörtelenül ki kell takarítani. Az alábbiakban két változatot mutatunk be. Egyet a manualból, amely a temp könyvtárban lévő sessionokat kezeli file-okként. Példa a session set save handler() használatáról <?php // Ezzel a függvénnyel kell beírni a megfelelő globális változókba a session eltárolásának // helyét és nevét function ss open ($save path, $session name) { global $sess save path, $sess session name; $sess save path = $save path; $sess session name = $session name; return(true); } 42 // Ez nem csinál semmit function ss close() { return(true); } //Beolvassa a session file adatait egy változóba, amit fel lehet dolgozni, function ss read ($id) { global $sess save path, $sess session name; $sess file = "$sess save path/sess $id"; if ($fp = @fopen($sess file, "r")) { $sess data = fread($fp, filesize($sess file)); return($sess data); } else { return(""); } } // Kiírja a session adatokat egy file-ba. function ss

write ($id, $sess data) { global $sess save path, $sess session name; $sess file = "$sess save path/sess $id"; if ($fp = @fopen($sess file, "w")) { return(fwrite($fp, $sess data)); } else { return(false); } } // A session file-t töröljük a sessionok tárolására szolgáló könyvtárból function ss destroy ($id) { global $sess save path, $sess session name; $sess file = "$sess save path/sess $id"; return(@unlink($sess file)); } /* * Figyelem! Garbage collection rutint kell ide írni! * */ // Itt azt vizsgáljuk meg, hogy az utolsó hozzáférés mikor zajlott le a file-on. function expirity($filename, $now, $maxlifetime) { $last = fileatime ($filename); return ($now - $last >= $maxlifetime); } function ss gc ($maxlifetime) { global $sess save path, $sess session name; $aktdir = dirname($PATH TRANSLATED); $now = time(); chdir($sess save path); $d=opendir($sess save path); while($filename=readdir($d)){ if ((substr($filename,0,4) == ”sess ”)

&& (expirity($filename,$now,$maxlifetime) )) unlink($filename); } closedir($d); chdir($aktdir); return true; } session set save handler ("ss open", "ss close", "ss read", "ss write", "ss destroy", "ss gc"); session start(); ?> A korábbiak alapján érthető lehet a példa. Talán az ss gc() függvény kicsit bonyolult Az aktuális könyvtárt elmentjük, majd belépünk a session adatait tároló helyre, ott megnyitva a könyvtárat 43 végignézzük a file-ok neveit. A ”sess ” kezdetű filenevek session file-okat takarnak, azoknak megnézzük és a jelenlegi időt és az utolsó hozzáférésének idejét kivonva egymásból megnézzük, hogy lejárt-e az élete. 44 Egy session kezelő működése - példa A továbbiakban megnézzük egy MySQL-es sessionkezelő működését. A működéséhez szükség van az alábbi adatbázis szerkezetre: CREATE TABLE sessions ( sesskey char(32) not null, exp

int(11) unsigned not null, value text not null, PRIMARY KEY (sesskey) ); <? //Ezt a file-telőbb kell lefuttatni. Mint a session start függvényt! $SESS DBHOST $SESS DBNAME $SESS DBUSER $SESS DBPASS = = = = "localhost"; "sessions"; "phpsession"; "phpsession"; /* /* /* /* adatbázis adatbázis adatbázis adatbázis szerver hostneve */ neve */ user */ jelszó */ $SESS DBH = ""; $SESS LIFE = get cfg var("session.gc maxlifetime"); function sess open($save path, $session name) { global $SESS DBHOST, $SESS DBNAME, $SESS DBUSER, $SESS DBPASS, $SESS DBH; if (! $SESS DBH = mysql pconnect($SESS DBHOST, $SESS DBUSER, $SESS DBPASS)) { echo "<li>Nem tudok kapcsolódnia stzerverhez: $SESS DBHOST, mint $SESS DBUSER user"; echo "<li>MySQL hiba: ", mysql error(); die; } if (! mysql select db($SESS DBNAME, $SESS DBH)) { echo "<li>Nem tudom kiválasztani az adatbázist: $SESS DBNAME";

die; } return true; } function sess close() { return true; } function global $qry = $qid = sess read($key) { $SESS DBH, $SESS LIFE; "SELECT value FROM sessions WHERE sesskey = $key AND exp > " . time(); mysql query($qry, $SESS DBH); if (list($value) = mysql fetch row($qid)) { return $value; } return false; } function sess write($key, $val) { global $SESS DBH, $SESS LIFE; $exp = time() + $SESS LIFE; $value = addslashes($val); $qry = "INSERT INTO sessions VALUES ($key, $exp, $value)"; $qid = mysql query($qry, $SESS DBH); if (! $qid) { $qry = "UPDATE sessions SET exp=$exp, value=$value WHERE sesskey=$key AND exp> " .time(); $qid = mysql query($qry, $SESS DBH); } return $qid; } function sess destroy($key) { global $SESS DBH; 45 $qry = "DELETE FROM sessions WHERE sesskey = $key"; $qid = mysql query($qry, $SESS DBH); return $qid; } function sess gc($maxlifetime) { global $SESS DBH; $qry = "DELETE FROM sessions WHERE exp < " .

time(); $qid = mysql query($qry, $SESS DBH); return mysql affected rows($SESS DBH); } session set save handler( "ss open", "ss close", "ss read","ss write","ss destroy","ss gc"); ?> A fenti két esetben mindannyiszor hasonló paraméterekkel kell meghívni a függvényeket: Ss open(”C:TEMP”,”PHPSESSID”) ezeket adja át a változóknak The <?=SID?> is not necessary, if --enable-trans-sid was used to compile PHP. A sessionkezelési rendszer több olyan beállítást figyelembe vesz, amelyek a PHP.INI-jében találhatók session.save handler a session kezelőjét űllítja be Default files session.save path meghatározza a session file-ok tárolásának helyét Ha a default filekezelőt használod, akkor a /tmp. Könyvtár lesz az Windowsos rendszeren célszerű a TEMP környezeti változót megadni, példul c:TEMP. session.name a session által használt cookie nevet határozza meg Default PHPSESSID

session.auto start meghatározza, hogy a session automatikusan induljon-e el, ha a PHP kérés lefutott. Default 0 (nem indul el) session.cookie lifetime meghatározza, hogy a cookie hány másodpercig éljen a böngésző indulása után. A 0 azt jelenti, hogy, amíg a böngésző fut Default 0 session.serialize handler defines the name of the handler which is used to serialize/deserialize data. Currently, a PHP internal format (name php) and WDDX is supported (name wddx) WDDX is only available, if PHP is compiled with WDDX support. Defaults to php session.gc probability meghatározza, hogy a gc (garbage collection) szemétgyűjtő rutin milyen százalékkal induljon el. Az elmúlt sessionok file-jai a temp könyvtárban ott maradnak és ha egy új PHP kérést kap a rendszer, akkor ennek a változónak az értékétől függően statisztikai valószínűséggel elindul a régi session file-ok kitörlése. Ha az érték kicsi, akkor sok session fle is felgyűlhet, hiszen ritkán fut

le a szemétszedés, ha nagy, akkor gyakran fut az algoritmus, tehát lassab lesz a kiszolgálás. Default érték 1, tesz környezetben 5 – 10. session.gc maxlifetime specifies the number of seconds after which data will be seen as garbage and cleaned up. session.referer check determines whether session ids referred to by external sites will be eliminated. If session ids are propagated using the URL method, users not knowing about the impact might publish session ids. This can lead to security problems which this check tries to defeat Defaults to 0. session.entropy file gives a path to an external resource (file) which will be used as an additional entropy source in the session id creation process. Examples are /dev/random or /dev/urandom which are available on many Unix systems. 46 session.entropy length specifies the number of bytes which will be read from the file specified above. Defaults to 0 (disabled) session.use cookies specifies whether the module will use cookies

to store the session id on the client side. Defaults to 1 (enabled) session.cookie path specifies path to set in session cookie Defaults to / session.cookie domain specifies domain to set in session cookie Default is none at all specifies cache (nocache/private/public). Defaults to nocache session.cache limiter control method to use for session pages session.cache expire specifies time-to-live for cached session pages in minutes, this has no effect for nocache limiter. Defaults to 180 A PHP4 sessionkezelője session start Session adatok inicializálása session destroy Session adatok megszüntetése session name Session név lekérdezése, beállítása session module name Session kezelő modul nevének lekérdezése/beállítása session save path Session mentési könyvtár lekérdezése beállítása session id Sessin ID (SID) lekérdezése/beállítása session register Register one or more variables with the current session session unregister Unregister a

variable from the current session session unset Session változók felszabadítása session is registered Megmondja, hogy egy változó regisztrálva van-e a sessionben session get cookie params Beolvassa a session cookie parametereket session set cookie params Beállítja a session cookie parametereket session decode Dekódolja a session adatokat egy stringből session encode Stringbe tárolja le a session adatokat 47 11.55 COOKIE-k (sütik) A cookiek használata a PHP környezetben lehetséges, de nem igazán ajánlott. A PHP alkalmazások a szerveren futnak és általában valamiféle user azonosításhoz kötöttek. A cookike-k használata esetén a cookie-ban tárolt adatok átkerülnek a böngészőt futtastó számítógépre és ott egy textfile-ban tárolódnak, aminek a visszafejtése csak idő kérdése, éppen ezért fontos vagy titkolni való adatot a cookie-kba sohas ne tároljunk, inkább használjunk sessionöket. bool setcookie ( string nev, string ertek,

int lejarat, string utvonal, sting domain, int titkos) A fenti függvény minden paramétere az elsőt kivéve elhagyható. A függvényt a html oldal headerében kell elküldeni, mielőtt az oldalra bármit kiírnánk! Az alábbi példában elküldünk egy egyszerű értéket: Param Leírás Példa Nev A süti neve teszt’ nevű változót hozzuk létre $ COOKIE[teszt] Ertek Ez az érték tárolódik a kliens Ezt az értéket tároljuk a teszt nevű változóban. $ertek oldalon =$ COOKIE[teszt] Lejarat A süti lejárati ideje másodtime()+60*60242 két napot állítunk be lejáratnak. Ha percekben megadva. Beállítása nincs beállítva, akkor aböngésző bezárásáig érvényes a süti. time() + lejárati idő. Utvonal Hol tároljuk a sütiket. Minden böngédsző rendelkezik egy alapértelmezett süti tárhellyel. Beállíthatjuk, hogy ehhez képest hol tárolja a sütiket. Például a /fz/ az fz alkönyvtárba teszi a sütiket Domain Az a domain, amire érvényes a

Itt adhatjuk meg, hogy melyik aldomainre legyen érvényes a süti süti. A wwwfzinihu esetén csak erre a domainre érvényes Titkos Ha az érték 1, akkor csak 0 vagy 1 , alapérterlmezés 0 HTTPS esetén küldi sütit. <?php $ertek = Ez itt a példaszöveg; setcookie ("teszt", $ertek); setcookie ("teszt", $ertek,time()+3600); /* egy óra múlva jár le a süti / setcookie ("teszt", $ertek,time()+3600, "/fz/", ".fzinihu", 1); /* Az /fz alkönyvtárban, a www.fzinihu domain és https protokoll esetén */ ?> Tömböket is tárolhatunk sütikben. <?php // A sütik beállítása setcookie ("cookie[three]", "cookiethree"); setcookie ("cookie[two]", "cookietwo"); setcookie ("cookie[one]", "cookieone"); // A következő oldalon betöltve az alábbi kóddal irathatjuk ki az adatokat: if (isset($ COOKIE[cookie])) { foreach ($ COOKIE[cookie] as $name => $value) { echo

"$name : $value <br /> "; } } /* Ez three two : one : */ ?> lesz az eredmény : cookiethree cookietwo cookieone A PHP 3 esetén fordított sorrendben kellett elküldeni a sütiket, mint ahogy tárolni szeretnénk, a PHP4 esetén már a sorrend a tárolási sorrendnek megfelelő. 48 A következő oldalt betöltve a böngészőbe a sütik automatikusan megjelennek a $ COOKIE tömbben, és azokat az értékeket lehet használni. Ha a register globals paramétert bekapcsoljuk a phpini-ben, akkor automatikusan létrejönnek a megfelelő változók, de korábban említettük, hogy ennek a paraméternek a bekapcsolása nem javallott. Ha a $ COOKIE tömb értékeit debuggolás céljából ki akarjuk iratni, akkor használjuk a következő utasítást: <?php Print r($ COOKIE) ?> 49 12 Konverzió Adattípusok között A PHP automatikusan, és meglehetősen szabadon kezeli a típusokat. Néha szükség lehet egy bizonyos adattípus alkalmazására. Ekkor

használhatjuk az alábbi módszereket: Előírjuk a típust, mint a C-ben: $a = (float) $b; $c = (int) $c; Használhatjuk a bool settype ( $valtozo, ”tipus”) függvényt. Ekkor a tetszőleges típusú $változó-t átkonvertáljuk az adott típusra. A konverzió sikerességéről bool eredményt ad vissza a függvény Lehetséges tipus értékek: • • • • • • • "boolean" (vagy a PHP 4.20 óta "bool") "integer" (vagy a PHP 4.20 óta "int") "float" (csak a PHP 4.20 óta, korábban "double") "string" "array" "object" "null" (a PHP 4.08 óta) TRUE értéket ad siker esetén, FALSE értéket egyébként. $ize = "5valami"; // string $valami = true; // boolean settype($ize, "integer"); // $ize most 5 (integer) settype($valami, "string"); // $valami most "1" (string) 50 13 Tömbök A tömbök, azok különböző lehetőségei, és

az azok köré felsorakoztatott függvények a PHP programozás egyik legerőteljesebb eszközrendszerét alkotják, ugyanakkor rendkívül egyszerűen és könnyedén használhatók. A tömb változók halmaza, melyeket a tömbön belül sorban tárolhatunk és a teljes adathalmazt egyszerre is kezelhetjük, ugyanakkor a tömb elemeihez külön-külön is hozzáférhetünk. Fontos tulajdonsága a tömböknek, hogy egy tömbön belül az elemek típusa különböző lehet. Egy tömb elemeit legegyszerűbben explicit módon, elemenként tölthetjük fel: $tomb[1] $tomb[2] $tomb[4] $tomb[5] = = = = "dBase"; "FoxPro"; "Clipper"; 42; Látható, hogy a tömb elemeinek megadásakor nem szükséges a sorrendiséget szigorúan betartani. Egy tömb elemeihez a fentieknél egyszerűbben is, a tömbindex használata nélkül is lehet elemeket adni: $tomb[] = "Basic"; $tomb[] = "FoxPro"; Ily módon a tömb végéhez kapcsolódnak az új elemek,

az index értéke pedig az legutolsó indexelemnél eggyel magasabb lesz. Hasonlóan működik az array push() függvény, azzal a különbséggel, hogy egy utasításon belül több értéket is hozzáfűzhetünk a tömbhöz: array push($tomb, "Cobol", "Fortran"); Szép lassan dagadó tömbünk a fenti utasításokat követően már így néz ki: Array ( [1] [2] [4] [5] [6] [7] [8] [9] ) => => => => => => => => dBase FoxPro Clipper 42 Basic FoxPro Cobol Fortran Természetesen a tömbök értékeinek megadásához hasonlóan férhetünk hozzá a tömbelemekhez, azonban a fent említett array push() függvény párja, az array pop() függvény is rendelkezésünkre áll, mely azonban nemcsak egyszerűen a tömb utolsó elemét adja vissza értékül, hanem a tömb elemeinek számát is csökkenti az utolsó elemmel: $nyelv1 = $tomb[1]; // $nyelv1 értéke "dBase" $nyelv2 = $tomb[4]; // $nyelv2 értéke "FoxPro" $nyelv9

= array pop($tomb);// $nyelv9 értéke "Fortran" és a tömb nyolc elemű lesz Bonyolítsuk egy kicsit a dolgokat. Ezidáig a tömbünk egy dimenziós volt, azonban a PHP nyelvben a tömbök kettő vagy akár több dimenziósak is lehetnek. Az értékadás legegyszerűbb módja ilyen esetben is az explicit értékadás: $auto[1][1] $auto[1][2] $auto[2][1] $auto[2][2] $auto[3][1] $auto[3][2] = = = = = = "Maserati"; "olasz"; "Renault"; "francia"; "Mercedes"; "német"; a tömb valahogyan így fog kinézni: Array ( [1] => Array ( [1] => Maserati [2] => olasz 51 ) [2] => Array ( [1] => [2] => ) [3] => Array ( [1] => [2] => ) Renault francia Mercedes német ) Ilyen és ehhez hasonló tömbök létrehozására, azonban sokkal tömörebb és olvashatóbb módszer az array() függvény használata. Ez a függvény a paraméterként megadott értékeket tömb formában adja vissza. Így

a fenti értékadással pontosan megegyező eredményt ad a következő: $auto[1] = array( "Maserati" , "olasz" ); $auto[2] = array( "Renault" , "francia" ); $auto[3] = array( "Mercedes" , "német" ); Ahogyan azonban a tömbelemek típusaira vonatkozóan nincsenek túl szigorú megkötései a PHP nyelvnek, ugyanúgy nem kezeli szigorúan a többdimenziós tömbök elemszámait sem a PHP. Az alábbi értékadás teljesen helyes eredményt ad: $auto[1] = array( "Maserati" , "olasz" ); $auto[2] = array( "Renault" , "francia" , "406", "206" ); $auto[3] = array( "Mercedes" , "német" , "E320", "Vito" , "Sprinter kisteherautó" ); Természetesen az array pop() és az array push() függvények az array() függvénnyel ötvözve több dimenziós tömbök esetén is használhatók. array push( $auto, array("Citroen"

, "francia" , "ZX" , "Xsara"); A fenti esetekben a tömb elemei azok sorszámaival voltak azonosítva. A PHP ismeri az asszociatív tömbök fogalmát is. Az asszociatív tömbök rendkívül hasznos és sokoldalú elemei a PHP nyelvnek A PERL nyelvben használt hash típusú tömbökhöz hasonlóan működnek. A tömbelemekre való hivatkozás ilyen esetben nem sorszámmal, hanem egy indexelem (kulcs) segítségével történik, egyszerűen úgy, hogy a sorszám helyére, az indexelemet helyezzük. $tomb["első"] = "Kis Gedeon"; $tomb["második"] = "Nagy Elemér"; Függetlenül attól, hogy a tömb elemeinek milyen sorrendben adtunk értéket, az elemeket az indexkulcs segítségével érhetjük el, és ez nem függ attól, ha a tömbhöz hozzáfűzünk, vagy attól elveszünk egy elemet. Új elem bármikor hozzáfűzhető a tömbhöz: $tomb["harmadik"] = "Kukonya Berkó"; Az asszociatív

tömbök lehetnek egydimenziósak, mint a fenti példában, de lehetnek több dimenziósak is. A fenti példát kibővíthetjük több dimenzióssá: $tomb["első"]["neve"] = "Kis Gedeon"; $tomb["első"]["kora"] = 27; $tomb["második"]["neve"] = "Nagy Elemér"; $tomb["második"]["kora"] = 22; Ha a "Nagy Elemér" értékű elemet a $tomb["második"]["neve"] hivatkozással tudjuk elérni, de ha $sorszam értéke "második" akkor akár $tomb[$sorszam]["neve"] hivatkozással is elérhetjük a keresett elemet. 52 A normál és az asszociatív tömbök létrehozására egyaránt használható az array() függvény, amit leginkább tömbök kezdő értékfeltöltése során használhatunk, egy értékadással kiküszöbölve többet. A fenti példákkal megegyezőek az alábbi értékadások: $tomb = array ( "első" =>

"Kis Gedeon", "második" => "Nagy Elemér"); $tomb = array ("első" => array ("neve" "kora" "második" => array ("neve" "kora" => => => => "Kis Gedeon", 27), "Nagy Elemér", 22) ); Mint az alábbi példa is mutatja, az értékadás esetén az index értékét nemcsak konkrétan, hanem változóval is megadhatjuk, így már meglehetősen rugalmasan töthetjük fel tömbjeinket adatainkkal. A következő példa megmutatja a print r() függvény használatát is, amit tetszőleges változó értékének kiíratásához használhatunk, de mivel tömbváltozó esetében a komplett tömbstruktúrát is megjeleníti leginkább tesztelési célokra használható nagyon jól. <?php $nick1 = "Tabbi"; $nick2 = "Chris"; $tomb = array ( $nick1 => array("nev" => "Tabi Imre", "email" =>

"tabbi@freemail.hu"), $nick2 => array("nev" => "Nagy Krisztián", "email" => "chris@nomail.hu") ); echo("<PRE><b>"); print r($tomb); echo("<HR>"); print r($tomb["Tabbi"]["nev"]); echo("</b></PRE>"); ?> A program kimenete a következő lesz: Array ( [Tabbi] => Array ( [nev] => Tabi Imre [email] => tabbi@freemail.hu ) [Chris] => Array ( [nev] => Nagy Krisztián [email] => chris@nomail.hu ) ) Asszociatív tömbök esetében azonban figyelemmel kell lenni arra, hogy ilyen tömb elemeit kizárólag a meghatározott indexértékkel érhetjük el, a tömb sorszámával nem. Ennek rendkívül egyszerű az oka Az egyszerű sorszámozott tömb is asszociatív tömb, ahol a tömbindex maga a sorszám. Sőt egy tömbön belül keverhetjük is a sorszámozott és az indexelt elemeket, de azért ezt kerüljük, csak gondot okozunk magunknak.

A normál és az asszociatív típusú tömbök a PHP programozás során rendkívül változatosan és hatékonyan használhatók, főleg akkor, ha tudjuk azt, hogy a PHP a tömbök elemeire, az elemszámokra és a tömbelemek típusaira vonatkozóan rendkívül szabad kezet ad nekünk: - többdimenziós tömbön belül az egyik index lehet asszociatív, a másik normál - többdimenziós tömb esetében a tömbelem tömböknek nem kell feltétlenül azonos elemszámúaknak lenni, vagyis $tomb[1] lehet öt elemű, míg $tomb[2] lehet akár 8 elemű is. - egydimenziós tömbök esetében a tömbelemek lehetnek különbözű típusú adatok, de még többdimenziós tömbök esetében sem kell a tömbelem tömbök adatszerkezetének megegyeznie. 53 Vagyis elég nagy szabadsággal használhatjuk a tömbváltozókat, mégis érdemes szem előtt tartani, hogy ha lehet, járjunk el következetesen a változók értékadásával és azok használatával. A PHP nyelvben a

tömbváltozókhoz is egy egész sor függvény és utasítás kapcsolódik. Ezek a http://weblabor.hu/php/refarrayphp címen találhatók meg Ezek a függvények egy egész sor feladatot láthatnak el kezdve a tömbök definíciójától az értékfeltöltésen és a tömbben való mozgáson keresztül a tömbelemek legváltozatosabb módú sorbarendezéséig. Mivel a tömbök a PHP programozás során igen kiterjedten használatosak, és a tömbökhöz kapcsolódó függvények fontossága kiemelkedő, így ezen függvényekből a fontosabbakat a következő részekben részletesebben is tárgyaljuk majd. 54 14 Sztringek, szövegek manipulációja A továbbiakban néhány gyakran előforduló szövegmanipulációs feladat megoldását tekintjük meg PHPban. Természetesen sok olyan feladat van, amit máshol, máshogy már vagy még érintünk, illetve sok egyéb, itt nem megemlített függvény található a stringkezelésnél. A példák a php manualból valók! Gyakori, hogy

egy string hosszát meg szeretnénk tudni: strlen() Ha egy string valahány karakterét ki akarjuk venni a szövegből, akkor a használandó függvény: substr() A 2. és harmadik paraméter lehet negatív is Ekkor a jelentésük a szöveg végéről értendő <?php $l=strlen(”szevasz tavasz!”); $rest = substr("abcdef", $rest = substr("abcdef", $rest = substr("abcdef", $rest = substr("abcdef", $string = abcdef; echo $string{0}; echo $string{3}; $rest = substr("abcdef", $rest = substr("abcdef", $rest = substr("abcdef", $rest = substr("abcdef", $rest = substr("abcdef", $rest = substr("abcdef", $rest = substr("abcdef", ?> 1); 1, 3); 0, 4); 0, 8); // // // // returns returns returns returns "bcdef" "bcd" "abcd" "abcdef” // returns a // returns d -1); // returns "f" -2); // returns "ef" -3, 1); // returns

"d" 0, -1); // returns "abcde" 2, -1); // returns "cde" 4, -4); // returns "" -3, -1); // returns "de" Ha ki akarom cserélni a szöveg egy részét más részre, akkor: substr replace() . <?php $var = ABCDEFGH:/MNRPQR/; echo "Eredeti: $var<hr> "; // Beszúrjuk a bob szót a $var elejére echo substr replace($var, bob, 0, 0) . "<br> "; // Ha a második paraméter negatív, akkor a szöveg végéről indul a csere. echo substr replace($var, bob, 10, -1) . "<br> "; echo substr replace($var, bob, -7, -1) . "<br> "; // Töröljük a szöveg elejéről echo substr replace($var, , 10, -1) . "<br> "; ?> A szövegben egyes karakterek, stringek előfordulásait kicseréljük másik stringekre. Str replace() <?php // Eredmény: <body text=black> $bodytag = str replace("%body%", "black", "<body text=%body%>"); //

Eredmény: Hll Wrld f PHP $vowels = array("a", "e", "i", "o", "u", "A", "E", "I", "O", "U"); $onlyconstants = str replace($vowels, "", "Hello World of PHP"); // Provides: You should eat pizza, beer, and ice cream every day $phrase = "You should eat fruits, vegetables, and fiber every day."; $healthy = array("fruits", "vegetables", "fiber"); $yummy = array("pizza", "beer", "ice cream"); $newphrase = str replace($healthy, $yummy, $phrase); ?> Ha egy string helyét akarom megtudni egy másik stringben, akkor: strpos(); Ugyanez a végéről: strrpos() 55 Ugyanezek kis/nagybetű érzéketlen módon: stripos(), strripos() <?php $findme = a; $mystring1 = xyz; $mystring2 = ABC; $pos0 = strpos ($mystring1, ”x”); $pos1 = stripos($mystring1, $findme); $pos2 = stripos($mystring2, $findme); if

($pos0 === false) { echo "A $findme stringet nem találtam a $mystring1 stringben"; }else{ echo "Az x karakter helye: $pos0"; } // a nincsen xyz-ben if ($pos1 === false) { echo "A $findme stringet nem találtam a $mystring1 stringben"; } if ($pos2 !== false) { echo "Megtaláltuk a $findme stringet $mystring2 stringben ezen a helyen: $pos2"; } ?> Egy string kiegészítése karakterekkel: str pad() <?php $input = "Alien"; print str pad($input, print str pad($input, print str pad($input, print str pad($input, ?> 10); 10, "-=", STR PAD LEFT); 10, " ", STR PAD BOTH); 6 , " "); // // // // produces produces produces produces "Alien " "-=-=-Alien" " Alien " "Alien " Ha egy szöveg elejéről és végéről le akarom vágni a bevezető és a záró szóközt, tab-ot, soremelés karaktert, akkor a trim() függvényt használhatom. Ha csak a szveg elejéről

akarom levágni a fent említett karaktereket, akkor ltrim(), ha a végéről, akkor rtrim(). Az alapesetben levágandó karakterekhez további kiegészítéseket is rendelhetek. <?php $text = " These are a few words :) . "; $trimmed = trim($text); // $trimmed = "These are a few words :) ." $trimmed = trim($text," ."); // $trimmed = "These are a few words :)" $clean = trim($binary,"x00.x1F"); // trim the ASCII control characters at the beginning and end of $binary ?> Érdekes lehetőség bizonyos speciális karakterek, tag-ek kihagyása a stringekből, illetve bizonyos speciális karakterek beszúúrása: Strip tags(), htmlentities(), htmlspecialchars(),stripslashes(), <?php $str = "Is your name O eilly?"; // Kivettük az idézőjel karaktert. Eredmény: Is your name Oreilly? echo stripslashes($str); echo strip tags($string, <a><b><i><u><span><body>); $str = "A quote is

<b>bold</b>"; // Kimenet: A quote is &lt;b&gt;bold&lt;/b&gt; echo htmlentities($str); 56 //Kivettük $new = htmlspecialchars("<a href=test>Test</a>", ENT QUOTES); echo $new; // &lt;a href=&#039;test&#039;&gt;Test&lt;/a&gt; ?> Gyakori feladat, hogy sté kell vágni egy stringet valailyen karakter mentén darabokra, például szavakra, ahol a szavakat határoló karakter többféle is lehet. Az eredmény egy stringekből álló tömb lesz: Explode() <?php // Example 1 $pizza = "piece1 piece2 piece3 piece4 piece5 piece6"; $pieces = explode(" ", $pizza); print $pieces[0]; // piece1 print $pieces[1]; // piece2 // Example 2 $data = "foo:*:1023:1000::/home/foo:/bin/sh"; list($user,$pass,$uid,$gid,$gecos,$home,$shell) = explode(":",$data); print $user; // foo print $pass; // * ?> Az alábbi példa egy PHP oldalról keresztreferenciát készít és kiírja a

beinclude-olt file-okat. <?php /* * Crossreference v1.0 * It makes a crossreference list about the * variables of current script * with command line PHP interpreter. * * Copyright by Fabian Zoltan 2004 * */ $lines = array(); $vars = array(); $terminal = array(" ","<",">","=",";",")","(",")",""","","!","+",""," ","*","/","?","&",":",".","#","@","{","}","[","]","|","%",","); $ar=str replace("\","/",$argv); //Az összes \ jelet /-re cserélem $text=file($ar[1]); //Megnyitom a file-t function includes($f) { $terminal = array(" ",";","!","+","-","*","/","="," "); //A

szöveghatároló jelek listája $fileterm = array(""",""); $inc =array(); //includes calling $lines = array(); $out = ""; $v = ""; $token = array("include","include once","require"," require once"); $text=file($f); while (list ($key, $val) = each ($text)) { $lin = str replace($terminal," ",$val); if( (strpos($lin,$token[0])>0) or (strpos($lin,$token[1])>0) or (strpos($lin,$token[2])>0) or (strpos($lin,$token[3])>0) ) { $lines[]=str replace($terminal," ",$val); } } $i=0; /*while ($i<$sizeof($lines)){ if( ) { $out .= includes($f); } 57 $i++; } */ print r($lines); Return $out; } // Variables crossreference function variables($text) { global $terminal,$lines,$vars; //change Terminator characters while (list ($key, $val) = each ($text)) { $lines[]=str replace($terminal," ",$val); } $splitted =array(); $line=0; while(list($key,$row)= each($lines)) {

$splitted = explode(" ",$row); //Szétvágom szavakra a sort. Az eredmény egy tömb for($i=0; $i<sizeof($splitted); $i++) { $st = $splitted[$i]; if(substr($st,0,1)== "$"){ if(!isset($vars[$st])) $vars[$st] = "->".sprintf("%4d",$line)", "; else $vars[$st].= sprintf("%6d",$line)", "; } } $line++; } ksort($vars); $out = "--------- Variables --------- "; while (list ($key, $val) = each ($vars)) { $out .=str pad($key,10)$val" "; } Return $out; } printf(variables($text)); printf(includes($ar[1])); ?> 58 15 Formok /űrlapok – Interaktív programok írása A PHP és általában a WEB-es programozás egyik sarokköve volt az interaktivitás megjelenése. Ehhez arra volt szükség, hogy a böngészőnkön beírt adatokat vissza tudjuk küldeni a szervernek, amely azt feldolgozza. A HTML-ben lehet űrlapokat létrehozni az alábbi szintaktikával: <form name=Urlap action=index.php

method=xxxx> <INPUT .> </form> A fenti xxxx= vagy GET vagy POST metódus lehet. Az űrlapok belsejében minden html elemet használhatunk, és itt használhatunk olyan beviteli mezőket, amelyek változóknak adnak értéket. A POST és a GET metódus segítségével a változók neve és értéke eljut az action-nal megjelölt laphoz, amely azt fel tudja dolgozni. Az űrlapon belül az alábbi adatbeviteli lheetőségek vannak: <INPUT TYPE=’TEXT’ Name=”text” VALUE=”Kezdőszöveg” WIDTH=”60”> Egy soros szöveg bevitelére szolgál <INPUT TYPE=’PASSWORD’ Name=”text” VALUE=”Kezdőszöveg” WIDTH=”60”> - Egy soros password, beviteléhez kell. 15.11 Önmagukat meghívó űrlapok Gyakori feladat, hogy egy Űrlapot meghívunk, leellenőrizzük és a következő oldalon csak akkor küldjük tovább a böngészőt, ha az oldal hibátlanul ki van töltve. Ehhez az alábbi dolgoknak kell teljesülnie: Az űrlapot saját magának

küldi el a PHP oldal Amikor beérkezik a kérés a szerver oldalon ellenőrizzük a megfelelő értékek meglétét. Ha az értékek megvannak, akkor feldolgozzuk őket Ha nincsenek meg az értékek, akkor újra meghívjuk a feldolgozandó adatot: Az alábbi példában két rértéket küldünk el egy feldolgozandó oldalnak. Ha nincs kitöltve mind a két érték, akkor újrahívjuk a feldolgozandó oldalt. A feldolgozás részen a feldolgozott értékek valamiféle lekérdezésbe torkollnak vagy akármilyen egyéb műveletet végezhetünk vele. Javasolt egyéb műveletek: Az átadott adatok típus szerinti ellenőrzése. Erre használhatók az alábbi függvények: is bool() – logikai-? is int(), is integer() – egész-e? is float(), is real(),– lebegőpontos-e? is object() – Objektum-e? is array(). – Tömb-e? Is string() – string-e? Az átadott adatokból célszerű kivenni a HTML kódokat, mivel biztonsági problémák merülhetnek fel <?php $string = strip

tags($string); ?> Az átadott értékekből célszerű kiszedni a [{()}] jeleket. 59 Ha az így bevitt értékek közvetlenül SQL lekérdezések összeállítására használatosak, akkor célszerű még egyéb speciális jelek kivétele is, például = <> OR, AND ! stb. $a =array(”[”,”{”,”(”,”)”,”}”,”]”,”or”,”and”,”!”); $str = str ireplace($a, " ", $str); <?php $OK=’’; $nev =’’; $pwd=’’; $uz =’’; if (isset($ POST[’OK’]) $OK =$ POST[’OK’]; if (isset($ POST[’nev’]) $nev =$ POST[’nev’]; if (isset($ POST[’pwd’]) $pwd =$ POST[’pwd’]; if ($OK =”OK”) { $nev =$ POST[„nev”]; $pwd =$ POST[”pwd”]; //HTML tag-ek kiszedése $nev = strip tags($nev); $pwd = strip tags($pwd); //speciális jelek kivétele $a =array(”[”,”{”,”(”,”)”,”}”,”]”,”or”,”and”,”!”); $str = str ireplace($a, " ", $str); if (!isset($nev) or empty($nev)) if (!isset($pwd)

or empty($pwd)) $uz =’Töltsd ki a név beviteli mezőt”; $uz .=’Töltsd ki a jelszó beviteli mezőt”; } if (!empty($uz)){ //Form kiiratása print(”<P>”.$uz”</P>”); print(’<FORM METHOD=”POST”>’); print(”<Table>”); print(”<TR><TD>Név:</TD><TD> print(”<input type=’text’name=’nev’ value=’”.$nev”’>”); print(”</TD></TR>”); print(”<TR><TD>Jelszó:</TD><TD>”); print(”<input type=’password’name=’pwd’ value=’”.$pwd”’></TD></TR>”); print(”<TR><TD> </TD><TD>”); print(”<input type=’submit’ name=’OK’ value=’OK’>”); print(”</TD></TR></TABLE>”); print(’</FORM>’); }else{ /* Feldolgozás/ } ?> 60 16 Formok adatainak feldolgozása – szerver- és kliens oldalon A PHP-ben a HTML űrlapok (FORM-ok) felhasználásával történik

meg az interakció a felhasználó és programja között. Az űrlapok használatának gyakori formája, hogy az űrlap a saját magát tartalmazó oldalt hívja meg és az űrlap kitöltöttségét olyan kóddal ellenőrizzük, amely ugyanazon az oldalon van. Ez célszerűen azért lehet így, mert a beviteli formátum és az ellenőrzés is egy helyen található. A példában egy egyész típusú, 1000-nél nagyobb adatot és egy folyószámla nevet vár a beviteli oldalon a program. Urlap.php <?php $message = ’’; $adat =’’; $ok = True; if (isset($ POST(”OK”) && $ POST[”OK”] ==”Elküld”){ // Ellenőrizzük az adat léteznik-e és megfelelő formátumúak? $adat = -1; if (isset($ POST[”adat”])){ $adat= $ POST[”adat”]; if (is int($adat)){ if (!($adat>1000)){ $ok = $ok && False; //Ezernél nagyobb értéket ellenőrzök éppen $mess adat = ’<FONT color=”#FF0000”>Túl kicsi érték!</FONT><BR>’; } }else{ $mess

adat = ’<FONT color=”#FF0000”>Hibás adattípus!</FONT><BR>’; } }else{ $mess adat = ’<FONT color=”#FF0000”>Hiányzó adat!</FONT><BR>’; } //Ellenőrizzük, hogy a folyószámla neve megfelel-e? $fszamla = -1; if (isset($ POST[”fszamla”])){ $fszamla= $ POST[”fszamla”]; if (is string($fszamla)){ $fszamla = $urldecode($fszamla); //Esetleges URL kódolás dekódolja $fszamla = strip tags ( $fszamla); //kiveszi a HTML és PHP tageket $fszamla = stripcslashes ( $fszamla); // kiveszi a jeleket //SQL injekció kiszűrése!!! $keres = array (”WHERE”,”LIKE”,”(”,”)”); $csere = array (” ”,” ”,” ”,” ”); $fszamla = str replace($keres,$csere,$fszamla); if (van e szamla($fszamla)){ $ok = $ok && False; //Ezernél nagyobb értéket ellenőrzök éppen $mess fszamla = ’<FONT color=”#FF0000”>Nincs ilyenfolyószámla!</FONT><BR>’; } }else{ $mess fszamla = ’<FONT

color=”#FF0000”>Hibás adattípus!</FONT><BR>’; } }else{ $mess fszamla = ’<FONT color=”#FF0000”>Hiányzó adat!</FONT><BR>’; } . itt ellenőrizzük a többi szükséges mező értékét és létezését } if(!$ok){ print(’<FORM name=”pelda” action=”urlap.php” method=”POST”>’); print($mess adat); print(<’INPUT type=”text” name=”adat” value=<% = $adat %> > ’); print($mess fszamla); print(<’INPUT type=”text” name=”fszamla” value=<% = $fszamla %> > ’); . további beviteli mezők . print(’<INPUT type=”submit” name =”OK” value=”Elküld”>’); print(’</FORM>’); }else{ 61 . adatok feldolgozása header("Location: http://www.examplecom/"); exit; //A böngészőt átdobom a következő oldalra // a kód többi része ne fusson le } A párbeszédek alkalmazásánál fontos, hogy ellenőrizzük a bevitt adatokat, mivel véletlenül,

akarva vagy akaratlanul olyan adatok kerülhetnek a meghívott oldalra, aminek típusa, formátuma nem felel meg az elvárásoknak ennek érdekében az alábbi ellenőrzéseket célszerű megtenni: • Egy oldalon minden mező ki van-e töltve • A megfelelő típusú, formátumú adat került-e bele • Nincs-e benne HTML vagy PHP, vagy SQL utasítás kód (ezek sanda szándékok esetén szoktak bekerülni) Az ellenőrzést két lépcsőben célszerű megtenni. A kliens oldalon megfelelő Javascript kód segítségével és a szerveroldalon a PHP kód segítségével, mint fent is látszik. Bár a Javascript ennek a jegyzetnek nem témája, azért az ellenőrzésre adunk példát itt. A megoldás alapja, hogy minden beviteli mező vagy a Formon lévő ”Elküld” gomb megnyomására lefut egy ellenőrző script a böngészőn, ami ellenőrzi, hogy ki vannak-e töltve a megfelelő mezők. A Javascript ellenőrzés ugyanakkor nem helyettesíti a PHP oldali ellenőrzést, mert a

böngésző oldalon megfelelő technikákkal el lehet kerülni az ellenőrzést. 62 17 Levélküldés, plain text, html levél, attachement A PHP-ban van lehetőség arra, hogy leveleket küldjünk el megadott címre, megadott tartalomal. Az üzenetküldéshez először a PHP.INI-ben be kell lenni állítani az alábbi szakasz értékeit Az alábbi sorok a Win32-es rendszeren beállítandókat tartalmazza. Be kell állítani annak az SMTP szervernek a címét kell írni, amelyik elküldi a levelünket és annak a usernek a nevét, akivel defaultban küldünk levelet. [mail function] SMTP = mail.szilysulinethu ;for win32 only sendmail from = fz@mail.szilysulinethu ;for win32 only A levél elküldése a mail paranccsal történik, de mielőtt elküldenénk, létre kell hozni azokat a stringeket, amelyek segítségével a levél különböző szakaszai létrejönnek. $cimzett = fz@mail.szilysulinethu; $tema = ”drágám”; $uzenet = ”A kölykök összementek. Mind a kettőt

hiába keresem Géza” $fejlecek .= "From: Tőlem <geza@kekazegto> "; $fejlecek .= "X-Sender: <birthday@phpnet> "; $fejlecek .= "X-Mailer: PHP "; // Levelezőprogram $fejlecek .= "X-Priority: 1 "; // Sürgős üzenet! $fejlecek .= "Return-Path: <geza@kekazegto> "; //Hiba esetén ide jön levél mail($cimzett, $tema, $uzenet, $fejlecek); A levél szövegét és a fejlécet tovább cifrázhatjuk. A fenti mezőkön kívül használhatjuk például a cc: bc: Reply-To: és a hasonló fejléc mezőket is. Hogy milyen mezőket lehet használni, bámelyik leveled fejlécéből kinézheted. Sajnos az attachmentek kezelése nem tartozik ele a php által támogatott dolgok körébe, ezért külső alkalmazás nélkül nem tudunk attachmentet küldeni php-ben. Egy lehetőség adódik komolyabb levelezési funkciók használatára. Meg kell hívni egy külső, parancssori levelezőszoftvert, amelynek a megfelelő

paraméterezésével tetszőleges levelezési funkcókat el lehet érni. Ilyen szoftver például a POSTIEEXE Windows alatt Ez a program és más hasonló programok az Internetről letölthetők. A levelezés kérdéskörében fontos, hogy formázott leveleket is tudjunk küldeni. Erre alkalmasak a HTML levelek. A HTML levelek küldéséhez elég sokmindent el kell végezni, alapesetben a PHP nem támogatja a HTML levelek küldését, de a NET-en találhatók egyszerű objektumcsomagok, amelyek ebben az esetben segítenek (http://phpmailer.sourceforgenet) Ennek a csomagnak a használatára álljon itt egy példa: <?php require("class.phpmailerphp"); $mail = new phpmailer(); $mail->IsSMTP(); $mail->Host = "smtp.mydomaincom"; $mail->SMTPAuth = true $mail->Username = "fz" $mail->Password = "titok" // // // // // set mailer to use SMTP specify main and backup server turn on SMTP authentication SMTP username SMTP password

$mail->From = "fz@mail.szilysulinethu”; $mail->FromName = "Levelező"; $mail->AddAddress("XY@mail.com", "X Y"); $mail->AddReplyTo("info@mail.com", "Information"); $mail->WordWrap = 50; $mail->AddAttachment("C: emp ext.zip"); $mail->IsHTML(true); // set word wrap to 50 characters // add attachments // set email format to HTML 63 $mail->Subject = "Ez itt a targy"; $mail->Body = "Ez a HTML szöveg rész <b>vastagon!</b>"; $mail->AltBody = "Ez a rész a nem HTMl szöveg"; if(!$mail->Send()) { echo "A szöveg nem ment el. <p>"; echo "Levelező hiba " . $mail->ErrorInfo; exit; } echo "A levél elment"; ?> A fenti csomag telepítésekor gondoskodni kell arról, hogy a PHP.INI-ben be legyen állítva az include path a class.phpmailerphp file-ra, amit az alábbi módon tehetünk meg futás közben: $incl

path = ini get("include path"); $incl path .= ”;/phpmailer”; ini set("include path", $incl path); 64 18 Adatbázisok A PHP programozási nyelv úgy kezeli az adatbázisokat, hogy a nyelvbe beépítették az elterjedt és támogatott adatbázis-kezelők támogatását. Az adatbáziskezelők általában SQL rendszerek, és kliensszerver minta szerint működnek együtt a PHP-val Egy PHP-val meghajtott adatbázis-kezelő rendszernek az alábbiakban éehet felrajzolni a működési sémáját: Szerver számítógép /szerver oldal HDD/ adatbázis ó Adatbáziskezelő program ó Adatbáziskezelő driver ó Kliens számítógép PHP ó WEB szerver ó Internet felhő ó WEB böngésző Egyes adatbázis-kezelőket a PHP alapból beépítve támogatja, míg másokhoz be kell tölteni a PHP.INIben a megfelelő sorok segítségével a támogatást A használhatóság módja három féle lehet: Alapból támogatja a PHP az aktuális rendszert Be kell

tölteni a megfelelő modult A Windows verzió esetén a PHP.INI file Windows Extensions részében az alábbi bejegyzés kell: Extensions = postgresql.dll Linux verzió esetén az alábbi sor kell: Extensions = postgresql.so Fordításkor be kell fordítani a támogató modult, LIB-ből A mi esetünkben az első és második módszer az, ami érdekes lehet. Természetesen minden esetben kell telepíteni egy adatbázis-szerver szoftvert, amely nem mindig ingyenes! Magyarországon elterjedt legfontosabb adatbáziskezelők az alábbiak Adatbáziskezelő Támogatás módja Az adatbázis-kezelő web címe Tulajdonságai MySQL Beépítve www.mysqlcom Free, gyors, Win és LINUX verzió létezik DBASE Beépítve www.dbasecom A dBase 3+ verzió standard, az adatcsere állományok gyakori formátuma. Nem ajánlott a használata éles alkalmazásban mSQL be kell fordítani www.hughescomau Kicsi, könnyen telepíthető, 14 napig free Ingres be kell fordítani www.ingrescom

Nem free, a Computer Associates fejleszti Interbase php interbase.dll www.interbasecom Teljes körű, jó adatbázis-kezelő, ajánlható, az InterBase 6.01 free! Microsoft SQL7.0/ 2000 php mssql70.dll php mssql.dll www.microsoftcom Régebbi verzió, létezik un. Personal és Evaulation Edition Minden MS fejlesztőtermék része a Personal Edition változat. Oracle8 php oci8.dll www.oraclecom Nem free, teljes körű, nagy tudású SQL szerver Oracle7 php oracle.dll www.oraclecom Nem free, teljes körű, nagy tudású SQL szerver régebbi verziói PostGres SQL php pgsql.dll www.postgresqlorg LINUX és Windows verzió is van, free, teljes SQL rendszer ODBC Beépítve Az ODBC = Open DataBaseConnectivity – A Microsoft által létrehozott, elvileg platform és adatbázis-kezelő független felület, minden elterjedt adatforrásnak van ODBC drivere. Win és Linux alatt is léteznek ODBC driverek 65 18.1 MySQL A fenti adatbázis-kezelőkről annyit, hogy jelenleg

a legelterjedtebb ilyen alkalmazás a Linuxon, Netware-en és Windows rendszereken is futó MySQL. Ez a rendszer talán a leggyorsabb az összes elterjedt adatbázis-kezelő között, de jelenleg a (MySQL 4.0*) MySQL nem valósítja meg az SQL összes lehetőségét, és nem támogatja a tárolt eljárásokat, továbbá a táblák közötti állandó (perzisztens) kapcsolatokat, csak egy speciális fajta adatbázis esetén (InnoDB). Ez a WEB-es alkalmazások esetén nem túlságosan nagy baj, mert azok tipikusan nem adatmódosítással foglalkoznak, hanem inkább lekérdezéssel, ebben pedig a MySQL nagyon gyors. A hírek szerint a MySQL 50 a fenti hiányosságokat kiküszöböli. A MySQL nagyon előnyös tulajdonsága, hogy GNU liszensszel lehet használni, azaz akkor is free, ha eladási céllal használjuk, de magát a MySQL adatbázis-kezelő programot nem adjuk el ( J). Miért is tennénk, ha egyszer az Internetről letölthető. A MySQL letölthető az alábbi címről:

http://www.mysqlcom/downloads/mysql-40html Telepítése egyszerű Windowson el kell indítani a ZIP-ből való kicsomagolás után a SETUP.EXE programot, a többit elkészíti ő. Ha firewall van a gépünkön, akkor a TCP/IP 3306-os portját kell szabaddá tennünk. Ha a szerver ugyanazon a gépen fut, mint amelyiken a WEB szervert és a PHP-t futtatjuk, akkor a Firewallon nem szabad (!) engedélyezni más gépről ehhez a porhoz való hozzáférést. Ha fejlesztés közben az adatbázisunkat módosítani akarjuk, különböző dolgokat akarunk elvégezni, akkor ajánlhatjuk a free phpMyAdmin nevű csomagot, illetve a professzonális, de pénzes EMS MySQL Manager programcsomagot. Magában a MySQL csomagban is van egy WinMySQLAdmin nevű eléggé bugyuta alkalmazás. Ha feltesszük a MySQL ODBC driverét, akkor viszont tetszőleges ODBC kompatibilis alkalmazásból el tudjuk végezni az adatok módosítását, feltöltését stb. Akár ez lehet egy Microsoft Access is. A MySQL

használatához dokumentációt innen lehet letölteni: http://www.mysqlcom/get/Downloads/Manual/manualchm-2002-10-07zip/from/pick 18.2 PostGres SQL A PostGres SQL egy kicsit komolyabb alkalmazás, mint a fent említett adatbázis-kezelő. A telepítése sajnos nem egyszerű, mivel alapvetően Linux-ra íródott program. A telepítés menetét Molnár László PHP listán közölt leírása alapján közlöm. 1. Letoltod: http://wwwcygwincom/setupexe 2. Ha megvan elinditod a setupexe -t Lassuk a telepitest: - Indulas utan kerdezi, hogy mit tegyen: * Install from internet * Download form internet <- EZT VALASZD * Install form local directory - Megkerdezi, hogy hova telepitsen (oda teszed ahova akarod) Kivalasztod a kapcsolatot Ha keri kivalasztasz egy szimpatikus mirrort ekkor letolti a setup.bz2-t Most jon a lenyeg elso fele SELECT PACKAGES A + jelekre kattintva kijeolheted, hogy mit toltson le ha kibomlik a lista, a Skip szóra kattintva kijeloli - itt celszeru minden kijeolni

hiszem most csak letoltod a csomagokat. - ha Tovabb lepsz szepen elkezd tolteni. (A teljes csomag lehet, akár 180 MB is!) Ha már letöltöttél minden csomagot, johet a telepites: Ujra futtasd a korabban letoltott setup.exe -t - Most valaszd az Install from local directoy -t - Add meg a root konyvtarat. (default: c:cygwin) - Add meg a csomagok helyet. (pl: f:ftprootftp%3a%2f%2fftpunivieacat%2fpackages%2fcygwin) - Jelöld ki azokat a csomagokat, amire szükséged lehet, illetve van, amit nem szabad kihagyni: 66 Archive - zip / unzip Database - postgresql !!!!!!!!! EZT NE HAGYD KI. EZERT JOTTEL :-)) Editors - valassz egyett. vagy mind :-)) Utils - bzip2 - ha nem teszed fel kesobb bajba lehetsz! - Ha kivalasztottad a szukseges csomagokat mehet az telepites (csak kattints a Tovabb gombra :-)))) Telepites kesz johet a postgreSQL. - most mart indulhat: futtasd: C:cygwincygwin.bat - es lass csodat ott a cygwin prompt. (Bshell prompt) Johet a inicializalas: $ ipc-daemon2 & $ initdb

-D /var/pgsql/data Ez is kesz! Akkor lassuk a medvet: FIGYELEM! az ipc-daemon & mindig ki kell adni ha nem fut :-)) Ezt eleg 1x megtenni amikor einditod a cygwin -t. Az server inditasahoz itt egy indito script, a neve és elérési helye: c:cygwininpg start #!/bin/bash ipc-daemon2 & postmaster -i -D /var/pgsql/data >/var/log/pgsql.log & Telepiteskor 1 usert felvesz a szerver, azt aki telepítette, tehát pl. magyar WinXP-n Rendszergazda. Ha elinditod pl. pgAdmin3-t, amit szintén le lehet tölteni a NET-ről, például innen: ftp://ftp2.czpostgresqlorg/pub/postgresql/pgadmin3/release/win32/pgadmin3-1 0 1zip Server: localhost Port: 5432 User: Rendszergazda <Login> Kész. A PostgresSQL használatához dokumentációt az alábbi helyen lehet elérni: http://www.postgresorg/docs/ Itt HTML és PDF formátumban vannak meg a megfelelő dokumentumok. 67 18.3 Adatbázis-kezelés natív módon Az adatbázis-kezelők használatához a PHP.INI-ben meg kell adni a

megfelelő beállítást (vagy, mint például a MySQL-nél, eleve a támogatás a rendszer része), és programunkban használhatjuk az adatbázisra vonatkozó utasításokat. A PHP az adatbáziskezelésre általában az alábbi utasításfajtákat tartalmazza. - Az adatbázis-kezelő szerverrel kapcsolatot teremtő, a kapcsolatot lezáró parancsok - Az adatbázisokra vonatkozó lekérdező és adminisztrációs parancsok - Egy megnyitott adatbázisra vonatkozó adminisztrációs és lekérdező parancsok - Az SQL lekérdezéseket átküldő parancs - A lekérdezés eredményét feldolgozó parancsok. A továbbiakban a MySQL utasításai alapján mutatom be az adatbáziskezeléssel kapcsolatos utasításokat. Más adatbáziskezelő esetén a változás általában csak annyi, hogy a névben az előtag más. Például: Mysql connect() //MySQL adatbázis-kezelő esetén pg connect() //PostgresSQL Kapcsolódás egy adatbáziskezelőhöz, amely vagy lokális gépen helyezkedik

el, vagy egy távoli, IP címmel meghatározott gépen. A kapcsolat létrehozása meg kell adni a kapcsolódási helyet (localhost, vagy IP cím), a kapcsolódó user-t, és a user jelszavát. $link = mysql connect(”localhost”,$username,$password); vagy $link = mysql pconnect(”localhost”,$username,$password); A fentiekhez egy kis magyarázat. A connect és pconnect között az a különbség, hogy a connect-tel megnyitott kapcsolat lezárul a kérdéses php oldal lefutása után, míg a pconnect kapcsolat nyitva marad (Persistent connection), és újbóli kapcsolódás során csak akkor kell egy viszonylag sokáig tartó kapcsolódási procedúrán átmennie a rendszernek, ha a kapcsolat nincsen nyitva. Egyébként a pconnect használata ugyanaz, mint a connect-é. A visszaadott érték a kapcsolat sorszáma. Ennek alapján lehet a továbbiakban azonosítani több megnyitott kapcsolat esetén, hogy éppen melyik kapcsolatot használjuk. A kapcsolat bezárása: mysql

close($kapcsolat) Példa <?php $link = mysql connect ("kraemer", "marliesle", "secret") or die ("Could not connect"); print ("Connected successfully"); mysql close ($link); ?> Az adatbáziskezelőn lévő adatbázisokra vonatkozó parancsok int mysql list dbs ([int link identifier]) int mysql create db (string database name [, int link identifier]) int mysql drop db (string database name [, int link identifier]) <?php $link = mysql pconnect ("kron", "jutta", "geheim") or die ("Could not connect"); if (mysql create db ("my db")) { print ("Database created successfully "); 68 } else { printf ("Error creating database: %s ", mysql error ()); } ?> int mysql select db (string database name [, int link identifier]) Egy konkrét adatbázis tábláinak kilistázása Egy adatbázis (lekérdezés) oszlopneveinek listázása. Ugyanez az utasítás a

lekérdezés eredményének tetszőleges adatait is kilistázza . object mysql fetch field (int result [, int result type]) Mezőnevek kiírása, és tárolása a mezonev tömbben <?php $result=mysql db query($querydb,$query); $m=mysql num rows($result); $n=mysql num fields($result); for($i=0;$i<$n;$i++) { //Oszlopnév/mezőnév bemásolása tömbbe későbbi felhasználásra $mezok=mysql fetch field($result); $meznev[]=$mezok->name; //Oszlop/Mező adatainak kilistázása. echo "<PRE> blob: $meta->blob max length: $meta->max length multiple key: $meta->multiple key name: $meta->name not null: $meta->not null numeric: $meta->numeric primary key: $meta->primary key table: $meta->table type: $meta->type unique key: $meta->unique key unsigned: $meta->unsigned zerofill: $meta->zerofill </PRE>"; } mysql close(); ?> Egy SQL parancs elküldése resource mysql query ( string query [, resource link identifier]) Az

Adatbáziskezelőnek adott SQL, vagy egyéb utasítás eredményének átvétele a pufferből. Az eredmény általában két dimenziós tömbbe érkezik, amelyet vagy a tömbkezelő függvények segítségével lehet feldolgozni, vagy indexel és ciklussal végig kell szaladni rajta. A visszaadott paraméterről mindig meg tudjuk mondani, hogy hány sorból áll. Az alábbi függvény megadja az eredmény sorainak számát Ha nincs eredmény sor, akkor az értéke 0. int mysql num rows() Ha Delete, Update utasítások eredményére vagyunk kiváncsiak, akkor az alábbi függvényt kell használnunk. int mysql affected rows ( [resource link identifier]) Egy sort ad vissza egy tömbbe az alábbi függvény. A tömb öt sorszámokkal lehet indexelni, a sorszámozás 0-val kezdődik. Akkor használhatjuk, ha egy lekérdezésről nem tudjuk előre, hogy hány sort ad majd vissza. array mysql fetch row([resource link identifier]) 69 Ennél a függvénynél szükségünk lehet a

visszaadott oszlopok számára is. Ezt az alábbi függvénnyel tudjuk meg: int mysql num fields ( [resource result]) Ez a függvény a sort szintén egy tömbben adja vissza, de a tömbelemek sorszámozva és a mezőnévvel is, mint asszociatív tömbindexxel elérhetők. array mysql fetch array([resource link identifier) Az alábbi példa elküld egy lekérdezést, az eredmény oszlopneveit lekérdezi, majd megjeleníti táblázatos formában. int mysql fetch object([resource link identifier]) Az alábbi példa elküld egy lekérdezést, az eredmény oszlopneveit lekérdezi, majd megjeleníti táblázatos formában. <?php . $qry = ”SELECT * FROM tabla”; $result=mysql db query($qry,$query); $m=mysql num rows($result); $n=mysql num fields($result); echo ”<TABLE><TR>”; for($i=0;$i<$n;$i++) { $mezok=mysql fetch field($result); echo "<TD>".$mezok->name"</TD>"; $meznev[]=$mezok->name; } echo"</TR>"; // mezok

kiirasanak vege // // mezokben levo adatok kiirasa // for($i=0;$i<$m;$i++) { echo"<TR>"; $adat=mysql fetch array($result); for($j=0;$j<$n;$j++) echo "<TD>".$adat[$meznev[$j]]"</TD>"; echo"</TR>"; } echo ”</TABLE>”; ?> 18.4 Tipikus feladatok adatbázis-kezelésnél Egy adatbázis-kezelő használata során az alábbi tipikusnak mondható feladatokat kell megoldani PHPban, (de hasonlóképpen más programozási nyelveken is). - Kapcsolódunk a szerveren lévő adatbázishoz.(láttunk mintát hozzá) - Elküldünk egy SQL lekérdezést az adatbázis-kezelő programnak (Láttunk mintát) - Az elküldött lekérdezésre kapott válasz általában egy táblázattal, vagy két-dimenziós tömbbel reprezentálható. Ezt szokás rekordszet-nek hívni Egy ilyen rekordszetet megjelenítünk, célszerűen táblázatos formában. Ha a rekordszet túl sok sorból áll, akkor vagy a lekérdezéskor adunk olyan

feltételeket, amely kevesebb sort ada eredményül, vagy megalkotjuk annak a lehetőségét, hogy a táblázat eredményét görgetni, vagy lapozni lehessen. (később általános mintát láttunk, az előző fejezetben bizonyos speciális eseteket néztünk) - A rekordszet egyes sorait „űrlap” formájában meg akarjuk jeleníteni (később látunk mintát a fejezetben) - Az űrlap vagy a rekordset eredményét ki akarjuk nyomtatni - Az adatbázisba új adatot akarunk bevinni. 70 o Egy rekordszethez illeszkedő új sorral o Egy rekordszethez illszkedő új sor-űrlap formájában bevitt adatokkal. o Minden adatbevitelnél valamilyen tipizálható ellenőrzési feladatot illik elvégezni, vagy a bevitt adatokat szintaktikailag és/vagy szemantikailag ellenőrizni illik. o Adatok bevitelekor vagy módosításkakor, amikor csak lehet az adatokat egy felkínált listából kelljen kiválasztani – a tévedések elkerülése miatt. - Adatok módosítása lehetőség

szerint az új adat bevitelével azonos formátumban és módon történjen. - Egyes adatok, adatsorok, rekordok törlése, ellenőrzött módon. - Az adatok bevitele vagy módosítása során, hibás adatfelvitel miatti ismétléskor a korábban bevitt vagy meglévő adat jelenjen meg a beviteli űrlapon. A fenti feladatokhoz az alábbi nem igazán PHP-ben megvalósított fogalmakat társíthatunk: Az adatok táblázatos megjelenéséhez az alábbi séma szerint érdemes eljárni abban az esetben, ha két dimenziós táblázatban kapom meg az adatokat. Print( ”<table>”); For($i=0;i<$maxsor;$i++){ Print(”<tr>”); For($j=0;$j<$maxoszlop; $j++);{ Print(”<td>); Print(adat[$i][$j]); Print(”</td>); } Print(”</tr>”); } print(”</table>”); Természetesen a táblázat formázását, a szegélyeket, stb mindenki a saját ízlése szerint alkothatja meg. Ha az adatokat soronként vezsem át az adatbáézis-kezelőtől, akkor a

fenti algoritmus kicsit megváltozik. Azt is megmutatom a következő példában, ha nem az oszlopok száma adott a lekérdezett rekordszetben, bár ezt is mindig meg lehet tudni egy adott esetben, hanem a mezőnevekkel, asszociatív módon tudok hivatkozni egy sorra. Erre az előző fejezetben láttunk példát <?php //egyszerű rekord megjelenítése $result=mysql db query($querydb,$query); $sor=mysql num rows($result); $n=mysql num fields($result); print(”<table>”); for($i=0;$i<$n;$i++) { print(”<tr>”); //Oszlopnév/mezőnév bemásolása tömbbe későbbi felhasználásra $mezok=mysql fetch field($result); $meznev[]=$mezok->name; //Oszlop/Mező adatainak kilistázása. print(”<td align=right>”); print($meznev[$i]); print(”</td>”) print(”<td>”); print($sor[$meznev]); print(”</td>”) print(”</tr>”); //A mező neve //A mező értéke } print(”</table>”); mysql close(); ?> A fenti

megjelenítés még elemi módomn sem alkalmas új adatok bevitelére, hiszen új adatokat WEB böngésző esetén csakis FORM-okon keresztül vihetünk fel. Mindezek mellett meg kell oldanunk a 71 mezők ellenőrzését is. Ennek megfelelően módosítanunk kell a fenti megoldást kissé A példáról annyit, hogy egy űrlap jelenik meg, amely a megjeleníti a mezőket egy INPUT HTML tag segítségével, amivel a z értéket rögtön módosítani is lehet. A bevitt adatokat minden mező esetén a böngésző javascript kódja rögtön ellenőrzi is (Hogy egyáltalán ki van-e töltve). Ha nincsen kitöltve, akkor hibaüzenet érkezik <HTML> <HEAD> </HEAD> <SCRIPT LANGUAGE="JavaScript1.2" type="text/JavaScript12"> function elenoriz() { var k=document.form1textvalue; if (k.length<1){ alert("Nincs kitöltve az adat!!"); return false; } else{ return true; } } </SCRIPT> <BODY> <?php //egyszerű rekord

megjelenítése $result=mysql db query($querydb,$query); $sor=mysql num rows($result); $n=mysql num fields($result); print(”<FORM name=”form1” ACTION=urlap.php method="get" "> print(”<table>”); for($i=0;$i<$n;$i++) { print(”<tr>”); //Oszlopnév/mezőnév bemásolása tömbbe későbbi felhasználásra $mezok=mysql fetch field($result); $meznev[]=$mezok->name; //Oszlop/Mező adatainak kilistázása. print(”<td align=right>”); print($meznev[$i]); //A mező neve print(”</td>”); print(”<td>”); print(”<INPUT name=”".$meznev[$i]"” type="text" value=””$sor[$meznev]”” onchange=”javascript:ellenoriz(”.$meznev[$i]”)”>”); print($sor[$meznev]); print(”</td>”) print(”</tr>”); //A mező értéke } print(”<tr>”); print(”<td>”); print(”<INPUT name="OK" type="submit" value="Oké">”);

print(”<INPUT name="Törlés" type="reset" value="Mégse">”); print(”</td>”) print(”<td>”); print(”</td>”); print(”</tr>”); print(”</table>”); mysql close(); ?> </BODY> </HTML> 72 18.5 Hibakezelés A MySQL szerver a lekérdezések során hibakódot és szöveges üzenetet is küld vissza a kliensnek. A hiábk kezelésére az alábbi függvényewk használhatók: string mysql error ([int link identifier]) A MySQL szerver által visszaadott hiba szövegesen int mysql errno ([int link identifier]) A MySQL szerver által visszaadott hiba kódja. <?php mysql connect("marliesle"); echo mysql errno().": "mysql error()"<BR>"; mysql select db("nincsadatbazis"); echo mysql errno().": "mysql error()"<BR>"; $conn = mysql query("SELECT * FROM nincsadattabla"); echo mysql errno().": "mysql

error()"<BR>"; ?> A fenti lehetőségek csak a MySQL-re vonatkoznak, de hasonlóan lehet használni őket más adatbázisok esetén is. 18.6 Adatbáziskezelés másképpen – absztrakciós rétegek, ADODB, ODBC Fontos kérdés, hogy mit tegyünk akkor, ha előre nem tudjuk, hogy milyen adatbáziskezelőt fogunk használni az oldalunkon, vagy ha hozzászoktunk olyan adatbáziskezelőkhöz, mint például az ADODB rendszerhez Microsoft Windows környezetben. Alapvető dolog, hogy az egyes adatbáziskezelők általában az SQL szintakszis szerint működnek, tehát ha készítünk egy olyan programcsomagot, amely eltakarja előlünk az adatbáziskezelők közti különbségeket, akkor tudunk erre alapozva olyan alkalmazást írni, amelynek mindegy, hogy melyik adatbáziskezelőt használja. Ez az absztrakciós réteg alkalmazásának módszere 18.61 Az absztrakciós réteg A konkrét adatbáziskezelőtől független olyan utilitycsomag, amely eltakarja az

adatbázis-kezelők közötti különbségeket, kiegészíti azokat plusz funkciókkal kényelmesebbé teszi az adatbáziskezeléssel kapcsolatos programozást. Persze felmerül a kérdés, hogy vajon nem, lassítja-e le nagyon a programjaink futását egy ilyen réteg alkalmazása. Megnyugtathatjuk a kedves olvasót, hogy bármiféle absztrakciós réteg lassítja a rendszert, de csak olyan csekély mértékben, hogy a lassulás észrevehetetlen, csak extrém nagy szerver terhelés, mellett észrevehető, ugyanakkor az alkalmazásfejlesztés nagyságrendekkel meggyorsul. Ilyen egyszerű absztrakciós réteget többet is lehet találni az interneten: 18.62 ODBC programcsomag A Microsoft már korábban megvalósított egy adatbáziskezelés esetén jól használható absztrakciós eljárást, ez pedig az ODBC driverek csoportja Az ODBC driverek olyan meghajtók, amelyek a windows rendszerre telepített (szinte) tetszőleges adatbáziskezelőt egységes módon érnek el. Ennek

megfelelően az ilyen drivert használü alkalmazások a Windows rendszeren az SQL szerver módosításával is működnek, ODBC-n keresztül érik el őket. Használatuk: 1. Létre kell hozni az adatbázist valamilyen adatbáziskezelővel: Egy windows rendszeren lehet, Access, MSSQL, MySQL, PostgresSQL, InterBase SQL, vagy bármi más, amelynek létezik ODBC drivere. 73 2. Létre kell hozni egy ODBC kapcsolatot Ezt az ODBC kezelővel tehetjük meg A különböző Windows verziók esetén ez máshol van, de alapvetően a Vezérlőpult környékén kell keresni „ODBC adatforrások” vagy hasonló néven. Az alábbiakban a Windows XP magyar verziójából vesszük a példát: A fenti beállításokkal most egy MySQL adatforrást adtunk meg. Ezek után az ODBC adatbáziskezelőt kell használni a PHP-ban. Az ODBC csomag részletes leírását lásd az alábbi helyen: http://www.phpnet/manual/hu/refodbcphp 18.63 Az ADODB rétegezés (Az alábbi leírást az eredeti ADODB manual

fordításával és rövidítésével készítettem el.) Az ADODB a Microsoft által kifejlesztett adatbáziskezelési programcsomag, amely egyesíti az SQL adatkezelés és a kliens oldali adatelérés előnyeit. A lényege, hogy az adatbáziskezelőtől lekérdezésekkel kapott eredményeket – rekordszeteket – nem csak szekvenciálisan dolgozhatunk fel, hanem véletlen eléréssel bármelyik részét elérhetjük. Segítségével könnyen tudunk gördíthető menüket, listboxokat és ehhez hasonló objektumokat készíteni grafikus rndszerben. Az phpADODB könyvtárszerkezete ehhez hasonló funkciókat valósít meg. Az ADOdb for PHP-hez legalább PHP 4.02 kell Használatának előnyei: 74 - Könnyen használható a windowson programozóknak, mivel szintaktikája hasonlít a Microsoft féle ADODB-hez. - A PHP natív adatbázis-kezelése felé egy réteget von, ami nem lassítja le lényegesen az adatbázis elérését, viszont tetszőleges adatbázison azonossá teszi az

adatbáziskok kezelését. - Nem csak lekérdezésekre, hanem Update és Insert utasításokra is jól használható. - Támogatja a PHP4 sessionját. - Alapvető adattípusokkal dolgozik – ez is a különböző rendszerek kompatibilitását segíti elő. Telepítése: Az ADODB library-t letöltés után be kell tenni az adodb alkönyvtárba, vagy a PHP include library-jai közé. Ez utóbbi esetben a PHPini file-t meg kell szerkeszteni egy kicsit: ; Windows: "path1;path2" include path = ".;i:phplibs;i:phplibsadodb;" Ekkor az alábbi formát lehet használnunk, mivel a PHP eléri mindig az ADODB-t. <?php include(adodb.incphp); $db = ADONewConnection(mysql); $db->debug = true; $db->Connect($server, $user, $password, $database); $rs = $db->Execute(select * from some small table); print r($rs->GetRows()); ?> Ha nem tudjuk library-be tenni, akkor egy alkönyvtárba tesszük az ADODB programcsomagot. <?php include(adodb/adodb.incphp); $db

= ADONewConnection(mysql); $db->debug = true; $db->Connect($server, $user, $password, $database); $rs = $db->Execute(select * from some small table); print r($rs->GetRows()); ?> A scriptben az include(’adodb/adodb.incphp’); utasítással mondjuk meg a scriptnek, hogy ADODB adatbázist fog kezelni a program. Az adatbázis típusát az $conn = ADONewConnection(mysql) vagy a $conn = &ADONewConnection( mysql); formát használhatjuk a kapcsolat létrehozására. Ennek hatására létrejön a $conn nevű objektum, amely minden olyan paramétert és metódust tartalmaz, ami a későbbi kezeléshez szükséges. Amennyiben egy másik oldalon újra szükségünk van ennek az objektumnak az adataira, az objektumot célszerű lementeni sessionba, majd a következő oldal elején újra betölteni. Feltéve azt, hogy az objektum definició már lefusson, amikor a session elindul, tehát, ha van egy általános session kezelő rutincsomagunk, akkor a helyes includolási

sorrend az alábbi: include(’adodb.incphp’); include(’session.php’); 75 Az alábbi táblázat a leggyakrabban előforduló adatbázisokat sorolja fel. Név Áll. Adatbázis-kezelő Rekord sorsz Hivatkozás, kliens Op.rend access B Microsoft Access/Jet. You need to create an ODBC DSN Y/N ODBC W ado B Általános Microsoft ADO, nem specializálva semmilyen Adatbázistól ADO, OLEDB W adatbázisra. Lehet DSN-nélküli Lehetőség szerint OLEDB függ adatforrás adatbázis. Kapcsolódás előtt állítsd be a $db->codePage értéket ado access B Microsoft Access/Jet ADO, DSN-nélküli kapcsolat. Használj Y/N OLEDB adatbázist. ADO,OLEDB W adatforrás ado mssql B Microsoft SQL Server ADO-t használva, DSN-nélkül Y/N ADO,OLEDB W adatforrás vfp A Microsoft Visual FoxPro. ODBC DSN-nel Y/N ODBC W mssql A Microsoft SQL Server 7 / 2000. A dátumok kezelése problémás Y/N Mssql client U, W mysql A MySQL tranzakció nélkül! Y/N MySQL

client U, W mysqlt, maxsql A MySQL tranzakcióval. Y/N MySQL client U,W oci8 A Oracle 8/9. Jobb, mint a többi oracle driver Használnod kell az Y/N alábbi parancsot: putenv(ORACLE HOME=.) Connect/Pconnect előtt Kétféle kapcsolódás létezik: IP és szerviz névvel: PConnect(serverip:1521,scott,tiger,service) vagy TNSNAMES.ORA és ONAMES vagy PConnect(false, scott, tiger, $oraname). U, W HOSTNAMES: Általános ODBC parancs kapcsolódás: Connect(DSN,user,pwd). ? depends on ODBC database W,U odbc mssql C ODBC, MSSQL kapcsolattal Y/N ODBC U,W odbc oracle C ODBC Oracle kapcsolattal Y/N ODBC U, W odbc A Oracle client oracle C Oracle 7. Jobb az oci8 driver Y/N Oracle client U, W postgres64 A PostgreSQL 6.4 és kjorábbi esetben LIMIT internally Y PostgreSQL client U,W postgres7 A PostgreSQL7 illetve későbbi. Y PostgreSQL client U,W A = Jól bevált, használatos B =Tesztelt, de bizonyos részei még nincsenek készen C = Még kisérleti

állapotban van W= windows U = Unix/Linux Ha a fenti adatbázisok egyikát használjuk ADODB-vel, az alábbi lehetőségeink vannak A továbbiakban nézzünk egy programot, amely a Microsoft Acces-hez adott NorthWind adatbázisból egy lekérdezést hajt végre, végigmegy a rekordokon és ha dátum vagy idő típusú mezőt talál, akkor azt megfelelő formátumban írja ki. 76 <?php include(adodb.incphp); $conn = &ADONewConnection(access); # Kapcsolat létrehozása $conn->PConnect(northwind); # MS ACCESS-hez kapcsolódunk, northwind dsn-nel $recordSet = &$conn->Execute(select CustomerID,OrderDate from Orders); if (!$recordSet) print $conn->ErrorMsg(); # Hibaüzenet, ha nincsen eredménye a lekérdezésnek else while (!$recordSet->EOF) { $fld = $recordSet->FetchField(1); # Az első mező beolvasása $type = $recordSet->MetaType($fld->type); if ( $type == D || $type == T) print $recordSet->fields[0].

$recordSet->UserDate($recordSet->fields[1],m/d/Y).<BR>; else print $recordSet->fields[0]. $recordSet->fields[1]<BR>; $recordSet->MoveNext(); } $recordSet->Close(); # optional $conn->Close(); # optional ?> A $conn ADO objektumhoz a $conn->Pconnect(‘northwind’) metódus kapcsolja hozzá a Northwind adatbázist, ami természetesen elérhető a windowsos rendszerben. Az adatok lekérdezését az $recordSet = $conn->execute(’select * from Orders’) ; metódus hajtja végre. Ez a $recordSet változóba visszatér egy ADO rekordszet objektummal Ha valamilyen ok miatt nem jön létre a rekordszet, akkor azt le lehet kérdezni, és hibakezelést lehet végrehajtani. A rekordszetnek van kurzora Ez a kurzor jelöli meg az aktuális rekordot A kurzort $recordSet->MoveNext() metódussal tudom tovább mozgatni. A sorok közötti mozgást további parancsok is könnyítik: $recordSet->Move($n) - az aktuális sorhoz képest n sorral ugrik

tovább a kurzor $recordSet->MoveNext() – következő sorra lép a kurzor $recordSet->MoveFirst() $recordSet->MoveLast() – első sorra ugrik a kurzor – utolsó sorra ugrik a kurzor $recordSet->AbsolutePosition (n) – Egy abszolút módon megadott sorra ugrik $sorszám = $recordSet->CurrentRow () – Az aktuális sor számát adja vissza A FetchField függvény teszteli le a mezők típusát. 3 elemű objektumot ad vissza - name: oszlop neve - type: az eredeti mezőtípus - max length: a mező max. hossza Néha nem ad vissza semmit (pl MySQL) A MetaType() lefordítja az eredeti típust általános ADODB típusra. Az alábbi generic típusok léteznek: • • • • • C: szöveg, a <input type="text"> taggal jeleníthető meg X: TeXt, nagy szöveg, a <textarea> taggal jeleníthető meg B: Blobs, Binary Large Objects. Általában képek D: Dátum T: Időbélyeg 77 • • • • L: Logikai (boolean vagy bit mező) I:

Egész N: Numerikus, illetve autoinkrementális. R: Sorozat típus. Lehet sorozat vagy, autoinkrement egész Dátum vagy Időbélyeg esetén a UserDate() függvény konvertálja és kiírja a megfelelő formátumú időt. 18.631 Lapozás ADODB-ben Akkor használhatjuk a z ADODB lapozó funkcióját, ha beincludoljuk az adodb-pager.incphp függvényt. A rekordszet lapokra bontható, minden lap megadott számú sorból áll. A lapok között is lehet mozogni Bool AtFirstPage() – True, ha az első lapon vagyunk Bool AtLastPage() - True, ha az utolsó lapon vagyunk $page= AbsolutePage(n) – Megadott lapra ugrik. Ezt Az alábbi viszonylag egyszerű példa ezt mutatja be: <?php include once(adodb.incphp); include once(adodb-pager.incphp); session start(); $db = NewADOConnection(mysql); $db->Connect(localhost,root,,xphplens); $sql = "select * from adoxyz "; $pager = new ADODB Pager($db,$sql); $pager->Render($rows per page=5); // A $pager objektum létrejön //

Megadjuk, hogy hány sor legyen rajta. ?> A példában az adodb-pager.incphp include engedélyezi a lapozást A sessionben tároljuk az oldal állapotát. A ADODB Pager() létrehozza az adott oldalon a megfelelő lapozó objektumot A Render metódus létrehozza a HTML oldalon a megfelelő vezérlőkkel ellátott táblázatot. A PHP adatbázis-motor generálta a $recordSet->fields[] tömböt. Némelyik adatbázis megengedi, hogy sorszámmal és mezőnévvel is indexelhessük a kapott eredménysor tömbjét. Ha mindenképpen névvel akarunk indexelni, akkor a SetFetchMode függvényt kell használnunk. Minden rekorszet letárolja, hogy milyen üzemmódban használtuk, mikor az Execute() vagy a SelectLimit() parancsot használtuk. Az Execute parancs az SQL parancs által visszaadott teljes rekordszetet visszadja a hivó eljárásnak, míg a SelectLimit() csak a megadott számú sorral tér vissza. $db->SetFetchMode(ADODB FETCH NUM); $rs1 = $db->Execute(select * from table);

$db->SetFetchMode(ADODB FETCH ASSOC); $rs2 = $db->Execute(select * from table); print r($rs1->fields); # shows array([0]=>v0,[1] =>v1) print r($rs2->fields); # shows array([col1]=>v0,[col2] =>v1) A lekérdezett sorok számát a $recordSet->RecordCount() utasítás adja vissza. -1 az eredmény, ha nem meghatározható a visszaadott sorok száma. $rs->GetArray([$number of rows]) Az alábbi függvény egy két dimenziós tömböt hoz létre a recordset adataiból és azt adja vissza. Ha nem adjuk meg a sorok számát, akkor az összes adatot visszadja EOf-ig. $rs = $db->Execute($sql); if ($rs) 78 while ($arr = $rs->FetchRow()) { # process $arr } } Example 3: Inserting Insert a row to the Orders table containing dates and strings that need to be quoted before they can be accepted by the database, eg: the single-quote in the word Johns. <? include(adodb.incphp); # load code common to ADOdb $conn = &ADONewConnection(access); # create a

connection $conn->PConnect(northwind); # connect to MS-Access, northwind dsn $shipto = $conn->qstr("Johns Old Shoppe"); $sql = "insert into orders (customerID,EmployeeID,OrderDate,ShipName) "; $sql .= "values (ANATR,2,"$conn->DBDate(time())",$shipto)"; if ($conn->Execute($sql) === false) { print error inserting: .$conn->ErrorMsg()<BR>; } ?> In this example, we see the advanced date and quote handling facilities of ADOdb. The unix timestamp (which is a long integer) is appropriately formated for Access with DBDate(), and the right escape character is used for quoting the Johns Old Shoppe, which is Johns Old Shoppe and not PHPs default Johns Old Shoppe with qstr(). Observe the error-handling of the Execute statement. False is returned by Execute() if an error occured. The error message for the last error that occurred is displayed in ErrorMsg() Note: php track errors might have to be enabled for error messages to be saved.

Example 4: Debugging <? include(adodb.incphp); # load code common to ADOdb $conn = &ADONewConnection(access); # create a connection $conn->PConnect(northwind); # connect to MS-Access, northwind dsn $shipto = $conn->qstr("Johns Old Shoppe"); $sql = "insert into orders (customerID,EmployeeID,OrderDate,ShipName) "; $sql .= "values (ANATR,2,"$conn->FormatDate(time())",$shipto)"; $conn->debug = true; if ($conn->Execute($sql) === false) print error inserting; ?> In the above example, we have turned on debugging by setting debug = true. This will display the SQL statement before execution, and also show any error messages. There is no need to call ErrorMsg() in this case. For displaying the recordset, see the rs2html() example Also see the section on Custom Error Handlers. 79 Example 5: MySQL and Menus Connect to MySQL database agora, and generate a <select> menu from an SQL statement where the <option>

captions are in the 1st column, and the value to send back to the server is in the 2nd column. <? include(adodb.incphp); # load code common to ADOdb $conn = &ADONewConnection(mysql); # create a connection $conn->PConnect(localhost,userid,,agora);# connect to MySQL, agora db $sql = select CustomerName, CustomerID from customers; $rs = $conn->Execute($sql); print $rs->GetMenu(GetCust,Mary Rosli); ?> Here we define a menu named GetCust, with the menu option Mary Rosli selected. See GetMenu() We also have functions that return the recordset as an array: GetArray(), and as an associative array with the key being the first column: GetAssoc(). Example 6: Connecting to 2 Databases At Once <? include(adodb.incphp); # load code common to ADOdb $conn1 = &ADONewConnection(mysql); # create a mysql connection $conn2 = &ADONewConnection(oracle); # create a oracle connection $conn1->PConnect($server, $userid, $password, $database); $conn2->PConnect(false, $ora

userid, $ora pwd, $oraname); $conn1->Execute(insert .); $conn2->Execute(update .); ?> Example 7: Generating Update and Insert SQL ADOdb 1.31 and later supports two new recordset functions: GetUpdateSQL( ) and GetInsertSQL( ) This allow you to perform a "SELECT * FROM table query WHERE.", make a copy of the $rs->fields, modify the fields, and then generate the SQL to update or insert into the table automatically. We show how the functions can be used when accessing a table with the following fields: (ID, FirstName, LastName, Created). Before these functions can be called, you need to initialize the recordset by performing a select on the table. Idea and code by Jonathan Younger jyounger#unilabcom <? #============================================== # SAMPLE GetUpdateSQL() and GetInsertSQL() code #============================================== include(adodb.incphp); include(tohtml.incphp); #========================== # This code tests an insert $sql = "SELECT

* FROM ADOXYZ WHERE id = -1"; # Select an empty record from the database $conn = &ADONewConnection("mysql"); # create a connection $conn->debug=1; $conn->PConnect("localhost", "admin", "", "test"); # connect to MySQL, testdb $rs = $conn->Execute($sql); # Execute the query and get the empty recordset $record = array(); # Initialize an array to hold the record data to insert # Set the values for the fields in the record # Note that field names are case-insensitive $record["firstname"] = "Bob"; $record["lastNamE"] = "Smith"; $record["creaTed"] = time(); 80 # Pass the empty recordset and the array containing the data to insert # into the GetInsertSQL function. The function will process the data and return # a fully formatted insert sql statement. $insertSQL = $conn->GetInsertSQL($rs, $record); $conn->Execute($insertSQL); # Insert the record into the database

#========================== # This code tests an update $sql = "SELECT * FROM ADOXYZ WHERE id = 1"; # Select a record to update $rs = $conn->Execute($sql); # Execute the query and get the existing record to update $record = array(); # Initialize an array to hold the record data to update # Set the values for the fields in the record # Note that field names are case-insensitive $record["firstname"] = "Caroline"; $record["LasTnAme"] = "Smith"; # Update Carolines lastname from Miranda to Smith # Pass the single record recordset and the array containing the data to update # into the GetUpdateSQL function. The function will process the data and return # a fully formatted update sql statement with the correct WHERE clause. # If the data has not changed, no recordset is returned $updateSQL = $conn->GetUpdateSQL($rs, $record); $conn->Execute($updateSQL); # Update the record in the database $conn->Close(); ?> 81 Example 8:

Implementing Scrolling with Next and Previous The following code creates a very simple recordset pager, where you can scroll from page to page of a recordset. include once(./adodbincphp); include once(./adodb-pagerincphp); session start(); $db = NewADOConnection(mysql); $db->Connect(localhost,root,,xphplens); $sql = "select * from adoxyz "; $pager = new ADODB Pager($db,$sql); $pager->Render($rows per page=5); This will create a basic record pager that looks like this: |< ID 36 37 38 39 40 << >> >| First Name Last Name Date Created Alan Turing Sat 06, Oct 2001 Serena Williams Sat 06, Oct 2001 Yat Sun Sun Sat 06, Oct 2001 Wai Hun See Sat 06, Oct 2001 Steven Oey Sat 06, Oct 2001 Page 8/10 The number of rows to display at one time is controled by the Render($rows) method. If you do not pass any value to Render(), ADODB Pager will default to 10 records per page. You can control the column titles by modifying your SQL (supported by most databases): $sql

= select id as "ID", firstname as "First Name", lastname as "Last Name", created as "Date Created" from adoxyz; The above code can be found in the adodb/tests/testpaging.php example included with this release, and the class ADODB Pager in adodb/adodb-pager.incphp The ADODB Pager code can be adapted by a programmer so that the text links can be replaced by images, and the dull white background be replaced with more interesting colors. You can also allow display of html by setting $pager->htmlSpecialChars = false. Some of the code used here was contributed by Iván Oliva and Cornel G. 82 Example 9: Exporting in CSV or Tab-Delimited Format We provide some helper functions to export in comma-separated-value (CSV) and tab-delimited formats: include once(/path/to/adodb/toexport.incphp); include once(/path/to/adodb/adodb.incphp); $db = &NewADOConnection(mysql); $db->Connect($server, $userid, $password, $database); $rs =

$db->Execute(select fname as "First Name", surname as "Surname" from table); print "<pre>"; print rs2csv($rs); # return a string, CSV format print <hr>; $rs->MoveFirst(); # note, some databases do not support MoveFirst print rs2tab($rs,false); # return a string, tab-delimited # false == suppress field names in first line print <hr>; $rs->MoveFirst(); rs2tabout($rs); # send to stdout directly (there is also an rs2csvout function) print "</pre>"; $rs->MoveFirst(); $fp = fopen($path, "w"); if ($fp) { rs2csvfile($rs, $fp); # write to file (there is also an rs2tabfile function) fclose($fp); } Carriage-returns or newlines are converted to spaces. Field names are returned in the first line of text Strings containing the delimiter character are quoted with double-quotes. Double-quotes are doublequoted again This conforms to Excel import and export guide-lines All the above functions take as an optional last

parameter, $addtitles which defaults to true. When set to false field names in the first line are suppressed. Example 10: Recordset Filters Sometimes we want to pre-process all rows in a recordset before we use it. For example, we want to ucwords all text in recordset. include once(adodb/rsfilter.incphp); include once(adodb/adodb.incphp); // ucwords() every element in the recordset function do ucwords(&$arr,$rs) { foreach($arr as $k => $v) { $arr[$k] = ucwords($v); } } $db = NewADOConnection(mysql); $db->PConnect(server,user,pwd,db); $rs = $db->Execute(select . from table); $rs = RSFilter($rs,do ucwords); The RSFilter function takes 2 parameters, the recordset, and the name of the filter function. It returns the processed recordset scrolled to the first record. The filter function takes two parameters, the current row as an array, and the recordset object. For future compatibility, you should not use the original recordset object. Example 11: Smart Transactions The old

way of doing transactions required you to use 83 $conn->BeginTrans(); $ok = $conn->Execute($sql); if ($ok) $ok = $conn->Execute($sql2); if (!$ok) $conn->RollbackTrans(); else $conn->CommitTrans(); This is very complicated for large projects because you have to track the error status. Smart Transactions is much simpler You start a smart transaction by calling StartTrans(): $conn->StartTrans(); $conn->Execute($sql); $conn->Execute($Sql2); $conn->CompleteTrans(); CompleteTrans() detects when an SQL error occurs, and will Rollback/Commit as appropriate. To specificly force a rollback even if no error occured, use FailTrans(). Note that the rollback is done in CompleteTrans(), and not in FailTrans(). $conn->StartTrans(); $conn->Execute($sql); if (!CheckRecords()) $conn->FailTrans(); $conn->Execute($Sql2); $conn->CompleteTrans(); Lastly, StartTrans/CompleteTrans is nestable, and only the outermost block is executed. In contrast,

BeginTrans/CommitTrans/RollbackTrans is NOT nestable. $conn->StartTrans(); $conn->Execute($sql); $conn->StartTrans(); # ignored if (!CheckRecords()) $conn->FailTrans(); $conn->CompleteTrans(); # ignored $conn->Execute($Sql2); $conn->CompleteTrans(); Note: Savepoints are currently not supported. 84 18.7 Using Custom Error Handlers and PEAR Error Apart from the old $con->debug = true; way of debugging, ADOdb 1.50 onwards provides another way of handling errors using ADOdbs custom error handlers. ADOdb provides two custom handlers which you can modify for your needs. The first one is in the adodb-errorhandler.incphp file This makes use of the standard PHP functions error reporting to control what error messages types to display, and trigger error which invokes the default PHP error handler. Including the above file will cause trigger error($errorstring,E USER ERROR) to be called when (a) Connect() or PConnect() fails, or (b) a function that executes SQL

statements such as Execute() or SelectLimit() has an error. (c) GenID() appears to go into an infinite loop. The $errorstring is generated by ADOdb and will contain useful debugging information similar to the error.log data generated below This file adodb-errorhandlerincphp should be included before you create any ADOConnection objects. If you define error reporting(0), no errors will be shown. If you set error reporting(E ALL), all errors will be displayed on the screen. <?php error reporting(E ALL); # show any error messages triggered include(adodb-errorhandler.incphp); include(adodb.incphp); include(tohtml.incphp); $c = NewADOConnection(mysql); $c->PConnect(localhost,root,,northwind); $rs=$c->Execute(select * from productsz); #invalid table productsz); if ($rs) $rs2html($rs); ?> If you want to log the error message, you can do so by defining the following optional constants ADODB ERROR LOG TYPE and ADODB ERROR LOG DEST. ADODB ERROR LOG TYPE is the error log message type

(see error log in the PHP manual). In this case we set it to 3, which means log to the file defined by the constant ADODB ERROR LOG DEST. <?php error reporting(0); # do not echo any errors define(ADODB ERROR LOG TYPE,3); define(ADODB ERROR LOG DEST,C:/errors.log); include(adodb-errorhandler.incphp); include(adodb.incphp); include(tohtml.incphp); $c = NewADOConnection(mysql); $c->PConnect(localhost,root,,northwind); $rs=$c->Execute(select * from productsz); ## invalid table productsz if ($rs) $rs2html($rs); ?> 85 The following message will be logged in the error.log file: (2001-10-28 14:20:38) mysql error: [1146: Table northwind.productsz doesnt exist] in EXECUTE("select * from productsz") The second error handler is adodb-errorpear.incphp This will create a PEAR Error derived object whenever an error occurs. The last PEAR Error object created can be retrieved using ADODB Pear Error(). <?php include(adodb-errorpear.incphp); include(adodb.incphp);

include(tohtml.incphp); $c = NewADOConnection(mysql); $c->PConnect(localhost,root,,northwind); $rs=$c->Execute(select * from productsz); #invalid table productsz); if ($rs) $rs2html($rs); else { $e = ADODB Pear Error(); echo <p>,$e->message,</p>; } ?> You can use a PEAR Error derived class by defining the constant ADODB PEAR ERROR CLASS before the adodb-errorpear.incphp file is included For easy debugging, you can set the default error handler in the beginning of the PHP script to PEAR ERROR DIE, which will cause an error message to be printed, then halt script execution: include(PEAR.php); PEAR::setErrorHandling(PEAR ERROR DIE); Note that we do not explicitly return a PEAR Error object to you when an error occurs. We return false instead. You have to call ADODB Pear Error() to get the last error or use the PEAR ERROR DIE technique. 18.711 Error Messages Error messages are outputted using the static method ADOConnnection::outp($msg,$newline=true). By

default, it sends the messages to the client. You can override this to perform error-logging 86 18.8 Data Source Names We now support connecting using PEAR style DSNs. A DSN is a connection string of the form: $dsn = "http://php.weblogscom/$driver://$username:$password@$hostname/$databasename";; You pass the DSN to the static class function DB::Connect. An example: include once(./adodb/adodb-pearincphp); $username = root; $password = ; $hostname = localhost; $databasename = xphplens; $driver = mysql; $dsn ="http://php.weblogscom/$driver://$username:$password@$hostname/$databasename"; $db = DB::Connect($dsn); $rs = $db->Execute(select firstname,lastname from adoxyz); $cnt = 0; while ($arr = $rs->FetchRow()) { print r($arr); print "<br>"; } This requires PEAR to be installed and in the default include path in php.ini 18.9 Caching of Recordsets ADOdb now supports caching of recordsets using the CacheExecute( ), CachePageExecute( ) and

CacheSelectLimit( ) functions. There are similar to the non-cache functions, except that they take a new first parameter, $secs2cache. An example: include(adodb.incphp); # load code common to ADOdb $ADODB CACHE DIR = /usr/ADODB cache; $conn = &ADONewConnection(mysql); # create a connection $conn->PConnect(localhost,userid,,agora);# connect to MySQL, agora db $sql = select CustomerName, CustomerID from customers; $rs = $conn->CacheExecute(15,$sql); The first parameter is the number of seconds to cache the query. Subsequent calls to that query will used the cached version stored in $ADODB CACHE DIR. To force a query to execute and flush the cache, call CacheExecute() with the first parameter set to zero. Alternatively, use the CacheFlush($sql) call For the sake of security, we recommend you set register globals=off in php.ini if you are using $ADODB CACHE DIR. In ADOdb 1.80 onwards, the secs2cache parameter is optional in CacheSelectLimit() and CacheExecute(). If you leave it

out, it will use the $connection->cacheSecs parameter, which defaults to 60 minutes. $conn->Connect(.); $conn->cacheSecs = 3600*24; # cache 24 hours $rs = $conn->CacheExecute(select * from table); Please note that magic quotes runtime should be turned off. More info 18.10 Pivot Tables Since ADOdb 2.30, we support the generation of SQL to create pivot tables, also known as crosstabulations For further explanation read this DevShed Cross-Tabulation tutorial We assume that your database supports the SQL case-when expression. In this example, we will use the Northwind database from Microsoft. In the database, we have a products table, and we want to analyze this table by suppliers versus product categories. We will place the suppliers on each row, and pivot on categories. So from the table on the left, we generate the pivottable on the right: 87 Supplier Category supplier1 category1 supplier2 category1 supplier2 category2 category1 category2 --> supplier1 1 0 1

supplier2 1 1 2 total The following code will generate the SQL for a cross-tabulation: # # # # # # Query the main "product" table Set the rows to CompanyName and the columns to the values of Categories and define the joins to link to lookup tables "categories" and "suppliers" include "adodb/pivottable.php"; $sql = PivotTableSQL( $gDB, # adodb connection products p ,categories c ,suppliers s, # tables CompanyName, # rows (multiple fields allowed) CategoryName, # column to pivot on p.CategoryID = cCategoryID and sSupplierID= pSupplierID # joins/where ); This will generate the following SQL: SELECT CompanyName, SUM(CASE WHEN CategoryName=Beverages THEN 1 ELSE 0 END) AS "Beverages", SUM(CASE WHEN CategoryName=Condiments THEN 1 ELSE 0 END) AS "Condiments", SUM(CASE WHEN CategoryName=Confections THEN 1 ELSE 0 END) AS "Confections", SUM(CASE WHEN CategoryName=Dairy Products THEN 1 ELSE 0 END) AS "Dairy

Products", SUM(CASE WHEN CategoryName=Grains/Cereals THEN 1 ELSE 0 END) AS "Grains/Cereals", SUM(CASE WHEN CategoryName=Meat/Poultry THEN 1 ELSE 0 END) AS "Meat/Poultry", SUM(CASE WHEN CategoryName=Produce THEN 1 ELSE 0 END) AS "Produce", SUM(CASE WHEN CategoryName=Seafood THEN 1 ELSE 0 END) AS "Seafood", SUM(1) as Total FROM products p ,categories c ,suppliers s WHERE p.CategoryID = cCategoryID and sSupplierID= p.SupplierID GROUP BY CompanyName You can also pivot on numerical columns and generate totals by using ranges. This code was revised in ADODB 2.41 and is not backward compatible The second example shows this: $sql = PivotTableSQL( $gDB, # adodb connection products p ,categories c ,suppliers s, # tables CompanyName, # rows (multiple fields allowed) array( # column ranges 0 => UnitsInStock <= 0, "1 to 5" => 0 < UnitsInStock and UnitsInStock <= 5, "6 to 10" => 5 < UnitsInStock and UnitsInStock

<= 10, "11 to 15" => 10 < UnitsInStock and UnitsInStock <= 15, "16+" => 15 < UnitsInStock ), p.CategoryID = cCategoryID and sSupplierID= pSupplierID, # joins/where UnitsInStock, # sum this field Sum # sum label prefix ); Which generates: 88 SELECT CompanyName, SUM(CASE WHEN UnitsInStock <= 0 THEN UnitsInStock ELSE 0 END) AS "Sum 0 ", SUM(CASE WHEN 0 < UnitsInStock and UnitsInStock <= 5 THEN UnitsInStock ELSE 0 END) AS "Sum 1 to 5", SUM(CASE WHEN 5 < UnitsInStock and UnitsInStock <= 10 THEN UnitsInStock ELSE 0 END) AS "Sum 6 to 10", SUM(CASE WHEN 10 < UnitsInStock and UnitsInStock <= 15 THEN UnitsInStock ELSE 0 END) AS "Sum 11 to 15", SUM(CASE WHEN 15 < UnitsInStock THEN UnitsInStock ELSE 0 END) AS "Sum 16+", SUM(UnitsInStock) AS "Sum UnitsInStock", SUM(1) as Total, FROM products p ,categories c ,suppliers s WHERE p.CategoryID = cCategoryID and sSupplierID=

p.SupplierID GROUP BY CompanyName 89 90 19 Class Reference Function parameters with [ ] around them are optional. 19.1 Global Variables $ADODB COUNTRECS If the database driver API does not support counting the number of records returned in a SELECT statement, the function RecordCount() is emulated when the global variable $ADODB COUNTRECS is set to true, which is the default. We emulate this by buffering the records, which can take up large amounts of memory for big recordsets. Set this variable to false for the best performance This variable is checked every time a query is executed, so you can selectively choose which recordsets to count. $ADODB CACHE DIR If you are using recordset caching, this is the directory to save your recordsets in. Define this before you call any caching functions such as CacheExecute( ). We recommend setting register globals=off in php.ini if you use this feature for security reasons If you are using Unix and apache, you might need to set your

cache directory permissions to something similar to the following: chown -R chgrp -R apache /path/to/adodb/cache apache /path/to/adodb/cache $ADODB FETCH MODE This is a global variable that determines how arrays are retrieved by recordsets. The recordset saves this value on creation (eg. in Execute( ) or SelectLimit( )), and any subsequent changes to $ADODB FETCH MODE have no affect on existing recordsets, only on recordsets created in the future. The following constants are defined: define(ADODB FETCH DEFAULT,0); define(ADODB FETCH NUM,1); define(ADODB FETCH ASSOC,2); define(ADODB FETCH BOTH,3); An example: $ADODB FETCH MODE = ADODB FETCH NUM; $rs1 = $db->Execute(select * from table); $ADODB FETCH MODE = ADODB FETCH ASSOC; $rs2 = $db->Execute(select * from table); print r($rs1->fields); # shows array([0]=>v0,[1] =>v1) print r($rs2->fields); # shows array([col1]=>v0,[col2] =>v1) As you can see in the above example, both recordsets store and use different

fetch modes based on the $ADODB FETCH MODE setting when the recordset was created by Execute(). If no fetch mode is predefined, the fetch mode defaults to ADODB FETCH DEFAULT. The behaviour of this default mode varies from driver to driver, so do not rely on ADODB FETCH DEFAULT. For portability, we recommend sticking to ADODB FETCH NUM or ADODB FETCH ASSOC. Many drivers do not support ADODB FETCH BOTH. SetFetchMode Function Some programmers prefer to use a more object-oriented solution, where the fetch mode is set by a object function, SetFetchMode. Once this function is called for a connection object, that connection object will ignore the global variable $ADODB FETCH MODE and will use the internal fetchMode property exclusively. 91 $db->SetFetchMode(ADODB FETCH NUM); $rs1 = $db->Execute(select * from table); $db->SetFetchMode(ADODB FETCH ASSOC); $rs2 = $db->Execute(select * from table); print r($rs1->fields); # shows array([0]=>v0,[1] =>v1) print

r($rs2->fields); # shows array([col1]=>v0,[col2] =>v1) To retrieve the previous fetch mode, you can use check the $db->fetchMode property, or use the return value of SetFetchMode( ). ADODB ASSOC CASE You can control the associative fetch case for certain drivers which behave differently. For the sybase, oci8po, mssql, odbc and ibase drivers and all drivers derived from them, ADODB ASSOC CASE will by default generate recordsets where the field name keys are lower-cased. Use the constant ADODB ASSOC CASE to change the case of the keys. There are 3 possible values: 0 = assoc lowercase field names. $rs->fields[orderid] 1 = assoc uppercase field names. $rs->fields[ORDERID] 2 = use native-case field names. $rs->fields[OrderID] -- this is the default since ADOdb 290 To use it, declare it before you incldue adodb.incphp define(ADODB ASSOC CASE, include(adodb.incphp); 2); # use 92 native-case for ADODB FETCH ASSOC 19.2 ADOConnection Object that performs the

connection to the database, executes SQL statements and has a set of utility functions for standardising the format of SQL statements for issues such as concatenation and date formats. ADOConnection Fields databaseType: Name of the database system we are connecting to. Eg odbc or mssql or mysql dataProvider: The underlying mechanism used to connect to the database. Normally set to native, unless using odbc or ado. host: Name of server or data source name (DSN) to connect to. database: Name of the database or to connect to. If ado is used, it will hold the ado data provider user: Login id to connect to database. Password is not saved for security reasons raiseErrorFn: Allows you to define an error handling function. See adodb-errorhandlerincphp for an example. debug: Set to true to make debug statements to appear. concat operator: Set to + or || normally. The operator used to concatenate strings in SQL Used by the Concat function. fmtDate: The format used by the DBDate function to send

dates to the database. is #Y-m-d# for Microsoft Access, and Y-m-d for MySQL. fmtTimeStamp: The format used by the DBTimeStamp function to send timestamps to the database. true: The value used to represent true.Eg T for Foxpro, 1 for Microsoft SQL false: The value used to represent false. Eg F for Foxpro, 0 for Microsoft SQL replaceQuote: The string used to escape quotes. Eg double single-quotes for Microsoft SQL, and backslash-quote for MySQL. Used by qstr autoCommit: indicates whether automatic commit is enabled. Default is true charSet: set the default charset to use. Currently only interbase supports this dialect: set the default sql dialect to use. Currently only interbase supports this metaTablesSQL: SQL statement to return a list of available tables. Eg SHOW TABLES in MySQL genID: The latest id generated by GenID() if supported by the database. cacheSecs: The number of seconds to cache recordsets if CacheExecute() or CacheSelectLimit() omit the $secs2cache parameter. Defaults to

60 minutes sysDate: String that holds the name of the database function to call to get the current date. Useful for inserts and updates. sysTimeStamp: String that holds the name of the database function to call to get the current timestamp/datetime value. leftOuter: String that holds operator for left outer join, if known. Otherwise set to false rightOuter: String that holds operator for left outer join, if known. Otherwise set to false ansiOuter: Boolean that if true indicates that ANSI style outer joins are permitted. Eg select * from table1 left join table2 on p1=p2. 93 connectSID: Boolean that indicates whether to treat the $database parameter in connects as the SID for the oci8 driver. Defaults to false Useful for Oracle 805 and earlier autoRollback: Persistent connections are auto-rollbacked in PConnect( ) if this is set to true. Default is false. ADOConnection Main Functions ADOConnection( ) Constructor function. Do not call this directly Use ADONewConnection( ) instead

Connect($host,[$user],[$password],[$database]) Non-persistent connect to data source or server $host, using userid $user and password $password. If the server supports multiple databases, connect to database $database. Returns true/false depending on connection. ADO Note: If you are using a Microsoft ADO and not OLEDB, you can set the $database parameter to the OLEDB data provider you are using. PostgreSQL: An alternative way of connecting to the database is to pass the standard PostgreSQL connection string in the first parameter $host, and the other parameters will be ignored. For Oracle and Oci8, there are two ways to connect. First is to use the TNS name defined in your local tnsnames.ora (or ONAMES or HOSTNAMES) Place the name in the $database field, and set the $host field to false. Alternatively, set $host to the server, and $database to the database SID, this bypassed tnsnames.ora Examples: # $oraname in tnsnames.ora/ONAMES/HOSTNAMES $conn->Connect(false, scott, tiger,

$oraname); $conn->Connect(server:1521, scott, tiger, ServiceName); # bypass tnsnames.ora There are many examples of connecting to a database at php.weblogscom/ADOdb, and in the testdatabases.incphp file included in the release PConnect($host,[$user],[$password],[$database]) Persistent connect to data source or server $host, using userid $user and password $password. If the server supports multiple databases, connect to database $database. We now perform a rollback on persistent connection for selected databases since 2.21, as advised in the PHP manual. See change log or source code for which databases are affected Returns true/false depending on connection. See Connect( ) above for more info Since ADOdb 2.21, we also support autoRollback If you set: $conn = &NewADOConnection(mysql); $conn->autoRollback = true; # default is false $conn->PConnect(.); # rollback here Then when doing a persistent connection with PConnect( ), ADOdb will perform a rollback first. This is

because it is documented that PHP is not guaranteed to rollback existing failed transactions when persistent connections are used. This is implemented in Oracle, MySQL, PgSQL, MSSQL, ODBC currently. Since ADOdb 3.11, you can force non-persistent connections even if PConnect is called by defining the constant ADODB NEVER PERSIST before you call PConnect. NConnect($host,[$user],[$password],[$database]) 94 Always force new connection. In contrast, PHP sometimes reuses connections when you use Connect() or PConnect(). Currently works only on mysql (PHP 430 or later) and oci8-derived drivers For other drivers, NConnect() works like Connect(). Execute($sql,$inputarr=false) Execute SQL statement $sql and return derived class of ADORecordSet if successful. Note that a record set is always returned on success, even if we are executing an insert or update statement. Returns derived class of ADORecordSet. Eg if connecting via mysql, then ADORecordSet mysql would be returned. False is

returned if there was an error in executing the sql The $inputarr parameter can be used for binding variables to parameters. Below is an Oracle example: $conn->Execute("SELECT * FROM TABLE WHERE COND=:val", array(val=> $val)); Another example, using ODBC,which uses the ? convention: $conn->Execute("SELECT * FROM TABLE WHERE COND=?", array($val)); Binding variables Variable binding speeds the compilation and caching of SQL statements, leading to higher performance. Currently Oracle and ODBC support variable binding. ODBC style ? binding is emulated in databases that do not support binding. Variable binding in the odbc and oci8po drivers. $rs = $db->Execute(select * from table where val=?, array(10)); Variable binding in the oci8 driver. $rs = $db->Execute(select name from table where val=:key, array(key => 10)); CacheExecute([$secs2cache,]$sql,$inputarr=false) Similar to Execute, except that the recordset is cached for $secs2cache seconds in the

$ADODB CACHE DIR directory. If CacheExecute() is called again with the same parameters, same database, same userid, same password, and the cached recordset has not expired, the cached recordset is returned. include(adodb.incphp); include(tohtml.incphp); $ADODB CACHE DIR = /usr/local/ADOdbcache; $conn = &ADONewConnection(mysql); $conn->PConnect(localhost,userid,password,database); $rs = $conn->CacheExecute(15, select * from table); # cache 15 secs rs2html($rs); /* recordset to html table / Alternatively, since ADOdb 1.80, the $secs2cache parameter is optional: $conn->Connect(.); $conn->cacheSecs = 3600*24; // cache 24 hours $rs = $conn->CacheExecute(select * from table); Note that the $secs2cache parameter is optional. If omitted, we use the value in $connection->cacheSecs (default is 3600 seconds, or 1 hour). Use CacheExecute() only with SELECT statements Performance note: I have done some benchmarks and found that they vary so greatly that its better to talk

about when caching is of benefit. When your database server is much slower than your Web server or the database is very overloaded then ADOdbs caching is good because it reduces the load on your database server. If your database server is lightly loaded or much faster than your Web server, then caching could actually reduce performance. 95 ExecuteCursor($sql,$cursorName=rs,$parameters=false) Execute an Oracle stored procedure, and returns an Oracle REF cursor variable as a regular ADOdb recordset. Does not work with any other database except oci8 Thanks to Robert Tuttle for the design $db = ADONewConnection("oci8"); $db->Connect("foo.com:1521", "uid", "pwd", "FOO"); $rs = $db->ExecuteCursor("begin :cursorvar := getdata(:param1); end;", cursorvar, array(param1=>10)); # $rs is now just like any other ADOdb recordset object rs2html($rs); ExecuteCursor() is a helper function that does the following internally: $stmt

= $db->Prepare("BEGIN :RS := SP FOO(); END;"); $db->Parameter($stmt, $cur, RS, false, -1, OCI B CURSOR); $rs = $db->Execute($stmt); SelectLimit($sql,$numrows=-1,$offset=-1,$inputarr=false) Returns a recordset if successful. Returns false otherwise Performs a select statement, simulating PostgreSQLs SELECT statement, LIMIT $numrows OFFSET $offset clause. In PostgreSQL, SELECT * FROM TABLE LIMIT 3 will return the first 3 records only. The equivalent is $connection->SelectLimit(SELECT * FROM TABLE,3). This functionality is simulated for databases that do not possess this feature. And SELECT * FROM TABLE LIMIT 3 OFFSET 2 will return records 3, 4 and 5 (eg. after record 2, return 3 rows). The equivalent in ADOdb is $connection->SelectLimit(SELECT * FROM TABLE,3,2). Note that this is the opposite of MySQLs LIMIT clause. You can also set $connection>SelectLimit(SELECT * FROM TABLE,-1,10) to get rows 11 to the last row. The last parameter $inputarr is for databases

that support variable binding such as Oracle oci8. This substantially reduces SQL compilation overhead. Below is an Oracle example: $conn->SelectLimit("SELECT * FROM TABLE WHERE COND=:val", 100,-1,array(val=> $val)); The oci8po driver (oracle portable driver) uses the more standard bind variable of ?: $conn->SelectLimit("SELECT * FROM TABLE WHERE COND=?", 100,-1,array(val=> $val)); Ron Wilson reports that SelectLimit does not work with UNIONs. CacheSelectLimit([$secs2cache,] $sql, $numrows=-1,$offset=-1,$inputarr=false) Similar to SelectLimit, except that the recordset returned is cached for $secs2cache seconds in the $ADODB CACHE DIR directory. Since 1.80, $secs2cache has been optional, and you can define the caching time in $connection>cacheSecs $conn->Connect(.); $conn->cacheSecs = 3600*24; // cache 24 hours $rs = $conn->CacheSelectLimit(select * from table,10); CacheFlush($sql=false,$inputarr=false) Flush (delete) any cached recordsets

for the SQL statement $sql in $ADODB CACHE DIR. If no parameter is passed in, then all adodb *.cache files are deleted If you want to flush all cached recordsets manually, execute the following PHP code (works only under Unix): system("rm -f `find ".$ADODB CACHE DIR" -name adodb *.cache`"); 96 For general cleanup of all expired files, you should use crontab on Unix, or at.exe on Windows, and a shell script similar to the following: #-----------------------------------------------------# This particular example deletes files in the TMPPATH # directory with the string ".cache" in their name that # are more than 7 days old. #-----------------------------------------------------AGED=7 find ${TMPPATH} -mtime +$AGED | grep ".cache" | xargs rm -f MetaError($errno=false) Returns a virtualized error number, based on PEAR DBs error number system. You might need to include adodb-error.incphp before you call this function The parameter $errno is the

native error number you want to convert. If you do not pass any parameter, MetaError will call ErrorNo() for you and convert it. If the error number cannot be virtualized, MetaError will return -1 (DB ERROR) MetaErrorMsg($errno) Pass the error number returned by MetaError() for the equivalent textual error message. ErrorMsg() Returns the last status or error message. This can return a string even if no error occurs In general you do not need to call this function unless an ADOdb function returns false on an error. Note: If debug is enabled, the SQL error message is always displayed when the Execute function is called. ErrorNo() Returns the last error number. Note that old versions of PHP (pre 406) do not support error number for ODBC. In general you do not need to call this function unless an ADOdb function returns false on an error. SetFetchMode($mode) Sets the current fetch mode for the connection and stores it in $db->fetchMode. Legal modes are ADODB FETCH ASSOC and ADODB FETCH

NUM. For more info, see $ADODB FETCH MODE Returns the previous fetch mode, which could be false if SetFetchMode( ) has not been called before. CreateSequence($seqName = adodbseq,$startID=1) Create a sequence. The next time GenID( ) is called, the value returned will be $startID Added in 260 DropSequenceD($seqName = adodbseq) Delete a sequence. Added in 260 GenID($seqName = adodbseq,$startID=1) Generate a sequence number (an integer except for mssql). Works for interbase, mysql, postgresql, oci8, oci8po, mssql, ODBC based (access,vfp,db2,etc) drivers currently. Uses $seqName as the name of the sequence. GenID() will automatically create the sequence for you if it does not exist (provided the userid has permission to do so). Otherwise you will have to create the sequence yourself If your database driver emulates sequences, the name of the table is the sequence name. The table has one column, "id" which should be of type integer, or if you need something larger - numeric(16).

For ODBC and databases that do not support sequences natively (eg mssql, mysql), we create a table for each sequence. If the sequence has not been defined earlier, it is created with the starting value set in $startID. 97 Note that the mssql drivers GenID() used to generate 16 byte GUIDs. We now return integers since 1.90 UpdateBlob($table,$column,$val,$where) Allows you to store a blob (in $val) into $table into $column in a row at $where. Usage: # for oracle $conn->Execute(INSERT INTO blobtable (id, blobcol) VALUES (1, empty blob())); $conn->UpdateBlob(blobtable,blobcol,$blobvalue,id=1); # non oracle databases $conn->Execute(INSERT INTO blobtable (id, blobcol) VALUES (1, null)); $conn->UpdateBlob(blobtable,blobcol,$blobvalue,id=1); Returns true if succesful, false otherwise. Supported by MySQL, PostgreSQL, Oci8, Oci8po and Interbase drivers. Other drivers might work, depending on the state of development Note that when an Interbase blob is retrieved using SELECT, it

still needs to be decoded using $connection->DecodeBlob($blob); to derive the original value in versions of PHP before 4.10 For PostgreSQL, you can store your blob using blob oids or as a bytea field. You can use bytea fields but not blob oids currently with UpdateBlob( ). Conversely UpdateBlobFile( ) supports oids, but not bytea data. If you do not pass in an oid, then UpdateBlob() assumes that you are storing in bytea fields. UpdateClob($table,$column,$val,$where) Allows you to store a clob (in $val) into $table into $column in a row at $where. Similar to UpdateBlob (see above), but for Character Large OBjects. Usage: # for oracle $conn->Execute(INSERT INTO clobtable (id, clobcol) VALUES (1, empty clob())); $conn->UpdateBlob(clobtable,clobcol,$clobvalue,id=1); # non oracle databases $conn->Execute(INSERT INTO clobtable (id, clobcol) VALUES (1, null)); $conn->UpdateBlob(clobtable,clobcol,$clobvalue,id=1); UpdateBlobFile($table,$column,$path,$where,$blobtype=BLOB)

Similar to UpdateBlob, except that we pass in a file path to where the blob resides. For PostgreSQL, if you are using blob oids, use this interface. This interface does not support bytea fields. Returns true if successful, false otherwise. BlobEncode($blob) Some databases require blobs to be encoded manually before upload. Note if you use UpdateBlob( ) or UpdateBlobFile( ) the conversion is done automatically for you and you do not have to call this function. For PostgreSQL, currently, BlobEncode() can only be used for bytea fields. Returns the encoded blob value. Note that there is a connection property called blobEncodeType which has 3 legal values: false no need to perform encoding or decoding. I - blob encoding required, and returned encoded blob is a numeric value (no need to quote). C - blob encoding required, and returned encoded blob is a character value (requires quoting). 98 This is purely for documentation purposes, so that programs that accept multiple database drivers

know what is the right thing to do when processing blobs. BlobDecode($blob) Some databases require blobs to be decoded manually after doing a select statement. If the database does not require decoding, then this function will return the blob unchanged. Currently BlobDecode is only required for one database, PostgreSQL, and only if you are using blob oids (if you are using bytea fields, we auto-decode for you). $rs = $db->Execute("select bloboid from postgres table where id=$key"); $blob = $db->BlobDecode( reset($rs->fields) ); Replace($table, $arrFields, $keyCols,$autoQuote=false) Try to update a record, and if the record is not found, an insert statement is generated and executed. Returns 0 on failure, 1 if update statement worked, 2 if no record was found and the insert was executed successfully. This differs from MySQLs replace which deletes the record and inserts a new record This also means you cannot update the primary key. The only exception to this is

Interbase and its derivitives, which uses delete and insert because of some Interbase API limitations. The parameters are $table which is the table name, the $keyCols which is an associative array where the keys are the field names, and keyCols is the name of the primary key, or an array of field names if it is a compound key. If $autoQuote is set to true, then Replace() will quote all values that are non-numeric; auto-quoting will not quote nulls. Note that auto-quoting will not work if you use SQL functions or operators. Examples: # single field primary key $ret = $db->Replace(atable, array(id=>1000,firstname=>Harun,lastname=>Al-Rashid), id, firstname,$autoquote = true); # generates UPDATE atable SET firstname=Harun,lastname=Al-Rashid WHERE id=1000 # or INSERT INTO atable (id,firstname,lastname) VALUES (1000,Harun,Al-Rashid) # compound key $ret = $db->Replace(atable2, array(firstname=>Harun,lastname=>Al-Rashid, age => 33, birthday => null),

array(lastname,firstname), firstname,$autoquote = true); # no auto-quoting $ret = $db->Replace(atable2, array(firstname=>"Harun",lastname=>"Al-Rashid", age => null), array(lastname,firstname), firstname); 99 GetUpdateSQL(&$rs, $arrFields, $forceUpdate=false,$magicq=false) Generate SQL to update a table given a recordset $rs, and the modified fields of the array $arrFields (which must be an associative array holding the column names and the new values) are compared with the current recordset. If $forceUpdate is true, then we also generate the SQL even if $arrFields is identical to $rs->fields. Requires the recordset to be associative $magicq is used to indicate whether magic quotes are enabled (see qstr()). The field names in the array are case-insensitive GetInsertSQL(&$rs, $arrFields,$magicq=false) Generate SQL to insert into a table given a recordset $rs. Requires the query to be associative $magicq is used to indicate whether magic

quotes are enabled (for qstr()). The field names in the array are caseinsensitive PageExecute($sql, $nrows, $page, $inputarr=false) Used for pagination of recordset. $page is 1-based See Example 8 CachePageExecute($secs2cache, $sql, $nrows, $page, $inputarr=false) Used for pagination of recordset. $page is 1-based See Example 8 Caching version of PageExecute Close( ) Close the database connection. PHP4 proudly states that we no longer have to clean up at the end of the connection because the reference counting mechanism of PHP4 will automatically clean up for us. StartTrans( ) Start a monitored transaction. As SQL statements are executed, ADOdb will monitor for SQL errors, and if any are detected, when CompleteTrans() is called, we auto-rollback. To understand why StartTrans() is superior to BeginTrans(), let us examine a few ways of using BeginTrans(). The following is the wrong way to use transactions: $DB->BeginTrans(); $DB->Execute("update table1 set val=$val1 where

id=$id"); $DB->Execute("update table2 set val=$val2 where id=$id"); $DB->CommitTrans(); because you perform no error checking. It is possible to update table1 and for the update on table2 to fail. Here is a better way: $DB->BeginTrans(); $ok = $DB->Execute("update table1 set val=$val1 where id=$id"); if ($ok) $ok = $DB->Execute("update table2 set val=$val2 where id=$id"); if ($ok) $DB->CommitTrans(); else $DB->RollbackTrans(); Another way is (since ADOdb 2.0): $DB->BeginTrans(); $ok = $DB->Execute("update table1 set val=$val1 where id=$id"); if ($ok) $ok = $DB->Execute("update table2 set val=$val2 where id=$id"); $DB->CommitTrans($ok); Now it is a headache monitoring $ok all over the place. StartTrans() is an improvement because it monitors all SQL errors for you. This is particularly useful if you are calling black-box functions in which SQL queries might be executed. Also all BeginTrans,

CommitTrans and RollbackTrans calls inside a StartTrans block will be disabled, so even if the black box function does a commit, it will be ignored. $DB->StartTrans(); CallBlackBox(); $DB->Execute("update table1 set val=$val1 where id=$id"); $DB->Execute("update table2 set val=$val2 where id=$id"); $DB->CompleteTrans($ok); 100 Note that a StartTrans blocks are nestable, the inner blocks are ignored. CompleteTrans($autoComplete=true) Complete a transaction called with StartTrans(). This function monitors for SQL errors, and will commit if no errors have occured, otherwise it will rollback. Returns true on commit, false on rollback If the parameter $autoComplete is true monitor sql errors and commit and rollback as appropriate. Set $autoComplete to false to force rollback even if no SQL error detected. BeginTrans( ) Begin a transaction. Turns off autoCommit Returns true if successful Some databases will always return false if transaction support is

not available. Interbase, Oracle and MSSQL support transactions Any open transactions will be rolled back when the connection is closed. Note that StartTrans() and CompleteTrans() is a superior method of handling transactions, available since ADOdb 3.40 For a explanation, see the StartTrans() documentation You can also use the ADOdb error handler to die and rollback your transactions for you transparently. Some buggy database extensions are known to commit all outstanding tranasactions, so you might want to explicitly do a $DB->RollbackTrans() in your error handler for safety. 19.211 Detecting Transactions Since ADOdb 2.50, you are able to detect when you are inside a transaction Check that $connection>transCnt > 0 This variable is incremented whenever BeginTrans() is called, and decremented whenever RollbackTrans() or CommitTrans() is called. CommitTrans($ok=true) End a transaction successfully. Returns true if successful If the database does not support transactions, will

return true also as data is always committed. If you pass the parameter $ok=false, the data is rolled back. See example in BeginTrans() RollbackTrans( ) End a transaction, rollback all changes. Returns true if successful If the database does not support transactions, will return false as data is never rollbacked. GetOne($sql,$inputarr=false) Executes the SQL and returns the first field of the first row. The recordset and remaining rows are discarded for you automatically. If an error occur, false is returned GetRow($sql,$inputarr=false) Executes the SQL and returns the first row as an array. The recordset and remaining rows are discarded for you automatically. If an error occurs, false is returned GetAll($sql) Executes the SQL and returns the all the rows as a 2-dimensional array. The recordset is discarded for you automatically. If an error occurs, false is returned GetCol($sql,$inputarr=false,$trim=false) Executes the SQL and returns all elements of the first column as a

1-dimensional array. The recordset is discarded for you automatically. If an error occurs, false is returned CacheGetOne([$secs2cache,] $sql,$inputarr=false), CacheGetRow([$secs2cache,] $sql,$inputarr=false), CacheGetAll([$secs2cache,] $sql,$inputarr=false), CacheGetCol([$secs2cache,] $sql,$inputarr=false,$trim=false) 101 Similar to above Get* functions, except that the recordset is serialized and cached in the $ADODB CACHE DIR directory for $secs2cache seconds. Good for speeding up queries on rarely changing data. Note that the $secs2cache parameter is optional If omitted, we use the value in $connection->cacheSecs (default is 3600 seconds, or 1 hour). Prepare($sql ) Prepares an SQL query for repeated execution. Only supported internally by interbase, oci8 and selected ODBC-based drivers, otherwise it is emulated. There is no performance advantage to using Prepare() with emulation. Returns an array containing the original sql statement in the first array element; the remaining

elements of the array are driver dependent. If there is an error, or we are emulating Prepare( ), we return the original $sql string. This is because all error-handling has been centralized in Execute( ) Example: $stmt = $DB->Prepare(insert into table (col1,col2) values (?,?)); for ($i=0; $i < $max; $i++) $DB->Execute($stmt,array((string) rand(), $i)); Important: Due to limitations or bugs in PHP, if you are getting errors when you using prepared queries, try setting $ADODB COUNTRECS = false before preparing. This behaviour has been observed with ODBC. PrepareSP($sql) In the mssql driver, preparing stored procedures requires a special function call, mssql init( ), which is called by this function. PrepareSP( ) is available in all other drivers, and is emulated by calling Prepare( ). For examples of usage, see Parameter( ) below Returns the same array or $sql string as Prepare( ) above. Parameter($stmt, $var, $name, $isOutput=false, $maxLen = 4000, $type = false ) Adds a bind

parameter in a fashion that is compatible with Microsoft SQL Server and Oracle oci8. The parameters are: $stmt Statement returned by Prepare() or PrepareSP(). $var PHP variable to bind to. Make sure you pre-initialize it! $name Name of stored procedure variable name to bind to. [$isOutput] Indicates direction of parameter 0/false=IN 1=OUT 2= IN/OUT. This is ignored in oci8 as this driver auto-detects the direction. [$maxLen] Maximum length of the parameter variable. [$type] Consult mssql bind and ocibindbyname docs at php.net for more info on legal values for type. In mssql, $opt can hold the following elements: array(type => integer, maxLen =>integer). Example: # @RETVAL = SP RUNSOMETHING @myid,@group $stmt = $db->PrepareSP(SP RUNSOMETHING); # note that the parameter name does not have @ in front! $db->Parameter($stmt,$id,myid); $db->Parameter($stmt,$group,group,false,64); # return value in mssql - RETVAL is hard-coded name $db->Parameter($stmt,$ret,RETVAL,true);

$db->Execute($stmt); An oci8 example: # For oracle, Prepare and PrepareSP are identical $stmt = $db->PrepareSP( "declare RETVAL integer; begin :RETVAL := SP RUNSOMETHING(:myid,:group); 102 end;"); $db->Parameter($stmt,$id,myid); $db->Parameter($stmt,$group,group,false,64); $db->Parameter($stmt,$ret,RETVAL,true); $db->Execute($stmt); Note that the only difference between the oci8 and mssql implementations is the syntax of $sql. If $type parameter is set to false, in mssql, $type will be dynamicly determined based on the type of the PHP variable passed (string => SQLCHAR, boolean =>SQLINT1, integer =>SQLINT4 or float/double=>SQLFLT8). In oci8, $type can be set to OCI B FILE (Binary-File), OCI B CFILE (Character-File), OCI B CLOB (Character-LOB), OCI B BLOB (Binary-LOB) and OCI B ROWID (ROWID). To pass in a null, use $db->Parameter($stmt, $null=null, param) Lastly, in oci8, bind parameters can be reused without calling PrepareSP( ) or

Parameters again. This is not possible with mssql. An oci8 example: $id = 0; $i = 0; $stmt = $db->PrepareSP( "update table set val=:i where id=:id"); $db->Parameter($stmt,$id,id); $db->Parameter($stmt,$i, i); for ($cnt=0; $cnt < 1000; $cnt++) { $id = $cnt; $i = $cnt * $cnt; # works with oci8! $db->Execute($stmt); } Bind($stmt, $var, $size=4001, $type=false, $name=false) This is a low-level function supported only by the oci8 driver. Avoid using unless you only want to support Oracle. The Parameter( ) function is the recommended way to go with bind variables Bind( ) allows you to use bind variables in your sql statement. This binds a PHP variable to a name defined in an Oracle sql statement that was previously prepared using Prepare(). Oracle named variables begin with a colon, and ADOdb requires the named variables be called :0, :1, :2, :3, etc. The first invocation of Bind() will match :0, the second invocation will match :1, etc. Binding can provide 100%

speedups for insert, select and update statements. The other variables, $size sets the buffer size for data storage, $type is the optional descriptor type OCI B FILE (Binary-File), OCI B CFILE (Character-File), OCI B CLOB (Character-LOB), OCI B BLOB (Binary-LOB) and OCI B ROWID (ROWID). Lastly, instead of using the default :0, :1, etc names, you can define your own bind-name using $name. The following example shows 3 bind variables being used: p1, p2 and p3. These variables are bound to :0, :1 and :2. $stmt = $DB->Prepare("insert into table (col0, col1, col2) values (:0, :1, :2)"); $DB->Bind($stmt, $p1); $DB->Bind($stmt, $p2); $DB->Bind($stmt, $p3); for ($i = 0; $i < $max; $i++) { $p1 = ?; $p2 = ?; $p3 = ?; $DB->Execute($stmt); } You can also use named variables: $stmt = $DB->Prepare("insert into table (col0, col1, col2) values (:name0, :name1, :name2)"); $DB->Bind($stmt, $p1, "name0"); $DB->Bind($stmt, $p2, "name1");

$DB->Bind($stmt, $p3, "name2"); for ($i = 0; $i < $max; $i++) { $p1 = ?; $p2 = ?; $p3 = ?; $DB->Execute($stmt); } 103 fnExecute and fnCacheExecute properties These two properties allow you to define bottleneck functions for all sql statements processed by ADOdb. This allows you to perform statistical analysis and query-rewriting of your sql For example, to count all cached queries and non-cached queries, you can do this: # $db is the connection object function CountExecs($db, $sql, $inputarray) { global $EXECS; $EXECS++; } # $db is the connection object function CountCachedExecs($db, $secs2cache, $sql, $inputarray) { global $CACHED; $CACHED++; } $db = NewADOConnection(mysql); $db->Connect(.); $db->fnExecute = CountExecs; $db->fnCacheExecute = CountCachedExecs; : : # After many sql statements:` printf("<p>Total queries=%d; total cached=%d</p>",$EXECS+$CACHED, $CACHED); The fnExecute function is called before the sql is parsed and

executed, so you can perform a query rewrite. If you are passing in a prepared statement, then $sql is an array (see Prepare) The fnCacheExecute function is only called if the recordset returned was cached. The function parameters match the Execute and CacheExecute functions respectively, except that $this (the connection object) is passed as the first parameter. 104 ADOConnection Utility Functions BlankRecordSet([$queryid]) No longer available - removed since 1.99 Concat($s1,$s2,.) Generates the sql string used to concatenate $s1, $s2, etc together. Uses the string in the concat operator field to generate the concatenation. Override this function if a concatenation operator is not used, eg MySQL. Returns the concatenated string. DBDate($date) Format the $date in the format the database accepts; this can be a Unix integer timestamp or an ISO format Y-m-d. Uses the fmtDate field, which holds the format to use If null or false or is passed in, it will be converted to an SQL null.

Returns the date as a quoted string. DBTimeStamp($ts) Format the timestamp $ts in the format the database accepts; this can be a Unix integer timestamp or an ISO format Y-m-d H:i:s. Uses the fmtTimeStamp field, which holds the format to use If null or false or is passed in, it will be converted to an SQL null. Returns the timestamp as a quoted string. qstr($s,[$magic quotes enabled=false]) Quotes a string to be sent to the database. The $magic quotes enabled parameter may look funny, but the idea is if you are quoting a string extracted from a POST/GET variable, then pass get magic quotes gpc() as the second parameter. This will ensure that the variable is not quoted twice, once by qstr and once by the magic quotes gpc. Eg. $s = $db->qstr(HTTP GET VARS[name],get magic quotes gpc()); Returns the quoted string. Quote($s) Quotes the string, automatically checking get magic quotes gpc() first. If get magic quotes gpc() is set, then we do not quote the string. Affected Rows( ) Returns

the number of rows affected by a update or delete statement. Returns false if function not supported. Not supported by interbase/firebird currently. Insert ID( ) Returns the last autonumbering ID inserted. Returns false if function not supported Only supported by databases that support auto-increment or object ids, such as PostgreSQL, MySQL and MSSQL currently. PostgreSQL returns the OID, which can change on a database reload MetaDatabases() Returns a list of databases available on the server as an array. You have to connect to the server first Only available for ODBC, MySQL and ADO. MetaTables() 105 Returns an array of tables and views for the current database as an array. The array should exclude system catalog tables if possible. MetaColumns($table) Returns an array of ADOFieldObjects, one field object for every column of $table. Currently Sybase does not recognise date types, and ADO cannot identify the correct data type (so we default to varchar). MetaColumnNames($table)

Returns an array of column names for $table. MetaPrimaryKeys($table) Returns an array containing column names that are the primary keys of $table. Only supported by mysql, postgres, oci8 currently. ServerInfo($table) Returns an array of containing two elements description and version. The description element contains the string description of the database. The version naturally holds the version number (which is also a string). 106 19.3 ADORecordSet When an SQL statement successfully is executed by ADOConnection->Execute($sql),an ADORecordSet object is returned. This object contains a virtual cursor so we can move from row to row, functions to obtain information about the columns and column types, and helper functions to deal with formating the results to show to the user. ADORecordSet Fields fields: Array containing the current row. This is not associative, but is an indexed array from 0 to columns-1. See also the function Fields, which behaves like an associative array

dataProvider: The underlying mechanism used to connect to the database. Normally set to native, unless using odbc or ado. blobSize: Maximum size of a char, string or varchar object before it is treated as a Blob (Blobs should be shown with textareas). See the MetaType function sql: Holds the sql statement used to generate this record set. canSeek: Set to true if Move( ) function works. EOF: True if we have scrolled the cursor past the last record. ADORecordSet Functions ADORecordSet( ) Constructer. Normally you never call this function yourself GetAssoc([$force array]) Generates an associative array from the recordset if the number of columns is greater than 2. The array is generated from the current cursor position till EOF. The first column of the recordset becomes the key to the rest of the array. If the columns is equal to two, then the key directly maps to the value unless $force array is set to true, when an array is created for each key. Inspired by PEARs getAssoc Example: We

have the following data in a recordset: row1: Apple, Fruit, Edible row2: Cactus, Plant, Inedible row3: Rose, Flower, Edible GetAssoc will generate the following associative array: Apple => [Fruit, Edible] Cactus => [Plant, Inedible] Rose => [Flower,Edible] Returns: The associative array, or false if an error occurs. GetArray([$number of rows]) Generate a 2-dimensional array of records from the current cursor position, indexed from 0 to $number of rows - 1. If $number of rows is undefined, till EOF GetRows([$number of rows]) Generate a 2-dimensional array of records from the current cursor position. Synonym for GetArray() for compatibility with Microsoft ADO. GetMenu($name, [$moreAttr=]) [$default str=], [$blank1stItem=true], 107 [$multiple select=false], [$size=0], Generate a HTML menu (<select><option><option></select>). The first column of the recordset (fields[0]) will hold the string to display in the option tags. If the recordset has more

than 1 column, the second column (fields[1]) is the value to send back to the web server. The menu will be given the name $name. If $default str is defined, then if $default str == fields[0], that field is selected. If $blank1stItem is true, the first option is empty. You can also set the first option strings by setting $blank1stItem = "$value:$text". $Default str can be array for a multiple select listbox. To get a listbox, set the $size to a non-zero value (or pass $default str as an array). If $multiple select is true then a listbox will be generated with $size items (or if $size==0, then 5 items) visible, and we will return an array to a server. Lastly use $moreAttr to add additional attributes such as javascript or styles Menu Example 1: GetMenu(menu1,A,true) will generate a menu: (C,3). Also see example 5 A for the data (A,1), (B,2), Menu Example 2: For the same data, GetMenu(menu1,array(A,B),false) will generate a menu with both A and B selected: A B C

GetMenu2($name, [$moreAttr=]) [$default str=], [$blank1stItem=true], [$multiple select=false], [$size=0], This is nearly identical to GetMenu, except that the $default str is matched to fields[1] (the option values). Menu Example 3: Given the data in menu example 2, GetMenu2(menu1,array(1,2),false) will generate a menu with both A and B selected in menu example 2, but this time the selection is based on the 2nd column, which holds the values to return to the Web server. UserDate($str, [$fmt]) Converts the date string $str to another format.UserDate calls UnixDate to parse $str, and $fmt defaults to Y-m-d if not defined. UserTimeStamp($str, [$fmt]) Converts the timestamp string $str to another format. The timestamp format is Y-m-d H:i:s, as in 200202-28 23:00:12 UserTimeStamp calls UnixTimeStamp to parse $str, and $fmt defaults to Y-m-d H:i:s if not defined. UnixDate($str) Parses the date string $str and returns it in unix mktime format (eg. a number indicating the seconds after

January 1st, 1970). Expects the date to be in Y-m-d H:i:s format, except for Sybase and Microsoft SQL Server, where M d Y is also accepted (the 3 letter month strings are controlled by a global array, which might need localisation). This function is available in both ADORecordSet and ADOConnection since 1.91 UnixTimeStamp($str) Parses the timestamp string $str and returns it in unix mktime format (eg. a number indicating the seconds after January 1st, 1970). Expects the date to be in Y-m-d H:i:s format, except for Sybase and Microsoft SQL Server, where M d Y h:i:sA is also accepted (the 3 letter month strings are controlled by a global array, which might need localisation). This function is available in both ADORecordSet and ADOConnection since 1.91 108 OffsetDate($dayFraction, $basedate=false) Allows you to calculate future and past dates based on $basedate in a portable fashion. If $basedate is not defined, then the current date (at 12 midnight) is used. Returns the SQL string

that performs the calculation when passed to Execute(). For example, in Oracle, to find the date and time that is 2.5 days from today, you can use: # get date one week from now $fld = $conn->OffsetDate(7); // returns "(trunc(sysdate)+7") # get date and time that is 60 hours from current date and time $fld = $conn->OffsetDate(2.5, $conn->sysTimeStamp); // returns "(sysdate+25)" $conn->Execute("UPDATE TABLE SET dodate=$fld WHERE ID=$id"); This function is available for mysql, mssql, oracle, oci8 and postgresql drivers since 2.13 It might work with other drivers provided they allow performing numeric day arithmetic on dates. SQLDate($dateFormat, $basedate=false) Use the native SQL functions to format a date or date column $basedate, using a case-insensitive $dateFormat, which supports: Y: Q: M: D: 4-digit Year Quarter (1-4) Month (01-12) Day (01-31) All other characters are treated as strings. You can also use to escape characters Available on

selected databases, including mysql, postgresql, mssql, oci8 and DB2. This is useful in writing portable sql statements that GROUP BY on dates. For example to display total cost of goods sold broken by quarter (dates are stored in a field called postdate): $sqlfn = $db->SQLDate(Y-QQ,postdate); # get sql that formats postdate to output 2002-Q1 $sql = "SELECT $sqlfn,SUM(cogs) FROM table GROUP BY $sqlfn ORDER BY 1 desc"; MoveNext( ) Move the internal cursor to the next row. The $this->fields array is automatically updated Return false if unable to do so (normally because EOF has been reached), otherwise true. If EOF is reached, then the $this->fields array is set to false (this was only implemented consistently in ADOdb 3.30) Note that if false is returned, then the previous array in $this->fields is preserved. Example: $rs = $db->Execute($sql); if ($rs) while (!$rs->EOF) { ProcessArray($rs->fields); $rs->MoveNext(); } Move($to) Moves the internal

cursor to a specific row $to. Rows are zero-based eg 0 is the first row The fields array is automatically updated. For databases that do not support scrolling internally, ADOdb will simulate forward scrolling. Some databases do not support backward scrolling If the $to position is after the EOF, $to will move to the end of the RecordSet for most databases. Some obscure databases using odbc might not behave this way. Note: This function uses absolute positioning, unlike Microsofts ADO. Returns true or false. If false, the internal cursor is not moved in most implementations, so AbsolutePosition( ) will return the last cursor position before the Move( ). MoveFirst() 109 Internally calls Move(0). Note that some databases do not support this function MoveLast() Internally calls Move(RecordCount()-1). Note that some databases do not support this function GetRowAssoc($toUpper=true) The above function is no longer the prefered way of getting associative arrays. Use the $ADODB FETCH MODE

variable instead. Returns an associative array containing the current row. The keys to the array are the column names The column names are upper-cased for easy access. To get the next row, you will still need to call MoveNext(). For example: Array ( [ID] =>1 [FIRSTNAME] =>Caroline [LASTNAME] =>Miranda [CREATED] =>2001-07-05 ) Note: do not use GetRowAssoc() with $ADODB FETCH MODE = ADODB FETCH ASSOC. Because they have the same functionality, they will interfere with each other. AbsolutePage($page=-1) Returns the current page. Requires PageExecute()/CachePageExecute() to be called See Example 8 AtFirstPage($status=) Returns true if at first page (1-based). Requires PageExecute()/CachePageExecute() to be called See Example 8. AtLastPage($status=) Returns true if at last page (1-based). Requires PageExecute()/CachePageExecute() to be called See Example 8. Fields($colname) This function is deprecated. Use $ADODB FETCH MODE instead Some database extensions (eg. MySQL) return

arrays that are both associative and indexed if you use the native extensions. GetRowAssoc() does not return arrays that combine associative and indexed elements. Returns the value of the associated column $colname for the current row The column name is case-insensitive. FetchRow() Returns array containing current row, or false if EOF. FetchRow( ) internally moves to the next record after returning the current row. Warning: Do not mix using FetchRow() with MoveNext(). Usage: $rs = $db->Execute($sql); if ($rs) while ($arr = $rs->FetchRow()) { # process $arr } FetchInto(&$array) Sets $array to the current row. Returns PEAR Error object if EOF, 1 if ok (DB OK constant) If PEAR is undefined, false is returned when EOF. FetchInto( ) internally moves to the next record after returning the current row. FetchRow() is easier to use. See above FetchField($column number) 110 Returns an object containing the name, type and max length of the associated field. If the max length cannot

be determined reliably, it will be set to -1. The column numbers are zero-based See example 2. FieldCount( ) Returns the number of fields (columns) in the record set. RecordCount( ) Returns the number of rows in the record set. If the number of records returned cannot be determined from the database driver API, we will buffer all rows and return a count of the rows after all the records have been retrieved. This buffering can be disabled (for performance reasons) by setting the global variable $ADODB COUNTRECS = false. When disabled, RecordCount( ) will return -1 for certain databases. See the supported databases list above for more details RowCount is a synonym for RecordCount. PO RecordCount($table, $where) Returns the number of rows in the record set. If the database does not support this, it will perform a SELECT COUNT(*) on the table $table, with the given $where condition to return an estimate of the recordset size. $numrows = $rs->PO RecordCount("articles table",

"group=$group"); NextRecordSet() For databases that allow multiple recordsets to be returned in one query, this function allows you to switch to the next recordset. Currently only supported by mssql driver $rs = $db->Execute(execute return multiple rs); $arr1 = $rs->GetArray(); $rs->NextRecordSet(); $arr2 = $rs->GetArray(); FetchObject($toupper=true) Returns the current row as an object. If you set $toupper to true, then the object fields are set to uppercase Note: The newer FetchNextObject() is the recommended way of accessing rows as objects See below. FetchNextObject($toupper=true) Gets the current row as an object and moves to the next row automatically. Returns false if at end-offile If you set $toupper to true, then the object fields are set to upper-case $rs = $db->Execute(select firstname,lastname from table); if ($rs) { while ($o = $rs->FetchNextObject()) { print "$o->FIRSTNAME, $o->LASTNAME<BR>"; } } There is some trade-off

in speed in using FetchNextObject(). If performance is important, you should access rows with the fields[] array. FetchObj() Returns the current record as an object. Fields are not upper-cased, unlike FetchObject FetchNextObj() Returns the current record as an object and moves to the next record. If EOF, false is returned Fields are not upper-cased, unlike FetctNextObject. CurrentRow( ) Returns the current row of the record set. 0 is the first row 111 AbsolutePosition( ) Synonym for CurrentRow for compatibility with ADO. Returns the current row of the record set 0 is the first row. MetaType($nativeDBType[,$field max length],[$fieldobj]) Determine what generic meta type a database field type is given its native type $nativeDBType as a string and the length of the field $field max length. Note that field max length can be -1 if it is not known. The field object returned by the database driver can be passed in $fieldobj This is useful for databases such as mysql which has additional

properties in the field object such as primary key. Uses the field blobSize and compares it with $field max length to determine whether the character field is actually a blob. For example, $db->MetaType(char) will return C. Returns: • • • • • • • • • C: Character fields that should be shown in a <input type="text"> tag. X: Clob (character large objects), or large text fields that should be shown in a <textarea> D: Date field T: Timestamp field L: Logical field (boolean or bit-field) N: Numeric field. Includes decimal, numeric, floating point, and real. I: Integer field. R: Counter or Autoincrement field. Must be numeric B: Blob, or binary large objects. Since ADOdb 3.0, MetaType accepts $fieldobj as the first parameter, instead of $nativeDBType Close( ) Close the recordset. function rs2html($adorecordset,[$tableheader attributes], [$col titles]) This is a standalone function (rs2html = recordset to html) that is similar to PHPs odbc result

all function, it prints a ADORecordSet, $adorecordset as a HTML table. $tableheader attributes allow you to control the table cellpadding, cellspacing and border attributes. Lastly you can replace the database column names with your own column titles with the array $col titles. This is designed more as a quick debugging mechanism, not a production table recordset viewer. You will need to include the file tohtml.incphp Example of rs2html: <? include(tohtml.incphp); # load code common to ADOdb include(adodb.incphp); # load code common to ADOdb $conn = &ADONewConnection(mysql); # create a connection $conn->PConnect(localhost,userid,,agora);# connect to MySQL, agora db $sql = select CustomerName, CustomerID from customers; $rs = $conn->Execute($sql); rs2html($rs,border=2 cellpadding=3,array(Customer Name,Customer ID)); ?> 112 Differences between this ADOdb library and Microsoft ADO 1. ADOdb only supports recordsets created by a connection object Recordsets cannot be

created independently. 2. ADO properties are implemented as functions in ADOdb This makes it easier to implement any enhanced ADO functionality in the future. 3. ADOdbs ADORecordSet->Move() uses absolute positioning, not relative. Bookmarks are not supported 4. ADORecordSet->AbsolutePosition() cannot be used to move the record cursor. 5. ADO Parameter objects are not supported Instead we have the ADOConnection::Parameter( ) function, which provides a simpler interface for calling preparing parameters and calling stored procedures. 6. Recordset properties for paging records are available, but implemented as in Example 8. 113 20 Database Driver Guide This describes how to create a class to connect to a new database. To ensure there is no duplication of work, kindly email me at jlim#natsoft.commy if you decide to create such a class First decide on a name in lower case to call the database type. Lets say we call it xbase Then we need to create two classes ADODB xbase and

ADORecordSet xbase in the file adodbxbase.incphp The simplest form of database driver is an adaptation of an existing ODBC driver. Then we just need to create the class ADODB xbase extends ADODB odbc to support the new date and timestamp formats, the concatenation operator used, true and false. For the ADORecordSet xbase extends ADORecordSet odbc we need to change the MetaType function. See adodb-vfpincphp as an example. More complicated is a totally new database driver that connects to a new PHP extension. Then you will need to implement several functions. Fortunately, you do not have to modify most of the complex code You only need to override a few stub functions. See adodb-mysqlincphp for example The default date format of ADOdb internally is YYYY-MM-DD (Ansi-92). All dates should be converted to that format when passing to an ADOdb date function. See Oracle for an example how we use ALTER SESSION to change the default date format in pconnect connect. ADOConnection Functions to

Override Defining a constructor for your ADOConnection derived function is optional. There is no need to call the base class constructor. connect: Low level implementation of Connect. Returns true or false Should set the connectionID pconnect: Low level implemention of PConnect. Returns true or false Should set the connectionID query: Execute a query. Returns the queryID, or false close: Close the connection -- PHP should clean up all recordsets. ErrorMsg: Stores the error message in the private variable errorMsg. ADOConnection Fields to Set bindInputArray: Set to true if binding of parameters for SQL inserts and updates is allowed using ?, eg. as with ODBC fmtDate fmtTimeStamp true false concat operator replaceQuote hasLimit support SELECT * FROM TABLE LIMIT 10 of MySQL. hasTop support Microsoft style SELECT TOP 10 * FROM TABLE. ADORecordSet Functions to Override You will need to define a constructor for your ADORecordSet derived class that calls the parent class constructor.

FetchField: as documented above in ADORecordSet 114 initrs: low level initialization of the recordset: setup the numOfRows and numOfFields fields -called by the constructor. seek: seek to a particular row. Do not load the data into the fields array This is done by fetch Returns true or false. Note that some implementations such as Interbase do not support seek Set canSeek to false. fetch: fetch a row using the database extension function and then move to the next row. Sets the fields array. If the parameter $ignore fields is true then there is no need to populate the fields array, just move to the next row. then Returns true or false close: close the recordset Fields: If the array row returned by the PHP extension is not an associative one, you will have to override this. See adodb-odbcincphp for an example For databases such as MySQL and MSSQL where an associative array is returned, there is no need to override this function. ADOConnection Fields to Set canSeek: Set to

true if the seek function works. 20.1 Idő kezelése PHP – MySQL esetén Az időpontok kezelése a Unix hagyományokra épül. A Unix „időszámítás” kezdete 1970 január01, 0 óra 0 perc. Az időt a Unix rendszerek innen számított másodpercekben mérik és tárolják Ennek megfelelően a PHP és a MySQL is innen indul ki. A UNIX idő elnevezése TIMESTAMP Az így kapott időpont azonban egy nagy egész szám, amit az adatok bevitelénél és kiiratásánál nemigen lehet használni, ezért léteznek konverziós függvények ilyen célokra. A PHP esetén az aktuális időpontot a string Date(formátumstring [,timestamp]) függvény állítja elő A fromátumstringben az alábbi megjegyzések lehetnek: Év – y két karakter (01), Y 4 karakter hosszú (2001) Hónap - m – két karakter, sorszám 01, 02,, M – a hónap angol neve (January, February, ) Nap – d –két karakter, a hónapban a nap sorszáma, D – elnevezése angolul (Monday, Thuesday, ) Óra – h – 12

órás ciklus 00-12, H – 24 órás ciklus két karakter 00 - 23 Perc – i – kt karakter 00-59 Az eredmény tehát string! Az időpont átalakítása TIMESTAMP formátumra az alábbi függvénnyel lehetséges: int mktime (int óra, int perc, int másodperc, int hónap, int nap, int év [, int is dst]) Amennyiben nem akarunk kitölteni bizonyos értékeket, akkor 0-val kell feltölteni őket. Az utolsó paraméter a nappal értékét tartalmazza, általában elhagyható, sőt gyakorlatilag elhagyandó. A MySQL esetén az időpont tárolása és formátuma hasonlóan kettős. Lehet tárolni időpontot TIMESTAMP formátumban. Ekkor a UNIX timestamp lesz a belső tárolási formátum, de a megjelenítésnél már karaktersorozatot kapunk vissza. Ahhoz, hogy a PHP-nek megfelelő Timestamp legyen egy lekérdezés eredménye, a MySQL TIMESTAMP()függvényét kell használni. Az alábbiakban egy ilyen megoldásra látunk példát. Function koncertlista($datum) { // A lekérdezés

összeállítása 115 $qry ="SELECT UNIX TIMESTAMP(Mikor) AS Ido,Mi,Hol FROM esemeny WHERE Mikor > ".$datum""; $result = @mysql query($qry, $fc); $str ="<UL>"; while ($a = mysql fetch object($result)) { $str .= "<LI>"date("YMd, D H:i",$a->Ido)", "$a->Mi"<BR>"; $str .= $a->Hol"<BR>Belépő:"$a->Belepo" Ft</LI>"; } $str .="</UL>"; echo $str; return; } // Itt hívom meg az aktuális dátummal a függvényt. A formátum azért fontos, mert csak így // hasonlítható össze a MySQL Timestamp-jével. koncertlista(date("YmdHis")); Az eredmény az alábbi lesz: 2002.Jan12, Sat 09:12, Koncert Uj várklub Belépõ:500 Ft Az alkalmazott adattípus az SQL táblában a TIMESTAMP(14) 20.2 Sokáig futó programok A PHP scriptek futásának a maximális ideje korlátozva van a PHP-ben, mert ha egy végtelen ciklust ír az ember, akkor

lefagyaszthatja a szervert. A korlát default értéke 30 sec Ha egy scriptünk mégis tovább futna, mert valamilyen oknál fogva a feldolgozás lassú, vagy esetleg egy adatbázisszervertől vár adatokat, akkor célszerű használnunk az alábbi függvényt a PHP oldalunk elején, mivel ez a kívánt ideig engedi futni a scriptet Set time limit( másodperc) Célszerűen csak akkora értéket írjunk be, hogy a script biztonságosan lefusson, ugyanakkor idejében ki is lépjen, ha kell. Ha időnek 0-t írunk, akkor soha nem jár le a script, és ha végtelen ciklust teszünk bele, akkor örökhajtós lesz a scriptünk. 116 21 File-ok, könyvtárak kezelése a szerveren és távoli URL-eken Az alábbi fejezetben megnézzük, hogy melyek a leggyakrabban használt függvények és módszerek a PHP programokban. Amennyiben valaki úgy vélné, hogy más függvények gyakrabban használatosak az ő programjaiban, nagyon sajnálom, a help alapján kell megnézni a működésüket –

sokszor én is ott nézem meg. Az alábbi esetek fordulnak elő a filekezelésnél leggyakrabban a PHP programok esetén: - Távoli szerverről szeretnénk olvasni, vagy távoli szerverre írni - Helyi könyvtárszerkezetből szeretnénk olvasni, vagy ide szeretnénk írni. Az írásnál előfordulhat, hogy a kimenetet a helyi standard outputra szeretnénk tenni. - A fenti eseményeket bináris vagy text file esetén is meg akarjuk valósítani. - Helyi és távoli gépen is szeretnénk könyvtárakat létrehozni, vagy könyvtárakat törölni. - Alkalmanként kell vizsgálnunk, hogy a kérdéses file a helyi filestruktúrában vagy távoli szerveren létezik-e? - Egy megadott elérési útvonal file-ra, könyvtárra vagy link-re mutat-e? - A fileok kezeléséhez jó, ha tudjuk az alábbiakat: o Az éppen aktuálisan futó alkalmazás lokális szerveren lévő elérési útvonalát a § $ SERVER[”PATH TRANSLATED”] stringváltozó tartalmazza o A WEB szerver

gyökérkönyvtárát a § $ SERVER[”SERVER ROOT”] változó tartalmazza o Az operációs rendszer temporary könyvtárát § a $ ENV[”TEMP”] vagy hasonló nevű szuperglobális változó tartalmazza. A file kezelésnél tundnunk kell, hogy az otthoni környezetben futtatott program eléri-e az éles szerveren is ugyanazt a könyvtárat. Ha egy web struktúrában lévő file-t kell elérnünk, akkor célszerű kiindulnunk az éppen futó alkalmazás könyvtárából. A fentiek alapján, ha az indexphp alkalmazásunk az alábbi helyen fut: C:wwwrootvalami És egy geza nevű alkönyvtárban lévő szoveg.txt file-ra szeretnénk hivatkozni, akkor az alábbi elérést kell alkalmazni: $el = $ SERVER[”PATH TRANSLATED”].”/geza/szovegtxt”; Az elérési útvonalak kezelése során gyakori, hogy szét kell választanom az elérési utat könyvtár, filenév illetve kiterjesztés részre. Az alábbi függvények a fenti elérési utat választják szét: $path =

”C:/wwwroot/valami/geza/szoveg.txt”; $file = basename ($path); // $file értéke "szoveg.txt" $file = basename ($path,".txt"); // $file értéke "szoveg", mivel a második paraméter hatására // a végéről levágja a megadott stringet. $dir = dirname ($path); // $d értéke ”C:wwwrootvalamigeza" lesz. Alternatív megoldás a fenti feladatra lehet a pathinfo függvény: <?php $path parts = pathinfo("/www/htdocs/index.html"); echo $path parts["dirname"] . " "; echo $path parts["basename"] . " "; echo $path parts["extension"] . " "; ?> 117 Ha el akarjuk dönteni, hogy a filerendszer egy bejegyzése könyvtár, file, vagy egy link, akkor az alábbi függvényeket használhatjuk: boolean is dir($path); boolean is file($path); boolean is link($path); Egy file további tulajdonságait – attributumait az alábbi függvényekkel kaphatjuk meg: int is executable($path

)- Megmondja, hogy a bejegyzés futtatható-e int is readable($filename) – Megmondja, hogy a file olvasható-e int is writeable($filename) – Megmondja, hogy a file írható-e int fileatime ($filename)- A file utolsó elérési ideje. A visszaadott idő UNIX időbélyeg formájában int filemtime($filename) – A file utolsó módosításának ideje Unix időbélyeg formájában int Fileowner($filename) – A file tulajdonosának ID-je. Csak lokális filerendszerben használható int fileperms($filename) – A filera vonatkozó jogokat adja vissza. Csak lokális filerendszerben használható. int filesize($filename) - a file mérete $filename = ”C:/wwwroot/valami/geza/szoveg.txt”; echo filesize($filename); A filekezelés meglehetősen hasonlít a C-ben megszokottakra: Egy file olvasása előtt meg kell nyitnunk azt. Erre a célra az $fp = fopen($filenev, mód) függvényt használhatjuk, ahol a $filenév egy lokális filerendszer egy file-ja vagy egy URL-lel megadott file

lehet. Ha windows rendszert használunk, akkor a filenévben az elérési útban szereplő könyvtárneveket a \ jellel kell elválasztani. $fp=fopen (”C:\wwwroot\index.htm”,”w”); Ha a $filenév a http:// vagy az ftp:// jelekkel kezdődik, akkor egy távoli szerveren lévő file-ról van szó. $fp = fopen(”http://www.szilysulinethu/indexhtml”,”r”); A file megnyitásának módja az alábbi lehet: mód leírás Példa ’r’ Olvasásra nyitom meg a file-t. File pointer a file elején áll $fp=fopen(”C:\autoexec.bat”,”r”) ’w’ Írásra nyitom meg a file-t. A file pointer a file elejére áll és ha volt ilyen file, akkor megsemmisül, zéró hosszúságúvá válik $fp=fopen(”C:\inetpub\default.htm”,”w”) r+ Írásra és olvasásra nyitom meg a file-t. A pointer a file elejére áll. $fp=fopen(”C:\inetpub\adat.ini”,”r+”) ’w+ Írásra és olvasásra nyitom meg a file-t. A pointer $fp=fopen(”C:\inetpub\adat.ini”,”w+”) 118

’ a file elejére áll. A file megnyitáskor 0 hosszúságúra csonkolódik a Írásra nyitom meg a file-t. A pointer a file végére áll. $fp=fopen(”C:\inetpub\adat.ini”,”a”) ’a+’ Írásra és olvasásra nyitom meg a file-t. A pointer a file végére áll. $fp=fopen(”C:\inetpub\adat.ini”,”a+”) ’b’ Ha biztosan bináris file-t akarok olvasni vagy írni, akkor a megnyitáskor a mód stringbe be kell írni ezt is. $fp=fopen(”C:\autoexec.bat”,”rb”) A fenti utasítás hibaüzenetet ad, ha nem létezik az olvasásra megnyitni akart file. Ezért a hibakezeléshez az alábbiakat kell tenni: if (file exists($File)) // Létezik a file? { $fp = fopen($File,"r"); // Megnyitjuk olvasásra . Mielőtt olvasni szeretnénk egy file-t, meg kell nézni, hogy létezik-e. A létezés ellenőrzésére a Boolean file exists($filename) függvényt használhatjuk. A visszatérési értéke igaz, ha a file létezik, hamis egyébként Ha az fopen-nel

megnyitottunk egy filet írásra és egy karaktert vagy byte információt akarunk beolvasni, akkor az alábbi függvényt használhatjuk $c =fgetch($fp); Ha az fopen-nel megnyitottunk egy filet írásra, és egy text file egy sorát akarjuk beolvasni, akkor az alábbi függvényt használjuk: $sor = fgets($fp[,sorhossz]); A sorhossz paraméter nem kötelező, ha nem tesszük ki, akkor alapértéke 1024 karaktert olvas a függvény. Ha az fopen-nel megnyitottunk egy filet írásra és, ki akarom szedni a beolvasott fileból az esetlegesen benne lévő html tag-okat, akkor ezt kell használni. $sor=fgetss($fp[,sorhossz]); Ha nem adjuk meg a sorhosszat, akkor max 1024 hosszú stringet olvas be. Ha egy text file összes sorát be akarjuk olvasni egy tömbbe, akkor az alábbi függvényt kell használni: $aline =file($Filename[,int include path]) A függvény beolvassa a megadottt $Filename elérési útvonalú text file sorait egy $aline nevű tömbbe. A függvénnyel nemcsak a lokális

filerendszerből, hanem URL-lel megadott file-ból is lehet olvasni! Ha a file nem létezik, akkor hibaüzenet keletkezik, és a tömb elemszáma 0 marad. A kezelésére nézzük az alábbi példát a Help alapján: <?php // A beolvasandó file egy URL-lel van megadva. $filename =”http://www.szilyhu/szily/szilycss”; $asor = @file($filename); if(count($asor==0)){ die(”Nem létező file”); } 119 // A beolvasott file feldolgozása és a sorok kiiratása. // A html sorokat kiírja, mint html szöveg, sor és sorszámot is kiír. foreach ($asor as $line num => $sor) { echo "#<b>{$line num}</b> sor : " . htmlspecialchars($sor) "<br> "; } // Ez a példa egy file-t beolvas, majd a sorokat egy stringgé összevonja. $html = implode (, file (http://www.szilyhu/szily/)); ?> Ha egy teljes file-t akarunk beolvasni, akkor az alábbi függvényt kell használnunk: $t=fread($fp,$filesize( $filenev)); A filesize($filenev) függvény megadja

az adott file méretét byte-okban és a paraméter hatására a fileméretnek megfelelő puffert foglal le a memóriában a PHP. A visszatérési érték változója tartalmazza majd a file összes byte-ját, mint string. Ez a függvény bináris olvasáskor használható igazán, mert a beolvasott tartalommal semmiféle konverzió nem történik. Egy írásra vagy írásra/olvasásra megnyitott fileokba való írásnál alapvető függvény az int fwrite($fp,$c); Ha a kiirandó érték egy karakter, akkor karakterenként írunk, ha egy textfile egy sora, akkor a sorvége jelet hozzá kell tennünk a kiirandó tartalomhoz az alábbi módon: $c=$sor,” ”; Ha egy file tartalmát akarjuk kiiratni, akkor a változó tartalmazza a teljes tartalmat. Álljon itt filekezelésre egy komplexebb példa. Egy file-ból olvasnom kell, de ehhez először meg kell nyitnom. <!Ez a program megvalósít egy egyszerű karakter alapú számlálót. A számláló pillanatnyi értéke a counter.txt

állományban van, amit a szkript beolvas értékét minden egyes beolvasás során megnöveli, a megnövelt értéket ugyanabba a fileb visszaírja, majd a számláló állását megjeleníti. Ahhoz, hogy program megfelelően müködjön a counter.txt állományt létre kell hoznunk, melynek tartalma csak 1 legyen, ezt a filet fel kell töltenünk ugyanabba a könyvtárba, ahol a program van, és írási jogosultságot kell adnunk rá. --> <hr> Látogatók száma:<BR> <?php $File = counter.txt; // A számláló file neve if (file exists($File)) // Létezik a file? { $fp = fopen($File,"r"); // Megnyitjuk olvasásra $num = fread($fp, filesize($File)); // Beolvassuk a tartalmát a $num változóba. fclose($fp); // Zárjuk a filet. $num=$num+1; // A változó értékét megnöveljük $fp = fopen($File,"w"); // Megnyitjuk ugyanazt a filet, de most írásra fwrite($fp, $num, 10); // Kiírjuk a változó értékét. fclose($fp); 120 // Zárjuk a

filet echo(<b>.chop($num)</b>); // Kiírjuk a HTML-kódba a változó értékét. } ?> <hr> Az alábbiakban elmondjuk a filekezeléshez szükséges tudnivalókat. 121 22 Grafika A PHP-ban a grafikai modult nem a képek egyszerű kitételére használhatjuk, hanem a szerver oldalon képekkel végzett manipulációkra. A PHP grafikához szükséges, hogy a szerver oldalon be legyen töltve a GD.DLL vagy a GD 2DLL (Windows szerver esetén) A GD 2DLL támogatja a BMP, JPEG, GIF, és PNG képekkel végzett manipulációkat. Az alábbi mintában egy fotoalbum készítő és hazsnáló programot mutatunk be. A program az első meghívásakor az aktuális könyvtárban lévő képekről kisképeket készít, majd táblázatos formában megjeleníti azokat. A programot objektum-orientált formában írtam meg. <?php /* Simple PhotoAlbum 2.2120040602 (c) by Zoltán Fábián, 1999-2004 Use the program free. email: fz@szilyhu This script works on this site:

http://fz.szilyhu, http://www.alarmsystemhu/fotoalbum Használata include("./photoalbumphp"); */ if(stristr($ SERVER["PHP SELF"], FILE )) die("Nem hívhatod meg a file-t közvetlenül!."); if(!defined("THUMBNAIL WIDTH")) define("THUMBNAIL WIDTH",150); define("SERVERTARGET",str replace("."," ",$ SERVER["SERVER NAME"])); define("DOCUMENT ROOT",$ SERVER["DOCUMENT ROOT"].(( substr($ SERVER["DOCUMENT ROOT"],-1)!="/") ? "/" :"")); define("PHOTOSCRIPT",relpath( FILE )); //The path of this script define("PHOTOALBUM"," photoalbum.txt"); define("DELIMITER","#"); define("CSV OK",True); if(!isset($col)) $col = 4; define("COLUMNS", $col); if(!isset($slide)) $slide = 5; define("SLIDE", $slide); // Number of columns // timeout of the sliding //Needed gd extension

DEFINE("GD",True); if(!extension loaded ("gd")) { if(ini get("enable dl")) { DEFINE("GD",dl("gd.dll")); }else{ DEFINE("GD",False); } } 122 //The DO // ---------- Image class image { var $Name; // var $Thumb; // var $dx; // var $dy; var $Text; // osztály ----------Picture picture Thumbnail name size of picture text under the picture function image($Entry="",$Txt="") { global $aktdir,$newThumbnails; if(strlen($Entry)>0) { $this->Name = $Entry; //get size of picture if(GD) { $size = GetImageSize($aktdir.$this->Name); }else{ $size=array(800,600); } $this->dx = $size[0]; $this->dy = $size[1]; //Text under the pictures if (strlen($Txt)>0){ $this->Text = $Txt; }else{ $pos = explode(".",$Entry); $this->Text = str replace(" "," ",$pos[0]); } //Is there thumbnail of image? $thn = $aktdir."tn "$this->Name; $origDate = filemtime (

$aktdir.$this->Name); $isthn = is file($thn); $thDate = $isthn ? filemtime ( $thn): 0; //print($origDate ." "$thDate"<BR>"); if((!$isthn || ($origDate > $thDate ))&& GD ) { $this->NewThumbnail(); $newThumbnails++; }else{ $this->ReadThumbnail(); } }else{ $this->Name = ""; $this->dx = 0; $this->dy = 0; $this->Text = ""; } } 123 //Make new thumbnails from GIF, PNG or JPG | JPEG |bmp! function NewThumbnail () { global $gd, $aktdir; //size of original big picture $size = GetImageSize($aktdir.$this->Name); $dx = $size[0]; $dy = $size[1]; $a = eregi(".gif",$aktdir$this->Name); if((!eregi(".gif",$aktdir$this->Name)) && (($dx> THUMBNAIL WIDTH) |($dy>THUMBNAIL WIDTH))) { if (eregi(".jpg|jpeg",$aktdir$this->Name)) { $im = ImageCreateFromJPEG ($aktdir.$this->Name); //Empty destination image $dst im = @ImageCreateTrueColor( THUMBNAIL WIDTH, THUMBNAIL

WIDTH*$dy /$dx); } if (eregi(".png",$aktdir$this->Name)){ $im = @ImageCreateFromPNG ($pics->ImagePath.$this->Name); $dst im = @ImageCreateTrueColor(THUMBNAIL WIDTH, THUMBNAIL WIDTH*$dy /$dx); } if (eregi(".wbmp",$aktdir$this->Name)){ $im = @ImageCreateFromwbmp ($pics->ImagePath.$this->Name); $dst im = @ImageCreateTrueColor(THUMBNAIL WIDTH, THUMBNAIL WIDTH*$dy /$dx); } if (eregi(".bmp",$aktdir$this->Name)){ $im = @ImageCreateFromwbmp ($aktdir.$this->Name); $dst im = @ImageCreateTrueColor(THUMBNAIL WIDTH, THUMBNAIL WIDTH*$dy /$dx); } // Image resize and copy from source to destination $a = imagecopyresized ($dst im, $im, 0, 0, 0, 0, THUMBNAIL WIDTH, THUMBNAIL WIDTH*$dy/$dx, $dx, $dy); $this->Thumb = $aktdir."tn "$this->Name; //New image on disk Imagejpeg ($dst im, $this->Thumb); }else{ $this->Thumb = $aktdir."tn "$this->Name; copy($aktdir.$this->Name,$aktdir"tn "$this->Name); } }

//Thumbnail reading function ReadThumbnail(){ if(GD) { $this->Thumb = "tn ".$this->Name; }else{ $this->Thumb = $this->Name; } } 124 //Write out a thumbnail into the table function ShowThumbnail() { $str=$this->GetString(); print($str); } //get the string of a thumbnail function GetString() { global $css td,$css link,$pics; $str = "<TD ".$css td" ALIGN="CENTER" VALIGN="top">"; $str .= "<a href=javascript:picturepopup("" PHOTOSCRIPT."?getimg="$this->Name"&picpath=" $pics->ImageWebPath."",""SERVERTARGET"") " $css link."> "; $str .= "<IMG SRC=""$this->Thumb"" ALT=""$this->Name "" border="0" width="".THUMBNAIL WIDTH"" ><BR>" $this->Text."</a> "; $str .= "</TD>"; return $str; } } //--------

Image list class ----------class ImageList { var $aPictures = array(); //Array of images var $ImageNumber; var $RowNumber; //number of rows var $ImagePath; //The directory of list var $ImageWebPath; //The Path in the website var $CSV OK; var var var var var var var $css file; $css link; $css body; $css table; $css tr; $css td; $css tag; //styles //It makes a list from the actual directory function ImageList($path) { $this->newThumbnails = 0; $this->ImageNumber = 0; $this->ImagePath = $path; $this->ImageWebPath = substr(relpath($path),0,-1); if(CSV OK){ $aCSV = array(); if (file exists(PHOTOALBUM)){ $row = 1; $handle = fopen (PHOTOALBUM,"r"); while ($row = fgetcsv ($handle, 1000, DELIMITER)) { $aCSV[$row[0]] = $row[1]; } fclose ($handle); }else{ $handle=fopen(PHOTOALBUM,"w"); fclose($handle); } } //Make an Image object $d=opendir($path); while($entry=readdir($d)){ if ($this->is image($entry)) { 125 $text=$entry; //Handling CSS text if(CSV OK){

if(isset($aCSV)){ if(isset($aCSV[$entry])){ $text=$aCSV[$entry]; }else{ $handle = fopen(PHOTOALBUM,"a"); fwrite($handle,$entry.DELIMITER$entry" "); fclose($handle); } }else{ $handle = fopen(PHOTOALBUM,"a"); fwrite($handle,$entry.DELIMITER$entry" "); fclose($handle); } } $this->aPictures[] = new Image($entry,$text); $this->ImageNumber++; } } closedir($d); sort($this->aPictures); $this->RowNumber = (int) ($this->ImageNumber / COLUMNS ); } //Is Image this filename function is image($str){ //This is the right soluton. $str=" ".strtolower($str); //exclude thumbnails $pos = strpos ($str, "tn "); if ($pos ==1){ return FALSE; }else{ return eregi(".gif|jpg|jpeg|mp|png",$str); } } function css(){ global $css file,$css link,$css body,$css table,$css tr,$css td,$css tr; $this->css file = ( isset($ GET["css file"]) )? $ GET["css file"] : (isset($css file) ? $css link : False); $this->css

link = ( isset($ GET["css link"]) )? $ GET["css link"] : (isset($css link) ? $css link : "style="font-family: Verdana,Arial, Helvetica, sans-serif; font-size: x-small; color: #000000""); $this->css body = ( isset($ GET["css body"]) )? $ GET["css body"] : (isset($css body) ? $css body : "style="background-color: #666666;""); $this->css table = ( isset($ GET["css table"]))? $ GET["css table"]: (isset($css table)? $css table: "style="border:0;""); $this->css tr = ( isset($ GET["css tr"] ))? $ GET["css tr"] : (isset($css tr) ? $css tr : "style="vertical-align:top;""); $this->css td = ( isset($ GET["css td"] ))? $ GET["css td"] : (isset($css td) ? $css td : "align="center""); $this->css tag = ( isset($ GET["css tag"] ))? $ GET["css tag"] : (isset($css tag) ?

$css tag : "class="kapcsolat""); } //It makes a table from the pictures function ShowList() { $str=$this->GetString(); print($str); } function GetString() { global $css table,$css tr,$css td,$newThumbnails; 126 $str = picturepopup(); $str .= "<TABLE "$css table">";// Border="0"> "; $str .= "<TR "$css tr"> "; $j=0; while (list ($key, $ertek) = each ($this->aPictures)) { $str .=$this->aPictures[$key]->GetString(); $j++; if ($j == COLUMNS){ $str .="</TR> <TR>"; $j =0; } } while(0<$j && $j<COLUMNS){ $str .= "<TD "$css td">&nbsp;</TD>"; $j++; } $str .="</TR> "; $str .="</TABLE> "; if ($newThumbnails>0){ $str .="<p align=center style=color: #ff0000> Found " $newThumbnails." new pictures and made thumbnails!</p>"; $newThumbnails=0; } Return

$str; } //Searches an image in array function Search($image) { $i =0; while( ($i<sizeof($this->aPictures) ) && ($this->aPictures[$i]->Name != $image) ) { $i++; } return $i; } function PreviousImage($idx){ if($idx==0) $idx = sizeof($this->aPictures); $idx--; Return $idx; } function NextImage($idx) { if($idx==sizeof($this->aPictures)-1) $idx=-1; $idx++; Return $idx; } } class popup { var $Image; var $PrevImage; var $NextImage; var $dx; //width of popup var $dy; //height of popup var $dxx; //width of picture var $dyy; //height of picture function popup($getimg){ global $pics; $idx= $pics->Search($getimg); $this->Image = new Image(); 127 $this->PrevImage $this->NextImage $this->Image $this->PrevImage $this->NextImage $this->dxx = = = = = = new Image(); new Image(); $pics->aPictures[$idx]; $pics->aPictures[$pics->PreviousImage($idx)]; $pics->aPictures[$pics->NextImage($idx)]; ($this->Image->dx<600) ? (600)

:($this->Image->dx); if ($this->dxx>1024) $this->dxx = 1024; $this->dyy = ($this->Image->dy) *$this->dxx/$this->Image->dx; $this->dx = $this->dxx + 28; $this->dy = $this->dyy + 40; } function GetString(){ global $pics,$isslide; //Javascript for show the picture $str ="<HTML> "; $str .="<HEAD> "; $str .="<TITLE>Kep:"$this->Image->Name"</TITLE> "; if($isslide) { $str .="<META HTTP-EQUIV=REFRESH CONTENT="".SLIDE";URL="basename($ SERVER["PATH TRANSLATED"])"?getimg="urlenco de($this->NextImage->Name)."&isslide=1">"; } $str .="</HEAD> "; $str .= picturepopup(); $str .="<BODY style="background-color: #666666;" style="margin:0"> "; $str .="<DIV ALIGN=CENTER> "; $str .="<A

HREF=javascript:picturepopup(""PHOTOSCRIPT"?getimg="$this>PrevImage->Name"&picpath="$pics->ImageWebPath"",""SERVERTARGET"") style="font-family: Verdana,Arial, Helvetica, sans-serif; font-size: x-small; color: #000000" ".$pics->css tag">[::Prev::</A> "; $str .="<A HREF=javascript:picturepopup(""PHOTOSCRIPT"?getimg="$this>NextImage->Name"&picpath="$pics->ImageWebPath"",""SERVERTARGET"") style="font-family: Verdana,Arial, Helvetica, sans-serif; font-size: x-small; color: #000000" ".$pics->css tag">::Next::</A> "; $str .="<A HREF=javascript:picturepopup(""PHOTOSCRIPT"?getimg="$this>NextImage->Name"&picpath="$pics>ImageWebPath"&isslide=1",""SERVERTARGET"") style="font-family:

Verdana,Arial, Helvetica, sans-serif; font-size: x-small; color: #000000" ".$pics->css tag">::Slide::</A> "; $str .="<A HREF=javascript:picturepopup(""PHOTOSCRIPT"?getimg="$this>Image->Name"&picpath="$pics->ImageWebPath"",""SERVERTARGET""), style="font-family: Verdana,Arial, Helvetica, sans-serif; font-size: x-small; color: #000000" ".$pics->css tag">::Stop::</A> "; $str .="<A HREF="Javascript:void()" onClick="selfclose()" "$pics>css tag">::Close::]</A> "; $str .="<BR> "; $str .="<IMG SRC=""$pics->ImageWebPath"/"$this->Image->Name"" width="".$this->dxx""> "; $str .="</DIV> "; $str $str $str $str $str $str $str $str $str $str $str .="<SCRIPT

language="JAVASCRIPT14"> "; .=" dx = ".$this->dx"; "; .=" dy = ".$this->dy"; "; .=" if(self.OuterWidth < dx) { "; .=" dy = (int)(dy * self.OuterWidth /dx); "; .=" dx = self.innerWidth; "; .=" } "; .=" if(self.OuterHeight < dy) { "; .=" dx = (int)(dx * self.OuterHeight /dy); "; .=" dy = self.OuterHeight; "; .=" } "; 128 $str .=" self.resizeTo(dx, dy) "; $str .="</SCRIPT> "; $str .="</BODY> "; $str .="</HTML> "; return $str; } function Show() { print($this->GetString()); } } // * Some functions function picturepopup(){ $str = "<SCRIPT LANGUAGE="JAVASCRIPT1.2"> "; $str .= " function picturepopup(url,target){ "; $str .= " winpops=window.open(url,target,"status=0,resizable=1,location=0,menubar=0,scr ollbars=0,toolbar=0");

"; $str .= " } "; $str .= "</SCRIPT> "; return $str; } function CSS File search() { $lines = file ($ SERVER["PATH TRANSLATED"]); $keresendo = "text/css"; $csere = array("<",">","""); $lnk = " "; $ok = False; while ((list ($kulcs, $ertek) = each ($lines)) && !$ok){ $e = strtolower($ertek); $p = strpos($e,$keresendo); if($p>0) { $ok = True; $p1 = strpos($e,"href"); $e1 = substr($e,$p1+6); $e2 = explode(" ",$e1); $lnk= substr($e2[0],0,-1); } } Return $lnk; } //Searching for the css style after the body tag function CSS Body search() { $fname =$ SERVER["PATH TRANSLATED"]; $handle = fopen ($fname, "r"); $contents = fread ($handle, filesize ($fname)); fclose ($handle); $text = strtolower($contents); $text = str replace(" ", "", $text); $atags = array(); $atags = explode("<body",$text); if (sizeof($atags)

>1 ){ $lnk =""; $p = explode(""",$atags[1]); $lnk = $p[0]; }else { $lnk ="style="background-color: #666666""; } Return $lnk; } 129 function relpath($dir){ $dir=str replace("\","/",$dir); $len = strlen(DOCUMENT ROOT); return substr($dir,$len-1); } function pathcomp($p){ return (( substr($p,-1)!= "/") ? ($p."/") : ($p) ); } /* end of functions / /* * The main program */ $newThumbnail =0; //* Calling parameters $isslide = ( isset($ GET["isslide"] ) )? $ GET["isslide"] : (isset($isslide) ? $isslide :False); $getimg = ( isset($ GET["getimg"] ) )? $ GET["getimg"] : (isset($getimg) ? $getimg : ""); //The name of viewing picture //The path of actual pictures if (!isset($aktdir)){ //from calling script first if (isset($ GET["picpath"])){ //From somewhere $aktdir =substr(DOCUMENT ROOT,0,-1).$ GET["picpath"]; } else { //Slide $aktdir =

dirname($ SERVER["PATH TRANSLATED"])."/"; } } $aktdir=pathcomp($aktdir); $pics = new ImageList($aktdir); //* searching for css style settings if(!isset($pics->css file)) $pics->css file = CSS File search(); if(!isset($pics->css link)) $pics->css body = CSS Body Search(); //* main things if( !$getimg){ $pics->Showlist(); }else{ $p = new popup($getimg); $p->show(); } ?> // * show one Image 130 23 A környezet feldolgozása, azonosítás 131 24 Beléptetés, jelszavak alkalmazása, titkosítás Az alábbi forrást használtam fel a következő oldalak leírásához: http://hotwired.lycoscom/webmonkey/00/05/index2a page2html?tw=programming Amikor egy könyvtárat vagy html oldalt le akarunk védeni azonosító névvel és jelszóval, akkor először is meg kell szerveznünk a WEB szerver oldali védelmet. Ez a különböző WEB szerverek esetén mindig egy kicsit másképpen megy. Az Apache WEB szerver esetén is több lehetőség

kínálkozik, de talán a következő a legegyszerűbb: Tegyük fel, hogy a /wwwroot/ceg nevű könyvtárat szeretnénk levédeni: A védett könyvtárban létre kell hozni a .htaccess nevű file-t Ennek a tartalma: AuthType Basic AuthName "Vedett terület" AuthUserFile /wwwroot/ceg/.htpasswd AuthGroupFile /dev/null <Limit GET POST PUT> require valid-user </Limit> A szerveren be kell állítani a megfelelő könyvtárra az alábbi sorokat: httpd.conf <Directory "/wwwroot"> . AllowOverride AuthConfig . </Directory> //itt a www gyökérkönyvtáráról van szó // a későbbiek során be kell töltve lenniük az alábbi soroknak LoadModule LoadModule LoadModule LoadModule LoadModule LoadModule LoadModule LoadModule LoadModule anon auth module modules/mod auth anon.so dbm auth module modules/mod auth dbm.so digest auth module modules/mod auth digest.so digest module modules/mod digest.so expires module modules/mod expires.so headers module

modules/mod headers.so info module modules/mod info.so status module modules/mod status.so php4 module x:/php/sapi/php4apache.dll #Ez itt a PHP4 miatt kell Az alábbi könyvtárban /apache/bin le kell futtatni az alábbi parancsot: htpasswd /wwwroot/ceg/.htpasswd usernév Ennek hatására létrejön egy text file, amiben a usernév és a hozzá tartozó jelszó található. Ha több usert akarunk azonosíttatni, akkor létre kell hozni egy user groupot és abban a usereket definiálni. Például létrehozzuk a htgroup nevű file-t, amiben definiáljuk a csoportot: userek: bela geza user1 user2 Lefuttatjuk a jelszógenerálást többször htpasswd htpasswd htpasswd htpasswd /wwwroot/ceg/.htpasswd /wwwroot/ceg/.htpasswd /wwwroot/ceg/.htpasswd /wwwroot/ceg/.htpasswd bela geza user1 user2 Módosítjuk a htaccess file tartalmát: 132 AuthUserFile /wwwroot/ceg/.htpasswd AuthGroupFile /wwwroot/ceg/.htgroup AuthName userek AuthType Basic <Limit GET> require group dorks

</Limit> Az adott könyvtár oldalának lekérésekor a szerver elküldi a böngészőnek a 401-es hibakódot, amely utasítja a böngészőt, hogy jelenítse meg az adatok bevitelére alkalmas oldalt párbeszédablakot. Itt beviszi a felhasználó az adatokat, amit a szerver ellenőriz. A fenti módszer használatához nincsen szükség PHP közreműködésére, ugyanakkor nagy számú felhasználó esetén nem túl gyors a módszer, csak a szerveren lehet módosítani a userlistát és a jelszavakat. A beléptetésre több megfelelő módszer kínálkozik a PHP esetén. Ha modulként futtatjuk a PHP-t, akkor viszonylag egyszerűen biztosíthatjuk, hogy egy HTTP bekérést szimulálhassunk, csak az alábbi sorokat kell elküldeni a böngészőnek: header(WWW-Authenticate: Basic realm="Magánterület!"); header(HTTP/1.0 401 Unauthorized); echo Authorization Required.; exit; Ennek hatására a $PHP AUTH USER és $PHP AUTH PWD változók fogják tartalmazni a

bevitelnél adott választ. Ekkor sessionok segítségével minden oldalon felhasználhatjuk a változók értékeit Ha CGI módszerrel futtatjuk a PHP-t, akkor sajnos nem egyszerű a fenti változók használata, ekkor gondoskodni kell arról, hogy minden oldal hívásakor a változó tartalma átadódjon. A továbbiakban bemutatjuk két példán, hogy mi történik akkor, ha egy párbeszédablakban bekértük a két változó értékét. Egy lehetőség, hogy létrehozzunk egy beviteli ablakot egy HTML form segítségével, majd POST metódussal elküldjük az eredményt a következő oldalnak. <Form method=”POST” ACTION=”login.php”> <p>Kérem a usernevet: <INPUT Type=”text” NAME=”PHP AUTH USER” SIZE=60><BR> Kérem a jelszót: <INPUT TYPE =”PASSWORD” NAME=”PHP AUTH PWD”><BR> <INPUT TYPE=”SUBMIT” NAME=”OK”> <INPUT TYPE=”RESET” NAME=”RESET”> </Form> A login.php oldal leellenőrzi, hogy a

megfelelő usernév jelszó páros szerepel-e benne Az ellenőrzés történhet adatbázisból vagy sima text file-ból is. 133 <?php // Megvizsgáljuk, hogy az előző form-ból kapott adatok között létezik-e //a $PHP AUTH USER változó és tartalmaz-e adatokat. if (!isset($PHP AUTH USER)) { // Ha nem létezik, a változó, akkor elküldünk egy fejlécet a böngészőnek. header(WWW-Authenticate: Basic realm="Magánterület!"); header(HTTP/1.0 401 Unauthorized); exit; } else if (isset($PHP AUTH USER)) { // Ha nem üres a változó, akkor megnézzük, hogy az adatbázisban megvan-e // a megfelelő usernév jeszó páros // MySQL kapcsolatot hozunk létre. Az itteni usernév nem azonos a beléptető userrel! mysql connect("hostname", "username", "password") or die ("Unable to connect to database."); // Megnyitjuk a jelszóadatbázist mysql select db("Userlista") or die ("Unable to select database."); //

Elküldjük a lekérdezést a users táblára $sql = "SELECT * FROM users WHERE username=$PHP AUTH USER and password=$PHP AUTH PW"; // Végrehajtjuk, majd az eredmény a $result változóba kerül $result = mysql query($sql); // Ha az eredménynek 0 sora van, akkor nincs ilyen user és jelszó páros, // ha 1, akkor van $num = mysql numrows($result); if ($num != "0") { echo "<P>Isten hozott!</p>"; exit; } else { header(WWW-Authenticate: Basic realm="Magánterület!"); header(HTTP/1.0 401 Unauthorized); echo Authorization Required.; exit; } } ?> Hasonló megoldás, amikor egy text file-t használunk az authentikációhoz: <?php // Megvizsgáljuk, hogy az előző form-ból kapott adatok között létezik-e //a $PHP AUTH USER változó és tartalmaz-e adatokat. if (!isset($PHP AUTH USER)) { // Ha nem létezik, a változó, akkor elküldünk egy fejlécet a böngészőnek. header(WWW-Authenticate: Basic

realm="Magánterület!"); header(HTTP/1.0 401 Unauthorized); exit; } else if (isset($PHP AUTH USER)) { // Ha nem üres a változó, akkor megnézzük, hogy egy text file-ban megvan-e // a megfelelő usernév jeszó páros. Beolvassuk a file-t a $file tartalom nevű // változóba $filename = "/wwwroot/ceg/file.txt"; $fp = fopen($filename, "r"); $file tartalom = fread($fp, filesize($filename)); fclose($fp); 134 // A text file sorait egy $sor nevű tömbbe visszük be. //A sorok végét a karakter jelzi. $sor = explode(" ", $file tartalom); // // // // Végignézzük a $sor tombot, hogy a megfelelő értéket megtaláljuk-e benne A sor minden elemét két részre bontjuk, usernév és jelszó párra. Az elválasztó jel a : A következőben a keresés programozási tételt alkalmazzuk. $i = 0; $adatok = explode(":", $sor[$i]); while($i<=sizeof($sor))&& !(($adatok[0]=="$PHP AUTH USER") &&($adatok[1]==

"$PHP AUTH PW")) { $data pair = explode(":", $sor[$i]); i++; } if ($i<=sizeof($sor)) $auth = 1; else $auth = 0; if ($auth == "1") { echo "<P>Isten hozott!</p>"; exit; } else { header(WWW-Authenticate: Basic realm="Magánterület!"); header(HTTP/1.0 401 Unauthorized); echo Authorization Required.; exit; } ?> A fenti rutinokat kissé módosítva beírhatjuk őket egy include file-ba. Ha minden php oldalon beszúrjuk a file-t, akkor automatikusan az oldal bekérésekor lefut és ellenőrzi a jogosultságot. Mindenesetre ekkor biztosítani kell, hogy átlépve a következő oldalra a $PHP AUTH USER és $PHP AUTH PWD változók tartalma megmaradjon és elérhető legyen. 135 Egy harmadik és talán elég jól használható megoldás. Alapja, hogy egy scriptet minden védett oldal elejére beszúrunk, ami az oldal hívásakor lefut és SESSION változóban tároljuk a beléptetés eredményét, illetve a beléptetett

user-t. $name =""; $pwd =""; Session start(); if(!isset($ SESSION["logged in"])) $ SESSION["logged in"] = False; If (!$ SESSION["logged in"]){ if( isset($ POST["name"]) && isset($ POST["pwd"])){ //Ha később login formot használunk POST-tal $name = $ POST["name"]; $pwd = $ POST["pwd"]; //Ha a Böngésző authhentikációs ablakát használjuk // if (isset($PHP AUTH USER) && isset ($PHP AUTH PW)){ // $name = $PHP AUTH USER; // $pwd = $PHP AUTH PW; // //A jelszó és usernév ellenőrzése adatbázisból mysql connect("hostname", "username", "password") or die ("Unable to connect to database."); // Megnyitjuk a jelszóadatbázist mysql select db("Userlista") or die ("Unable to select database."); // Elküldjük a lekérdezést a users táblára $sql = "SELECT * FROM users WHERE username=$name and password=$pwd";

// Végrehajtjuk, majd az eredmény a $result változóba kerül $result = mysql query($sql); // Ha az eredménynek 0 sora van, akkor nincs ilyen user és jelszó páros, // ha 1, akkor van $num = mysql numrows($result); if($num>0){ //Ide kell betenni a jelszóellenőrzést $ SESSION["logged in"] = True; //vagy sima text vagy mysql lekérdezés stb. } } } If (!($ SESSION["logged in"])){ //Vagy egy login formot használunk, ekkor POST-tal küldjük el a megfelelő értékeket include ("login.html"); // vagy szimuláljuk a WEBböngésző beléptető oldalát. //header(WWW-Authenticate: Basic realm="Beléptetés!"); //header(HTTP/1.0 401 Unauthorized); exit; } 24.1 Titkosított átvitele a kliens és a szerver között: MD5() A PHP-ban van egy jól használható függvény, amellyel adatok módosítatlanását tudjuk vizsgálnialapvető titkosítását tudjuk elvégezni, illetve a titkosított adatokat tudjuk visszakódolni plain text-é. Az

adatoknak karakter formátumúaknak kell lenni A függvény az String md5( string) /* * md5.jvs 10b 27/06/96 * * Javascript implementation of the RSA Data Security, Inc. MD5 136 * Message-Digest Algorithm. * * Copyright (c) 1996 Henri Torgemane. All Rights Reserved * * Permission to use, copy, modify, and distribute this software * and its documentation for any purposes and without * fee is hereby granted provided that this copyright notice * appears in all copies. * * Of course, this soft is provided "as is" without express or implied * warranty of any kind. * * $Id: md5.js,v 12 1998/11/22 14:27:42 sas Exp $ * */ function array(n) { for(i=0;i<n;i++) this[i]=0; this.length=n; } /* Some basic logical functions had to be rewritten because of a bug in * Javascript. Just try to compute 0xffffffff >> 4 with it * Of course, these functions are slower than the original would be, but * at least, they work! */ function integer(n) { return n%(0xffffffff+1); } function

shr(a,b) { a=integer(a); b=integer(b); if (a-0x80000000>=0) { a=a%0x80000000; a>>=b; a+=0x40000000>>(b-1); } else a>>=b; return a; } function shl1(a) { a=a%0x80000000; if (a&0x40000000==0x40000000) { a-=0x40000000; a*=2; a+=0x80000000; } else a*=2; return a; } function shl(a,b) { a=integer(a); b=integer(b); for (var i=0;i<b;i++) a=shl1(a); return a; } function and(a,b) { a=integer(a); b=integer(b); var t1=(a-0x80000000); var t2=(b-0x80000000); if (t1>=0) if (t2>=0) return ((t1&t2)+0x80000000); else return (t1&b); else if (t2>=0) return (a&t2); else 137 return (a&b); } function or(a,b) { a=integer(a); b=integer(b); var t1=(a-0x80000000); var t2=(b-0x80000000); if (t1>=0) if (t2>=0) return ((t1|t2)+0x80000000); else return ((t1|b)+0x80000000); else if (t2>=0) return ((a|t2)+0x80000000); else return (a|b); } function xor(a,b) { a=integer(a); b=integer(b); var t1=(a-0x80000000); var t2=(b-0x80000000); if (t1>=0) if

(t2>=0) return (t1^t2); else return ((t1^b)+0x80000000); else if (t2>=0) return ((a^t2)+0x80000000); else return (a^b); } function not(a) { a=integer(a); return (0xffffffff-a); } /* Here begin the real algorithm / var state = new array(4); var count = new array(2); count[0] = 0; count[1] = 0; var buffer = new array(64); var transformBuffer = new array(16); var digestBits = new array(16); var var var var var var var var var var var var var var var var S11 S12 S13 S14 S21 S22 S23 S24 S31 S32 S33 S34 S41 S42 S43 S44 = = = = = = = = = = = = = = = = 7; 12; 17; 22; 5; 9; 14; 20; 4; 11; 16; 23; 6; 10; 15; 21; function F(x,y,z) { return or(and(x,y),and(not(x),z)); } function G(x,y,z) { return or(and(x,z),and(y,not(z))); 138 } function H(x,y,z) { return xor(xor(x,y),z); } function I(x,y,z) { return xor(y ,or(x , not(z))); } function rotateLeft(a,n) { return or(shl(a, n),(shr(a,(32 - n)))); } function FF(a,b,c,d,x,s,ac) { a = a+F(b, c, d) + x + ac; a = rotateLeft(a, s); a = a+b;

return a; } function GG(a,b,c,d,x,s,ac) { a = a+G(b, c, d) +x + ac; a = rotateLeft(a, s); a = a+b; return a; } function HH(a,b,c,d,x,s,ac) { a = a+H(b, c, d) + x + ac; a = rotateLeft(a, s); a = a+b; return a; } function II(a,b,c,d,x,s,ac) { a = a+I(b, c, d) + x + ac; a = rotateLeft(a, s); a = a+b; return a; } function transform(buf,offset) { var a=0, b=0, c=0, d=0; var x = transformBuffer; a b c d = = = = state[0]; state[1]; state[2]; state[3]; for (i = 0; i < 16; i++) { x[i] = and(buf[i*4+offset],0xff); for (j = 1; j < 4; j++) { x[i]+=shl(and(buf[i*4+j+offset] ,0xff), j 8); } } /* Round a = FF ( d = FF ( c = FF ( b = FF ( a = FF ( d = FF ( c = FF ( b = FF ( a = FF ( d = FF ( c = FF ( b = FF ( a = FF ( d = FF ( c = FF ( b = FF ( 1 */ a, b, d, a, c, d, b, c, a, b, d, a, c, d, b, c, a, b, d, a, c, d, b, c, a, b, d, a, c, d, b, c, c, b, a, d, c, b, a, d, c, b, a, d, c, b, a, d, d, c, b, a, d, c, b, a, d, c, b, a, d, c, b, a, x[ 0], x[ 1], x[ 2], x[ 3], x[ 4], x[ 5], x[ 6],

x[ 7], x[ 8], x[ 9], x[10], x[11], x[12], x[13], x[14], x[15], S11, S12, S13, S14, S11, S12, S13, S14, S11, S12, S13, S14, S11, S12, S13, S14, 0xd76aa478); 0xe8c7b756); 0x242070db); 0xc1bdceee); 0xf57c0faf); 0x4787c62a); 0xa8304613); 0xfd469501); 0x698098d8); 0x8b44f7af); 0xffff5bb1); 0x895cd7be); 0x6b901122); 0xfd987193); 0xa679438e); 0x49b40821); 139 /* /* /* /* /* /* /* /* /* /* /* /* /* /* /* /* 1 */ 2 */ 3 */ 4 */ 5 */ 6 */ 7 */ 8 */ 9 */ 10 */ 11 */ 12 */ 13 */ 14 */ 15 */ 16 */ /* Round a = GG ( d = GG ( c = GG ( b = GG ( a = GG ( d = GG ( c = GG ( b = GG ( a = GG ( d = GG ( c = GG ( b = GG ( a = GG ( d = GG ( c = GG ( b = GG ( 2 */ a, b, d, a, c, d, b, c, a, b, d, a, c, d, b, c, a, b, d, a, c, d, b, c, a, b, d, a, c, d, b, c, c, b, a, d, c, b, a, d, c, b, a, d, c, b, a, d, d, c, b, a, d, c, b, a, d, c, b, a, d, c, b, a, x[ 1], x[ 6], x[11], x[ 0], x[ 5], x[10], x[15], x[ 4], x[ 9], x[14], x[ 3], x[ 8], x[13], x[ 2], x[ 7], x[12], S21, S22, S23, S24, S21, S22, S23,

S24, S21, S22, S23, S24, S21, S22, S23, S24, 0xf61e2562); 0xc040b340); 0x265e5a51); 0xe9b6c7aa); 0xd62f105d); 0x2441453); 0xd8a1e681); 0xe7d3fbc8); 0x21e1cde6); 0xc33707d6); 0xf4d50d87); 0x455a14ed); 0xa9e3e905); 0xfcefa3f8); 0x676f02d9); 0x8d2a4c8a); /* /* /* /* /* /* /* /* /* /* /* /* /* /* /* /* 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 */ */ */ */ */ */ */ */ */ */ */ */ */ */ */ */ /* Round a = HH ( d = HH ( c = HH ( b = HH ( a = HH ( d = HH ( c = HH ( b = HH ( a = HH ( d = HH ( c = HH ( b = HH ( a = HH ( d = HH ( c = HH ( b = HH ( 3 */ a, b, d, a, c, d, b, c, a, b, d, a, c, d, b, c, a, b, d, a, c, d, b, c, a, b, d, a, c, d, b, c, c, b, a, d, c, b, a, d, c, b, a, d, c, b, a, d, d, c, b, a, d, c, b, a, d, c, b, a, d, c, b, a, x[ 5], x[ 8], x[11], x[14], x[ 1], x[ 4], x[ 7], x[10], x[13], x[ 0], x[ 3], x[ 6], x[ 9], x[12], x[15], x[ 2], S31, S32, S33, S34, S31, S32, S33, S34, S31, S32, S33, S34, S31, S32, S33, S34, 0xfffa3942); 0x8771f681); 0x6d9d6122); 0xfde5380c);

0xa4beea44); 0x4bdecfa9); 0xf6bb4b60); 0xbebfbc70); 0x289b7ec6); 0xeaa127fa); 0xd4ef3085); 0x4881d05); 0xd9d4d039); 0xe6db99e5); 0x1fa27cf8); 0xc4ac5665); /* /* /* /* /* /* /* /* /* /* /* /* /* /* /* /* 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 */ */ */ */ */ */ */ */ */ */ */ */ */ */ */ */ /* Round a = II ( d = II ( c = II ( b = II ( a = II ( d = II ( c = II ( b = II ( a = II ( d = II ( c = II ( b = II ( a = II ( d = II ( c = II ( b = II ( 4 */ a, b, d, a, c, d, b, c, a, b, d, a, c, d, b, c, a, b, d, a, c, d, b, c, a, b, d, a, c, d, b, c, c, b, a, d, c, b, a, d, c, b, a, d, c, b, a, d, d, c, b, a, d, c, b, a, d, c, b, a, d, c, b, a, x[ 0], x[ 7], x[14], x[ 5], x[12], x[ 3], x[10], x[ 1], x[ 8], x[15], x[ 6], x[13], x[ 4], x[11], x[ 2], x[ 9], S41, S42, S43, S44, S41, S42, S43, S44, S41, S42, S43, S44, S41, S42, S43, S44, 0xf4292244); 0x432aff97); 0xab9423a7); 0xfc93a039); 0x655b59c3); 0x8f0ccc92); 0xffeff47d); 0x85845dd1); 0x6fa87e4f); 0xfe2ce6e0); 0xa3014314);

0x4e0811a1); 0xf7537e82); 0xbd3af235); 0x2ad7d2bb); 0xeb86d391); /* /* /* /* /* /* /* /* /* /* /* /* /* /* /* /* 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 */ */ */ */ */ */ */ */ */ */ */ */ */ */ */ */ state[0] state[1] state[2] state[3] +=a; +=b; +=c; +=d; } function init() { count[0]=count[1] = 0; state[0] = 0x67452301; state[1] = 0xefcdab89; state[2] = 0x98badcfe; state[3] = 0x10325476; for (i = 0; i < digestBits.length; i++) digestBits[i] = 0; } function update(b) { var index,i; 140 index = and(shr(count[0],3) , 0x3f); if (count[0]<0xffffffff-7) count[0] += 8; else { count[1]++; count[0]-=0xffffffff+1; count[0]+=8; } buffer[index] = and(b,0xff); if (index >= 63) { transform(buffer, 0); } } function finish() { var bits = new array(8); var padding; var i=0, index=0, padLen=0; for (i = 0; i < 4; i++) { bits[i] = and(shr(count[0],(i * 8)), 0xff); } for (i = 0; i < 4; i++) { bits[i+4]=and(shr(count[1],(i * 8)), 0xff); } index = and(shr(count[0], 3)

,0x3f); padLen = (index < 56) ? (56 - index) : (120 - index); padding = new array(64); padding[0] = 0x80; for (i=0;i<padLen;i++) update(padding[i]); for (i=0;i<8;i++) update(bits[i]); for (i = 0; i < 4; i++) { for (j = 0; j < 4; j++) { digestBits[i*4+j] = and(shr(state[i], (j 8)) , 0xff); } } } /* End of the MD5 algorithm / function hexa(n) { var hexa h = "0123456789abcdef"; var hexa c=""; var hexa m=n; for (hexa i=0;hexa i<8;hexa i++) { hexa c=hexa h.charAt(Mathabs(hexa m)%16)+hexa c; hexa m=Math.floor(hexa m/16); } return hexa c; } var ascii="01234567890123456789012345678901" + " !"#$%&()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ"+ "[\]^ `abcdefghijklmnopqrstuvwxyz{|}~"; function MD5(entree) { var l,s,k,ka,kb,kc,kd; init(); for (k=0;k<entree.length;k++) { l=entree.charAt(k); update(ascii.lastIndexOf(l)); } finish(); ka=kb=kc=kd=0; for (i=0;i<4;i++) ka+=shl(digestBits[15-i], (i*8)); for

(i=4;i<8;i++) kb+=shl(digestBits[15-i], ((i-4)*8)); for (i=8;i<12;i++) kc+=shl(digestBits[15-i], ((i-8)*8)); for (i=12;i<16;i++) kd+=shl(digestBits[15-i], ((i-12)*8)); s=hexa(kd)+hexa(kc)+hexa(kb)+hexa(ka); 141 return s; } 142 25 Biztonság, tippek és trükkök Egy nyilvános szerveren futó PHP program futtatásának a biztonságossá tétele rendkívül fontos dolog, és két tényezőn, a szerver beállításain és a programozó gondosságán is múlik. Bemenő adatok ellenőrzése és szűrése A bemenő adatokat két oldalon lehet vagy kell ellenőrizni. - A user oldalon a formok adatbevitelének felprogramozásával - A szerver oldalon a már elküldött adatok érvényességének vizsgálatával Az első változat arra való csakis és kizárólag, hogy a felhasználó user hibáit kiküszöböljk illetve minimalizáljuk. Az adatbevitel általában egy ormon keresztül zajlik, tehát a formon való adatbevitelt célszeű ellenőrizni. Erre a célra

általában Javascript kódot használhatunk, amely például akkor fut le, - ha a Form submit gombját megnyomjuk – ekkor a Form onSubmit eseményére indulhat el a Javascript kód, - vagy minden egyes mező értékének változásakor lefuttatunk egy ellenőrző rutint – ekkor a mező onChange eseményére indulhat a javascript kód. Mely mezőket kell ellenőrizni? Gondos programozással csak néhányat. A HTML Formoknál az alábbi beviteli mezők vannak: - Input mező Text – ellenőrizni kell TEXTarea – ellenőrizni kell Checkbox – ellenőrizni lehet RadioButton – célszerű ellenőrizni Select menü – a kiválasztottságot célszerű ellenőrizni File mező – Igazából a file létezését ellene ellenőrizni, de nem illik. Csak annyit leet, hogy a file mezőben van-e valamiféle bejegyzés. A fentiek alapján llátszik, hogy egyszerű esetben csak a text és a textarea ellenőrzése igazán fontos. Ott ellenőrizhetjük a string hosszát, azt hogy bizonyos

karakterek benne vannak-e vagy nincsenek. Mevizsgálhatjuk, hogy a bevitt adat numerikus-e, és ha igen, akkor milyen tartományba esik. A szerver oldalon már ellenőrzött adatot kapunk, miért kell a szerver oldalon ismételten ellenőrizni? A a kliens oldali ellenőrzés sokkal gyorsabb, továbbá a userek sanda szándékait a szerver oldalon lehet csak elkapni. Itt is minden fenti dolgot ellenrizhetünk, azaz: - Egy változó értékét - Egy változó formáját (milyen hosszú, milyen karakterek vannak bene vagy hiányoznak). Itt kell kiszűrni az esetlegesen bevitt HTML tag-eket, a ” és a ’ jeleket, az esetlegesen bevitt SQL utasításneveket (SQL injection). - Az adat numerikus-e, és ha igen, akkor megfelelő-e az értéke. - Ez azt jelenti, hogy itt már a változók létét, a formátumát, és értékét kell csak ellenőrizni. Itt kell felkészülni esetleges sanda szándékú userek datbevitelére is. File-k elérésének a kezelése 143 A PHP.INI

megfelelő (biztonságos) beállítása Biztonságos kapcsolatok, kapcsolati módok használata 144 26 A PHP.INI file paraméterezése A PHP.INI file általában a PHP beállítáasait tartalmazó file Itt nem sorolhajuk fel az összes lehetséges paraméterét, de néhány általunk fontosabbnak tartott paramétert igen. Megjegyzendő, hogy a paramétereket a set ini(változónév, érték) függvénnyel állíthatjuk be futás közben programból, és a pillanatnyi értékeket a get ini(változónév) függvénnyel lehet lekérni. Az ini restore(változónév) a korábbi értékeket állítja vissza, az ini alter(változónév, érték) pedig a változó korábbi értékével tér vissza, ha a módosítás sikeres volt, ha nem , akkor False értéket ad vissza. Változónév Default érték Hol módosítható define syslog variables "0" PHP INI ALL highlight.bg HL BG COLOR PHP INI ALL highlight.comment HL COMMENT COLOR PHP INI ALL highlight.default HL

DEFAULT COLOR PHP INI ALL highlight.html HL HTML COLOR PHP INI ALL highlight.keyword HL KEYWORD COLOR PHP INI ALL highlight.string HL STRING COLOR PHP INI ALL allow call time pass reference "1" PHP INI SYSTEM|PHP INI PERDIR asp tags "0" PHP INI SYSTEM|PHP INI PERDIR display errors "1" PHP INI ALL display startup errors "0" PHP INI ALL enable dl "1" PHP INI SYSTEM error append string NULL PHP INI ALL error prepend string NULL PHP INI ALL expose php "1" PHP INI SYSTEM html errors "1" PHP INI SYSTEM ignore user abort "0" PHP INI ALL implicit flush "0" PHP INI PERDIR|PHP INI SYSTEM log errors "0" PHP INI ALL magic quotes gpc "1" PHP INI ALL magic quotes runtime "0" PHP INI ALL magic quotes sybase "0" PHP INI ALL output buffering "0" PHP INI PERDIR|PHP INI SYSTEM 145 Változónév Default

érték Hol módosítható output handler NULL PHP INI PERDIR|PHP INI SYSTEM register argc argv "1" PHP INI ALL register globals "1" PHP INI PERDIR|PHP INI SYSTEM safe mode "0" PHP INI SYSTEM short open tag "1" PHP INI SYSTEM|PHP INI PERDIR sql.safe mode "0" PHP INI SYSTEM track errors "0" PHP INI ALL y2k compliance "0" PHP INI ALL arg separator "&" PHP INI ALL auto append file NULL PHP INI ALL auto prepend file NULL PHP INI ALL doc root NULL PHP INI SYSTEM default charset SAPI DEFAULT CHARSET PHP INI ALL default mimetype SAPI DEFAULT MIMETYPE PHP INI ALL error log NULL PHP INI ALL extension dir PHP EXTENSION DIR PHP INI SYSTEM gpc order "GPC" PHP INI ALL include path PHP INCLUDE PATH PHP INI ALL max execution time "30" PHP INI ALL open basedir NULL PHP INI SYSTEM safe mode exec dir "1" PHP INI SYSTEM upload

max filesize "2M" PHP INI ALL file uploads "1" PHP INI ALL post max size "8M" PHP INI SYSTEM upload tmp dir NULL PHP INI SYSTEM user dir NULL PHP INI SYSTEM variables order NULL PHP INI ALL SMTP "localhost" PHP INI ALL browscap NULL PHP INI SYSTEM 146 Változónév Default érték Hol módosítható error reporting NULL PHP INI ALL memory limit "8M" PHP INI ALL precision "14" PHP INI ALL sendmail from NULL PHP INI ALL sendmail path DEFAULT SENDMAIL PATH PHP INI SYSTEM disable functions "" PHP INI SYSTEM allow url fopen "1" PHP INI ALL 147 Sablonok – Template-ek, LIB-ek Template vagy más előregyártott library-t akkor használunk, ha 1. Gyorsítani akarjuk a PHP alkalmazás futtatását 2. Gyorsítani akarjuk a programfejlesztést 3. El akarjuk választani a fejlesztés design és a logikai részét 4. Nem akarjuk feltalálni a spanyolviaszt, azaz a

más által jól megírt kódot használni akarjuk 26.1 Template-ek, Smarty A template rendszerek olyan PHP-ban vagy egyéb módon kifejlesztett alkalmazások, amelyek segítségével el tudjuk választani egymástól az üzleti logika és a design elemeket. Ezek a gyakorlatban azt jelentik, hogy a design elemek egy HTML-hez hasonló kódolási rendszerben jönnek létre, z adatbázis, és egyéb prorgramozási részek a kifejleszett PHP kód alapján, és a futás közben amTemplate rendszer összeszerkeszti a design template-eket és a PHPkódot, majd az így létrejött kódot futtatja. Felvetődik a kérdés, hogy mennyire lassítja le az alkalmazást az így kifejlesztett kód? A tapasztalatok azt mutatják, hogy egyes template rendszerek használata esetén a kód futási sebessége nő, mivel nem a PHP-nak kell előállítania a teljes HTML tartalmat, hanem azt HTML kódban tartjuk. A PHP programozónak és a Designernek könnyű elválasztania a munkáját, hiszen a

programozó és a designer egy jól definiált felhasználói interface-en keresztül kapcsolódik egymáshoz. A programnak az a feladata, hogy az általa előállított PHP kód eredményét helyezze el egy tipikusan string típusú változóba, amit aztán a sablon feldolgozó modulja beszerkeszt a Sablon tartalmába és elküldi a WEB szerveren keresztül a kliensnek. Tekintettel arra, hogy a Web oldalak jelentős része még akkor is statikusnak tekinthető, ha PHP-val állítkjuk elő, egyes sablon rendszerek arra is képeske, hogy az összeszerkesztett oldalakat cache-eljék, azaz az összeszerkesztett oldallal szolgáljanak ki bizonyos kéréseket. Az alábbiakban a Smarty nevű népszerű alkalmazáscsomaggal ismerkedünk meg egy kicsit. A telepítése során a smarty.incphp oldalt kell beszerkesztenünk az oldalaink elejére, ami egyúttal inicializálja a rendszert. A példában egy program leőállítja a kódot, a kimenete egy stringbe kerül, majd a smarty rendszer a

tartalmat egy változóban helyezi el. Azután a template változó tartalmával együtt a smarty megjeleníti az eredényt. 26.2 PEAR Csomag 148 27 PHP Cache programok Zend Cache Turck- MMCache 149