Scrigroup - Documente si articole

     

HomeDocumenteUploadResurseAlte limbi doc
AccessAdobe photoshopAlgoritmiAutocadBaze de dateCC sharp
CalculatoareCorel drawDot netExcelFox proFrontpageHardware
HtmlInternetJavaLinuxMatlabMs dosPascal
PhpPower pointRetele calculatoareSqlTutorialsWebdesignWindows
WordXml


De ce PHP si PostgreSQL?

php



+ Font mai mare | - Font mai mic



De ce PHP si PostgreSQL?

La inceputul erei Internet, multe situri Web erau bazate pe aplicatii Perl, care utilizau interfatǎ CGI. Prin intermediul interfetei CGI, este posibil sǎ utilizǎm orice limbaj de programare pentru generarea directǎ a codului HTML. Limbajul de programare Perl este optimizat pentru construirea procesoarelor text, din acest motiv fiind cel mai adecvat pentru construirea siturilor Web. Codul HTML este bazat pe text, paginile dinamice fiind usor de generat. Perl nu a fost proiectat sǎ fie un limbaj Web. PHP dispune de multiple avantaje fatǎ de Perl deoarece PHP a fost optimizat pentru Web.



PHP si PostgreSQL sunt open source, codul sursǎ PHP si PostgreSQL putand fi utilizat si distribuit gratuit. Utilizarea software-ului open source are multiple avantaje:

- costuri - nu trebuie sǎ plǎtim pentru software, care duce la reducerea costurilor totale ale proiectelor software;

- securitate - software-ul gratuit este mult mai sigur decat software-ul comercial. In multe cazuri aducerea la zi a software-ului gratuit este rapid disponibil, probleme de securitate grave fiind imediat rezolvate;

- informatii - cand utilizǎm software comercial, trebuie sǎ stim exact ce anume realizeazǎ anumite componente. In cazul software-ului gratuit trebuie doar sǎ ne uitǎm in codul sursǎ PHP sau PostgreSQL si vom vedea ce anume realizeazǎ codul;

- independentǎ - software-ul gratuit ne ajutǎ sǎ castigǎm independentǎ fatǎ de fabricantii de software. Aceasta este important deoarece nu trebuie sǎ urmǎm calea propusǎ de marii "jucǎtori" de pe piata afacerilor software;

- calitate - in majoritatea cazurilor software-ul gratuit contine cod de calitate superioarǎ. Persoanele care implementeazǎ open source sunt foarte bine motivate, din acest motiv software-ul gratuit oferind stabilitate si flexibilitate;

- libertate - software-ul gratuit oferǎ posibilitatea de a modifica software-ul in functie de necesitǎtile pe care le avem. Putem adǎuga usor facilitǎti, si, in plus, putem optimiza software-ul pentru aplicatiile noastre.

Ultimul element este foarte important. "Software-ul gratuit nu este bere gratis", sustine Richard M. Stallman, fondatorul software-ului gratuit; dacǎ nu ai nici o sansǎ sǎ modifici software-ul, mintea ta nu este liberǎ si din acest motiv trebuie sǎ ne ferim de acest lucru.

In prezent existǎ o multitudine de baze de date gratuite. Multi dezvoltatori au incredere in baze de date ca MySQL. MySQL oferǎ o versiune specialǎ de SQL care nu este conformǎ cu ANSI-SQL. Cand portǎm aplicatiile MySQL pentru alte baze de date, incompatibilitatea MySQL-ului reprezintǎ o problemǎ realǎ deoarece este necesar sǎ rescriem sau cel putin sǎ modificǎm pǎrti majore ale codului SQL. In plus, PostgreSQL oferǎ facilitǎti sofisticate cum ar fi mostenirea, triggere si limbaje incorporate.

Spre deosebire de MySQL, PostgreSQL este conform cu standardul ANSI SQL-92. Portarea aplicatiilor pe PosgreSQL este o sarcinǎ usoarǎ si existǎ si posibilitatea sǎ trecem de la PostgreSQL la baze de date comerciale cum ar fi DB2 sau Oracle.

PHP oferǎ o interfatǎ usor de folosit pentru PostgreSQL. Interfata de programare a PHP-ului este construitǎ pe baza librǎriilor PostgreSQL libpq. Aceastǎ librǎrie este utilizatǎ de toate limbajele de programare mai importante: Python, Tcl sau Perl si oferǎ toate facilitǎtile de care avem nevoie pentru a construi aplicatii robuste cu baze de date.

Ce anume putem realiza cu PHP si PostgreSQL

Vom discuta instalarea si vom vedea cum poate fi setat PHP si cum PHP poate interactiona cu serverul Web. De asemenea vom urmǎri:

- implementarea si intretinerea unei aplicatii simple in PHP;

- scopul variabilelor, lucrul cu fisiere, construirea pachetelor, lucrul cu formulare si debugging-ul;

- posibilitǎtile orientate-obiect ale PHP-ului: constructori, clase, mostenire, construirea de aplicatii modulare, reutilizarea codului in aplicatii;

- principii teoretice ale bazelor de date relationale si obiect;

- instalarea PostgreSQL-ului; ne vom focaliza pe instalarea PostgreSQL pe Unix si Windows;

- SQL, tipuri de date avansate care pot fi utilizate pentru a stoca date privind informatiile de retea sau geometrice, view-uri, subselecturi, alias-uri, autojoin-uri, constrangeri si tranzactii, orientarea obiect, reguli care permit redefinirea comenzilor SQL in functie de necesitǎti;

- PL/pgSQL - limbaj embedded similar cu cu Oracle PL/SQL, scrierea de triggere;

- administrarea bazelor de date, definirea drepturilor utilizatorilor si managementul securitǎtii retelei;

- PHP cu PostgreSQL - scrierea unor aplicatii simple cu baze de date, introducerea si afisarea datelor din baza de date, blocarea si mostenirea;

- lucrul cu fisiere mari (BLOB), cum stocǎm fisierele in bazele de date PostgreSQL, upload-ul de fisiere pe serverele Web remote in mod sigur;

- lucrul cu conexiuni persistente la bazele de date - pericole si beneficii;

- expresiile regulate in stil Perl si POSIX si ultizarea acestora in PostgreSQL;

- managementul sesiunilor;

- generarea imaginilor, sunetelor filmelor si documentelor. Ex:

In combinatie cu utilitare ca LaTeX, pot fi generate documente. Continutul documentului este preluat din baza de date si poate fi administrat usor. Este posibil sǎ generǎm documente care contin sute de pagini, rapid si eficient.

- lucrul cu data si ora, tuning-ul Postgres-ului, mǎsurarea performantei;

- securitatea mediului Web;

- prototipuri de aplicatii: Web shop, managementul continutului, grafice;

- construirea unor extensii in PostgreSQL: construirea indecsilor substring;

Situri Web construite in PHP si PostgreSQL

Ecomtel oferǎ utilitare online de billing. Software-ul de billing este extrem de sigur si performant, fiind necesarǎ o testare si o aplicatie rapidǎ cum ar fi PHP si PostgreSQL.

Universitatea din Vienna - construirea unor baze de date geografice si generarea hǎrtilor cu PHP si PostgreSQL. Datoritǎ interfetei excelente pentru lucrul cu tipuri de date geometrice, baza de date este adecvatǎ pentru oamenii de stiintǎ si pentru studenti.

PHP - istoric

PHP este un limbaj optimizat pentru generarea siturilor Web dinamice. Teoretic poate fi utilizat si ca limbaj de programare obisnuit, dar nu a fost optimizat pentru acest lucru.

In 1994, Rasmus Lerdorf cǎuta o metodǎ usoarǎ de a programa serverul Web personal. El a denumit prima sa incercare "Personal Home Page Tools". In 1995, aceste utilitare au devenit mult mai profesionale, o versiune numitǎ PHP/FI (Personal Home Page Tools/Form Interface) fiind lansatǎ. Dupǎ versiunea 2 (PHP/FI), PHP a fost dezvoltat mult mai rapid, si in 1997 PHP3 a fost lansat. PHP 3 a fost folosit pe scarǎ largǎ si poate fi regǎsit pe multe situri Web deoarece a fost un limbaj foarte sigur si usor de folosit. Spre deosebire de Perl, PHP a fost proiectat pentru Web de la inceput, multe lucruri care pot fi greu de realizat in Perl putand fi usor de realizat cu ajutorul PHP-ului. Versiunea recentǎ de PHP, PHP4 este bazatǎ pe motorul Zend. Motorul Zend este mult mai rapid decat versiunea anterioarǎ de PHP datoritǎ compilatorului intern.

In prezent, PHP reprezintǎ o platformǎ rapidǎ si sigurǎ pentru dezvoltarea aplicatiilor Web. Dezvoltarea PHP-ului va continua si multe facilitǎti vor adǎugate.

Instalarea Apache cu PHP din surse

PHP ruleazǎ pe platforme multiple si poate interactiona cu variate servere Web. Cel mai rǎspandit server Web este Apache si Microsoft IIS.

Apache cu PHP pe UNIX

Instalarea din surse are unele avantaje fatǎ de cea din pachete binare. Cel mai important avantaj este cǎ vom sti exact ce flag a fost activat si ce componente au fost compilate in fisierele binare. Pentru aceasta vom compila codul sursǎ. Dezavantajul constǎ in faptul cǎ presupune mai multǎ muncǎ instalarea surselor decat instalarea binarelor. Un dezavantaj suplimentar este lipsa de cunostinte sau experientǎ pe Linux sau Unix.

Primul lucru care trebuie sǎ-l facem este sǎ descǎrcǎm sursele Apache-ului si PHP-ului de la adresele www.apache.org respectiv www.php.net.

Pe masinile Unix codul sursǎ este de obicei stocat in /usr/src. In acest scenariu vom genera un director numi apache_php localizat in /usr/src. Acest director va contine sursele Apache-ului si PHP-ului dar si scriptul shell pentru compilarea surselor. Vom descǎrca sursele in /usr/src/apache_php si vom extrage cele douǎ pachete utilizand tar xvfz packname, unde packname reprezintǎ numele pachetului (de ex, apache_1.3.22.tar.gz). Urmǎtorul pas implicǎ crearea unor legǎturi soft, utilizand ln.

[root@duron apache_php]# ln -s apache_1.3.22/ apache

[root@duron apache_php]# ln -s php-4.1.0/ php

Configurarea Apache-ului

Vom face o trecere in revistǎ a parametrilor de configurare suportati de Apache 1.3.22. Pentru aceasta vom intra in directorul apache si vom tasta ./configure --help:

[root@duron apache]# ./configure --help
[hang on a moment, generating help]

Usage: configure [options]
Options: [defaults in brackets after descriptions]
Optiuni generale:
--quiet, --silent nu va afisa mesajele
--verbose, -v afiseazǎ mai multe mesaje
--shadow[=DIR] comutǎ in director pentru compilare

Optiuni stand-alone:
--help, -h va afisa acest mesaj
--show-layout afiseaza calea de instalare

Optiuni de instalare:
--with-layout=[F:]ID utilizeazǎ ID-ul cǎii de instalare
--target=TARGET instaleazǎ fisierele asociate numelui utilizand numele lor de bazǎ TARGET
--prefix=PREFIX instaleazǎ fisierele dependente de arhitecturǎ in PREFIX
--exec-prefix=EPREFIX instaleazǎ fisierele dependente de arhitecturǎ in EPREFIX
--bindir=DIR instaleazǎ executabilele utilizator in DIR
--sbindir=DIR instaleazǎ executabilele sysadmin in DIR
--libexecdir=DIR instaleazǎ programele executabilele in DIR
--mandir=DIR instaleazǎ paginiel de manual in DIR
--sysconfdir=DIR instaleazǎ fisierele de configurare in DIR
--datadir=DIR instaleazǎ fisierele de date read-only in DIR
--iconsdir=DIR instaleazǎ fisierele iconite in DIR
--htdocsdir=DIR instaleazǎ paginile de welcome read-only in DIR
--manualdir=DIR instaleazǎ documentatia online read-only in DIR
--cgidir=DIR instaleazǎ fisierele cgi read-only in DIR
--includedir=DIR instaleazǎ fisierele include in DIR
--localstatedir=DIR instaleazǎ fisierele de date modificabile in DIR
--runtimedir=DIR install datele runtime in DIR
--logfiledir=DIR install datele de tip log in DIR
--proxycachedir=DIR install datele de tip proxy cache in DIR

Optiuni de configurare:
--enable-rule=NAME permite o regulǎ particularǎ numitǎ 'NAME'
--disable-rule=NAME nu permite o regulǎ particularǎ numitǎ 'NAME'
[DEV_RANDOM=default EXPAT=default IRIXN32=yes ]
[IRIXNIS=no PARANOID=no SHARED_CHAIN=de]
[SHARED_CORE=default SOCKS4=no SOCKS5=no ]
[WANTHSREGEX=default ]
--add-module=FILE copierea directǎ si activare unui modul tert
--activate-module=FILE activarea directǎ a unui modul tert existent
--permute-module=N1:N2 permutarea directǎ a modulului 'N1' cu modulul 'N2'
--enable-module=NAME activarea unui modul particular numit 'NAME'
--disable-module=NAME dezactivarea unui modul particular numit 'NAME'
[access=yes actions=yes alias=yes ]
[asis=yes auth_anon=no auth_dbm=no ]
[auth_db=no auth_digest=no auth=yes ]
[autoindex=yes cern_meta=no cgi=yes ]
[digest=no dir=yes env=yes ]
[example=no expires=no headers=no ]
[imap=yes include=yes info=no ]
[log_agent=no log_config=yes log_referer=no ]
[mime_magic=no mime=yes mmap_static=no ]
[negotiation=yes proxy=no rewrite=no ]
[setenvif=yes so=no speling=no ]
[status=yes unique_id=no userdir=yes ]
[usertrack=no vhost_alias=no ]
--enable-shared=NAME permite construirea unui modul numit 'NAME' ca DSO
--disable-shared=NAME dezactiveazǎ construirea unui modul numit 'NAME' ca DSO
--with-perl=FILE calea cǎtre interpretorul Perl optional
--with-port=PORT specificarea numǎrulu portului pentru httpd.conf
--without-support dezactiveazǎ construirea si instalarea utilitarelor
--without-confadjust dezactiveazǎ posibilitatea ca utilizatorul sǎ facǎ ajustǎri in config
--without-execstrip dezactiveazǎ stripping-ul executabilelor la instalare
--server-uid=UID seteazǎ ID-ul user al serverului Web la [nobody]
--server-gid=GID seteazǎ ID-ul grupului al serverului Web

optiuni suEXEC:
--enable-suexec permite facilitatea suEXEC
--suexec-caller=NAME seteazǎ utilizatorul suEXEC al apelantului permis [www]
--suexec-docroot=DIR seteazǎ directorul root suEXEC [PREFIX/share/htdocs]
--suexec-logfile=FILE seteazǎ fisierul de log suEXEC [PREFIX/var/log/suexec_log]
--suexec-userdir=DIR seteazǎ subdirectorul utilizator suEXEC [public_html]
--suexec-uidmin=UID seteazǎ minimul UID permis suEXEC [100]
--suexec-gidmin=GID seteazǎ GID-ul suEXEC minim permis [100]
--suexec-safepath=PATH seteazǎ calea sigurǎ suEXEC [/usr/local/bin:/usr/bin:/bin]
--suexec-umask=UMASK seteazǎ umask-ul pentru scriptul suEXEC

Configurarea PHP-ului

PHP nu este inclus in distributia Apache. PHP este incǎ un modul extern care trebuie configurat independent. Dupǎ extragerea surselor PHP si intrarea in direcotrul care contine sursele, putem utiliza ./configure --help pentru a obtine o listǎ a tuturor parametrilor de configurare PHP (PHP 4.1). Vom trece in revistǎ cele mai importante flag-uri:

--prefix - defineste locatia in care PHP va fi instalat;

--with-aolserver - dacǎ se doreste rularea PHP-ului in combinatie cu serverul Web AOL, trebuie setat acest flag;

--with-apache - pentru a rula PHP cu Apache, acest flag poate fi utilizat pentru a spune PHP-ului unde poate fi gǎsit codul sursǎ al Apache-ului;

--with-tux - recent Tux a devenit foarte popular. Tux este un server Web optimizat pentru performante ridicate, care poate fi utilizat soar in combinatie cu nucleul Linux;

--with-pear - PEAR este o librǎrie pentru PHP; se va defini locul unde librǎria va fi instalatǎ;

--with-openssl - acest flag este necesar dorim ca PHP sǎ suporte OpenSSL, care reprezintǎ un strat pentru o comunicatie sigurǎ bazatǎ pe criptarea cheilor publice-private;

--enable-bcmath - bc este un limbaj care calculeazǎ precizia arbitrarǎ. Bc reprezintǎ un utilitar standard pe masinile Unix si este deseori utilizat in combinatie cu scripturile shell. Dacǎ bcmath este activ, PHP va suporta aceastǎ modalitate de calcul;

--with-cpdflib - acest flag este necesar dacǎ dorim ca interfata PDF a PHP-ului sǎ fie activǎ. Din acest motiv cpdflib >=2 este necesar. Dacǎ librǎria nu este instalatǎ pe sistem, o putem descǎrca de la https://www.pdflib.com/pdflib/index.html;

--with-jpeg-dir - pentru lucrul cu imagini JPEG, este necesar sǎ activǎm acest flag. In special cand lucrǎm cu imagini generate dinamic, acest flag este esential; altfel, PHP nu va fi capabil sǎ inteleagǎ fisierele JPG;

--witg-gd - librǎria gd este una din librǎriile standard pentru procesarea imaginilor. Dacǎ planificǎm sǎ modificǎm imaginile, acest flag este necesar;

--enable-gd-native-ttf - acest flag activeazǎ suportul pentru fonturile True Type. Spre deosebire de fonturile "pixel", fonturile True Type sunt mult mai omogene. Cand lucrǎm cu imagini dinamice si text acest flag va fi esential pentru generarea imaginilor de inaltǎ calitate;

--with-freetype-dir - pentru a lucra cu FreeType 2 (un motor de afisare a fonturilor True Type), acest flag trebuie sǎ foe activat;

--with-ttf - dacǎ dorim sǎ lucrǎm cu o versiune veche de FreeType (versiuni 1.x), trebuie sǎ utilizǎm --with-ttf in loc de --with-freetype-dir;

--with-imap - IMAP (Internet Message Access Protocol) este un protocol pentru interactionarea cu e-mail-ul. IMAP este un complement al lui POP (Post Office Protocol) si suportǎ o varietate de facilitǎti sofisticate. Pentru a lucra cu IMAP si PHP acest flag trebuie sǎ fie activ;

--with-kerberos - Kerberos reprezintǎ un sistem bine dezvoltat pentru autentificarea utilizatorilor in retea.

--with-pgsql[=DIR] - vom include suport pentru PostgreSQL. DIR reprezintǎ directorul de bazǎ al instalǎrii, implicit /usr/local/pgsql.

Dacǎ sunt necesare componente aditionale cum ar fi suport pentru DB2 sau Oracle, vom utiliza flag-urile corespunzǎtoare.

Este necesar ca dupǎ procesul de compilare sǎ verificǎm dacǎ urmǎtoarea linie a fost adǎugatǎ in httpd.conf, fisierul care contine configurarea Apache-ului:

AddType application/x-httpd-php .php

Pornirea si testarea Apache-ului

Dupǎ compilarea si instalarea Apache-ului, putem porni daemon-ul. Vom trece in directorul care contine binarele Apache:

[root@duron root]# cd /usr/local/apache/bin/

Comanda pentru pornirea Apache-ului este numitǎ apachectl. Comanda porneste diferite procese care vor fi utilizate pentru a dirija cererile trimise serverului Web. Pentru a afla cum apachectl lucreazǎ, putem utiliza comanda:

[root@duron bin]# ./apachectl --help

utilizare: ./apachectl (start|stop|restart|fullstatus|status|graceful|configtest|help)

start - porneste httpd-ul

stop  - opreste httpd-ul

restart - reporneste httpd-ul dacǎ acesta ruleazǎ prin trimiterea unui SIGHUP sau start dacǎ nu ruleazǎ

fullstatus - afiseazǎ un ecran cu starea completǎ a serverului; necesitǎ lynx si activarea modulului mod_status

status - afiseazǎ un ecran cu starea serverului; necesitǎ lynx si activarea modulului mod_status

graceful - realizeazǎ un restart elegant prin trimiterea unui SIGUSR1 sau unui start dacǎ acesta nu ruleazǎ

configtest - realizeazǎ o testare a sintaxei de configurare

help  - acest ecran

Pentru a porni Apache-ul, vom folosi ./apachectl start:

[root@duron bin]# ./apachectl start

[Mon Dec 31 01:06:20 2001] [alert] httpd: Could not determine the server's

fully qualified domain name, using 127.0.0.1 for ServerName

./apachectl start: httpd started

Mesajul de avertizare este determinat de setǎrile gresite ale Apache-ului. Mesajul de avertizare poate fi usor evitat prin schimbarea directivei ServerName la o valoare utilǎ cum ar fi localhost. Dupǎ pornirea serverului Web, putem verifica dacǎ Apache ruleazǎ. Acest pas este foarte recomandat deoarece este singura cale sigurǎ de verifica dacǎ serverul web a fost pornit cu succes:

[root@duron bin]# ps ax | grep http

5570 ? S 0:00 /usr/local/apache/bin/httpd

5571 ? S 0:00 /usr/local/apache/bin/httpd

5572 ? S 0:00 /usr/local/apache/bin/httpd

5573 ? S 0:00 /usr/local/apache/bin/httpd

5574 ? S 0:00 /usr/local/apache/bin/httpd

5575 ? S 0:00 /usr/local/apache/bin/httpd

5578 pts/3 S 0:00 grep http

Observǎm cǎ doar cateva procese ruleazǎ. Apache 1.3.x se mai numeste si server preforking, ceea ce inseamnǎ cǎ, de obicei, imparte procesele in memorie astfel incat fiecare cerere cǎtre serverul Web sǎ poatǎ fi usor procesatǎ.

Dupǎ ce am pornit Apache-ul, putem verifica dacǎ PHP lucreazǎ corect. Vom trece in /usr/local/apache/htdocs si vom scrie o aplicatie simplǎ in PHP:

<?php phpinfo() ?>

Aceastǎ linie va face PHP-ul sǎ afiseze mai multe informatii referitoare la instalare:

Dacǎ informatia despre componenta doritǎ este afisatǎ, nu ar trebui sǎ existe nici o problemǎ cand lucrǎm cu PHP. Dacǎ o anumitǎ particularitate nu este afisatǎ, ceva anume a avut loc pe parcursul compilǎrii.

Instalarea ApacheToolBox pe Unix

Multe persoane sunt nemultumite de instalarea Apache-ului si si de componentele aditionale care trebuie adǎugate in timp. Instalarea serverului Web cu suport pentru PHP, mod_perl, Jakarta, Tomcat si multe alte pachete pot fi greoaie si consumatoare de timp.

Pentru a evita aceastǎ problemǎ, putem utiliza produsul ApacheToolBox, care poate fi descǎrcat de la https://www.apachetoolbox.com, care contine un set recent al tuturor modulelor care sunt larg utilizate:

Instalarea Apache-ului cu PHP pe Windows

Instalarea Apache-ului cu PHP si PosgreSQL este mai dificilǎ decat instalarea pe masinile Unix. Primul lucru care trebuie sǎ-l realizǎm este sǎ instalǎm Cygwin-ului. Acest pachet contine binarele PostgreSQL necesare pentru rularea pe Windows.

Urmǎtorul pas constǎ in instalarea Apache-ului. Vom descǎrca binarele pentru Windows de la adresa https://www.apache.org/dist/httpd/binaries/win32/ si vom lansa fisierul executabil care va porni un wizard interactiv.

Dupǎ ce am instalat Apache-ul, vom testa serverul Web. Dacǎ pagina HTML a fost afisatǎ, Apache este pornit si ruleazǎ:

Urmǎtorul pas implicǎ oprirea serverului Web si instalarea PHP-ului de la adresa www.php.net. Dupǎ instalarea PHP-ului, vom realiza unele modificǎri necesare pentru a rula PostgreSQL pe Windows. Primul lucru implicǎ modificarea fisierului php.ini. In acest fisier vom gǎsi linia:

;extension=php_pgsql.dll

in care vom elimina ; dupǎ care vom iesi din fisier.

Dupǎ aceasta vom edita fisierul httpd.conf si vom adǎuga urmǎtoarea linie:

AddType application/x-httpd-php .php

Instalarea binarelor pe Linux

Pachete RPM - Sistemul RPM a fost initial dezvoltat de Red Hat si este cel mai rǎspandit instrument de management pentru pachetele binare si cele sursǎ. Pentru a vedea dacǎ PostgreSQL este deja instalat pe sistem putem utiliza rpm -qva pentru a afisa o listǎ a tuturor pachetelor instalate pe sistem. Pentru a extrage doar pachetele PostgreSQL, putem utiliza grep, rezultatul fiind de genul:

[root@duron root]# rpm -qva | grep postgr

postgresql-libs-7.2.0

postgresql-python-7.2.0

postgresql-jdbc-7.2.0

postgresql-7.2.0

postgresql-odbc-7.2.0

postgresql-tk-7.2.0

postgresql-devel-7.2.0

postgresql-contrib-7.2.0

postgresql-perl-7.2.0

postgresql-server-7.2.0

postgresql-docs-7.2.0

postgresql-tcl-7.2.0

Pentru a instala pachetele aditionale, putem utiliza urmǎtoarea comandǎ:

rpm -Uvh numele_pachetelor

unde U spune RPM-ului sǎ actualizeze toate pachetele existente, v reprezintǎ verbose si h spune PHP-ului sǎ afiseze 50 hash mark-uri cand arhiva pachetului este dezarhivatǎ.

Pachete Debian - Vom utiliza dselect pentru a adǎuga sau elimina pachetele de pe sistem. Utilizarea unui manager de pachete garanteazǎ cǎ toate pachetele software PostgreSQL de care depinde sunt instalate pe sistem.

Configurarea PHP-ului

Fisierul de configurare PHP este denumit php.ini si este localizat in /etc pe sistemul Red Hat. Ne vom uita la fisierul de configurare si vom discuta setǎrile relevante:

- engine - pentru a permite PHP-ului sǎ-l utilizeze, acest flag trebuie setat pe On. Cuvantul engine se referǎ la motorul Zend, care este inima PHP4;

- short_open_tag - dacǎ este activ, serverul Web va aceepta <? Si ?> pe langǎ <?php si <script>. Pentru a face scriptul mai portabil, se recomandǎ utilizarea <?php pentru definirea inceputului de script PHP deoarece vom intampina probleme dacǎ rulǎm scriptul pe un server in care tag-urile scurte sunt inactive;

- asp_tags - ASP (Active Server Pages) suportǎ tag-urile <% %>, care au aceeasi semnificatie cu <?. In configuratia implicitǎ acest tip de tag este inactiv;

- precision - PHP suportǎ precizia variabilelor cu virgulǎ mobilǎ;

- y2k_compliance - forteazǎ conformitatea Y2K. Aceasta poate cauza probleme cu browserele non-conforme Y2K. Valoarea implicitǎ este Off;

- output_buffering - permite trimiterea liniilor header dupǎ trimiterea continutului. Implicit aceasta este setat pe Off pentru o mai bunǎ performantǎ;

- output_handler - iesirea scriptului poate fi trimis cǎtre o functie. In acest mod, pot fi realizate operatii ca filtarea si compresia;

- zlib.output_compression - dacǎ acest flag este setat la On, va fi utilizatǎ la iesire compresia transparentǎ;

- implicit_flush - acest flag spune stratului de iesire sǎ curete buffer-ul dupǎ fiecare blocare;

- safe_mode - modul safe mode PHP este o incercare de a obtine un inalt nivel de securitate. Cand lucrǎm cu safe mode, unele functii PHP cum ar fi cele pentru executia apelurilor sistem si pg_loimport (responsabilǎ pentru lucrul cu obiectele binare stocate in baza de date PostgreSQL) sunt inactive;

- open_basedir - acest flag poate fi utilizat pentru a restrictiona toate operatiile cu fisiere din afara directorului definit de acest flag;

- disable_functions - unele functii care sunt beta sau reprezintǎ o amenintare potentialǎ pentru sistem poat fi dezactivate de acest flag. Functiile trebuie definite intr-o listǎ separate prin virgulǎ;

- max_execution_time - pentru a preveni problemele cauzate de buclele de final sau scripturile care necesitǎ un timp mare de executie, putem defini perioada maximǎ permisǎ pentru rularea unui script. Cand perioada limitǎ este atinsǎ, scriptul va fi terminat imediat;

- memory_limit - Consumul de momorie a scripturilor PHP poate fi limitat de dimensiunea definitǎ de scriptul memory_limit. Dimensiunea este definitǎ in megabytes. Fiecare script PHP poate consuma aceastǎ cantitate de memorie;

- error_reporting - defineste modul in care erorile sunt afisate in PHP. In functie de catǎ informatie de debugging este necesarǎ, acest flag poate fi modificat;

- display_errors - spune PHP-ului dacǎ sǎ afiseze erorile. Valoarea implicitǎ a acestui flag este on;

- display_startup_errors - erorile pot apare cand porneste PHP-ul. In configuratia implicitǎ aceste erori nu sunt afisate;

- log_errors - pentru debugging este util sǎ setǎ acest flag la On deoarece erorile nu vor fi logate;

- track_errors - stocheazǎ cele mai recente mesaje de eroare in $php_errormsg;

- arg_separator.input - implicit, argumentele trecute in PHP via URL sunt separate utilizand &. Acestea pot fi schimbate prin modificarea acestei setǎri;

- variables_order - defineste in ce ordine vor fi inregistrate GET, POST, cookie, variabilele de mediu si variabilele incorporate. Valoarea implicitǎ este EGPCS;

- register_argc_argv - defineste ce variabile trecute in PHP via "intrǎri standard" vor fi inregistrate;

- post_max_size - POST realizeazǎ o cerere pentru datele trimise unui script. Din motive de securitate, cantitatea maximǎ de date trebuie limitatǎ utilizand parametrul post_max_size;

- default_mimetype - implicit header-ul trimis browserului este text/html;

- enable_dl - dl este o comandǎ importantǎ. Dacǎ dorim sǎ adǎugǎm extensii PHP-ului fǎrǎ recompilarea serverului, sau dacǎ dorim sǎ incercǎm o nouǎ versiune a unei componente, obiectele distribuite pot fi incluse dinamic utilizand comanda dl. Enable_dl spune PHP-ului cand sǎ suporte o incǎrcare dinamicǎ si cand nu;

- file_uploads - upload-ul de fisiere reprezintǎ un risc potential de securitate si poate fi usor dezactivat prin setarea lui file_uploads pe Off;

- upload_max_filesize - dimensiunea maximǎ a unui fisier incǎrcat pe serverul Web poate fi definitǎ in douǎ moduri. O cale o reprezintǎ adǎugarea unui parametru in documentul HTML. A doua cale si cea mai sigurǎ este sǎ spunem PHP-ului cat de mare poate fi un fisier;

- extension - extensiile Windows pot fi usor adǎugate serverului prin adǎugarea unei intrǎri care specificǎ un DLL;

- odbc.allow_persistent - acest flag spune PHP-ului cand este permisǎ utilizarea conexiunilor persistente cu bazele de date in combinatie cu ODBC;

- odbc.check_persistent - pentru a vedea dacǎ conexiunile persistente sunt incǎ valide inainte de reutilizarea manipulatorului de conexiune, acest flag trebuie setat pe On;

- odbc.max_persistent - defineste numǎrul maxim de conexiuni persistente simultane. -1 inseamnǎ nelimitate;

- odbc.max_links - defineste numǎrul total de conexiuni permise (total=persistente+nonpersistente);

- pgsql.allow_persistent - acest flag spune PHP-ului dacǎ este permis sǎ utilizǎm conexiuni persistente cu baza de date in combinatie cu PostgreSQL;

- pgsql.max_persistent - defineste numǎrul maxim de conexiuni persistente simultane. -1 inseamnǎ nelimitate;

- pgsql.max_links - defineste numǎrul total de conexiuni permise (total=persistente+nonpersistente);

- session.save_handler - spune PHP-ului ce manipulator este utilizat pentru managementul sesiunilor;

- session.save_path - defineste directorul unde informatiile privind sesiunile sunt stocate. Valoarea implicitǎ este /tmp;

- session.use_cookies - defineste dacǎ vor fi utilizate cookies;

- session.name - defineste numele sesiunii.

Dacǎ PHP este utilizat ca modul in serverul Web, fisierul este citit cand serverul este pornit. Este necesar sǎ repornim serverul dacǎ realizǎm modificǎri in fisierul de configurare PHP. In cazul scripturilor CGI, configuratia este cititǎ de fiecare datǎ cand scriptul CGI este pornit.

Interactiunea PHP/PostgreSQL

Scrierea unor aplicatii cu baze de date

Vom vedea interactiunea PHP/PostgreSQL si cum vom trimite declaratii catre serverul de baze de date.

Conectarea la baza de date

Similar cu lucrul cu fisierele, este necesara identificarea unui manipulator de conexiuni si interactiunea cu acesta. Pentru a genera aceast manipulator, vom utiliza pg_connect. pg_connect stabileste o conexiune cu baza de date si returneaza un manipulator al bazei de date. Stringul de conectare trimis bazei de date este acelasi cu cel utilizat intr-un program C. Acest lucru este important deoarece interfata PostgreSQL a PHP-ului este construita in C, comportamentul PHP-ului fiind usor de inteles daca suntem familiari cu interfata C.

Sa vedem cum realizam conexiunea la baza de date (in prealabil vom crea baza de date phpdb folosind comanda createdb phpdb):

<?php

$connstr = 'dbname=phpdb user=postgres host=localhost port=5432';

$dbh = pg_connect($connstr);

if ($dbh)

else

?>

In primul rand, este definit un sir de conectare care contine numele bazei de date la care dorim sa ne conectam, si gazda unde poate fi gasita baza de date. In plus, a fost specificat portul. Acest sir este trecut in pg_connect si este returnat un manipulator de bazǎ de date. Dacǎ manipulatorul de baze de date este returnat corect, este afisat un mesaj. Cauzele care determinǎ ca PHP-ul sǎ returneze un manipulator de baze de date eronat sunt:

- PHP sau PostgreSQL au fost incorect instalate;

- am definit o bazǎ de date, nume, host, utilizator, port sau parolǎ incorect;

- PostgreSQL a epuizat conexiunile deoarece prea multi utilizatori sunt conectati la baza de date;

- baza de date nu poate fi accesatǎ in retea. Este posibil sǎ nu fi pornit postmaster utilizand -i;

Modalitatea de scriere:

int pg_connect (string host, string port, string options, string tty, string dbname) este veche si nu ar trebui utilizatǎ

Dupǎ ce am deschis conexiunea cu baza de date, este momentul sǎ vedem cum inchidem conexiunea la finalul scriptului:

<?php

$connstr = 'dbname=phpdb user=postgres host=localhost port=5432';

$dbh = @pg_connect($connstr);

if ($dbh)

$status = pg_close ($dbh);

if ($status == TRUE)

?>

In primul rand, am stabilit o conexiune cu baza de date si scriptul va verfica dacǎ totul a decurs corect. Dacǎ apare o eroare, eroarea va fi suprimatǎ de simbolul @. Aceasta este destul de important deoarece in aplicatiile reale este fatal ca utilizatorul sǎ vadǎ mesajul de eroare pe ecran. Pe de o parte, nu este profesional dacǎ un site afiseazǎ erori, dar, pe de altǎ parte este un risc de securitate potential dacǎ o anumitǎ informatie este afisatǎ.

Dacǎ nu au fost definiti la conectare toate componentele sirului, va fi utilizatǎ valoarea implicitǎ a parametrului. Ex:

<?php

$connstr = 'dbname=phpdb user=postgres';

$dbh = pg_connect($connstr);

if ($dbh)

$connstr = 'user=postgres';

$dbh = pg_connect($connstr);

if ($dbh)

?>

Primul sir de conectare nu contine numele gazdei. Aceasta va determina conectarea PHP-ului la PostgreSQL utilizand soclurile Unix. In acest caz nu va fi utilizat TCP/IP. In plus, portul implicit nu este necesar deoarece soclurile Unix nu au nevoie de un port. Deoarece baza de date si utlizatorul existǎ, conexiunea poate stabilitǎ cu succes. Urmǎtorul sir de conectare nu contine numele bazei de date, PostgreSQL presupunand cǎ numele bazei de date este acelasi cu cel al utilizatorului Cand scriptul va fi executat va fi afisatǎ o eroare:

Warning: Unable to connect to PostgreSQL server: FATAL 1: Database 'postgres'

does not exist in the system catalog. in /var/www/html/connect.php on line 7

Dupǎ ce o conexiune a fost stabilitǎ, este necesar sǎ vedem ce parametri au fost utilizati pentru a stabili conexiunea cu PostgreSQL. De aceea, PHP oferǎ un set de functii pentru a regǎsi aceastǎ informatie:

<?php

$connstr = 'dbname=phpdb user=postgres host=localhost';

$dbh = @pg_connect($connstr);

if ($dbh)

echo 'Host: '.pg_host($dbh).'<br>';

echo 'Baza de date: '.pg_dbname($dbh).'<br>';

echo 'Port: '.pg_port($dbh).'<br>';

echo 'tty: '.pg_tty($dbh).'<br>';

?>

Pg_host returnezǎ host-ul la care suntem conectati, pg_dbname returneazǎ numele bazei de date, pg_port returneazǎ numǎrul portului pe care PostgreSQL ascultǎ, si pg_tty returneazǎ tty-ul curent.

Dupǎ stabilirea conexiunii, inchiderea explicitǎ se realizeazǎ prin utilizarea lui pg_close. Inchiderea manipulatorului de baze de date nu este necesarǎ deoarece procesul backend asociat cu conexiunea este distrus automat la sfarsitul scriptului PHP.

Introducerea si regǎsirea datelor

Conectarea la baza de date nu este suficientǎ. Vom vedea in cele ce urmeazǎ cum comunicǎm cu baza de date, cum creem tabele, si cum introducem si regǎsim datele.

Vom crea o nouǎ tabelǎ si vom scrie un script in acest sens:

<?php

$connstr = 'dbname=phpdb user=postgres host=localhost';

$dbh = pg_connect($connstr);

if ($dbh)

$sql = 'CREATE TABLE person (id serial, name text, location text)';

$stat = pg_exec($dbh, $sql);

if ($stat)

else

pg_close($dbh);

?>

Dupǎ conectarea la baza de date, un sir care contine codul SQL a fost generat. Urmǎtorul pas implicǎ trimiterea interogǎrii cǎtre server. Pg_exec returneazǎ un cod de stare care poate fi verificat. Trebuie specificati doi parametri in pg_exec: primul parametru este manipulatorul de conexiune, iar al doilea va contine declaratia SQL pe care dorim sǎ o executǎm. Dacǎ o declaratie a fost executatǎ cu succes, urmǎtorul text a fost afisat:

conexiunea cu phpdb a fost stabilita

Tabela a fost creaat cu succes

Pentru a vedea dacǎ tabela se aflǎ in baza de date, putem utiliza psql si d:

phpdb=# d person

Table 'public.person'

Column | Type | Modifiers

id | integer | not null default nextval('public.person_id_seq'::text)

name | text |

location | text |

Dupǎ ce am creat tabela, vom introduce inregistrǎri. Urmǎtorul exemplu demonstreazǎ cum putem adǎuga o inregistrare in tebelǎ:

<?php

$connstr = 'dbname=phpdb user=postgres host=localhost';

$dbh = pg_connect($connstr);

if ($dbh)

$sql = 'INSERT INTO person (name, location) VALUES ('Paul', 'Vienna')';

$stat = pg_exec($dbh, $sql);

if ($stat)

else

pg_close($dbh);

?>

Dupǎ cum putem observa, adǎugarea de inregistrǎri in tabelǎ lucreazǎ in acelasi mod cu adǎugarea tabelelor sau executia oricǎrei declaratii SQL. In aceastǎ privintǎ, PHP este flexibil si usor de utilizat

Dacǎ tabela contine cateva date, putem afisa cateva inregistrǎri. Pentru a regǎsi datele, trebuie in primul rand sǎ executǎm o interogare. In urmǎtorul pas numǎrul de inregistrǎri poate fi evaluat. In cele din urmǎ, datele pot fi regǎsite utlizand o singurǎ buclǎ:

<?php

$connstr = 'dbname=phpdb user=postgres host=localhost';

$dbh = pg_connect($connstr);

if ($dbh)

$sql = 'SELECT id, name, location FROM person';

$stat = pg_exec($dbh, $sql);

if ($stat)

else

pg_close($dbh);

?>

Pentru a evalua numǎrul de linii returnate de o interogare, vom folosi pg_numrows. In acest scenariu prezentat anterior, este afisat pe ecran numǎrul de linii:

conexiunea la phpdb a fost stabilita
1 linii returnate de PostgreSQL

In urmǎtorul exemplu vom vedea cum liniile returnate de interogare pot fi regǎsite si afisate:

<?php

$connstr = 'dbname=phpdb user=postgres host=localhost';

$dbh = pg_connect($connstr);

if ($dbh)

$stat = pg_exec($dbh, 'SELECT id, name, location FROM person');

$rows = pg_numrows($stat);

for ($i = 0; $i < $rows; $i++)

pg_close($dbh);

?>

Dupǎ ce am evaluat numǎrul de linii, o buclǎ parcurge toate inregistrǎrile si afiseazǎ datele in result. Pentru a extrage o linie de date, trebuie utilizatǎ comanda pg_fetch_row. Comanda returneazǎ un array care poate fi usor procesat si afisat pe ecran utilizand echo:

conexiunea la phpdb a fost stabilita
data: 1, Paul, Vienna

In exemplul anterior, a fost utilizat un numǎr exact de de coloane si afisat pe ecran. In majoritatea cazurilor, un numǎr dinamic de coloane trebuie afisat. Din acest motiv numǎrul de coloane trebuie evaluat in momentul executiei. Ex:

<?php

$connstr = 'dbname=phpdb user=postgres host=localhost';

$dbh = pg_connect($connstr);

if ($dbh)

$stat = pg_exec($dbh, 'SELECT id, name, location FROM person');

$rows = pg_numrows($stat);

$cols = pg_numfields($stat);

echo 'linii: $rows; coloane: $cols<br>n';

for ($i = 0; $i < $rows; $i++)

echo '<br>n';

}

pg_close($dbh);

?>

pg_numfields este utilizat pentru a extrage numǎrul de coloane intr-un result. Similar cu result-ul lui pg_numrows, este utilizat de o buclǎ. Rezultatul este:

conexiunea la phpdb a fost stabilita
linii: 1; coloane: 3
1 Paul Vienna

In exemplele anterioare, datele au fost extrase utilizand pg_fetch_row. Urmǎtorul exemplu afiseazǎ acelasi rezultat care poate fi obtinut folosind pg_fetch_array:

<?php

$connstr = 'dbname=phpdb user=postgres host=localhost';

$dbh = pg_connect($connstr);

if ($dbh)

$stat = pg_exec($dbh, 'SELECT id, name, location FROM person');

$rows = pg_numrows($stat);

echo 'linii: $rows<br>n';

for ($i = 0; $i < $rows; $i++)

pg_close($dbh);

?>

Acum datele pot fi accesate utilizand numele coloanei. Este mult mai indicat acest mod decat lucrul cu indecsi deoarece coloanele din result nu pot fi mixate. Rezultatul este:

conexiunea la phpdb a fost stabilita
linii: 1
1 Paul Vienna

Un aspect important cand lucrǎm cu pg_fetch_array este lucrul cu alias-uri:

<?php

$connstr = 'dbname=phpdb user=postgres host=localhost';

$dbh = pg_connect($connstr);

if ($dbh)

$stat = pg_exec($dbh, 'SELECT cos(id) AS a FROM person');

$rows = pg_numrows($stat);

echo 'linii: $rows<br>n';

for ($i = 0; $i < $rows; $i++)

pg_close($dbh);

?>

Un alias este utilizat pentru campul denumit cos, care contine cosinusul lui id. Pentru a extrage datele din result, este necesar sǎ accesǎm alias-ul pentru a gǎsi rezultatul corect. Rezultatul este:

conexiunea la phpdb a fost stabilita
linii: 1
data: 0.54030230586814

In multe cazuri, este necesar sǎ extragem informatia despre rezultatul in sine. Anterior am vǎzut cum evaluǎm numǎrul de linii returnate de o interogare. In urmǎtorul exemplu vom vedea cum vom obtine informatii aditionale:

<?php

$connstr = 'dbname=phpdb user=postgres host=localhost';

$dbh = pg_connect($connstr);

if ($dbh)

$stat = pg_exec($dbh, 'SELECT id, name, location FROM person');

$myid = pg_fieldname($stat, 0);

echo 'campul cu numarul 1 este denumit $myid<br>n';

$myname = pg_fieldnum($stat, 'name') + 1;

echo ''name' este campul cu numarul $myname<br>';

$myloc = pg_fieldsize($stat, 2);

echo 'al treilea camp este de $myloc bytes lungime<br>';

pg_close($dbh);

?>

Pentru a depista numele unei coloane, putem utiliza pg_fieldname. Vom specifica numele result-ului si indexul coloanei ca parametri ai functiei, PHP si PostgreSQL ocupandu-se re restul. Pentru a gǎsi id-ul unei anumite coloane, PHP oferǎ functia pg_fieldnum. In acest caz numele result-ului si numele coloanei trebuie specificati in functie.

Ultima functie folositǎ in exemplul anterior este pg_fieldsize, care returneazǎ lungimea unei coloane. In situatia lungimii variabilei, functia va returna -1 deoarece lungimea nu poate fi evaluatǎ precis. Iesirea scriptului este:

conexiunea la phpdb a fost stabilita

campul cu numarul 1 este denumit id
'name' este campul cu numarul 2
al treilea camp este de -1 bytes lungime

Operatiile complexe cu o cantitate mare de date poate utiliza o cantitate mare de memorie. Dacǎ avem multe cereri consumatoare de memorie care trebuie procesate simultan, serverul Web poate rǎmane fǎrǎ memorie si performanta sistemului poate scǎdea semnificativ datoritǎ swapping-ului si comportamentului ineficient. Pentru a reduce cantitatea de memorie utilizatǎ pe durata operatiilor complexe, PHP oferǎ o comandǎ numitǎ pg_freeresult. Dacǎ rezultatul interogǎrii nu este necesar, comanda ne va ajuta sǎ eliberǎm memoria alocatǎ de PHP pentru a stoca result-ul returnat de PostgreSQL. In mod normal, memoria alocatǎ de PHP este eliberatǎ automat la sfarsitul scriptului. pg_freeresult poate fi utilizatǎ pentru a o elibera mai devreme. Ex:

<?php

$connstr = 'dbname=phpdb user=postgres host=localhost';

$dbh = pg_connect($connstr);

if ($dbh)

$result = pg_exec($dbh, 'SELECT cos(id) AS a FROM person');

for ($i = 0; $i < pg_numrows($result); $i++)

$stat = pg_freeresult($result);

if ($stat)

pg_close($dbh);

?>

In acest exemplu, memoria a fost eliberatǎ manual si scriptul va verifica dacǎ comanda a avut succes:

conexiunea la phpdb a fost stabilita
data: 0.54030230586814
memoria a fost eliberata cu succes

Manipularea si monitorizarea erorilor

Manipularea erorilor este un aspect foarte important. PHP si PostgreSQL dispun de un mecanism de manipulare a erorilor care sunt sigure si usor de folosit.

Vom crea o tabelǎ pentru a stoca numerele de telefon:

phpdb=# CREATE TABLE phone (id serial, name text, phone text NOT NULL);

NOTICE: CREATE TABLE will create implicit sequence 'phone_id_seq' for SERIAL

column 'phone.id'

NOTICE: CREATE TABLE/UNIQUE will create implicit index 'phone_id_key' for

table 'phone'

CREATE

Ultima coloanǎ nu a fost definitǎ ca NOT NULL, ceea ce inseamnǎ cǎ o valoare trebuie adǎugatǎ la coloanǎ. In urmǎtorul pas vom scrie un script care va introduce date in tabelǎ.

<?php

$connstr = 'dbname=phpdb user=postgres host=localhost';

$dbh = pg_connect($connstr);

if ($dbh)

$stat = pg_exec($dbh, 'INSERT INTO phone (name) VALUES ('Florin')');

if ($stat)

else

pg_close($dbh);

?>

Dupǎ conectarea la baza de date, declaratia INSERT a fost executatǎ. Deoarece nu a fost specificat numǎrul de telefon, a apǎrut o eroare care a fost afisatǎ pe ecran utilizand pg_errormessage. Manipulatorul bazei de date, nu valoarea returnatǎ de declaratia de executat, a fost specificatǎ in functie. Output-ul scriptului este:

conexiunea la phpdb a fost stabilita
Warning: pg_exec() [
function.pg-exec]: Query failed: ERROR: null value in column 'phone' violates not-null constraint in c:wampwwwscriptslab2_script14.php on line 6
a aparut o eroare
ERROR: null value in column 'phone' violates not-null constraint

In primul rand pg_exec afiseazǎ o eroare. Dupǎ ce mesajul de eroare a fost afisat, rezultatul lui pg_errormessage a fost afisat pe ecran. PostgreSQL ne spune cǎ valoarea NULL nu poate fi adǎugatǎ in tabel deoarece a treia coloanǎ a fost declaratǎ ca NOT NULL. Vom vedea un alt exemplu:

<?php

$connstr = 'dbname=phpdb user=postgres host=localhost';

$dbh = pg_connect($connstr);

if ($dbh)

echo 'prima incercare<br>n';

$stat = pg_exec($dbh, 'INSERT INTO phone (name) VALUES ('Susan')');

echo '<br>a doua incercare<br>n';

$stat = pg_exec($dbh, 'INSERT INTO phone (name, phone) VALUES

('Susan', '3432434')');

if ($stat)

else

pg_close($dbh);

?>

Prima declaratie SQL trimisǎ serverului incalcǎ constrangerea definitǎ in a treia coloanǎ. A doua declaratie SQL este corectǎ si datele vor fi adǎugate in tabelǎ. Cel mai important aspect in acest exemplu este sǎ observǎm cǎ pg_errormessage nu returneazǎ o eroare dacǎ declaratia SQL anterioarǎ a fost executatǎ cu succes. Pare destul de clar dar nu este: in unele sisteme de baze de date, functiile returneazǎ intotdeauna cea mai recentǎ eroare chiar dacǎ o declaratie corectǎ a fost executatǎ dupǎ ce o eroare a apǎrut. Mesajul generat de scriptul PHP este:

conexiunea la phpdb a fost stabilta
prima incercare

Warning: pg_exec() [
function.pg-exec]: Query failed: ERROR: null value in column 'phone' violates not-null constraint in c:wampwwwscriptslab2_script15.php on line 7

a doua incercare
datele au fost introduse cu succes
corect:

In unele cazuri este necesar sǎ aflǎm cate linii au fost afectate de interogare. Indeosebi atunci cand realizǎm operatii de UPDATE, este util sǎ aflǎm ce anume se intamplǎ in interiorul bazei de date. Comanda utilizatǎ pentru a extrage numǎrul de linii afectate de declaratia SQL este pg_cmdtuples. Ex:

<?php

$connstr = 'dbname=phpdb user=postgres host=localhost';

$dbh = pg_connect($connstr);

if ($dbh)

$stat = pg_exec($dbh, 'UPDATE phone SET phone='123456'

WHERE name='Susan'');

if ($stat)

pg_close($dbh);

?>

In acest scenariu numǎrul de telefon al lui Susan a fost actualizat. In baza noastrǎ de date Susan a a fost adǎugatǎ odatǎ, din acest motiv pg_cmdtuples returnand 1. Pe ecran va fi afisat:

conexiunea la phpdb a fost stabilita
UPDATE realizat cu succes
1

Manipularea erorilor este o sarcinǎ usor de realizat cand lucrǎm cu PHP si PostgreSQL, fiind necesare doar cateva comenzi pentru manipularea erorilor.

Manipularea unei cantitǎti mari de date

Dacǎ lucrǎm cu mai mult de cateva inregistrǎri, utilizarea lui INSERT este prea lentǎ. PostgreSQL oferǎ comanda COPY, care poate fi utilizatǎ pentru a introduce mai mult de o inregistrare intr-o tabelǎ odatǎ.

Utilizarea lui COPY este diferitǎ fatǎ de lucrul cu setul de comenzi INSERT. Ex:

<?php

$connstr = 'dbname=phpdb user=postgres host=localhost';

$dbh = pg_connect($connstr);

if ($dbh)

echo 'pornim procesul <br>n';

echo 'inceput: '.date('Y-m-d H:i:s').'<br>n';

$result = pg_exec($dbh, 'COPY testdata FROM stdin');

for ($i = 0; $i < 40000; $i++)

}

pg_put_line($dbh, '.n');

pg_end_copy($dbh);

echo 'sfarsit: '.date('Y-m-d H:i:s').'<br>n';

pg_close($dbh);

echo 'sfarsitul procesului <br>n';

?>

Inainte de a rula scriptul trebuie sǎ creem tabela testdata:

CREATE TABLE testdata (idx int4, val numeric(9,8));

Dupǎ conectarea la baza de date, antetul comenzii COPY este trimis cǎtre server. Dupǎ aceasta, PostgreSQL asteaptǎ datele panǎ cand . este gǎsit. Fiecare linie de date este trimisǎ cǎtre baza de date prin utilizarea comenzii pg_put_line.

Tabela in care dorim sǎ adǎugǎm date contine douǎ coloane. Prima coloanǎ contine un numǎr si a doua coloanǎ contine cosinusul acelui numǎr. Dupǎ ce datele au fost trimise cǎtre PostgreSQL, comanda COPY este terminatǎ prin utilizarea lui pg_end_copy. Pentru a vedea cat de repede lucreazǎ comanda COPY, pe ecran este afisatǎ ora curentǎ:

conexiunea la phpdb a fost stabilita
pornim procesul
inceput: 2005-10-19 19:03:22
sfarsit: 2005-10-19 19:03:24
sfarsitul procesului

Comanda COPY nu a durat mai mult de douǎ secunde, testul find realizat pe un procesor Pentium 4 la 1514 Mhz.

Vom sterge inregistrǎrile din tabelǎ:

phpdb=# DELETE FROM testdata;

Pentru a intelege de ce comanda COPY trebuie folositǎ, urmǎtorul exemplu ajunge la acelasi rezultat folosind comanda INSERT:

<?php

$connstr = 'dbname=phpdb user=postgres host=localhost';

$dbh = pg_connect($connstr);

if ($dbh)

echo 'incepem procesul <br>n';

echo 'inceput: '.date('Y-m-d H:i:s').'<br>n';

for ($i = 0; $i < 40000; $i++)

}

echo 'sfarsit: '.date('Y-m-d H:i:s').'<br>n';

pg_close($dbh);

echo 'sfarsitul procesului <br>n';

?>

Rezultatul cand am utilizat INSERT este:

conexiunea la phpdb a fost stabilita
incepem procesul
inceput: 2005-10-19 20:00:27

Fatal error: Maximum execution time of 30 seconds exceeded in c:wampwwwscriptslab2_script18.php on line 10

Procesul ia mai mult de 30 de secunde, in acest interval fiind introduse doar 22068 de inregistrǎri. Cu cat avem mai multe date de procesat, cu atat performanta va spori dacǎ utilizǎm COPY. Tehnic, pg_put_line trimite un sir terminat in NULL cǎtre procesul backend manipuland conexiunea cu PostgreSQL. Dupǎ trimiterea datelor cǎtre baza de date, procesul de backend si frontend trebuie sǎ fie sincronizat, aceasta realizandu-se utilizand pg_end_copy.

Regǎsirea obiectelor din baza de date

Cand lucrǎm cu PHP orientat obiect, poate fi de ajutor regǎsirea datelor din tabel ca obiecte. Astfel PHP oferǎ o comandǎ numitǎ pg_fetch_object, care poate fi utilizatǎ la fel ca pg_fetch_array si pg_fetch_row. Pentru a vedea cum lucreazǎ aceastǎ comandǎ, vom crea o tabelǎ si vom introduce cateva date:

phpdb=# CREATE TABLE plant(id int4, name text, color text);

CREATE TABLE

phpdb=# INSERT INTO plant VALUES (1, 'Sambucus nigra', 'galben');

INSERT 221721 1

phpdb=# INSERT INTO plant VALUES (2, 'Abies', 'verde');

INSERT 221722 1

phpdb=# INSERT INTO plant VALUES (3, 'Colchicum autumnale', 'roz');

INSERT 221723 1

Dacǎ nu a fost semnalatǎ nici o eroare, am creat o tabelǎ care contine informatii despre trei plante si trei culori. In urmǎtorul exemplu vom regǎsi datele ca obiecte:

<?php

$connstr = 'dbname=phpdb user=postgres host=localhost';

$dbh = pg_connect($connstr);

$sql = 'SELECT id, name, color FROM plant WHERE id=1';

$result = pg_exec($dbh, $sql);

$data = pg_fetch_object($result, 0);

echo 'Daca aveti gripa puteti bea un ceai de $data->name<br>n';

echo 'Luati partile de $data->color ale plantei si fierbieti-le.<br>n';

pg_close($dbh);

?>

Pentru a aceesa diferite componente ale obiectului, trebuie utilizat operatorul ->. Singura diferentǎ intre utilizarea unui array si utilizarea obiectelor constǎ in sintaxa pe care trebuie sǎ o utilizǎm. Output-ul scriptului este:

Daca aveti gripa puteti bea un ceai de Sambucus nigra
Luati partile de galben ale plantei si fierbieti-le.

"Trasarea" conexiunii PostgreSQL

In scopul realizǎrii unui debug, "trasarea" unei conexiuni la serverul PosgreSQL poate fi utilǎ. "Trasarea" unei conexiuni se referǎ la faptul cǎ datele transmise de la si inapoi este monitorizat si poate fi utilizat pentru a descoperi ceea ce are loc in interiorul PostgreSQL. In general, informatia generatǎ este utilǎ doar dacǎ suntem familari cu protocolul intern al PosgreSQL. Vom vedea cum "trasarea" poate fi pornitǎ si opritǎ:

<?php

$dbh = pg_connect('host=localhost user=postgres dbname=phpdb');

if (!$dbh)

$status = pg_trace('/tmp/trace.log');

$result = pg_exec($dbh, 'SELECT id, name, color FROM plant LIMIT 1');

$rows = pg_numrows($result);

for ($i = 0; $i < $rows; $i++)

?>

Scopul este sǎ selectǎm o inregistrare din tabelǎ numitǎ plant si sǎ stocǎm informatia de "trasare" in /tmp/trace.log. Pentru a activa monitorizarea, PHP oferǎ o functie numitǎ pg_trace. La executie scriptul va afisa pe ecran:

1, Sambucus nigra, galben

In plus, fisierul log a fost creat si contine liniile:

To backend> Q

To backend> SELECT id, name, color FROM plant LIMIT 1

From backend> P

From backend> 'blank'

From backend> T

From backend (#2)> 3

From backend> 'id'

From backend (#4)> 23

From backend (#2)> 4

From backend (#4)> -1

From backend> 'name'

From backend (#4)> 25

From backend (#2)> 65535

From backend (#4)> -1

From backend> 'color'

From backend (#4)> 25

From backend (#2)> 65535

From backend (#4)> -1

From backend> D

From backend (1)>

From backend (#4)> 5

From backend (1)> 1

From backend (#4)> 18

From backend (14)> Sambucus nigra

From backend (#4)> 10

From backend (6)> galben

From backend> C

From backend> 'SELECT'

From backend> Z

From backend> Z

To backend> X

Dupǎ cum se poate observa, au fost scrise in fisier mai multe informatii de logging. Pentru a utiliza efectiv aceste informatii de logging, trebuie sǎ privim in detaliu interiorul PostgreSQL. Pentru a opri monitorizarea vom utiliza pg_untrace.

Blocarea

Dacǎ scriem software pentru un server Web frecvent utilizat, trebuie sǎ avem in vedere si blocarea. De obicei, blocarea este realizatǎ de PostgreSQL intern, dar este posibil sǎ influentǎm blocarea in mod explicit. In multe situatii aceasta este necesar si ne poate ajuta sǎ rezolvǎm usor anumite probleme.

Cel mai important aspect cand lucrǎm cu blocarea explicitǎ, este sǎ vedem cum scripturile concurente trateazǎ blocarea. Blocarea se poate realiza printr-o singurǎ comandǎ:

phpdb=# h LOCK

Command: LOCK

Description: lock a table

Syntax:

LOCK [ TABLE ] name [, ] [ IN lockmode MODE ] [ NOWAIT ]

where lockmode is one of:

ACCESS SHARE | ROW SHARE | ROW EXCLUSIVE | SHARE UPDATE EXCLUSIVE

| SHARE | SHARE ROW EXCLUSIVE | EXCLUSIVE | ACCESS EXCLUSIVE

LOCK oferǎ multe optiuni pentru definirea modului in care este blocatǎ o tabelǎ. Un aspect important il reprezintǎ modul in care PostgreSQL trateazǎ blocarea care nu este specificatǎ explicit. Ex:

<?php

$dbh = pg_connect('host=localhost user=postgres dbname=phpdb');

if (!$dbh)

execute('INSERT INTO plant VALUES (4, 'pin', 'verde')');

execute('LOCK plant IN EXCLUSIVE MODE');

execute('INSERT INTO plant VALUES (5, 'trandafir', 'rosu')');

function execute($sql)

?>

Functia apelatǎ realizeazǎ o combinatie a executiei declaratiei SQL si a manipulǎrii erorilor. Aceasta este util deoarece manipularea erorilor trebuie implementatǎ o singurǎ datǎ. In plus, perioada de inceput si perioada de sfarsit a declaratiei SQL este afisatǎ. Aceastǎ informatie este necesarǎ pentru a observa efectele blocǎrii.

Prima inregistrare este adǎugatǎ in tabelǎ. In pasul urmǎtor tabela este blocatǎ exclusiv si o inregistrare aditionalǎ este adǎugatǎ in tabelǎ. Dupǎ prima executie a scriptului, in plant putem gǎsi douǎ valori aditionale:

phpdb=# select * from plant;

id | name | color

1 | Sambucus nigra | galben

2 | Abies | verde

3 | Colchicum autumnale | roz

4 | pin | verde

5 | trandafir | rosu

(5 rows)

Informatia de logging afisatǎ de script nu contine nimic special:

start: 2005-10-23 11:33:34 --- INSERT INTO plant VALUES (4, 'pin', 'verde')
end: 2005-10-23 11:33:34 --- INSERT INTO plant VALUES (4, 'pin', 'verde')
start: 2005-10-23 11:33:34 --- LOCK plant IN EXCLUSIVE MODE
end: 2005-10-23 11:33:34 --- LOCK plant IN EXCLUSIVE MODE
start: 2005-10-23 11:33:34 --- INSERT INTO plant VALUES (5, 'trandafir', 'rosu')
end: 2005-10-23 11:33:34 --- INSERT INTO plant VALUES (5, 'trandafir', 'rosu')

Totul a fost procesat intr-o singurǎ secundǎ. Sǎ vdem ce se va afisa cand scriptul este executat a doua oarǎ:

start: 2005-10-25 13:35:51 --- INSERT INTO plant VALUES (4, 'pin', 'verde')
end: 2005-10-25 13:35:51 --- INSERT INTO plant VALUES (4, 'pin', 'verde')
start: 2005-10-25 13:35:51 --- LOCK plant IN EXCLUSIVE MODE
end: 2005-10-25 13:35:51 --- LOCK plant IN EXCLUSIVE MODE
start: 2005-10-25 13:35:51 --- INSERT INTO plant VALUES (5, 'trandafir', 'rosu')
end: 2005-10-25 13:35:51 --- INSERT INTO plant VALUES (5, 'trandafir', 'rosu')

Blocarea nu afecteazǎ scriptul executat dupǎ ce prima oarǎ a fost terminat. Cand conexiunea la PostgreSQL este inchisǎ de PHP in mod automat, toate blocǎrile fǎcute de aceastǎ conexiune vor fi eliberate automat. Scriptul PHP care acceseazǎ tabela plant in perioada in care primul script PHP a blocat tabela si scriptul a fost terminat trebuie sǎ astepte panǎ cand blocarea este eliberatǎ. Dacǎ scriptul necesitǎ mult timp pentru a avea succes, aceasta va conduce la scǎderea semnificativǎ a performantei sistemului.

PHP si tranzactii

Tranzactiile si blocǎrile sunt in stransǎ legǎturǎ unul cu altul. Vom vedea ce se intamplǎ in cazul in care tranzactiile nu au fost "comise" manual:

<?php

$dbh = pg_connect('host=localhost user=postgres dbname=phpdb');

if (!$dbh)

execute('BEGIN;');

execute('INSERT INTO plant VALUES (6, 'cactus', 'verde')');

function execute($sql)

?>

Tranzactia a fost pornitǎ. In urmǎtorul pas este adǎugatǎ o valoare in tabelǎ, dar tranzactia nu este comisǎ manual. Astfel noua valoare nu poate fi gǎsitǎ in tabel:

phpdb=# SELECT * FROM plant WHERE id=6;

id | name | color

(0 rows)

Cand scriptul a fost executat, PHP inchide conexiunea la PostgreSQL si baza de date executǎ implicit un ROLLBACK. In acest mod, nici o datǎ din tranzactiile necomise vor afacta datele noastre.

Situatia diferǎ cand tranzactia este terminatǎ explicit:

<?php

$dbh = pg_connect('host=localhost user=postgres dbname=phpdb');

if (!$dbh)

execute('BEGIN;');

execute('INSERT INTO plant VALUES (6, 'cactus', 'verde')');

execute('COMMIT;');

function execute($sql)

?>

De aceastǎ datǎ inregistrarea poate fi gǎsitǎ in tabelǎ deoarece tranzactia a fost comisǎ corect.

phpdb=# SELECT * FROM plant WHERE id=6;

id | name | color

6 | cactus | verde

(1 row)

Dacǎ utilizǎm BEGIN si COMMIT explicit, fiecare comandǎ va fi executǎ ca o tranzactie separatǎ. Acest aspect este important deoarece nu trebuie sǎ tratǎm tranzactiile explicit. PHP nu oferǎ utilitare pentru manipularea tranzactiilor, aceasta realizandu-se prin declaratii SQL.

Interfata de programare PHP pentru PostgreSQL se bazeazǎ pe librǎrii C. Inserarea, extragerea si selectarea datelor poate fi realizatǎ prin trimiterea declaratiilor SQL cǎtre baza de date. Pentru a extrage datele din result PostgreSQL oferǎ diferite metode; datele pot fi extrase ca linii, inregistrǎri sau obiecte.

Lucrul cu BLOB-uri

Fiecare bazǎ de date suportǎ o metodǎ de stocare a fisierelor in baza de date. Aceasta este foarte important in cazul utilitarelor de management al continutului. Unii preferǎ stocarea fisierelor in sistemul de fisiere, nu in baza de date. In loc de a incǎrca un fisier in baza de date, putem stoca doar numele fisierului in baza de date. Problema cu acest algoritm este cǎ consistenta datelor din baza de date si sistemul de fisiere trebuie verificatǎ. In plus, este necesar un backup al fisierelor si bazelor de date individual, si nu este usor dumping-ul bazelor da date care includ BLOB-uri (Binary Large Objects).

Lucrul cu BLOB-urile PostgreSQL utilizand SQL

PostgreSQL oferǎ un set de functii usor de utilizat pentru lucrul cu BLOB-uri. BLOB-urile nu sutn stocate intr-o tabelǎ ci ca obiecte in baza de date. Obiectul id al BLOB-ului poate fi stocat intr-o tabelǎ si nu va fi perdut in baza de date. Vom crea o tabelǎ pentru stocarea id-urilor obiectelor si o descriere a fisierelor pe care id-ul obiect in indicǎ:

phpdb=# CREATE TABLE ext4(file_oid oid, description text);

CREATE TABLE

Prima coloanǎ a tabelei contine id-ul obiectului fisierului la care facem referire. A doua coloanǎ contine descrierea fisierului.

Cand se creaza o noua tabela care contine id-urile obiectului, trebuie sa nu o numim oid.

phpdb=# CREATE TABLE ext5(oid oid, description text);

ERROR: name of column 'oid' conflicts with an existing system column

La nivel intern PostgreSQL utilizeaza o coloana pentru stocarea id-ului obiectului unei linii intr-o tabela. Pentru a afisa obiectul id din tabela, trebuie adaugat oid la lista coloanelor pe care dorim sa le afisam.

phpdb=# SELECT oid, * FROM ext4;

oid | file_oid | description

44294 | 44293 | file used to store user data

44296 | 44295 | hostnames

Incepand cu PostgreSQL 7.2, este posibil sa creem tabele fara a avea o coloana care sa contina un id al obiectului:

phpdb=# CREATE TABLE ext5(oid oid, description text) WITHOUT OIDS;

CREATE TABLE

Este suficient sa adaugam WITHOUT OIDS la declaratia CREATE TABLE, si nu vor exista conflicte daca numele coloanelor vor fi dublate.

phpdb=# d ext5;

Table 'public.ext5'

Column | Type | Modifiers

oid | oid |

description | text |

Dupa cum putem observa, tabela a fost creata cu succes.

Pentru a importa un fisier in baza de date, putem folosi lo_import:

As you can see, the table has been created successfully.

Let's get back to the first example you saw in this section. To import a file into the database, you can use lo_import:

phpdb=# SELECT lo_import('/etc/passwd');

lo_import

17254

(1 row)

Functia returneaza un object_id: fisierul a fost stocat in baza de date dar nu a fost importat intr-o tabela. Pentru a introduce id-ul obiectului returnat de lo_import, putem folosi o declaratie INSERT.

phpdb=# INSERT INTO ext4 VALUES (17254, 'file used to store user data');

INSERT 17256 1

Utilizarea a doua comenzi nu este cea mai buna cale petru a realiza acest tip de operatie. Pentru a importa un fisier si a adauga o inregistrare in tabela, putem scrie o declaratie SQL de genul:

phpdb=# INSERT INTO ext4 VALUES (lo_import('/etc/hosts'), 'hostnames');

INSERT 17258 1

Pentru a vedea daca inregistrarea a fost generata cu succes, vom interoga tabela:

phpdb=# SELECT * FROM ext4;

file_oid | description

17254 | file used to store user data

17257 | hostnames

(2 rows)

Doua inregistrari au fost adaugate in tabela. Sa vedem acum cum exportam BLOB-urile. Pentru a exporta un BLOB, PostgreSQL ofera comanda lo_export:

phpdb=# SELECT lo_export(17254, '/tmp/tmpfile.txt');

lo_export

1

(1 row)

Primul parametru specificat in functie este id-ul obiect al fisierului. Al doilea parametru defineste numele fisierului pe care dorim sa-l exportam ca BLOB. Dupa ce un fisier a fost importat in baza de date PostgreSQL, numele fisierului original este pierdut. Cand exportam din nou fisierul, trebuie sa atribuim din nou nume fisierului. Sa vizualizam continutul noului fisier. Cu ajutorul lui head -n3, vor fi afisate primele 3 linii:

salexis@b2-1$ head -n3 /tmp/tmpfile.txt

# $FreeBSD: src/etc/master.passwd,v 1.39 2004/08/01 21:33:47 markm Exp $

root:*:0:0:Charlie &:/root:/bin/csh

Fisierul a fost exportat cu succes. Urmatorul exemplu, afiseaza modul cum un obiect care include si intrarea id a obiectului in ext4 poate fi eliminat:

phpdb=# BEGIN;

BEGIN

phpdb=# SELECT lo_unlink(17254);

lo_unlink

1

(1 row)

phpdb=# DELETE FROM ext4 WHERE file_oid=17254;

DELETE 1

phpdb=# COMMIT;

COMMIT

Este recomandata realizarea operatiei intr-o singura tranzactie astfel incat operatiile concurente sa nu afecteze lucrul cu baza de date. lo_unlink elimina un BLOB.

Pe langa functiile prezentate PostgreSQL ofera functii aditionale pentru manipularea BLOB-urilor, cum ar fi lo_open and lo_write.

Lucrul cu BLOB-urile utulizand PHP

Functiile PHP legate de PostgreSQL si BLOB-uri sunt usor de utilizat. Functiile sunt disponibile pentru toate operatiile de import, export, crearea de noi obiecte sau scrierea datelor intr-un obiect.

Urmatorul exemplu demonstreaza cum poate fi importat si sters un fisier in baza de date:

<?php

$dbh = pg_connect('host=localhost user=postgres dbname=phpdb');

if (!$dbh)

pg_exec($dbh, 'BEGIN');

$oid = pg_loimport('/etc/passwd', $dbh);

if (!$oid)

echo 'Id-ul obiectului: $oid<br>n';

$status = pg_lounlink($dbh, $oid);

if (!$status)

pg_exec($dbh, 'COMMIT');

?>

Functiile PHP pentru lucrul cu BLOB-uri poate fi utilizat doar in cadrul unei tranzactii. Din acest motiv, o tranzactie este pornita inainte ca fisierul sa fie inserat in baza de date prin utilizarea lui pg_loimport. Vom specifica doar numele fisierului pe care dorim sa-l importam si manipulatorul de conexiune pentru functie; daca suntem in interiorul ueni tranzactii, operatia va avea succes daca nu exista o eroare legata de drepturile utilizatorului.

pg_loimport returneaza obiectul id-ul al noului obiect, care este afisat pe ecran utilizand comanda echo. In final, noul obiect este sters:

Id-ul obiectului: 17262

Cand lucram cu date multimedia, este deseori necesar sa trimitem datele intr-un fisier stocat intr-o baza de date PostgreSQL direct catre browser. Astfel PHP ofera o comanda numita pg_loreadall. Pentru a utiliza aceasta functie, fisierul trebuie deschis utilzand pg_loopen.

<?php

$dbh = pg_connect('host=localhost user=postgres dbname=phpdb');

if (!$dbh)

pg_exec($dbh, 'BEGIN');

$oid = pg_loimport('/etc/passwd', $dbh);

if (!$oid)

$file = pg_loopen($dbh, $oid, 'rw');

pg_loreadall($file);

$status = pg_lounlink($dbh, $oid);

if (!$status)

pg_exec($dbh, 'COMMIT');

?>

pg_loreadall returneaza void si nu returneaza data ca o variabila; continutul BLOB-ului este trimis direct catre browser. Rezultatul este:

# $FreeBSD: src/etc/master.passwd,v 1.39 2004/08/01 21:33:47 markm Exp $ # root:*:0:0:Charlie &:/root:/bin/csh toor:*:0:0:Bourne-again Superuser:/root: daemon:*:1:1:Owner of many system processes:/root:/usr/sbin/nologin operator:*:2:5:System &:/:/usr/sbin/nologin bin:*:3:7:Binaries Commands and Source:/:/usr/sbin/nologin tty:*:4:65533:Tty Sandbox:/:/usr/sbin/nologin kmem:*:5:65533:KMem Sandbox:/:/usr/sbin/nologin games:*:7:13:Games pseudo-user:/usr/games:/usr/sbin/nologin news:*:8:8:News Subsystem:/:/usr/sbin/nologin man:*:9:9:Mister Man Pages:/usr/share/man:/usr/sbin/nologin sshd:*:22:22:Secure Shell Daemon:/var/empty:/usr/sbin/nologin smmsp:*:25:25:Sendmail Submission User:/var/spool/clientmqueue:/usr/sbin/nologin mailnull:*:26:26:Sendmail Default User:/var/spool/mqueue:/usr/sbin/nologin bind:*:53:53:Bind Sandbox:/:/usr/sbin/nologin proxy:*:62:62:Packet Filter pseudo-user:/nonexistent:/usr/sbin/nologin _pflogd:*:64:64:pflogd privsep user:/var/empty:/usr/sbin/nologin uucp:*:66:66:UUCP pseudo-user:/var/spool/uucppublic:/usr/local/libexec/uucp/uucico pop:*:68:6:Post Office Owner:/nonexistent:/usr/sbin/nologin www:*:80:80:World Wide Web Owner:/nonexistent:/usr/sbin/nologin nobody:*:65534:65534:Unprivileged user:/nonexistent:/usr/sbin/nologin salexis:*:1001:1001:Alexandru Sireteanu:/home/salexis:/usr/local/bin/bash postfix:*:125:125:Postfix Mail System:/var/spool/postfix:/usr/sbin/nologin clamav:*:106:106:Clam Antivirus:/nonexistent:/sbin/nologin mysql:*:88:88:MySQL Daemon:/nonexistent:/sbin/nologin pgsql:*:70:70:PostgreSQL Daemon:/usr/local/pgsql:/bin/sh oracle:*:71:71:Oracle:/usr/local/oracle7:/bin/sh

Putem importa si exporta fisiere, dar in unele situatii BLOB-ul trebuie modificat. PHP si PostgreSQL ofera functii similare cu functiile C utilizate pentru interactiunea cu fisierele. Pentru a crea un obiect gol, vom folosi pg_locreate, iar pentru a scrie date intr-un BLOB, vom utiliza pg_lowrite. Vom vedea un exemplu de adaugare a cuvantului SUSI la un BLOB gol.

<?php

$dbh = pg_connect('host=localhost user=postgres dbname=phpdb');

if (!$dbh)

pg_exec($dbh, 'BEGIN');

$oid = pg_locreate($dbh);

if (!$oid)

echo 'id-ul obiectului: $oid<br>n';

$file = pg_loopen($dbh, $oid, 'rw');

pg_lowrite($file, 'SUSI');

pg_loclose($file);

pg_exec($dbh, 'COMMIT');

?>

Sa vedem ce date gasim in fisier. BLOB-ul poate fi exportat intr-un fisier:

phpdb=# SELECT lo_export(17268, '/tmp/test_lowrite.txt');

lo_export

-----------

1

(1 row)

si putem afisa continutul fisierului pe ecran:

salexis@b2-1$ cat /tmp/test_lowrite.txt; echo

SUSI

SUSI a fost adaugat la BLOB si fisierul a fost inchis corect. Pentru a afisa datele din BLOB, putem scrie un script PHP:

<?php

$dbh = pg_connect('host=localhost user=postgres dbname=phpdb');

if (!$dbh)

pg_exec($dbh, 'BEGIN');

$file = pg_loopen($dbh, 17268, 'r');

$data = pg_loread($file, 4);

echo 'data: $data<br>n';

pg_loclose($file);

pg_exec($dbh, 'COMMIT');

?>

In primul rand este deschis BLOBsi sunt extrasi 4 bytes de date din BLOB utilizand pg_loread. Dupa aceasta datele sunt afisate pe ecran:

data: SUSI

Managementul Upload-ului de fisiere

Managementul fisierelor poate fi realizat cu orice browser care este in acord cu RFC-1867, ca Mozilla si Netscape. Uploadul fisierelor se referǎ la posibilitatea de a stoca un fisier pe un server Web unde poate fi utilizat pentru o prelucrare ulteriorǎ.Nu conteazǎ dacǎ fisierul este in format ASCII sau binar deorece el este procesat ca o unitate byte cu byte. De obicei fisierele sunt incǎrcate cu o cerere POST, ca in exemplul:

<html>

<head>

<title>Titlu</title>

</head>

<body>

<h1>Lucrul cu Upload-ul de fisiere</h1>

<form id='data' method='post' action='input_file.php'

enctype='multipart/form-data'>

<p>

Alege un fisier: <br>

<input name='testfile' type='file' size='50' maxlength='100000'><br>

<input name='submit' type='submit'>

</p>

</form>

</body>

</html>

Dupǎ antet si titlu, distingem formularul. Primul camp din formular utilizeazǎ file ca tip. Campul va fi folosit pentru upload-ul de fisiere. Dintre parametri distingem lungimea maximǎ a fisierului care va fi incǎrcat. Urmǎtorul camp contine butonul Submit Query pentru inceperea cererii POST:

Fisierul responsabil pentru managementul upload-ului de fisiere se numeste input_file.php:

<?php

if ($testfile)

else

}

else

?>

Campul din fisierul PHP responsabil cu realizarea upload-ului se numeste testfile. PHP defineste automat o variabilǎ avand acelasi nume cu campul din fisierul HTML. Se poate verifica dacǎ variabila este definitǎ sǎ verficǎm dacǎ fisierul a foat incǎrcat cu succes. $testfile contine numele fisierului de pe serverul Web iar $testfile_name contine numele original al fisierului de pe masina utilizatorului. La upload, fisierul nu va avea numele original de pe serverul Web deoarece aceasta poate cauza o problemǎ legatǎ de numele identice. In plus a fost definit si $testfile_size, care contine dimensiunea fisierului in bytes. Rezultatul va fi:

userfile: /tmp/phpTdZESc

userfile_name: example.tar.gz

userfile_size: 7194

Dupǎ cum se poate observa, continutul lui $testfile este putin criptic, avantajul constand in faptul cǎ numele fisierelor generate de PHP sunt intotdeauna unice.

Stocarea fisierelor ca text toasted

Datele pot fi convertite ca cod hexa si stocate intr-o variabilǎ text. De la PostgreSQL 7.0, dimensiunea variabilelor text a fost limitatǎ la dimensiunea unei singure pagini, care este de obicei 8192 bytes. Odatǎ cu aparitia lui PostgreSQL 7.1, lucrurile s-au schimbat si textul se numeste tip de datǎ toasted, ceea ce inseamnǎ cǎ un camp poate fi mai mare decat o paginǎ utilizatǎ de PostgreSQL intern. De obicei, un camp poate avea maxim 1GB. Dacǎ se doreste lucrul cu campuri mai mari de 1GB, vom utiliza interfata BLOB a PostgreSQL.

Sǎ vedem cum continutul unui fisier poate fi stocat intr-o coloanǎ text. Vom crea o tabelǎ pentru stocarea fisierelor.

phpdb=> CREATE TABLE filesystem(name text, data text, tstamp timestamp);

CREATE TABLE

Vom scrie o micǎ aplicatie rin care vom importa un fisier (/etc/passwd) in baza de date:

<?php

# numele fisierului pe care dorim sa-l importam

$filename = '/etc/passwd';

$dbh = pg_connect('host=localhost user=postgres dbname=phpdb');

if (!$dbh)

# deschiderea fisierului si extragerea informatiilor despre acesta

$fp = fopen($filename, 'r');

$fstats = fstat($fp);

$data = fread($fp, $fstats[6]);

# conversia datelor la date hexa

$hexdata = bin2hex($data);

# introducerea datelor in baza de date

$sql = 'INSERT INTO filesystem VALUES

('$filename', '$hexdata', now())';

$stat = pg_exec($dbh, $sql);

if (!$stat)

else

?>

Dupǎ conectarea la baza de date, fisierul este deschis pentru citire utilizand fopen. Manipulatorul de fisier returnat de fopen este necesar pentru fstats. Cu ajutorul lui fstats, informatiile referitoare la dimensiune si inode pot fi afisate. Este necesarǎ dimensiunea fisierului pentru a vedea cate date au fost citite utilizand fread. Dupǎ ce datele sunt citite, ele sunt codate utilizand bin2hex. $hexdata este apoi introdus apoi in baza de date si pe ecran este afisat un mesaj. Vom verifica dacǎ datele au fost importate cu succes:

phpdb=# SELECT name, length(data), tstamp FROM filesystem;

name | length | tstamp

/etc/passwd | 2400 | 2005-10-31 23:42:53.644758+01

(1 row)

Numele fisierului este stocat in prima coloanǎ. Continutul celei de-a doua coloane nu este afisat complet deoarece nu este folosit pentru a afisa datele hexazecimale. Campul are dimensiunea totalǎ 2400 byes. Dacǎ ne uitǎm la /etc/passwd, observǎm cǎ cantitatea de depozitare necesarǎ s-a dublat:

ls -l /etc/passwd

-rw-r--r-- 1 root root 1200 Dez 15 01:13 /etc/passwd

Exportul datelor este la fel de simplu ca importul datelor:

<?php

# numele fisierului pe care dorim sa-l extragem

$filename = '/etc/passwd';

# conectarea la baza de date

$dbh = pg_connect('host=localhost user=postgres dbname=phpdb');

if (!$dbh)

# selectarea datelor

$sql = 'SELECT name, data, tstamp FROM filesystem

WHERE name='$filename'';

$result = pg_exec($dbh, $sql);

$data = pg_fetch_row($result, 0) or

exit ('a aparut o eroare<br>');

$bindata = hex2bin($data[1]);

# compararea datelor

$fp = fopen($filename, 'r');

$fstats = fstat($fp);

$data = fread($fp, $fstats[6]);

if ($bindata == $data)

else

function hex2bin($data)

?>

In primul randm inregistrarea contine fisierul necesar a fi afisat din baza de date. In urmǎtorul pas, continutul celei de-a doua coloane este transformat in formatul original prin functia hex2bin. La sfarsitul programului PHP putem observa cum lucreazǎ hex2bin: lungimea sirului specificat in functie este evaluat si apoi sirul decodat este returnat programului principal. Acum $bindata contine datele originale, si datele sunt comparate cu datele din fisierul original /etc/passwd. Rezultatul este:

the data is the same

Exemplu de utilitar pentru managementul imaginilor

Idea este de a arǎta cum datele pot fi extrase din baza de date si trimise browser-ului direct.

Vom crea o tabelǎ pentru a stoca imagini despre imagini:

CREATE TABLE pic_db (

id serial, -- id-ul of imaginii

name text, -- numele imaginii

picoid oid, -- id-ul obiectului imaginii

added timestamp DEFAULT now()

Codul HTML pentru incǎrcarea fisierelor este:

<html>

<head>

<title>Titlu</title>

</head>

<body>

<?php

echo '<b>Lista imaginilor din tabela </b><br>n';

# conectarea la baza de date

$dbh = pg_connect('dbname=phpdb user=postgres');

if (!$dbh)

$result = pg_exec($dbh, 'SELECT id, name, picoid, added FROM pic_db');

$rows = pg_numrows($result);

for ($i = 0; $i < $rows; $i++)

?>

<br><br><hr>

<b>Incarcarea fisierelor:</b>

<form id='data' method='post' action='input_file.php'

enctype='multipart/form-data'>

<p>

Alegeti un fisier: <br>

<input name='testfile' type='file' size='50' maxlength='100000'><br>

<input name='submit' type='submit'>

</p>

</form>

</body>

</html>

Dupǎ ce a fost afisat header-ul, incepe scriptul PHP. Conexiunea la baza de date este stabilitǎ si informatia referitoare la imagini care este deja in baza de date este afisatǎ. Fiecare nume de fisier este afisat si o legǎturǎ cǎtre detail.php este generatǎ. Detail.php va contine codul pentru extragerea imaginii. Dupǎ generarea legǎturilor, este afisat un formular. Acest formular poate fi utilizat pentru incǎrcarea fisierelor aditionale:

Input_file.php este apelat cand cineva executǎ clic pe butonul Submit Query, Conexiunea la baza de date este deschisǎ si fisierul incǎrcat de utilizator este importat in baza de date. Dacǎ fisierul este importat cu succes, este afisat un mesaj. Fisierul input_file.php:

<?php

# conectarea la baza de date

$dbh = pg_connect('dbname=phpdb user=postgres');

if (!$dbh)

# verific incarcarea fisierului

if ($testfile)

else

}

else

}

pg_close($dbh);

?>

Scriptul numit detail.php este utilizat pentru a afisa o imagine pe ecran:

<?php

# conectarea la baza de date

$dbh = pg_connect('dbname=phpdb user=postgres');

if (!$dbh)

$sql = 'SELECT id, name, picoid, added FROM pic_db WHERE id=$id';

$result = pg_exec($dbh, $sql);

$data = pg_fetch_row($result, 0);

if (!$data)

else

$img = pg_loreadall($ofp);

print $img;

pg_loclose($ofp);

pg_exec($dbh, 'END');

}

?>

Conexiunea la baza de date este stabilitǎ. Id-ul obiect al imaginii este extras. Pentru a deshide BLOB-ul, trebuie pornitǎ tranzactia. Pg_loopen returneazǎ un manipulator care poate fi utilizat pentru operatii ca citirea fisierelor din BLOB. In final, toate manipulatoarele si tranzactiile sunt inchise. In plus, datele sunt trimise cǎtre browser.

Lucrul cu conexiuni persistente la baza de date

Conexiunile persistente la baza de date reprezintǎ o facilitate principalǎ a PHP-ului. Avantajul principal al conexiunilor persistente la baza de date constǎ in faptul cǎ timpul necesar pentru autentificare este redus semnificativ. Aceastǎ sarcinǎ poate fi realizatǎ prin "reutilizarea conexiunii". PHP pǎstreazǎ o rezervǎ internǎ a conexiunilor deschise la o anumitǎ bazǎ de date, a utilizatorului si a sistemului gazdǎ. De fiecare datǎ cand utilizatorul doreste sǎ se conecteze la baza de date, PHP verificǎ dacǎ existǎ o conexiune internǎ liberǎ si o atribuie noului utilizator. Dacǎ nu existǎ o conexiune liberǎ, PHP incearcǎ sǎ stabileascǎ o nouǎ conexiune la baza de date. Imediat cum utilizatorul se deconecteazǎ, conexiunea nu va fi terminatǎ, ea fiind disponibilǎ din nou in rezerva de conexiuni libere. Cu ajutorul acestui algoritm, sunt salvate multe procese de autentificare a utilizatorilor, fiind obtinutǎ o performantǎ sporitǎ.

Exemplu

Dacǎ utilizǎm PostgreSQL 7.2, putem observa douǎ procese care ruleazǎ la initializarea sistemului. Putem verifica acest lucru prin redirectarea tabelului de procese cǎtre grep:

salexis@b2-1$ ps ax | grep postgres

21647 pts/4 S 0:00 postgres: stats buffer process

21649 pts/4 S 0:00 postgres: stats collector process

4338 pts/4 S 0:00 grep postgres

Vom scrie un script care doar se conecteazǎ la baza de date si afiseazǎ un mesaj:

<?php

$dbh = pg_connect('host=localhost user=postgres dbname=phpdb');

if (!$dbh)

else

?>

Dupǎ cum putem observa, mumǎrul de procese care ruleazǎ nu s-a schimbat, desi conexiunea la baza de date nu a fost inchisǎ explicit.

salexis@b2-1$ ps ax | grep postgres

21647 pts/4 SW 0:00 postgres: stats buffer process

21649 pts/4 SW 0:00 postgres: stats collector process

4344 pts/4 S 0:00 grep postgres

Toate procesele pornite de PHP au fost eliminate fǎrǎ nici o problemǎ. In continuare vom scriptul PHP anterior prin utilizarea comenzii de conectare la baza de date pg_pconnect:

<?php

$dbh = pg_pconnect('host=localhost user=postgres dbname=phpdb');

if (!$dbh)

else

?>

Scriptul realizeazǎ acelasi lucru, dar a fost stabilitǎ o conexiune persistentǎ la baza de date. Vom verifica acum toate procesele PostgreSQL active:

salexis@b2-1$ ps ax | grep postgres

21647 pts/4 S 0:00 postgres: stats buffer process

21649 pts/4 S 0:00 postgres: stats collector process

4347 pts/4 S 0:00 postgres: postgres phpdb 127.0.0.1 idle

4349 pts/4 S 0:00 grep postgres

O conexiune activǎ este incǎ in memorie deoarece nu a fost inchisǎ la sfarsitul scriptului PHP. Dacǎ executǎm scriptul PHP mai mult de o datǎ, PostgreSQL nu va crea un nou proces backend deoarece backend-urile care ruleazǎ pot fi reutilizate, aceasta salvand timp si reducand incǎrcarea bazei de date.

Conexiunile persistente si performanta

In continuare vom studia efectele conexiunilor persistente asupra vitezei. Vom crea un script care se conecteazǎ si deconecteazǎ la baza de date de 25000 de ori. In plus, este calculat timpul mediu necesar de conectare la baza de date.

<?php

$number = 25000; # numarul de conexiuni

$begin = time(); # Timp de start

for ($i = 0; $i < $number; $i++)

pg_close($dbh);

}

$end = time(); # Timp de sfarsit

$diff = $end - $begin; # Timp total

$tpconn = $diff / $number; # Timp pe conexiune

# afiseaza rezultatul

echo 'Inceput: $begin<br>n';

echo 'Sfarsit: $end<br>n';

echo 'Timp total: $diff<br>n';

printf('Timp pe conexiune: %9.8f<br>n', $tpconn);

?>

La inceputul scriptului este calculat timpul de inainte de conectare. Timpul este returnat in secunde de la 1 ianuarie 1970. In continuare sunt stabilite conexiunile persistente la baza de date. Dupǎ aceasta, timpul este extras din nou si sunt realizate calcule. Valorile afisate sunt:

Inceput: 1132163153
Sfarsit: 1132163166
Timp total: 13
Timp pe conexiune: 0.00052000

Dupǎ cum se poate observa, au fost stabilite 25000 de conexiuni in 13 secunde dacǎ o rezervǎ de conexiune este deja in memorie. Timpul necesar pentru stabilirea unei conexiuni este foarte mic deoarece PHP nu a trebuit sǎ cearǎ PostgreSQL-ului autentificarea utilizatorului. Cu conexiuni nonpersistente situatia este diferitǎ; de fiecare datǎ cand este stabilitǎ o conexiune, un proces backend trebuie pornit si PostgreSQL trebuie sǎ verifice baza de date, utilizatorul si parola.

In urmǎtorul exemplu ne vom conecta la aceeasi bazǎ de date utilizand acelasi script, utilizand conexiuni nonpersistente. Vom utiliza 250 de conexiuni in loc de 25000. Rezultatul va fi:

Inceput: 1132164436
Sfarsit: 1132164444
Timp total: 8
Timp pe conexiune: 0.03200000

Au fost necesare 8 secunde pentru a stabili 250 de conexiuni (0.03 secunde pentru a stabili o conexiune). De retinut cǎ conexiunea este stabilitǎ la masina localǎ unde toti utilizatorii sunt trusted.

Vom modifica pg_hba.conf si vom rula scriptul utilizand IP-ul oficial al masinii:

local all trust

host  all 127.0.0.1 255.255.255.255 trust

hostssl phpdb 194.176.165.12 255.255.255.255 crypt

Pentru a activa modificǎrile vom restarta PostgreSQL (vom activa SSL utilizand flag-ul -l cand pornim postmaster-ul). Vom crea si un nou utilizator:

phpdb=# CREATE USER testuser WITH PASSWORD 'mypasswd';

CREATE USER

Vom utiliza scriptul de conectare la baza de date:

<?php

$number = 250; # numarul de conexiuni

$begin = time(); # Timp de start

for ($i = 0; $i < $number; $i++)

pg_close($dbh);

}

$end = time(); # Timp de sfarsit

$diff = $end - $begin; # Timp total

$tpconn = $diff / $number; # Timp pe conexiune

# afiseaza rezultatul

echo 'Inceput: $begin<br>n';

echo 'Sfarsit: $end<br>n';

echo 'Timp total: $diff<br>n';

printf('Timp pe conexiune: %9.8f<br>n', $tpconn);

?>

De aceastǎ datǎ procesul de autentificare necesitǎ mai mult timp deoarece ne-am conectat la baza de date utilizand SSL:

Inceput: 1132165428
Sfarsit: 1132165436
Timp total: 26
Timp pe conexiune: 0.03200000

In scenariul anterior, lucrul cu conexiuni persistente la baza de date este de 2600 de ori mai rapid decat lucrul cu conexiuni SSL nonpersistente (desigur este greu de comparat conexiunile persistente cu cele SSL nonpersistente). Cand lucrǎm cu baze de date pentru a cosntrui un sit Web dinamic, timpul necesar pentru conectarea la baza de date este adesea subestimat.

Pericole si probleme hardware

Conexiunile persistente la baza de date pot fi periculoase in privinta consumului de memorie si configurǎrii sistemului.

Tranzactii

Conexiunile persistente la baza de date si tranzactiile sunt elemente critice. Dacǎ nu asigurǎm un debug la aplicatie putem avea probleme grave dificil de rezolvat.

Exemplu:

Vom vrea o tabelǎ:

phpdb=# CREATE TABLE course (id int4, name text, description text);

CREATE TABLE

Vom testa un script care foloseste tranzactii explicite:

<?php

$dbh = pg_pconnect('user=postgres dbname=phpdb');

if (!$dbh)

$stat = pg_exec($dbh, 'BEGIN');

if (!$stat)

echo 'incerc sa introduc date <br>n';

$sql = 'INSERT INTO course VALUES (9, 'Programare C', NULL)';

$stat = pg_exec($dbh, $sql);

if (!$stat)

echo '<a href='data2.php'>continua</a>';

pg_close($dbh);

?>

Tranzactia a fost pornitǎ si o inregistrare a fost adǎugatǎ in tabelǎ. La prima executia a scriptului, nu apare nici o problemǎ:

incerc sa introduc date
continua

Tranzactia nu poate fi pornitǎ deoarece o tranzactie este deja in curs. Sǎ vedem continutul tabelei:

phpdb=# SELECT * FROM course;

id | name | description

(0 rows)

Nu a fost introdusǎ nici o inregistrare in tabelǎ, dar problema este cǎ sistemul este blocat intr-un anumit mod. Cauza este cǎ nu existǎ un script care sǎ comitǎ tranzactia si procesul backend nu este distrus automat. Problema se poate rezolva doar restartand baza de date.

Managementul sesiunilor

Pentru aplicatii de tipul Web shop, este necesar sǎ trecem informatia de pe un ecran pe altul. Dacǎ cantitatea de informatie care trebuie trimisǎ pe mai multe ecrane creste, formularele si campurile ascuse nu sunt necesare pentru a ne satisface cerintele. Managementul sesiunilor cu Cookies

O modalitate de a identifica utlizatorii si de a stoca date este utlizarea de cookie. HTTP nu este un protocol orientat pe conexiune, cookie putand fi utilizat pentru a simula un anumit tip de interactiune permanentǎ cu serverul. Idea principalǎ este de a stoca informatia direct pe sistemul clientului. Cand un sit este solicitat, informatia dintr-un cookie adecvat este trimisǎ cǎtre server automat. Serverul nu se uitǎ dupǎ cookie: informatia este trimisǎ cǎtre server de cǎtre browser automat. Exemplu:

<?php

setcookie ('YourName', 'John & Vangelis');

header('Content-type: text/html');

echo 'Numele tau a fost adaugat in cookie <br>n';

?>

<a href='checkcookie.php'>Treci pe pagina urmatoare</a>

Scriptul seteazǎ un cookie numit YourName. Valoarea cookie-ului este John & Vangelis. Acest cookie a fost setat inainte de a trimite header-ul clientului. Dupǎ aceasta este afisat un sir si o legǎturǎ. Dacǎ executǎm clic pe legǎturǎ, va fi apelat scriptul checkcookie.php:

<?php

echo 'Afisare informatie stocata in cookie:<br>n';

if ($YourName)

else

?>

Scriptul verificǎ dacǎ $YourName existǎ. Dacǎ variabila existǎ, continutul acesteia va fi afisat pe ecran. De remarcat cǎ nu existǎ un buton submitm datele din cookie fiind disponibile pe ecranul urmǎtor. La un clic pe legǎturǎ vor fi afisate douǎ linii:

Afisare informatie stocata in cookie

Date stocate in cookie: John & Vangelis

A doua linie contine datele stocate in cookie. Componentele unui cookie pot fi:

- name - defineste numele unui cookie;

- value - contine valoarea unui cookie;

- expires - defineste timpul dupǎ care un cookie va expira;

- domain - defineste domeniile pentru care cookie este valid;

- path - defineste calea pentru care cookie este valid;

- secure - restrictioneazǎ transmiterea de cookie cǎtre un canal sigur;

In exemplu anterior, am vǎzut cum un cookie poate fi generat sǎ dureze mereu. In anumite cazuri nu este util; dacǎ dorim sǎ utilizǎm un cookie doar pentru stocarea continutului unui shopping cart, nu dorim ca datele sǎ rǎmanǎ in cookie pentru totdeauna. Putem defini perioada de timp pentru care un cookie este valid. Ex:

<?php

$t = time()+3600*24;

setcookie('yourname','Shelley',$t,'/','postgresql.org');

header('Content-type: text/html');

echo 'Numele tau a fost adaugat in cookie<br>n';

?>

<a href='checkcookie.php'>Treci pe pagina urmatoare</a>

Ora curentǎ este calculatǎ prin apelarea functie PHP time. Dupǎ aceasta sunt adǎugate 24 ore la acest etalon de timp (timestamp) si valoarea acesuia este preluatǎ pentru a spune cookie-ului cǎ este valid pentru intregul domeniu numit postgresql.org.

Masina din exemplu pe care a fost testat nu apartine domeniului postgresql.org, si nu va fi disponibilǎ nici un fel de datǎ cand executǎm clic pe legǎturǎ:

Afisare informatie stocata in cookie:
nici o data nu a fost stocata in cookie

In urmǎtorul exemplu, vom vedea cum stergem valoarea unui cookie:

<?php

if ($yourname)

else

echo '<a href='main.php'>Reincarca pagina</a>';

?>

Scriptul genereazǎ un cookie dacǎ nu a fost setat nici un cookie si sterge cookie dacǎ cookie a fost deja setat deja. Dupǎ cum putem observa, un cookie poate fi sters prin setarea celui de-al treilea parametru la data anterioarǎ. In acest mod, un cookie este marcat ca fiind expirat si este sters automat. Dacǎ executǎm scriptul de douǎ ori, rezultatul va fi:

stergem cookie .

valoarea cookie a fost: Shelley

Reincarca pagina

Cookie sunt usor de utilizat, dar pot apare anumite probleme:

- utilizatorii au dezactivat cookie din motive de securitate;

- utilizarea acestora in combinatie cu conexiuni HTTP sigure si nesigure.

Managementul sesiunilor

Concepul de managemnt al sesiunilor este mai sofisticat decat lucrul cu cookie. Cu ajutorul sesiunilor, este posibil sǎ urmǎrim un utilizator fǎrǎ a lucra cu campuri ascunse sau cookie explicit. Aceasta este un mare avantaj; se castigǎ flexibilitate si lucrul cu sesiuni ne ajutǎ sǎ implementǎm componente mult mai eficient.

Cand un utilizator viziteazǎ un sit Web, un id unic este atribuit acestuia. Id-ul sesiunii este de asemena stocat intr-un cookie sau este trecut cǎtre urmǎtorul script via URL.

Pe langǎ utilizarea id-ului de sesiunii, purem inregistra variabilele. Aceste variabile pot fi usor extrase si este o sarcinǎ usoarǎ sǎ trecem informatia dintr-un formular in altul.

Id-urile sesiunii

Inainte de a lucra cu variabilele inregistrate, vom vedea un exemplu in care sesiunile sunt utilizate.

<?php

@session_start();

$sid = session_id();

echo 'Apel de la a.php<br>n';

echo 'Acesta este id-ul sesiunii: $sid<br>n';

?>

Primul lucru a fost inceperea sesiunii (pate fi ca un tip de inregistrare). In continuare este generat id-ul sesiunii. Scriptul va afisa informatia pe ecran:

Apel de la a.php
Acesta este id-ul sesiunii: d11b6df32697826c6b784754fdfd45a9

Este afisat id-ul sesiunii. Dacǎ executǎm scriptul incǎ o datǎ, id-ul sesiunii va fi acelasi.

Fisierul a.php este punctul de pornire. Fisierul b.php este al doilea fisier din exemplu. Vom incepe cu a.php:

<?php

@session_start();

$sid = session_id();

echo 'Apel de la a.php<br>n';

echo 'Acesta este id-ul sesiunii: $sid<br><br>n';

echo 'Mergem la b.php: ';

echo '<a href='b.php'>b.php</a>';

?>

Codul pentru b.php este:

<?php

@session_start();

$sid = session_id();

echo 'Apel de la b.php<br>n';

echo 'Aceasta este id-ul sesiunii: $sid<br><br>n';

echo 'Mergem la a.php: ';

echo '<a href='a.php'>a.php</a>';

?>

Dacǎ mergem la a.php, vom vedea id-ul sesiunii. Dacǎ mergem la b.php, acelasi id de sesiune va fi afisat. Dacǎ inchidem brwser-ul si incepem din nou, id-ul sesiunii va fi diferit. Acest lucru este important deoarece ne ajutǎ sǎ aflǎm cand o sesiune este terminatǎ.

Vom modifica b.php din nou:

<?php

setcookie(session_name(),'','','/');

@session_start();

$sid = session_id();

echo 'Apel de la b.php<br>n';

echo 'Acesta este id-ul sesiunii: $sid<br><br>n';

echo 'Mergem la a.php: ';

echo '<a href='a.php'>a.php</a>';

echo '<br>numele sesiunii: '.session_name().'<br>n';

?>

Dupǎ cum putem observa, sesiunile pot fi manipulate folosind cookie. In acest caz este setat un cookie. Cookie are acelasi nume cu sesiunea curentǎ. O sesiuen poate fi usor stearsǎ prin setarea unui cookie la o valoare invalidǎ ca in acest exemplu. Cand rulǎm scriptul putem observa cǎ id-ul sesiunii se schimbǎ cand apelǎm a.php.

PHP oferǎ si o functie numitǎ session_destroy().

Inregistrarea variabilelor

Trecerea datelor de pe un ecran pe altul este o sarcinǎ importantǎ. Librǎriile de sesiuni PHP oferǎ o modalitate usoarǎ pentru a stoca variabilele pe mai multe ecrane. Variabilele pot fi inregistrate intr-o sesiune. Aceste variabile vor fi disponibile automat si pot fi utilizate de utilizator in sigurantǎ.

Vom crea din nou un scenariu din douǎ fisiere. Fisierul a.php este:

<?php

@session_start();

$sid = session_id();

echo 'Apel de la a.php<br>n';

echo 'Acesta este id-ul sesiunii: $sid<br><br>n';

echo 'mesaj: $message<br>n';

$message = 'Inregistrat in a.php<br>n';

session_register('message');

echo 'Mergem la to b.php: ';

echo '<a href='b.php'>b.php</a>';

?>

Dupǎ ce sesiunea porneste, id-ul sesiunii este afisat. In plus, o variabilǎ numitǎ $message va fi afisatǎ pe ecran. In continuare, $message este inregistrat in sesiune. Fisierul b.php este:

<?php

@session_start();

$sid = session_id();

echo 'Apel de la b.php<br>n';

echo 'Acesta este id-ul sesiunii: $sid<br><br>n';

echo 'mesaj: $message<br>n';

$message = 'Inregistrat in b.php<br>n';

session_register('message');

echo 'Mergem la a.php: ';

echo '<a href='a.php'>a.php</a>';

?>

A.php afiseazǎ @message si il inregistreazǎ din nou. Cand rulǎ scriptul, putem observa cǎ o variabilǎ va fi disponibilǎ in urmǎtorul script cand executǎm clic pe legǎturǎ. In a.php, $message, care a fost inregistrat in b.php, va fi afisat. In b.php, variabila definitǎ in a.php va fi afisatǎ. Rezultatul lui b.php va fi:

Apel de la b.php

Acesta este id-ul sesiunii: 963d468e5e21042a6175af7a53f0cc95

message: Inregistrat in a.php

Mergem la a.php:a.php

Singurul lucru care trebuie sǎ-l facem este sǎ-i spunem PHP-ului ce variabile trebuie trecute in urmǎtoare paginǎ. Vom modifica din nou b.php:

<?php

@session_start();

$sid = session_id();

echo 'Apel de la b.php<br>n';

echo 'Acesta este id-ul sesiunii: $sid<br><br>n';

echo 'mesaj: $message<br>n';

echo 'Mergem la a.php: ';

echo '<a href='a.php'>a.php</a>';

?>

De aceastǎ datǎ nu este inregistratǎ nici o variabilǎ in b.php. In acest caz continutul lui $message va fi afisat in "Inregistrat in a.php". Acest lucru este important deoarece datele nu pot fi pierdute cand inregistrǎm variabilele pe mai multe ecrane.

In continuare vom vedea ce se intamplǎ cu array-urile si obiectele:

<?php

@session_start();

$sid = session_id();

$message = unserialize($x);

echo 'mesaj 0: '.$message[0].'<br>';

echo 'mesaj 1: '.$message[1].'<br>';

$message[0] = 'campul numarul unu n';

$message[1] = ' campul numarul doi n';

$x = serialize($message);

echo 'versiune dispusa in serie: <br> $x<br>n';

session_register('x');

echo '<br>Repornim a.php: <br>';

echo '<a href='a.php'>a.php</a>';

?>

Cand lucrǎm cu array-uri este foarte important sǎ le dispunem in serie inainte de a apela session_register; altfel, sistemul nu va merge. Dispunerea in serie inseamnǎ cǎ un obiect sau un array este transformat intr-un sir. In acest mod, poate fi procesat la fel ca alt sir. Aceasta este modalitatea cea mai rapidǎ de a trece obiecte de pe un ecran pe altul. Pentru a elimina un obiect dintr-un sir dispus in serie, putem folosi unserialize.

Rezulatul este:

mesaj 0: campul numarul unu
mesaj 1: campul numarul doi
versiune trimisa in serie:
a:2:

Repornim a.php:
a.php

Dupǎ cum putem observa, valorile sunt disponibile si este afisat sirul dispus in serie. Dacǎ dorim sǎ vedem dacǎ o variabilǎ a fost deja inregistratǎ, putem utiliza comanda session_is_registered. Ex:

<?php

@session_start();

$sid = session_id();

$message = unserialize($x);

$message[0] = ' campul numarul unu n';

$message[1] = ' campul numarul doi n';

$x = serialize($message);

session_register('x');

$val = session_is_registered('x');

echo 'val: $val<br>n';

session_unregister('x');

$val = session_is_registered('x');

echo 'val: $val<br>n';

echo '<br>Repornim a.php: <br>';

echo '<a href='a.php'>a.php</a>';

?>

Rezultatul afiseazǎ ce se intamplǎ dacǎ executǎm scriptul de douǎ ori:

val: 1
val:

Repornim a.php:
a.php

Prima datǎ, session_is_registered returneazǎ 1 deoarece $x a fost inregistrat in linia anterioarǎ. In continuare, $x este neinregistrat, session_is_registered nemaireturnand 1.



Politica de confidentialitate | Termeni si conditii de utilizare



DISTRIBUIE DOCUMENTUL

Comentarii


Vizualizari: 2030
Importanta: rank

Comenteaza documentul:

Te rugam sa te autentifici sau sa iti faci cont pentru a putea comenta

Creaza cont nou

Termeni si conditii de utilizare | Contact
© SCRIGROUP 2024 . All rights reserved