Manuale PHP

Mehdi Achour
Friedhelm Betz
Antony Dovgal
Nuno Lopes
Philip Olson
Georg Richter
Damien Seguy
Jakub Vrana
E diversi altri

A cura di

Gabor Hojtsy

A cura di

Luca Perugini
Simone Cortesi
Marco Cucinato
Darvin Andrioli
Tradotto con la collaborazione di:
Massimo Colombo
Marco De Nittis
Fabio Gandola
Sergio Marchesini
Alan D'Angelo
Giacomo Tesio
Marco Spisto
Gabriele Scaroni
Mariano Calandra
Rocco Curcio
Luca Costantino
Fernando Fusano
Andrea Paramithiotti

11-03-2005

Copyright

Questo manuale è © Copyright 1997-2005 del Gruppo di Documentazione PHP. Questo manuale può essere redistribuito secondo i termini e le condizioni indicate dalla Open Publication License, v1.0 o successive (l'ultima versione è disponibile a http://www.opencontent.org/openpub/).

La distribuzione di versioni modificate di questo manuale è proibita senza l'esplicito consenso dei detentori del copyright.

La distribuzione di parte o di derivati da parti del manuale in qualsiasi forma di libro standard (cartaceo) è proibita senza un preventivo permesso ottenuto dai detentori del copyright.

In caso si desideri distribuire o pubblicare questo documento, totalmente od in parte, sia in versione integrale o modificata, oppure se si hanno dubbi, contattare i detentori del copyright a phpdoc@lists.php.net. Nota: questo indirizzo porta ad una mailing list pubblica.

La sezione 'Estendere PHP 4.0' di questo manuale è copyright © 2000 della Zend Technologies, Ltd. Questo materiale può essere distribuito solo secondo i termini e le condizioni della Open Publication License, v1.0 o successiva (la versione più recente è al momento disponibile qui http://www.opencontent.org/openpub/).


Sommario
Prefazione
Authors and Contributors
I. Guida Rapida
1. Introduzione
2. Una semplice introduzione
II. Installazione e configurazione
3. General Installation Considerations
4. Installation on Unix systems
5. Installation on Mac OS X
6. Installation on Windows systems
7. Installation of PECL extensions
8. Problems?
9. Runtime Configuration
III. Struttura del Linguaggio
10. Sintassi Fondamentale
11. Types
12. Variables
13. Costanti
14. Expressions
15. Operatori
16. Strutture di controllo
17. Funzioni
18. Classi e Oggetti
19. Classes and Objects (PHP 5)
20. Exceptions
21. Spiegazioni sui riferimenti
IV. Security
22. Introduction
23. General considerations
24. Installed as CGI binary
25. Installed as an Apache module
26. Filesystem Security
27. Database Security
28. Error Reporting
29. Using Register Globals
30. User Submitted Data
31. Magic Quotes
32. Hiding PHP
33. Keeping Current
V. Caratteristiche
34. Autenticazione HTTP usando PHP
35. Cookies
36. Sessions
37. Dealing with XForms
38. Caricare file
39. Utilizzo di file remoti
40. Gestione della connessione
41. Connessioni Persistenti ai Database
42. Modalità sicura (Safe mode)
43. Utilizzo di PHP da linea di comando
VI. Guida Funzioni
I. Funzioni Apache
II. Advanced PHP debugger
III. Funzioni di Array
IV. Funzioni Aspell [deprecated]
V. Funzioni Matematiche BCMath a precisione arbitraria
VI. PHP bytecode Compiler
VII. Funzioni di compressione Bzip2
VIII. Funzioni Calendar
IX. Funzioni API CCVS [deprecate]
X. Classkit Functions
XI. Funzioni per Classi/Oggetti
XII. Funzioni di supporto COM per Windows
XIII. Funzioni ClibPDF
XIV. Funzioni di Crack
XV. Funzioni di tipo dei caratteri
XVI. Funzioni CURL, Client URL Library
XVII. Funzioni di pagamento Cybercash
XVIII. Funzioni di amministrazione Cyrus IMAP
XIX. Funzioni di Data e Ora
XX. Database (dbm-style) Abstraction Layer Functions
XXI. Funzioni dBase
XXII. Funzioni DBM
XXIII. DB++ Functions
XXIV. dbx Functions
XXV. Funzioni per l'IO diretto
XXVI. Funzioni per le directory
XXVII. Funzioni DOM
XXVIII. Funzioni DOM XML
XXIX. Funzioni .NET
XXX. Funzioni di gestione degli errori e di logging
XXXI. Funzioni per l'esecuzione di programmi
XXXII. Exif Functions
XXXIII. File Alteration Monitor Functions
XXXIV. FrontBase Functions
XXXV. Funzioni Forms Data Format
XXXVI. Funzioni filePro
XXXVII. Filesystem Functions
XXXVIII. Funzioni FriBiDi
XXXIX. Funzioni FTP
XL. Function Handling Functions
XLI. Gettext
XLII. Funzioni GMP
XLIII. Funzioni HTTP
XLIV. Hyperwave Functions
XLV. Hyperwave API Functions
XLVI. Funzioni Firebird/InterBase
XLVII. ICAP Functions [deprecated]
XLVIII. Iconv
XLIX. ID3 Functions
L. Informix Functions
LI. Funzioni di Amministrazione IIS
LII. Funzioni per le immagini
LIII. IMAP, POP3 and NNTP Functions
LIV. PHP Opzioni&Informazioni
LV. Ingres II Functions
LVI. IRC Gateway Functions
LVII. PHP / Java Integration
LVIII. LDAP Functions
LIX. libxml Functions
LX. Funzioni LZF
LXI. Funzioni di Mail
LXII. mailparse Functions
LXIII. Funzioni Matematiche
LXIV. MaxDB PHP Extension
LXV. Multibyte String Functions
LXVI. MCAL Functions
LXVII. Mcrypt Encryption Functions
LXVIII. MCVE Payment Functions
LXIX. Memcache Functions
LXX. Mhash Functions
LXXI. Mimetype Functions
LXXII. Ming functions for Flash
LXXIII. Miscellaneous Functions
LXXIV. mnoGoSearch Functions
LXXV. Mohawk Software Session Handler Functions
LXXVI. mSQL Functions
LXXVII. Funzioni per Microsoft SQL Server
LXXVIII. muscat Functions
LXXIX. MySQL Functions
LXXX. Improved MySQL Extension
LXXXI. Ncurses Terminal Screen Control Functions
LXXXII. Funzioni di rete
LXXXIII. YP/NIS Functions
LXXXIV. Lotus Notes Functions
LXXXV. NSAPI-specific Functions
LXXXVI. Object Aggregation/Composition Functions
LXXXVII. Funzioni Oracle 8
LXXXVIII. OpenAL Audio Bindings
LXXXIX. OpenSSL Functions
XC. Funzioni Oracle
XCI. Output Control Functions
XCII. Proprietà object e method call overloading
XCIII. Ovrimos SQL Functions
XCIV. Parsekit Functions
XCV. Process Control Functions
XCVI. Funzioni per le espressioni regolari (Perl compatibili)
XCVII. PDF functions
XCVIII. PDO Functions
XCIX. Verisign Payflow Pro Functions
C. Funzioni PostgreSQL
CI. Funzioni POSIX
CII. Funzioni per le Stampanti
CIII. Pspell Functions
CIV. Funzioni qtdom
CV. Rar Functions
CVI. GNU Readline
CVII. GNU Recode Functions
CVIII. Funzioni per le espressioni regolari (POSIX estesa)
CIX. Funzioni per i semafori, la memoria condivisa ed IPC
CX. SESAM Database Functions
CXI. Funzioni di gestione della sessione
CXII. Funzioni relative alla memoria condivisa
CXIII. SimpleXML functions
CXIV. Funzioni per SNMP
CXV. SOAP Functions
CXVI. Funzioni relative ai Socket
CXVII. Standard PHP Library (SPL) Functions
CXVIII. SQLite
CXIX. Secure Shell2 Functions
CXX. Stream Functions
CXXI. Stringhe
CXXII. Shockwave Flash Functions
CXXIII. Sybase Functions
CXXIV. TCP Wrappers Functions
CXXV. Tidy Functions
CXXVI. Tokenizer Functions
CXXVII. Funzioni ODBC (Unificate)
CXXVIII. URL Functions
CXXIX. Funzioni di Variabili
CXXX. Funzioni vpopmail
CXXXI. Funzioni W32api
CXXXII. WDDX Functions
CXXXIII. xattr Functions
CXXXIV. xdiff Functions
CXXXV. Funzioni relative al parser XML
CXXXVI. Funzioni XML-RPC
CXXXVII. XSL functions
CXXXVIII. Funzioni XSLT
CXXXIX. YAZ Functions
CXL. Funzioni per File Zip (Accesso di Sola Lettura)
CXLI. Funzioni di compressione Zlib
VII. Zend API
44. Overview
45. Extension Possibilities
46. Source Layout
47. PHP's Automatic Build System
48. Creating Extensions
49. Using Extensions
50. Troubleshooting
51. Source Discussion
52. Accepting Arguments
53. Creating Variables
54. Duplicating Variable Contents: The Copy Constructor
55. Returning Values
56. Printing Information
57. Startup and Shutdown Functions
58. Calling User Functions
59. Initialization File Support
60. Where to Go from Here
61. Reference: Some Configuration Macros
62. API Macros
VIII. PHP API: Interfacce per gli autori di estensioni
63. Streams API for PHP Extension Authors
IX. FAQ: Frequently Asked Questions (domande e risposte ricorrenti)
64. Informazioni Generali
65. Mailing list
66. Ottenere PHP
67. Database issues
68. Installazione
69. Problemi di installazione
70. Using PHP
71. PHP and HTML
72. PHP e COM
73. PHP e gli altri linguaggi di programmazione
74. Migrazione da PHP 2 a PHP 3
75. Migrazione da PHP3 a PHP4
76. Migrating from PHP 4 to PHP 5
77. Domande varie
X. Appendici
A. History of PHP and related projects
B. Migrating from PHP 4 to PHP 5
C. Migrating from PHP 3 to PHP 4
D. Migrazione da PHP/FI 2 a PHP 3
E. Debugging PHP
F. Extending PHP 3
G. Configure options
H. php.ini directives
I. Lista dei sinonimi delle funzioni PHP
J. Parole riservate nel PHP
K. List of Resource Types
L. List of Supported Protocols/Wrappers
M. List of Available Filters
N. List of Supported Socket Transports
O. PHP type comparison tables
P. List of Parser Tokens
Q. Informazioni sul manuale
R. Open Publication License
S. Indice delle Funzioni
T. Informazioni mancanti

Prefazione

PHP, che significa "PHP: Hypertext Preprocessor", è un linguaggio di scripting general-purpose Open Source molto utilizzato, è specialmente indicato per lo sviluppo Web e può essere integrato nell'HTML. La sua sintassi è basata su quella di C, Java e Perl, ed è molto semplice da imparare. L'obiettivo principale del linguaggio è quello di permettere agli sviluppatori web di scrivere velocemente pagine web dinamiche, ma con PHP si possono fare molte altre cose.

Questo manuale consiste principalmente in un elenco commentato di funzioni, ma contiene anche una guida al linguaggio, la spiegazione di alcune delle principali caratteristiche e altre informazioni aggiuntive.

Il manuale è fornito in diversi formati qui: ???. Maggiori informazioni su come questo manuale viene sviluppato possono essere trovate nell'appendice 'Informazioni sul Manuale'. Se si è interessati alla storia del PHP, leggere l'appendice.


Authors and Contributors

We highlight the currently most active people on the manual frontpage, but there are many more contributors who currently help in our work or provided a great amount of help to the project in the past. There are a lot of unnamed people who help out with their user notes on manual pages, which continually get included in the references, the work of whom we are also very thankful. All the lists provided below are in alphabetical order.


Authors and Editors

The following contributors should be recognized for the impact they have made and/or continue to make by adding content to the manual: Jouni Ahto, Alexander Aulbach, Daniel Beckham, Stig Bakken, Jesus M. Castagnetto, Ron Chmara, John Coggeshall, Simone Cortesi, Markus Fischer, Wez Furlong, Sara Golemon, Rui Hirokawa, Brad House, Moriyoshi Koizumi, Rasmus Lerdorf, Andrew Lindeman, Stanislav Malyshev, Rafael Martinez, Yasuo Ohgaki, Derick Rethans, Sander Roobol, Egon Schmid, Thomas Schoefbeck, Sascha Schumann, Lars Torben Wilson, Jim Winstead, Jeroen van Wolffelaar e Andrei Zmievski.

The following contributors have done significant work editing the manual: Stig Bakken, Hartmut Holzgraefe e Egon Schmid.


User Note Maintainers

The currently most active maintainers are: Mehdi Achour, Friedhelm Betz, Vincent Gevers, Aidan Lister, Nuno Lopes e Tom Sommer.

These people have also put a lot of effort into managing user notes: Daniel Beckham, Victor Boivie, Jesus M. Castagnetto, Nicolas Chaillan, Ron Chmara, James Cox, Sara Golemon, Zak Greant, Szabolcs Heilig, Oliver Hinckel, Hartmut Holzgraefe, Rasmus Lerdorf, Andrew Lindeman, Maxim Maletsky, James Moore, Sebastian Picklum, Derick Rethans, Sander Roobol, Damien Seguy, Jason Sheets, Jani Taskinen, Yasuo Ohgaki, Philip Olson, Lars Torben Wilson, Jim Winstead, Jared Wyles e Jeroen van Wolffelaar.

I. Guida Rapida


Capitolo 1. Introduzione

Che cos'è il PHP?

PHP (acronimo ricorsivo per "PHP: Hypertext Preprocessor") è un linguaggio di scripting general-purpose Open Source molto utilizzato, è specialmente indicato per lo sviluppo Web e può essere integrato nell'HTML.

Risposta banale, ma che cosa significa? Un esempio:

Esempio 1-1. Un esempio introduttivo

<html>
    <head>
        <title>Esempio</title>
    </head>
    <body>

        <?php 
        echo "Ciao, sono uno script PHP!"; 
        ?>

    </body>
</html>

Notate come questo esempio è differente da uno script scritto in altri linguaggi tipo Perl o C -- invece di scrivere un programma con parecchi comandi per produrre HTML, si scrive in HTML con qualche comando immerso per ottenere dei risultati (in questo semplice esempio, la visualizzazione di una frase). Il codice PHP è delimitato da speciali start ed end tag che ne indicano l'inizio e la fine e che consentono di passare dal modo HTML al modo PHP.

Ciò che distingue PHP da altri linguaggi di scripting del tipo client-side JavaScript è che il codice viene eseguito nel server. Per avere uno script simile a quello sopra nel vostro server, il client dovrebbe ricevere il risultato ottenuto con lo script, senza sapere mai quali sono le funzioni eseguite. Potete persino configurare il vostro web server per processare tutte i vostri file HTML con PHP ed allora non ci sarebbe realmente alcun modo per gli utenti di sapere cosa avete sul vostro server.

La cosa più interessante nell'uso di PHP è che si tratta di un linguaggio estremamente semplice per il neofita, ma che, tuttavia, offre molte prestazioni avanzate al programmatore di professione. Non lasciatevi impressionare dalla lunga lista delle potenzialità di PHP. In poco tempo potrete iniziare a creare velocemente semplici scripts.

Sebbene lo sviluppo di PHP abbia come obiettivo lo scripting server-side, si può fare molto di più con esso. Leggete, e consultate la sezione Che cosa può fare PHP?.


Che cosa può fare PHP?

Qualsiasi cosa. PHP ha come obiettivo principale lo scripting server-side, per cui può fare tutto ciò che può fare un qualunque programma CGI, come raccogliere dati da un form, generare pagine dai contenuti dinamici, oppure mandare e ricevere cookies. Ma PHP può fare molto di più.

Esistono tre campi principali in cui vengono usati gli scripts PHP.

  • Lo scripting server-side. Questo è il campo più tradizionale ed il maggiore obiettivo del PHP. Per fare questo lavoro occorrono tre cose. Il parser PHP (CGI o server module), un webserver ed un browser web. Occorre avviare il server web con un'installazione di PHP attiva. Si può accedere all'output del programma PHP con un browser web e vedere la pagina PHP tramite il server. Consultate la sezione Istruzioni per l'installazione per ulteriori informazioni.

  • Lo scripting di righe di comando. Si può creare uno script PHP da usare senza alcun server o browser. Per usarlo in questo modo, l'unica cosa necessaria è un parser PHP. Questo tipo di utilizzo è ideale per gli scripts eseguiti con cron (task scheduler di Windows) o per tasks di solo testo. Vedere la sezione Uso di righe di comando in PHP per maggiori informazioni.

  • La creazione di applicazioni client-side GUI. Probabilmente PHP non è il linguaggio più adatto per scrivere applicazioni windowing, ma, se lo si conosce molto bene, e se se ne vogliono usare delle caratteristiche avanzate in applicazioni client-side, si può anche adoperare PHP-GTK per scrivere questo tipo di pogrammi. Allo stesso modo, c'è anche la possibilità di scrivere applicazioni cross-platform. PHP-GTK è un'estensione di PHP non reperibile nella grande distribuzione. Se vi interessa, visitate il sito web.

PHP può essere usato su tutti i principali sistemi operativi, inclusi Linux, molte varianti di Unix (compresi HP-UX, Solaris e OpenBSD), Microsoft Windows, MacOS X, MacOS Xserver, RISC OS, e probabilmente altri. Inoltre supporta anche la maggior parte dei server web esistenti. Ciò comprende Apache, Microsoft Internet Information Server, Personal Web Server, i servers Netscape ed iPlanet, Oreilly Website Pro Server, Caudium, Xitami, OmniHTTPd, e molti altri. Per la maggioranza dei servers PHP ha un modulo, per gli altri che supportano lo standard CGI, può funzionare come un processore CGI.

Pertanto, con PHP si ha la libertà di scegliere praticamente qualsiasi sistema operativo e qualsiasi server web. Inoltre, si può anche scegliere se fare uso di una programmazione procedurale oppure orientata agli oggetti, o una combinazione di entrambe. Sebbene non tutte le caratteristiche standard di OOP siano realizzate dalla versione corrente di PHP, molte librerie di codice e grandi applicazioni (compresa PEAR library) sono state scritte usando codice OOP.

Con PHP non siete limitati soltanto ad un output in HTML. Le possibilità di PHP, infatti, includono l'abilità di generare immagini, files PDF e perfino filmati Flash al volo (utilizzando libswf e Ming). Sarete in grado di generare facilmente qualsiasi testo, come XHTML e qualsiasi altro file XML. PHP può autogenerare questi file, e salvarli nel file system, piuttosto che eseguire un printing esterno, o creare server-side cache per contenuti dinamici.

Una delle caratteristiche più importanti e significative di PHP è la possibilit` di supportare una completa gamma di databases. Scrivere una pagina web collegata ad un database è incredibilmente semplice. Attualmente sono supportati i seguenti database:

Adabas DIngresOracle (OCI7 and OCI8)
dBaseInterBaseOvrimos
EmpressFrontBasePostgreSQL
FilePro (read-only)mSQLSolid
HyperwaveDirect MS-SQLSybase
IBM DB2MySQLVelocis
InformixODBCUnix dbm

Esiste anche un'estensione DBX database abstraction extension, che vi permette di usare in modo trasparente qualsiasi database da essa supportato. Inoltre PHP supporta ODBC, lo standard di collegamento con i database, pertanto è possibile collegarsi con qualsiasi database che supporti questo standard mondiale.

PHP fa anche da supporto per dialogare con altri servizi utilizzando i protocolli del tipo LDAP, IMAP, SNMP, NNTP, POP3, HTTP, COM (in Windows) e innumerevoli altri. Potete anche aprire network sockets ed interagire usando qualsiasi altro protocollo. Inoltre supporta l'interscambio di dati complessi WDDX tra, virtualmente, tutti i linguaggi di programmazione web. A proposito di interconessioni, PHP supporta l'installazione dei JavaObjects e l'utilizzo di questi come oggetti PHP in modo trasparente. Si può anche usare la nostra estensione CORBA per accedere ad oggetti remoti.

PHP possiede alcune caratteristiche molto utili per la gestione del testo, da POSIX Extended o Perl regular expressions al parsing di documenti XML. Per fare il parsing ed accedere ai documenti XML, supportiamo gli standard SAX e DOM. Si può usare la nostra estensione XSLT per trasformare i documenti XML.

Se si usa PHP nel campo dell'E-commerce, si avranno a disposizione funzioni utili per i programmi di pagamento online, come: Cybercash, CyberMUT, Verysign Payflow Pro e CCVS.

L'ultimo, ma di non poca importanza, PHP ha molte altre estensioni interessanti, come funzioni per motori di ricerca mnoGoSearch, le funzioni IRC Gateway, molte utilità di compressione (gzip, bz2), conversione dei calendari, traduzione...

Come si può notare, questa pagina non è sufficiente per elencare tutte le funzioni che PHP offre. Per approfondire il discorso sulle suddette caratteristiche, consultate le sezioni Installazione di PHP, e function reference


Capitolo 2. Una semplice introduzione

Di seguito, in una breve e semplice introduzione, vorremmo mostrare alcuni esempi per l'utilizzo di PHP. Essi sono relativi soltanto alla creazione dinamica di pagine web, anche se PHP non ha funzionalità limitate esclusivamente alla creazione delle sole pagine web. Fare riferimento alla sezione intitolata Cosa può fare PHP per avere ulteriori informazioni.

Le pagine web create con PHP vengono trattate come normali pagine HTML e possono essere create e modificate nello stesso modo in cui si sviluppano normali pagine HTML.


Di cosa ho bisogno?

In questo tutorial assumiamo che il vostro server abbia il suporto PHP attivato e che tutti i file con estensione .php vengano gestiti da questo. Quasi in tutti i server questa è l'estensione di default per i file PHP., ma consultatevi col vostro system administrator per sicurezza. Se il vostro server supporta PHP, allora, non è necessario fare nulla. Semplicemente create i vostri file .php e scaricateli nella vostra directory web, il server le analizzerà e le eseguirà magicamente. Non è necessario compilare nulla nè installare strumenti aggiuntivi. Si pensi ai file PHP come a dei semplici file HTML con una intera famiglia aggiuntiva di magici tags che consentono di fare ogni sorta di cose.


La prima pagina PHP

Creare un file con nome ciao.php nella directory del web server che abbia il seguente contenuto:

Esempio 2-1. Il nostro primo script PHP: ciao.php

<html>
 <head>
  <title>Test PHP</title>
 </head>
 <body>
 <?php echo "Hello World!<p>"; ?>
 </body>
</html>

L'output di questo script sarà:
<html>
 <head>
  <title>Test PHP</title>
 </head>
 <body>
Hello World!<p>
 </body>
</html>

Si noti che questo file non è come uno script CGI. Il file non necessita in alcun modo di essere eseguibile o speciale in alcuna maniera. Si pensi ad esso come ad un normale file HTML nel quale sono contenuti uno speciale set di tags che permettono di eseguire una moltitudine di cose interessanti.

Questo programma è molto semplice e sicuramente non era necessario fare ricorso a PHP per creare una pagina come quella. Tutto ciò che essa fa è di visualizzare: Hello World! usando la funzione echo() di PHP.

Se si è provato questo esempio e non ha dato alcun output, o è apparso un pop-up che chiedeva se scaricare la pagina, o se è apparso il file come testo, probabilmente che il server su cui si stanno effettuando le prove non ha abilitato PHP. Provare a chiedere al proprio amministratore di sistema di abilitarlo per voi usando il capitolo del manuale dedicato all'Installazione. Se si vogliono sviluppare in locale script PHP, fare riferimento alla sezione download. Si può sviluppare senza problemi sul proprio Sistema Operativo in locale, è bene installare anche un web server.

L'obiettivo dell'esempio è quello di mostrare il formato speciale dei tag PHP. In questo esempio abbiamo usato <?php per indicare l'inizio di un tag PHP. Quindi abbiamo scritto la funzione PHP e abbiamo lasciato la modalità PHP usando il tag di chiusura, ?>. All'interno di un file HTML si può entrare ed uscire dalla modalità PHP quante volte si desidera.

Nota riguardo gli editor di testo: Esistomo molti editor di testo e Integrated Development Environment (IDE) che possono essere usati per creare, modificare e gestire file PHP. Una lista parziale di questi strumenti è disponibile qui: PHP Editor's List. Se si desidera suggerire un nuovo programma, visitare la pagina sopra e chiedere al curatore di aggiungerlo alla lista.

Nota riguardo i Word Processor: Word processor quali StarOffice Writer, Microsoft Word e Abiword non sono una buona scelta per modificare i file PHP.

Se si vogliono provare comunque per scrivere questo script di test, ci si deve assicurare di salvare il file come SOLO TESTO, altrimenti PHP non sarà in grado di leggerlo e quindi non riuscirà ad eseguire lo script.

Nota riguardo Blocco Note di Windows: Se si scrive codice usando l'applicazione di Windows Blocco Note, occorre assicurarsi che i file vengano salvati con estensione .php. (Blocco Note aggiunge automaticamente l'estensione .txt ai file, a meno che non si intraprenda uno dei passi descritti di seguito.)

Quando si salva il file e viene chiesto il nome da assegnargli, scrivere il nome fra virgolette (ad esempio: "ciao.php").

In alternativa, si può cliccare sul menu a tendina 'Documenti di Testo' nella finestra di salvataggio e cambiare l'impostazione in "Tutti i File". A quel punto si può inserire il nome del file, senza usare le virgolette.


Qualcosa di utile

Andiamo a fare qualcosa di leggermente più utile. Andremo a controllare che tipo di browser sta utilizzando la persona che visita le nostre pagine. Per fare questo si andrà a controllare la stringa dell'user agent che il browser invia come parte della richiesta HTTP. Quest'informazione viene inviata in una variabile. Le Variabili iniziano sempre con il simbolo di dollaro $ in PHP. La variabile alla quale ci riferiamo adesso è $_SERVER["HTTP_USER_AGENT"].

Note sulle variabili Autoglobali di PHP: $_SERVER è una variabile speciale riservata a PHP la quale contiene tutte le informazioni relative al Web Server. È conosciuta come Variabile autoglobale (o Superglobale). Per maggiori informazioni è possibile vedere la pagina del manuale relativa alle Variabili Autoglobali. Questo tipo di variabili sono state introdotte nella versione 4.1.0 di PHP. Nelle versioni precedenti abbiamo utilizzato le ormai vecchie $HTTP_SERVER_VARS, oggi in disuso, anche se queste continuano ad esistere. (Potete guardare nelle note del vecchio codice.)

Per visualizzare questa variabile, dobbiamo semplicemente:

Esempio 2-2. Stampare video una variable (elemento d'Array)

<?php echo $_SERVER["HTTP_USER_AGENT"]; ?>

L'output (risultato) di questo script potrebbe essere:
Mozilla/4.0 (compatible; MSIE 5.01; Windows NT 5.0)

Ci sono molti types (tipi) di variabili disponibili in PHP. Nell'esempio di sopra abbiamo stampato un elemento di un Array. Gli Array possono essere molto utili.

$_SERVER è soltanto una variabile che automaticamente viene resa diponibile da PHP. È possibile visualizzare una lunga lista nella sezione Variabili riservate del manuale oppure ottenere la lista completa creando un file php nella seguente forma:

Esempio 2-3. Mostrare tutte le variabili predefinite di PHP con phpinfo()

<?php phpinfo(); ?>

Se caricate questo documento da un browser riceverete una pagina piena d'informazioni circa PHP, così come la lista di tutte le variabili disponibili.

Potete mettere dichiarazioni multipli di PHP all'interno di un tag di PHP e generare piccoli blocchi di codice che fanno di più di un singolo echo. Per esempio, se desiderassimo controllare per vedere se l'utente usa Internet Explorer potremmo fare qualcosa come questo:

Esempio 2-4. Esempi usando le strutture di controllo e le funzioni

<?php
if (strstr($_SERVER["HTTP_USER_AGENT"], "MSIE")) {
	echo "Stai usando Internet Explorer<br />";
}
?>

L'output di esempio di questo script potrebbe essere:
Stai usando Internet Explorer<br />

Qui introduciamo una coppia di nuovi concetti. Abbiamo la dichiarazione if (se). Se avete una conoscenza con la sintassi di base usata dal linguaggio C questo dovrebbe sembrare logico per voi. Se non conoscete abbastanza C od un altro linguaggio che utilizza la sintassi qui sopra descritta, dovreste probabilmente prendere qualsiasi libro introduttivo di PHP e leggere i primi capitoli, o leggere la parte del manuale relativa ai Riferimenti del Linguaggio. Potete trovare una lista dei libri di PHP su http://www.php.net/books.php.

Il secondo concetto che abbiamo introdotto era la chiamata alla funzione strstr(). Questa è una funzione sviluppata in PHP che cerca una stringa all'interno di un'altra stringa. In questo caso abbiamo cercato "MSIE" all'interno della stringa $_SERVER["HTTP_USER_AGENT"]. Se la stringa viene trovata, la funzione restituisce TRUE altrimenti, FALSE. Se restituisce TRUE, la dichiarazione if viene valuta come TRUE ed il codice all'interno dei relativi {braces} (sostegni) sarà eseguito. Altrimenti, non esegue altro. Sentitevi liberi di generare esempi simili, con if, else (altrimenti) ed altre funzioni quali strtoupper() e strlen(). Ogni pagina del manuale, relativa a queste funzioni contiene anche degli esempi pratici.

Possiamo fare un passo avanti e mostrarvi come potete entrare ed uscite dal modo PHP anche dall' interno di un blocco PHP:

Esempio 2-5. Intercalare i modi PHP e HTML

<?php
if (strstr($_SERVER["HTTP_USER_AGENT"], "MSIE")) {
?>
<h3>strstr dovrebbe ritornare true</h3>
<center><b>Stai usando Internet Explorer</b></center>
<?php
} else {
?>
<h3>strstr dovrebbe ritornare false</h3>
<center><b>Non stai usando Internet Explorer</b></center>
<?php
}
?>

L'output di esempio di questo script potrebbe essere:
<h3>strstr dovrebbe ritornare true</h3>
<center><b>Stai usando Internet Explorer</b></center>

Invece di usare la dichiarazione echo per fare l'output di qualcosa, saltiamo fuori dal modo PHP inviando soltanto HTML puro. Il punto importante da notare qui è che il flusso logico dello script rimane intatto. Solo uno dei blocchi di di HTML finirà per essere inviato come risposta, dipendendo se strstr() ritorna TRUE o FALSE in altre parole, se la stringa MSIE viene trovata o meno.


Trattare con i Form

Una delle caratteritiche più forti di PHP è il modo in cui gestisce i form. Il concetto da comprendere principalmente è che qualsiasi elemento di un form sarà automaticamente disponibile per i vostri script PHP. Per maggiori informazioni ed esempi relativi all'utilizzo dei form consultate la sezione del manuale che si riferisce a le Variabili al di fuori di PHP. A seguire un esempio di un form HTML:

Esempio 2-6. Un semplice form HTML

<form action="action.php" method="POST">
 Il tuo Nome: <input type="text" name="name" value="" />
 La tua et&agrave;: <input type="text" name="age" value ="" />
 <input type="submit">
</form>

Questo form non ha niente di speciale. È un semplice form in HTML che non presenta nessun tipo di tags particolari. Quando l'utente riempie questo form e preme il pulsante submit, viene richiamata la pagina action.php. In questo file il risultato sarà qualcosa di simile:

Esempio 2-7. La stampa video di dati dal nostro form

Ciao <?php echo $_POST["name"]; ?>.
La tua età è di <?php echo $_POST["age"]; ?> anni.

Ecco un possibile output di questo script:
Ciao Joe.
La tua et&agrave; &egrave; di 22 anni.

Ciò che avviene dovrebbe risultare ovvio. Non c' è altro da aggiungere. Le variabili $_POST["name"] e $_POST["age"] vengono impostate automaticamente dal PHP. Prima avevamo usato la variabile autoglobal $_SERVER, ora invece abbiamo introdotto la variabile autoglobal $_POST che contiene tutti i dati di tipo POST. Notate che il metodo del nostro form è il POST. Se usassimo il metodo GET le informazioni ricavate dal nostro form si troverebbero invece in $_GET. Si può anche usare la variabile $_REQUEST se la provenienza dei dati richiesti non ci interessa. Questa variabile contiene un misto di dati GET, POST, COOKIE e FILE. Vedere anche la funzione import_request_variables().


L' uso di vecchi codici con le nuove versioni di PHP

Da quando il PHP è divenuto un linguaggio di scripting popolare, esistono più fonti che producono listati di codice che si possono adoperare nei propri scripts. La maggioranza degli sviluppatori del PHP ha cercato di renderlo compatibile con le versioni precedenti, perciò uno script creato per una vecchia versione del PHP dovrebbe girare senza modifiche (in teoria) in una più recente, ma in pratica spesso possono servire delle correzioni.

Ecco due delle più importanti modifiche apportate al vecchio codice:

  • Il disuso dei vecchi arrays $HTTP_*_VARS (che devono essere dichiarati global quando vengano adoperati all' interno di una funzione o di un metodo). L' introduzione in PHP 4.1.0 dei seguenti autoglobal arrays: $_GET, $_POST, $_COOKIE, $_SERVER, $_ENV, $_REQUEST, and $_SESSION. I vecchi arrays $HTTP_*_VARS quali $HTTP_POST_VARS, invece, continuano ad essere adoperati fin da PHP3.

  • Le variabili esterne non vengono più registrate nel global scope per default. In altre parole, da PHP 4.2.0 la direttiva PHP register_globals è off per default in php.ini. Il metodo consigliato per accedere a questi valori è quello che fa uso degli arrays autoglobali suddetti. Scripts, libri e tutorials più vecchi devono attenersi a queste direttive. Se, per esempio, qualcuno potesse usare $id dall'URL http://www.example.com/foo.php?id=42. La variabile, $_GET['id'] sarebbe disponibile indifferentemente del fatto che sia on od off.

Per ulteriori dettagli su queste innovazioni, vedere la sezione sulle variabili predefinite ed i links ad essa connessi.


E poi?

Con quello che sapete ora dovreste essere in grado di comprendere la maggior parte del manuale ed anche i vari scripts di esempio reperibili nelle raccolte di esempi. Inoltre potete trovarne altri sui siti web di php.net nella sezione links: http://www.php.net/links.php.


Capitolo 3. General Installation Considerations

Before starting the installation, first you need to know what do you want to use PHP for. There are three main fields you can use PHP, as described in the What can PHP do? section:

  • Server-side scripting

  • Command line scripting

  • Client-side GUI applications

For the first and most common form, you need three things: PHP itself, a web server and a web browser. You probably already have a web browser, and depending on your operating system setup, you may also have a web server (e.g. Apache on Linux and MacOS X; IIS on Windows). You may also rent webspace at a company. This way, you don't need to set up anything on your own, only write your PHP scripts, upload it to the server you rent, and see the results in your browser.

While setting up the server and PHP on your own, you have two choices for the method of connecting PHP to the server. For many servers PHP has a direct module interface (also called SAPI). These servers include Apache, Microsoft Internet Information Server, Netscape and iPlanet servers. Many other servers have support for ISAPI, the Microsoft module interface (OmniHTTPd for example). If PHP has no module support for your web server, you can always use it as a CGI or FastCGI processor. This means you set up your server to use the CGI executable of PHP to process all PHP file requests on the server.

If you are also interested to use PHP for command line scripting (e.g. write scripts autogenerating some images for you offline, or processing text files depending on some arguments you pass to them), you always need the command line executable. For more information, read the section about writing command line PHP applications. In this case, you need no server and no browser.

With PHP you can also write desktop GUI applications using the PHP-GTK extension. This is a completely different approach than writing web pages, as you do not output any HTML, but manage windows and objects within them. For more information about PHP-GTK, please visit the site dedicated to this extension. PHP-GTK is not included in the official PHP distribution.

From now on, this section deals with setting up PHP for web servers on Unix and Windows with server module interfaces and CGI executables. You will also find information on the command line executable in the following sections.

PHP source code and binary distributions for Windows can be found at http://www.php.net/downloads.php. We recommend you to choose a mirror nearest to you for downloading the distributions.


Capitolo 4. Installation on Unix systems

This section will guide you through the general configuration and installation of PHP on Unix systems. Be sure to investigate any sections specific to your platform or web server before you begin the process.

As our manual outlines in the General Installation Considerations section, we are mainly dealing with web centric setups of PHP in this section, although we will cover setting up PHP for command line usage as well.

There are several ways to install PHP for the Unix platform, either with a compile and configure process, or through various pre-packaged methods. This documentation is mainly focused around the process of compiling and configuring PHP. Many Unix like systems have some sort of package installation system. This can assist in setting up a standard configuration, but if you need to have a different set of features (such as a secure server, or a different database driver), you may need to build PHP and/or your webserver. If you are unfamiliar with building and compiling your own software, it is worth checking to see whether somebody has already built a packaged version of PHP with the features you need.

Prerequisite knowledge and software for compiling:

  • Basic Unix skills (being able to operate "make" and a C compiler)

  • An ANSI C compiler

  • flex: Version 2.5.4

  • bison: Version 1.28 (preferred), 1.35, or 1.75

  • A web server

  • Any module specific components (such as gd, pdf libs, etc.)

The initial PHP setup and configuration process is controlled by the use of the commandline options of the configure script. You could get a list of all available options along with short explanations running ./configure --help. Our manual documents the different options separately. You will find the core options in the appendix, while the different extension specific options are descibed on the reference pages.

When PHP is configured, you are ready to build the module and/or executables. The command make should take care of this. If it fails and you can't figure out why, see the Problems section.


Apache 1.3.x on Unix systems

This section contains notes and hints specific to Apache installs of PHP on Unix platforms. We also have instructions and notes for Apache 2 on a separate page.

You can select arguments to add to the configure on line 10 below from the list of core configure options and from extension specific options described at the respective places in the manual. The version numbers have been omitted here, to ensure the instructions are not incorrect. You will need to replace the 'xxx' here with the correct values from your files.

Esempio 4-1. Installation Instructions (Apache Shared Module Version) for PHP

1.  gunzip apache_xxx.tar.gz
2.  tar -xvf apache_xxx.tar
3.  gunzip php-xxx.tar.gz
4.  tar -xvf php-xxx.tar
5.  cd apache_xxx
6.  ./configure --prefix=/www --enable-module=so
7.  make
8.  make install
9.  cd ../php-xxx

10. Now, configure your PHP.  This is where you customize your PHP
    with various options, like which extensions will be enabled.  Do a
    ./configure --help for a list of available options.  In our example
    we'll do a simple configure with Apache 1 and MySQL support.  Your
    path to apxs may differ from our example.

      ./configure --with-mysql --with-apxs=/www/bin/apxs

11. make
12. make install

    If you decide to change your configure options after installation,
    you only need to repeat the last three steps. You only need to 
    restart apache for the new module to take effect. A recompile of
    Apache is not needed.
  
    Note that unless told otherwise, 'make install' will also install PEAR,
    various PHP tools such as phpize, install the PHP CLI, and more.

13. Setup your php.ini file:

      cp php.ini-dist /usr/local/lib/php.ini

    You may edit your .ini file to set PHP options.  If you prefer your
    php.ini in another location, use --with-config-file-path=/some/path in
    step 10. 
    
    If you instead choose php.ini-recommended, be certain to read the list
    of changes within, as they affect how PHP behaves.

14. Edit your httpd.conf to load the PHP module.  The path on the right hand
    side of the LoadModule statement must point to the path of the PHP
    module on your system.  The make install from above may have already
    added this for you, but be sure to check.
        
    For PHP 4:
            
      LoadModule php4_module libexec/libphp4.so

    For PHP 5:
                      
      LoadModule php5_module libexec/libphp5.so
      
15. And in the AddModule section of httpd.conf, somewhere under the
    ClearModuleList, add this:
    
    For PHP 4:
    
      AddModule mod_php4.c
      
    For PHP 5:
    
      AddModule mod_php5.c

16. Tell Apache to parse certain extensions as PHP.  For example,
    let's have Apache parse the .php extension as PHP.  You could
    have any extension(s) parse as PHP by simply adding more, with
    each separated by a space.  We'll add .phtml to demonstrate.

      AddType application/x-httpd-php .php .phtml

    It's also common to setup the .phps extension to show highlighted PHP
    source, this can be done with:
    
      AddType application/x-httpd-php-source .phps

17. Use your normal procedure for starting the Apache server. (You must
    stop and restart the server, not just cause the server to reload by
    using a HUP or USR1 signal.)

Alternatively, to install PHP as a static object:

Esempio 4-2. Installation Instructions (Static Module Installation for Apache) for PHP

1.  gunzip -c apache_1.3.x.tar.gz | tar xf -
2.  cd apache_1.3.x
3.  ./configure
4.  cd ..

5.  gunzip -c php-4.x.y.tar.gz | tar xf -
6.  cd php-4.x.y
7.  ./configure --with-mysql --with-apache=../apache_1.3.x
8.  make
9.  make install

10. cd ../apache_1.3.x

11. ./configure --prefix=/www --activate-module=src/modules/php4/libphp4.a
    (The above line is correct! Yes, we know libphp4.a does not exist at this
    stage. It isn't supposed to. It will be created.)

12. make
    (you should now have an httpd binary which you can copy to your Apache bin dir if
    is is your first install then you need to "make install" as well)

13. cd ../php-4.x.y
14. cp php.ini-dist /usr/local/lib/php.ini

15. You can edit /usr/local/lib/php.ini file to set PHP options.
    Edit your httpd.conf or srm.conf file and add:
    AddType application/x-httpd-php .php

Depending on your Apache install and Unix variant, there are many possible ways to stop and restart the server. Below are some typical lines used in restarting the server, for different apache/unix installations. You should replace /path/to/ with the path to these applications on your systems.

Esempio 4-3. Example commands for restarting Apache

1. Several Linux and SysV variants:
/etc/rc.d/init.d/httpd restart

2. Using apachectl scripts:
/path/to/apachectl stop
/path/to/apachectl start

3. httpdctl and httpsdctl (Using OpenSSL), similar to apachectl:
/path/to/httpsdctl stop
/path/to/httpsdctl start

4. Using mod_ssl, or another SSL server, you may want to manually
stop and start:
/path/to/apachectl stop
/path/to/apachectl startssl

The locations of the apachectl and http(s)dctl binaries often vary. If your system has locate or whereis or which commands, these can assist you in finding your server control programs.

Different examples of compiling PHP for apache are as follows:

./configure --with-apxs --with-pgsql

This will create a libphp4.so shared library that is loaded into Apache using a LoadModule line in Apache's httpd.conf file. The PostgreSQL support is embedded into this libphp4.so library.

./configure --with-apxs --with-pgsql=shared

This will create a libphp4.so shared library for Apache, but it will also create a pgsql.so shared library that is loaded into PHP either by using the extension directive in php.ini file or by loading it explicitly in a script using the dl() function.

./configure --with-apache=/path/to/apache_source --with-pgsql

This will create a libmodphp4.a library, a mod_php4.c and some accompanying files and copy this into the src/modules/php4 directory in the Apache source tree. Then you compile Apache using --activate-module=src/modules/php4/libphp4.a and the Apache build system will create libphp4.a and link it statically into the httpd binary. The PostgreSQL support is included directly into this httpd binary, so the final result here is a single httpd binary that includes all of Apache and all of PHP.

./configure --with-apache=/path/to/apache_source --with-pgsql=shared

Same as before, except instead of including PostgreSQL support directly into the final httpd you will get a pgsql.so shared library that you can load into PHP from either the php.ini file or directly using dl().

When choosing to build PHP in different ways, you should consider the advantages and drawbacks of each method. Building as a shared object will mean that you can compile apache separately, and don't have to recompile everything as you add to, or change, PHP. Building PHP into apache (static method) means that PHP will load and run faster. For more information, see the Apache webpage on DSO support.

Nota: Apache's default httpd.conf currently ships with a section that looks like this:

User nobody
Group "#-1"

Unless you change that to "Group nogroup" or something like that ("Group daemon" is also very common) PHP will not be able to open files.

Nota: Make sure you specify the installed version of apxs when using --with-apxs=/path/to/apxs. You must NOT use the apxs version that is in the apache sources but the one that is actually installed on your system.


Apache 2.0 on Unix systems

This section contains notes and hints specific to Apache 2.0 installs of PHP on Unix systems.

Avvertimento

We do not recommend using a threaded MPM in production with Apache2. Use the prefork MPM instead, or use Apache1. For information on why, read the following FAQ entry

You are highly encouraged to take a look at the Apache Documentation to get a basic understanding of the Apache 2.0 Server.

PHP and Apache 2.0.x compatibility notes: The following versions of PHP are known to work with the most recent version of Apache 2.0.x:

These versions of PHP are compatible to Apache 2.0.40 and later.

Apache 2.0 SAPI-support started with PHP 4.2.0. PHP 4.2.3 works with Apache 2.0.39, don't use any other version of Apache with PHP 4.2.3. However, the recommended setup is to use PHP 4.3.0 or later with the most recent version of Apache2.

All mentioned versions of PHP will work still with Apache 1.3.x.

Download the most recent version of Apache 2.0 and a fitting PHP version from the above mentioned places. This quick guide covers only the basics to get started with Apache 2.0 and PHP. For more information read the Apache Documentation. The version numbers have been omitted here, to ensure the instructions are not incorrect. You will need to replace the 'NN' here with the correct values from your files.

Esempio 4-4. Installation Instructions (Apache 2 Shared Module Version)

1.  gzip -d httpd-2_0_NN.tar.gz
2.  tar xvf httpd-2_0_NN.tar
3.  gunzip php-NN.tar.gz
4.  tar -xvf php-NN.tar
5.  cd httpd-2_0_NN
6.  ./configure --enable-so
7.  make
8.  make install

    Now you have Apache 2.0.NN available under /usr/local/apache2,
    configured with loadable module support and the standard MPM prefork.
    To test the installation use your normal procedure for starting
    the Apache server, e.g.:
    /usr/local/apache2/bin/apachectl start
    and stop the server to go on with the configuration for PHP:
    /usr/local/apache2/bin/apachectl stop.

9.  cd ../php-NN

10. Now, configure your PHP.  This is where you customize your PHP
    with various options, like which extensions will be enabled.  Do a
    ./configure --help for a list of available options.  In our example
    we'll do a simple configure with Apache 2 and MySQL support.  Your
    path to apxs may differ, in fact, the binary may even be named apxs2 on
    your system. 
    
      ./configure --with-apxs2=/usr/local/apache2/bin/apxs --with-mysql

11. make
12. make install

    If you decide to change your configure options after installation,
    you only need to repeat the last three steps. You only need to
    restart apache for the new module to take effect. A recompile of
    Apache is not needed.
                
    Note that unless told otherwise, 'make install' will also install PEAR,
    various PHP tools such as phpize, install the PHP CLI, and more.
    
13. Setup your php.ini 
    
    cp php.ini-dist /usr/local/lib/php.ini
          
    You may edit your .ini file to set PHP options.  If you prefer having
    php.ini in another location, use --with-config-file-path=/some/path in
    step 10.
    
    If you instead choose php.ini-recommended, be certain to read the list
    of changes within, as they affect how PHP behaves.

14. Edit your httpd.conf to load the PHP module.  The path on the right hand
    side of the LoadModule statement must point to the path of the PHP
    module on your system.  The make install from above may have already
    added this for you, but be sure to check.

    For PHP 4:
  
      LoadModule php4_module libexec/libphp4.so
      
    For PHP 5:
    
      LoadModule php5_module libexec/libphp5.so
 
15. Tell Apache to parse certain extensions as PHP.  For example,
    let's have Apache parse the .php extension as PHP.  You could
    have any extension(s) parse as PHP by simply adding more, with
    each separated by a space.  We'll add .phtml to demonstrate.
            
      AddType application/x-httpd-php .php .phtml
                  
    It's also common to setup the .phps extension to show highlighted PHP
    source, this can be done with:
    
      AddType application/x-httpd-php-source .phps
 
16. Use your normal procedure for starting the Apache server, e.g.:
   
      /usr/local/apache2/bin/apachectl start

Following the steps above you will have a running Apache 2.0 with support for PHP as SAPI module. Of course there are many more configuration options available for both, Apache and PHP. For more information use ./configure --help in the corresponding source tree. In case you wish to build a multithreaded version of Apache 2.0 you must overwrite the standard MPM-Module prefork either with worker or perchild. To do so append to your configure line in step 6 above either the option --with-mpm=worker or --with-mpm=perchild. Take care about the consequences and understand what you are doing. For more information read the Apache documentation about the MPM-Modules.

Nota: If you want to use content negotiation, read related FAQ.

Nota: To build a multithreaded version of Apache your system must support threads. This also implies to build PHP with experimental Zend Thread Safety (ZTS). Therefore not all extensions might be available. The recommended setup is to build Apache with the standard prefork MPM-Module.


Caudium

PHP 4 can be built as a Pike module for the Caudium webserver. Note that this is not supported with PHP 3. Follow the simple instructions below to install PHP 4 for Caudium.

Esempio 4-5. Caudium Installation Instructions

1.  Make sure you have Caudium installed prior to attempting to
    install PHP 4. For PHP 4 to work correctly, you will need Pike
    7.0.268 or newer. For the sake of this example we assume that
    Caudium is installed in /opt/caudium/server/.
2.  Change directory to php-x.y.z (where x.y.z is the version number).
3.  ./configure --with-caudium=/opt/caudium/server
4.  make
5.  make install
6.  Restart Caudium if it's currently running.
7.  Log into the graphical configuration interface and go to the
    virtual server where you want to add PHP 4 support.
8.  Click Add Module and locate and then add the PHP 4 Script Support module.
9.  If the documentation says that the 'PHP 4 interpreter isn't
    available', make sure that you restarted the server. If you did
    check /opt/caudium/logs/debug/default.1 for any errors related to
    <filename>PHP4.so</filename>. Also make sure that 
    <filename>caudium/server/lib/[pike-version]/PHP4.so</filename>
    is present.
10. Configure the PHP Script Support module if needed.

You can of course compile your Caudium module with support for the various extensions available in PHP 4. See the reference pages for extension specific configure options.

Nota: When compiling PHP 4 with MySQL support you must make sure that the normal MySQL client code is used. Otherwise there might be conflicts if your Pike already has MySQL support. You do this by specifying a MySQL install directory the --with-mysql option.


fhttpd related notes

To build PHP as an fhttpd module, answer "yes" to "Build as an fhttpd module?" (the --with-fhttpd=DIR option to configure) and specify the fhttpd source base directory. The default directory is /usr/local/src/fhttpd. If you are running fhttpd, building PHP as a module will give better performance, more control and remote execution capability.

Nota: Support for fhttpd is no longer available as of PHP 4.3.0.


Sun, iPlanet and Netscape servers on Sun Solaris

This section contains notes and hints specific to Sun Java System Web Server, Sun ONE Web Server, iPlanet and Netscape server installs of PHP on Sun Solaris.

From PHP 4.3.3 on you can use PHP scripts with the NSAPI module to generate custom directory listings and error pages. Additional functions for Apache compatibility are also available. For support in current webservers read the note about subrequests.

You can find more information about setting up PHP for the Netscape Enterprise Server (NES) here: http://benoit.noss.free.fr/php/install-php4.html

To build PHP with Sun JSWS/Sun ONE WS/iPlanet/Netscape webservers, enter the proper install directory for the --with-nsapi=[DIR] option. The default directory is usually /opt/netscape/suitespot/. Please also read /php-xxx-version/sapi/nsapi/nsapi-readme.txt.

  1. Install the following packages from http://www.sunfreeware.com/ or another download site:

    autoconf-2.13
    automake-1.4
    bison-1_25-sol26-sparc-local
    flex-2_5_4a-sol26-sparc-local
    gcc-2_95_2-sol26-sparc-local
    gzip-1.2.4-sol26-sparc-local
    m4-1_4-sol26-sparc-local
    make-3_76_1-sol26-sparc-local
    mysql-3.23.24-beta (if you want mysql support)
    perl-5_005_03-sol26-sparc-local
    tar-1.13 (GNU tar)

  2. Make sure your path includes the proper directories PATH=.:/usr/local/bin:/usr/sbin:/usr/bin:/usr/ccs/bin and make it available to your system export PATH.

  3. gunzip php-x.x.x.tar.gz (if you have a .gz dist, otherwise go to 4).

  4. tar xvf php-x.x.x.tar

  5. Change to your extracted PHP directory: cd ../php-x.x.x

  6. For the following step, make sure /opt/netscape/suitespot/ is where your netscape server is installed. Otherwise, change to the correct path and run:
    ./configure --with-mysql=/usr/local/mysql \
    --with-nsapi=/opt/netscape/suitespot/ \
    --enable-libgcc

  7. Run make followed by make install.

After performing the base install and reading the appropriate readme file, you may need to perform some additional configuration steps.

Configuration Instructions for Sun/iPlanet/Netscape. Firstly you may need to add some paths to the LD_LIBRARY_PATH environment for the server to find all the shared libs. This can best done in the start script for your webserver. The start script is often located in: /path/to/server/https-servername/start. You may also need to edit the configuration files that are located in: /path/to/server/https-servername/config/.

  1. Add the following line to mime.types (you can do that by the administration server):
    type=magnus-internal/x-httpd-php exts=php

  2. Edit magnus.conf (for servers >= 6) or obj.conf (for servers < 6) and add the following, shlib will vary depending on your system, it will be something like /opt/netscape/suitespot/bin/libphp4.so. You should place the following lines after mime types init.
    Init fn="load-modules" funcs="php4_init,php4_execute,php4_auth_trans" shlib="/opt/netscape/suitespot/bin/libphp4.so"
    Init fn="php4_init" LateInit="yes" errorString="Failed to initialize PHP!" [php_ini="/path/to/php.ini"]
    (PHP >= 4.3.3) The php_ini parameter is optional but with it you can place your php.ini in your webserver config directory.

  3. Configure the default object in obj.conf (for virtual server classes [version 6.0+] in their vserver.obj.conf):
    <Object name="default">
    .
    .
    .
    .#NOTE this next line should happen after all 'ObjectType' and before all 'AddLog' lines
    Service fn="php4_execute" type="magnus-internal/x-httpd-php" [inikey=value inikey=value ...]
    .
    .
    </Object>
    (PHP >= 4.3.3) As additional parameters you can add some special php.ini-values, for example you can set a docroot="/path/to/docroot" specific to the context php4_execute is called. For boolean ini-keys please use 0/1 as value, not "On","Off",... (this will not work correctly), e.g. zlib.output_compression=1 instead of zlib.output_compression="On"

  4. This is only needed if you want to configure a directory that only consists of PHP scripts (same like a cgi-bin directory):
    <Object name="x-httpd-php">
    ObjectType fn="force-type" type="magnus-internal/x-httpd-php"
    Service fn=php4_execute [inikey=value inikey=value ...]
    </Object>
    After that you can configure a directory in the Administration server and assign it the style x-httpd-php. All files in it will get executed as PHP. This is nice to hide PHP usage by renaming files to .html.

  5. Setup of authentication: PHP authentication cannot be used with any other authentication. ALL AUTHENTICATION IS PASSED TO YOUR PHP SCRIPT. To configure PHP Authentication for the entire server, add the following line to your default object:
    <Object name="default">
    AuthTrans fn=php4_auth_trans
    .
    .
    .
    </Object>

  6. To use PHP Authentication on a single directory, add the following:
    <Object ppath="d:\path\to\authenticated\dir\*">
    AuthTrans fn=php4_auth_trans
    </Object>

Nota: The stacksize that PHP uses depends on the configuration of the webserver. If you get crashes with very large PHP scripts, it is recommended to raise it with the Admin Server (in the section "MAGNUS EDITOR").


CGI environment and recommended modifications in php.ini

Important when writing PHP scripts is the fact that Sun JSWS/Sun ONE WS/iPlanet/Netscape is a multithreaded web server. Because of that all requests are running in the same process space (the space of the webserver itself) and this space has only one environment. If you want to get CGI variables like PATH_INFO, HTTP_HOST etc. it is not the correct way to try this in the old PHP 3.x way with getenv() or a similar way (register globals to environment, $_ENV). You would only get the environment of the running webserver without any valid CGI variables!

Nota: Why are there (invalid) CGI variables in the environment?

Answer: This is because you started the webserver process from the admin server which runs the startup script of the webserver, you wanted to start, as a CGI script (a CGI script inside of the admin server!). This is why the environment of the started webserver has some CGI environment variables in it. You can test this by starting the webserver not from the administration server. Use the command line as root user and start it manually - you will see there are no CGI-like environment variables.

Simply change your scripts to get CGI variables in the correct way for PHP 4.x by using the superglobal $_SERVER. If you have older scripts which use $HTTP_HOST, etc., you should turn on register_globals in php.ini and change the variable order too (important: remove "E" from it, because you do not need the environment here):
variables_order = "GPCS"
register_globals = On


Special use for error pages or self-made directory listings (PHP >= 4.3.3)

You can use PHP to generate the error pages for "404 Not Found" or similar. Add the following line to the object in obj.conf for every error page you want to overwrite:
Error fn="php4_execute" code=XXX script="/path/to/script.php" [inikey=value inikey=value...]
where XXX is the HTTP error code. Please delete any other Error directives which could interfere with yours. If you want to place a page for all errors that could exist, leave the code parameter out. Your script can get the HTTP status code with $_SERVER['ERROR_TYPE'].

Another possibility is to generate self-made directory listings. Just create a PHP script which displays a directory listing and replace the corresponding default Service line for type="magnus-internal/directory" in obj.conf with the following:
Service fn="php4_execute" type="magnus-internal/directory" script="/path/to/script.php" [inikey=value inikey=value...]
For both error and directory listing pages the original URI and translated URI are in the variables $_SERVER['PATH_INFO'] and $_SERVER['PATH_TRANSLATED'].


Note about nsapi_virtual() and subrequests (PHP >= 4.3.3)

The NSAPI module now supports the nsapi_virtual() function (alias: virtual()) to make subrequests on the webserver and insert the result in the webpage. This function uses some undocumented features from the NSAPI library. On Unix the module automatically looks for the needed functions and uses them if available. If not, nsapi_virtual() is disabled.

Nota: But be warned: Support for nsapi_virtual() is EXPERIMENTAL!!!


CGI and commandline setups

The default is to build PHP as a CGI program. This creates a commandline interpreter, which can be used for CGI processing, or for non-web-related PHP scripting. If you are running a web server PHP has module support for, you should generally go for that solution for performance reasons. However, the CGI version enables users to run different PHP-enabled pages under different user-ids.

Avvertimento

By using the CGI setup, your server is open to several possible attacks. Please read our CGI security section to learn how to defend yourself from those attacks.

As of PHP 4.3.0, some important additions have happened to PHP. A new SAPI named CLI also exists and it has the same name as the CGI binary. What is installed at {PREFIX}/bin/php depends on your configure line and this is described in detail in the manual section named Using PHP from the command line. For further details please read that section of the manual.


Testing

If you have built PHP as a CGI program, you may test your build by typing make test. It is always a good idea to test your build. This way you may catch a problem with PHP on your platform early instead of having to struggle with it later.


Benchmarking

If you have built PHP 3 as a CGI program, you may benchmark your build by typing make bench. Note that if safe mode is on by default, the benchmark may not be able to finish if it takes longer then the 30 seconds allowed. This is because the set_time_limit() can not be used in safe mode. Use the max_execution_time configuration setting to control this time for your own scripts. make bench ignores the configuration file.

Nota: make bench is only available for PHP 3.


Using Variables

Some server supplied environment variables are not defined in the current CGI/1.1 specification. Only the following variables are defined there: AUTH_TYPE, CONTENT_LENGTH, CONTENT_TYPE, GATEWAY_INTERFACE, PATH_INFO, PATH_TRANSLATED, QUERY_STRING, REMOTE_ADDR, REMOTE_HOST, REMOTE_IDENT, REMOTE_USER, REQUEST_METHOD, SCRIPT_NAME, SERVER_NAME, SERVER_PORT, SERVER_PROTOCOL, and SERVER_SOFTWARE. Everything else should be treated as 'vendor extensions'.


HP-UX specific installation notes

This section contains notes and hints specific to installing PHP on HP-UX systems. (Contributed by paul_mckay at clearwater-it dot co dot uk).

Nota: These tips were written for PHP 4.0.4 and Apache 1.3.9.

  1. You need gzip, download a binary distribution from http://hpux.connect.org.uk/ftp/hpux/Gnu/gzip-1.2.4a/gzip-1.2.4a-sd-10.20.depot.Z uncompress the file and install using swinstall.

  2. You need gcc, download a binary distribution from http://gatekeep.cs.utah.edu/ftp/hpux/Gnu/gcc-2.95.2/gcc-2.95.2-sd-10.20.depot.gz. uncompress this file and install gcc using swinstall.

  3. You need the GNU binutils, you can download a binary distribution from http://hpux.connect.org.uk/ftp/hpux/Gnu/binutils-2.9.1/binutils-2.9.1-sd-10.20.depot.gz. uncompress this file and install binutils using swinstall.

  4. You now need bison, you can download a binary distribution from http://hpux.connect.org.uk/ftp/hpux/Gnu/bison-1.28/bison-1.28-sd-10.20.depot.gz, install as above.

  5. You now need flex, you need to download the source from one of the http://www.gnu.org mirrors. It is in the non-gnu directory of the ftp site. Download the file, gunzip, then tar -xvf it. Go into the newly created flex directory and run ./configure, followed by make, and then make install.

    If you have errors here, it's probably because gcc etc. are not in your PATH so add them to your PATH.

  6. Download the PHP and apache sources.

  7. gunzip and tar -xvf them. We need to hack a couple of files so that they can compile OK.

  8. Firstly the configure file needs to be hacked because it seems to lose track of the fact that you are a hpux machine, there will be a better way of doing this but a cheap and cheerful hack is to put lt_target=hpux10.20 on line 47286 of the configure script.

  9. Next, the Apache GuessOS file needs to be hacked. Under apache_1.3.9/src/helpers change line 89 from echo "hp${HPUXMACH}-hpux${HPUXVER}"; exit 0 to: echo "hp${HPUXMACH}-hp-hpux${HPUXVER}"; exit 0

  10. You cannot install PHP as a shared object under HP-UX so you must compile it as a static, just follow the instructions at the Apache page.

  11. PHP and Apache should have compiled OK, but Apache won't start. you need to create a new user for Apache, e.g. www, or apache. You then change lines 252 and 253 of the conf/httpd.conf in Apache so that instead of

    User nobody 
    Group nogroup

    you have something like

    User www 
    Group sys

    This is because you can't run Apache as nobody under hp-ux. Apache and PHP should then work.


OpenBSD installation notes

This section contains notes and hints specific to installing PHP on OpenBSD 3.6.


Using Binary Packages

Using binary packages to install PHP on OpenBSD is the recommended and simplest method. The core package has been separated from the various modules, and each can be installed and removed independently from the others. The files you need can be found on your OpenBSD CD or on the FTP site.

The main package you need to install is php4-core-4.3.8.tgz, which contains the basic engine (plus gettext and iconv). Next, take a look at the module packages, such as php4-mysql-4.3.8.tgz or php4-imap-4.3.8.tgz. You need to use the phpxs command to activate and deactivate these modules in your php.ini.

Esempio 4-6. OpenBSD Package Install Example

# pkg_add php4-core-4.3.8.tgz
# /usr/local/sbin/phpxs -s
# cp /usr/local/share/doc/php4/php.ini-recommended /var/www/conf/php.ini
  (add in mysql)
# pkg_add php4-mysql-4.3.8.tgz
# /usr/local/sbin/phpxs -a mysql
  (add in imap)
# pkg_add php4-imap-4.3.8.tgz
# /usr/local/sbin/phpxs -a imap
  (remove mysql as a test)
# pkg_delete php4-mysql-4.3.8
# /usr/local/sbin/phpxs -r mysql
  (install the PEAR libraries)
# pkg_add php4-pear-4.3.8.tgz

Read the packages(7) manual page for more information about binary packages on OpenBSD.


Using Ports

You can also compile up PHP from source using the ports tree. However, this is only recommended for users familiar with OpenBSD. The PHP 4 port is split into two sub-directories: core and extensions. The extensions directory generates sub-packages for all of the supported PHP modules. If you find you do not want to create some of these modules, use the no_* FLAVOR. For example, to skip building the imap module, set the FLAVOR to no_imap.


Common Problems

  • The default install of Apache runs inside a chroot(2) jail, which will restrict PHP scripts to accessing files under /var/www. You will therefore need to create a /var/www/tmp directory for PHP session files to be stored, or use an alternative session backend. In addition, database sockets need to be placed inside the jail or listen on the localhost interface. If you use network functions, some files from /etc such as /etc/resolv.conf and /etc/services will need to be moved into /var/www/etc. The OpenBSD PEAR package automatically installs into the correct chroot directories, so no special modification is needed there. More information on the OpenBSD Apache is available in the OpenBSD FAQ.

  • The OpenBSD 3.6 package for the gd extension requires XFree86 to be installed. If you do not wish to use some of the font features that require X11, install the php4-gd-4.3.8-no_x11.tgz package instead.


Older Releases

Older releases of OpenBSD used the FLAVORS system to compile up a statically linked PHP. Since it is hard to generate binary packages using this method, it is now deprecated. You can still use the old stable ports trees if you wish, but they are unsupported by the OpenBSD team. If you have any comments about this, the current maintainer for the port is Anil Madhavapeddy (avsm at openbsd dot org).


Solaris specific installation tips

This section contains notes and hints specific to installing PHP on Solaris systems.


Required software

Solaris installs often lack C compilers and their related tools. Read this FAQ for information on why using GNU versions for some of these tools is necessary. The required software is as follows:

  • gcc (recommended, other C compilers may work)

  • make

  • flex

  • bison

  • m4

  • autoconf

  • automake

  • perl

  • gzip

  • tar

  • GNU sed

In addition, you will need to install (and possibly compile) any additional software specific to your configuration, such as Oracle or MySQL.


Using Packages

You can simplify the Solaris install process by using pkgadd to install most of your needed components.


Gentoo installation notes

This section contains notes and hints specific to installing PHP on Gentoo Linux.


Using Portage (emerge)

While you can just download the PHP source and compile it yourself, using Gentoo's packaging system is the simplest and cleanest method of installing PHP. If you are not familiar with building software on Linux, this is the way to go.

If you have built your Gentoo system so far, you are probably used to Portage already. Installing Apache and PHP is no different than the other system tools.

The first decision you need to make is whether you want to install Apache 1.3.x or Apache 2.x. While both can be used with PHP, the steps given below will use Apache 1.3.x. Another thing to consider is whether your local Portage tree is up to date. If you have not updated it recently, you need to run emerge sync before anything else. This way, you will be using the most recent stable version of Apache and PHP.

Now that everything is in place, you can use the following example to install Apache and PHP:

Esempio 4-7. Gentoo Install Example with Apache 1.3

# emerge \<apache-2
# USE="-*" emerge php mod_php
# ebuild /var/db/pkg/dev-php/mod_php-<your PHP version>/mod_php-<your PHP version>.ebuild config
# nano /etc/conf.d/apache
  Add "-D PHP4" to APACHE_OPTS
  
# rc-update add apache default
# /etc/init.d/apache start

You can read more about emerge in the excellent Portage Manual provided on the Gentoo website.

If you need to use Apache 2, you can simply use emerge apache in the last example.


Better control on configuration

In the last section, PHP was emerged without any activated modules. As of this writing, the only module activated by default with Portage is XML which is needed by PEAR. This may not be what you want and you will soon discover that you need more activated modules, like MySQL, gettext, GD, etc.

When you compile PHP from source yourself, you need to activate modules via the configure command. With Gentoo, you can simply provide USE flags which will be passed to the configure script automatically. To see which USE flags to use with emerge, you can try:

Esempio 4-8. Getting the list of valid USE flags

# USE="-*" emerge -pv php

[ebuild  N    ] dev-php/php-4.3.6-r1  -X -berkdb -crypt -curl -debug -doc 
-fdftk -firebird -flash -freetds -gd -gd-external -gdbm -gmp -hardenedphp 
-imap -informix -ipv6 -java -jpeg -kerberos -ldap -mcal -memlimit -mssql 
-mysql -ncurses -nls -oci8 -odbc -pam -pdflib -png -postgres -qt -readline 
-snmp -spell -ssl -tiff -truetype -xml2 -yaz  3,876 kB

As you can see from the last output, PHP considers a lot of USE flags. Look at them closely and choose what you need. If you choose a flag and you do not have the proper libraries, Portage will compile them for you. It is a good idea to use emerge -pv again to see what Portage will compile in accordance to your USE flags. As an example, if you do not have X installed and you choose to include X in the USE flags, Portage will compile X prior to PHP, which can take a couple of hours.

If you choose to compile PHP with MySQL, cURL and GD support, the command will look something like this:

Esempio 4-9. Install PHP with USE flags

# USE="-* curl mysql gd" emerge php mod_php

As in the last example, do not forget to emerge php as well as mod_php. php is responsible for the command line version of PHP as mod_php is for the Apache module version of PHP.


Common Problems

  • If you see the PHP source instead of the result the script should produce, you have probably forgot to edit /etc/conf.d/apache. Apache needs to be started with the -D PHP4 flag. To see if the flag is present, you should be able to see it when using ps ax | grep apache while Apache is running.

  • Due to slotting problems, you might end up with more than one version of PHP installed on your system. If this is the case, you need to unmerge the old versions manually by using emerge unmerge mod_php-<old version>.

  • If you cannot emerge PHP because of Java, try putting -* in front of your USE flags like in the above examples.

  • If you are having problems configuring Apache and PHP, you can always search the Gentoo Forums. Try searching with the keywords "Apache PHP".


Capitolo 5. Installation on Mac OS X

This section contains notes and hints specific to installing PHP on Mac OS X. There are two slightly different versions of Mac OS X, Client and Server, our manual deals with installing PHP on both systems. Note that PHP is not available for MacOS 9 and earlier versions.


Using Packages

There are a few pre-packaged and pre-compiled versions of PHP for Mac OS X. This can help in setting up a standard configuration, but if you need to have a different set of features (such as a secure server, or a different database driver), you may need to build PHP and/or your web server yourself. If you are unfamiliar with building and compiling your own software, it's worth checking whether somebody has already built a packaged version of PHP with the features you need.


Compiling for OS X Server

Mac OS X Server install.

  1. Get the latest distributions of Apache and PHP.

  2. Untar them, and run the configure program on Apache like so.
    ./configure --exec-prefix=/usr \
    --localstatedir=/var \
    --mandir=/usr/share/man \
    --libexecdir=/System/Library/Apache/Modules \
    --iconsdir=/System/Library/Apache/Icons \
    --includedir=/System/Library/Frameworks/Apache.framework/Versions/1.3/Headers \
    --enable-shared=max \
    --enable-module=most \
    --target=apache

  3. If you want the compiler to do some optimization, you may also want to add this line:
    setenv OPTIM=-O2

  4. Next, go to the PHP 4 source directory and configure it.
    ./configure --prefix=/usr \
        --sysconfdir=/etc \
        --localstatedir=/var \
        --mandir=/usr/share/man \
        --with-xml \
        --with-apache=/src/apache_1.3.12
    If you have any other additions (MySQL, GD, etc.), be sure to add them here. For the --with-apache string, put in the path to your apache source directory, for example /src/apache_1.3.12.

  5. Type make and make install. This will add a directory to your Apache source directory under src/modules/php4.

  6. Now, reconfigure Apache to build in PHP 4.
    ./configure --exec-prefix=/usr \
    --localstatedir=/var \
    --mandir=/usr/share/man \
    --libexecdir=/System/Library/Apache/Modules \
    --iconsdir=/System/Library/Apache/Icons \
    --includedir=/System/Library/Frameworks/Apache.framework/Versions/1.3/Headers \
    --enable-shared=max \
    --enable-module=most \
    --target=apache \
    --activate-module=src/modules/php4/libphp4.a
    You may get a message telling you that libmodphp4.a is out of date. If so, go to the src/modules/php4 directory inside your Apache source directory and run this command: ranlib libmodphp4.a. Then go back to the root of the Apache source directory and run the above configure command again. That'll bring the link table up to date. Run make and make install again.

  7. Copy and rename the php.ini-dist file to your bin directory from your PHP 4 source directory: cp php.ini-dist /usr/local/bin/php.ini or (if your don't have a local directory) cp php.ini-dist /usr/bin/php.ini.


Compiling for MacOS X Client

The following instructions will help you install a PHP module for the Apache web server included in MacOS X. This version includes support for the MySQL and PostgreSQL databases. These instructions are graciously provided by Marc Liyanage.

Avvertimento

Be careful when you do this, you could screw up your Apache web server!

Do this to install:

  1. Open a terminal window.

  2. Type wget http://www.diax.ch/users/liyanage/software/macosx/libphp4.so.gz, wait for the download to finish.

  3. Type gunzip libphp4.so.gz.

  4. Type sudo apxs -i -a -n php4 libphp4.so

  5. Now type sudo open -a TextEdit /etc/httpd/httpd.conf. TextEdit will open with the web server configuration file. Locate these two lines towards the end of the file: (Use the Find command)
    #AddType application/x-httpd-php .php 
    #AddType application/x-httpd-php-source .phps
    Remove the two hash marks (#), then save the file and quit TextEdit.

  6. Finally, type sudo apachectl graceful to restart the web server.

PHP should now be up and running. You can test it by dropping a file into your Sites folder which is called test.php. Into that file, write this line: <?php phpinfo() ?>.

Now open up 127.0.0.1/~your_username/test.php in your web browser. You should see a status table with information about the PHP module.


Capitolo 6. Installation on Windows systems

This section applies to Windows 98/Me and Windows NT/2000/XP/2003. PHP will not work on 16 bit platforms such as Windows 3.1 and sometimes we refer to the supported Windows platforms as Win32. Windows 95 is no longer supported as of PHP 4.3.0.

There are two main ways to install PHP for Windows: either manually or by using the installer.

If you have Microsoft Visual Studio, you can also build PHP from the original source code.

Once you have PHP installed on your Windows system, you may also want to load various extensions for added functionality.

Avvertimento

There are several all-in-one installers over the Internet, but none of those are endorsed by PHP.net, as we believe that the manual installation is the best choice to have your system secure and optimised.


Windows Installer

The Windows PHP installer is available from the downloads page at http://www.php.net/downloads.php. This installs the CGI version of PHP and for IIS, PWS, and Xitami, it configures the web server as well. The installer does not include any extra external PHP extensions (php_*.dll) as you'll only find those in the Windows Zip Package and PECL downloads.

Nota: While the Windows installer is an easy way to make PHP work, it is restricted in many aspects as, for example, the automatic setup of extensions is not supported. Use of the installer isn't the preferred method for installing PHP.

First, install your selected HTTP (web) server on your system, and make sure that it works.

Run the executable installer and follow the instructions provided by the installation wizard. Two types of installation are supported - standard, which provides sensible defaults for all the settings it can, and advanced, which asks questions as it goes along.

The installation wizard gathers enough information to set up the php.ini file, and configure certain web servers to use PHP. One of the web servers the PHP installer does not configure for is Apache, so you'll need to configure it manually.

Once the installation has completed, the installer will inform you if you need to restart your system, restart the server, or just start using PHP.

Avvertimento

Be aware, that this setup of PHP is not secure. If you would like to have a secure PHP setup, you'd better go on the manual way, and set every option carefully. This automatically working setup gives you an instantly working PHP installation, but it is not meant to be used on online servers.


Manual Installation Steps

This install guide will help you manually install and configure PHP with a web server on Microsoft Windows. To get started you'll need to download the zip binary distribution from the downloads page at http://www.php.net/downloads.php.

Although there are many all-in-one installation kits, and we also distribute a PHP installer for Microsoft Windows, we recommend you take the time to setup PHP yourself as this will provide you with a better understanding of the system, and enables you to install PHP extensions easily when needed.

Upgrading from a previous PHP version: Previous editions of the manual suggest moving various ini and DLL files into your SYSTEM (i.e. C:\WINDOWS) folder and while this simplifies the installation procedure it makes upgrading difficult. We advise you remove all of these files (like php.ini and PHP related DLLs from the Windows SYSTEM folder) before moving on with a new PHP installation. Be sure to backup these files as you might break the entire system. The old php.ini might be useful in setting up the new PHP as well. And as you'll soon learn, the preferred method for installing PHP is to keep all PHP related files in one directory and have this directory available to your systems PATH.

MDAC requirements: If you use Microsoft Windows 98/NT4 download the latest version of the Microsoft Data Access Components (MDAC) for your platform. MDAC is available at http://msdn.microsoft.com/data/. This requirement exists because ODBC is built into the distributed Windows binaries.

The following steps should be completed on all installations before any server specific instructions are performed:

Extract the distribution file into a directory of your choice. If you are installing PHP 4, extract to C:\, as the zip file expands to a foldername like php-4.3.7-Win32. If you are installing PHP 5, extract to C:\php as the zip file doesn't expand as in PHP 4. You may choose a different location but do not have spaces in the path (like C:\Program Files\PHP) as some web servers will crash if you do.

The directory structure extracted from the zip is different for PHP versions 4 and 5 and look like as follows:

Esempio 6-1. PHP 4 package structure

c:\php
   |
   +--cli
   |  |
   |  |-php.exe           -- CLI executable - ONLY for commandline scripting
   |
   +--dlls                -- support DLLs required by some extensions
   |  |
   |  |-expat.dll
   |  |
   |  |-fdftk.dll
   |  |
   |  |-...
   |
   +--extensions          -- extension DLLs for PHP
   |  |
   |  |-php_bz2.dll
   |  |
   |  |-php_cpdf.dll
   |  |
   |  |-..
   |
   +--mibs                -- support files for SNMP
   |
   +--openssl             -- support files for Openssl
   |
   +--pdf-related         -- support files for PDF
   |
   +--sapi                -- SAPI (server module support) DLLs
   |  |
   |  |-php4activescript.dll
   |  |
   |  |-php4apache.dll
   |  |
   |  |-php4apache2.dll
   |  |
   |  |-..
   |
   +--PEAR                -- initial copy of PEAR
   |
   |
   |-go-pear.bat          -- PEAR setup script
   |
   |-..
   |
   |-php.exe              -- CGI executable
   |
   |-..
   |
   |-php.ini-dist         -- default php.ini settings
   |
   |-php.ini-recommended  -- recommended php.ini settings
   | 
   |-php4ts.dll           -- core PHP DLL
   | 
   |-...

Or:

Esempio 6-2. PHP 5 package structure

c:\php
   |
   +--dev
   |  |
   |  |-php5ts.lib
   |
   +--ext                 -- extension DLLs for PHP
   |  |
   |  |-php_bz2.dll
   |  |
   |  |-php_cpdf.dll
   |  |
   |  |-..
   |
   +--extras
   |  |
   |  +--mibs             -- support files for SNMP
   |  |
   |  +--openssl          -- support files for Openssl
   |  |
   |  +--pdf-related      -- support files for PDF
   |  |
   |  |-mime.magic
   |
   +--pear                -- initial copy of PEAR
   |
   |
   |-go-pear.bat          -- PEAR setup script
   |
   |-fdftk.dll
   |
   |-..
   |
   |-php-cgi.exe          -- CGI executable
   |
   |-php-win.exe          -- executes scripts without an opened command prompt
   |
   |-php.exe              -- CLI executable - ONLY for command line scripting
   |
   |-..
   |
   |-php.ini-dist         -- default php.ini settings
   |
   |-php.ini-recommended  -- recommended php.ini settings
   | 
   |-php5activescript.dll
   |
   |-php5apache.dll
   |
   |-php5apache2.dll
   |
   |-..
   |
   |-php5ts.dll           -- core PHP DLL
   | 
   |-...

Notice the differences and similarities. Both PHP 4 and PHP 5 have a CGI executable, a CLI executable, and server modules, but they are located in different folders and/or have different names. While PHP 4 packages have the server modules in the sapi folder, PHP 5 distributions have no such directory and instead they're in the PHP folder root. The supporting DLLs for the PHP 5 extensions are also not in a seperate directory.

Nota: In PHP 4, you should move all files located in the dll and sapi folders to the main folder (e.g. C:\php).

Here is a list of server modules shipped with PHP 4 and PHP 5:

  • sapi/php4activescript.dll (php5activescript.dll) - ActiveScript engine, allowing you to embed PHP in your Windows applications.

  • sapi/php4apache.dll (php5apache.dll) - Apache 1.3.x module.

  • sapi/php4apache2.dll (php5apache2.dll) - Apache 2.0.x module.

  • sapi/php4isapi.dll (php5isapi.dll) - ISAPI Module for ISAPI compliant web servers like IIS 4.0/PWS 4.0 or newer.

  • sapi/php4nsapi.dll (php5nsapi.dll) - Sun/iPlanet/Netscape server module.

  • sapi/php4pi3web.dll (no equivalent in PHP 5) - Pi3Web server module.

Server modules provide significantly better performance and additional functionality compared to the CGI binary. The CLI version is designed to let you use PHP for command line scripting. More information about CLI is available in the chapter about using PHP from the command line.

Avvertimento

The SAPI modules have been significantly improved as of the 4.1 release, however, in older systems you may encounter server errors or other server modules failing, such as ASP.

The CGI and CLI binaries, and the web server modules all require the php4ts.dll (php5ts.dll) file to be available to them. You have to make sure that this file can be found by your PHP installation. The search order for this DLL is as follows:

  • The same directory from where php.exe is called, or in case you use a SAPI module, the web server's directory (e.g. C:\Program Files\Apache Group\Apache2\bin).

  • Any directory in your Windows PATH environment variable.

To make php4ts.dll / php5ts.dll available you have three options: copy the file to the Windows system directory, copy the file to the web server's directory, or add your PHP directory, C:\php to the PATH. For better maintenance, we advise you to follow the last option, add C:\php to the PATH, because it will be simpler to upgrade PHP in the future. Read more about how to add your PHP directory to PATH in the corresponding FAQ entry.

The next step is to set up a valid configuration file for PHP, php.ini. There are two ini files distributed in the zip file, php.ini-dist and php.ini-recommended. We advise you to use php.ini-recommended, because we optimized the default settings in this file for performance, and security. Read this well documented file carefully because it has changes from php.ini-dist that will drastically affect your setup. Some examples are display_errors being off and magic_quotes_gpc being off. In addition to reading these, study the ini settings and set every element manually yourself. If you would like to achieve the best security, then this is the way for you, although PHP works fine with these default ini files. Copy your chosen ini-file to a directory that PHP is able to find and rename it to php.ini. PHP searches for php.ini in the following locations (in order):

  • PHPIniDir directive (Apache 2 module only)

  • HKEY_LOCAL_MACHINE\SOFTWARE\PHP\IniFilePath

  • The PHPRC environment variable

  • Directory of PHP (for CLI), or the web server's directory (for SAPI modules)

  • Windows directory (C:\windows or C:\winnt)

If you are running Apache 2, the simpler option is to use the PHPIniDir directive (read the installation on Apache 2 page), otherwise your best option is to set the PHPRC environment variable. This process is explained in the following FAQ entry.

Nota: If you're using NTFS on Windows NT, 2000, XP or 2003, make sure that the user running the web server has read permissions to your php.ini (e.g. make it readable by Everyone).

The following steps are optional:

  • Edit your new php.ini file. If you plan to use OmniHTTPd, do not follow the next step. Set the doc_root to point to your web servers document_root. For example:

    doc_root = c:\inetpub\wwwroot // for IIS/PWS
    
    doc_root = c:\apache\htdocs // for Apache

  • Choose the extensions you would like to load when PHP starts. See the section about Windows extensions, about how to set up one, and what is already built in. Note that on a new installation it is advisable to first get PHP working and tested without any extensions before enabling them in php.ini.

  • On PWS and IIS, you can set the browscap configuration setting to point to: c:\windows\system\inetsrv\browscap.ini on Windows 9x/Me, c:\winnt\system32\inetsrv\browscap.ini on NT/2000, and c:\windows\system32\inetsrv\browscap.ini on XP. For an up-to-date browscap.ini, read the following FAQ.

PHP is now setup on your system. The next step is to choose a web server, and enable it to run PHP. Choose a webserver from the table of contents.


ActiveScript

This section contains notes specific to the ActiveScript installation.

ActiveScript is a windows only SAPI that enables you to use PHP script in any ActiveScript compliant host, like Windows Script Host, ASP/ASP.NET, Windows Script Components or Microsoft Scriptlet control.

As of PHP 5.0.1, ActiveScript has been moved to the PECL repository. You may download this PECL extension DLL from the PHP Downloads page or at http://snaps.php.net/.

Nota: You should read the manual installation steps first!

After installing PHP, you should download the ActiveScript DLL (php5activescript.dll) and place it in the main PHP folder (e.g. C:\php).

After having all the files needed, you must register the DLL on your system. To achieve this, open a Command Prompt window (located in the Start Menu). Then go to your PHP directory by typing something like cd C:\php. To register the DLL just type regsvr32 php5activescript.dll.

To test if ActiveScript is working, create a new file, named test.wsf (the extension is very important) and type:
<job id="test">
 
 <script language="PHPScript">
  $WScript->Echo("Hello World!");
 </script>
 
</job>
Save and double-click on the file. If you receive a little window saying "Hello World!" you're done.

Nota: ActiveScript doesn't use the default php.ini file. Instead, it will look only in the same directory as the .exe that caused it to load. You should create php-activescript.ini and place it in that folder, if you wish to load extensions, etc.


Microsoft IIS / PWS

This section contains notes and hints specific to IIS (Microsoft Internet Information Server). We have included installation instructions for PWS/IIS 3, PWS 4 or newer and IIS 4 or newer versions.

Important for CGI users: Read the faq on cgi.force_redirect for important details. This directive needs to be set to 0.

Avvertimento

By using the CGI setup, your server is open to several possible attacks. Please read our CGI security section to learn how to defend yourself from those attacks.


Windows and PWS/IIS 3

The recommended method for configuring these servers is to use the REG file included with the distribution (pws-php4cgi.reg in the SAPI folder for PHP 4, or pws-php5cgi.reg in the main folder for PHP 5). You may want to edit this file and make sure the extensions and PHP install directories match your configuration. Or you can follow the steps below to do it manually.

Avvertimento

These steps involve working directly with the Windows registry. One error here can leave your system in an unstable state. We highly recommend that you back up your registry first. The PHP Development team will not be held responsible if you damage your registry.

  • Run Regedit.

  • Navigate to: HKEY_LOCAL_MACHINE /System /CurrentControlSet /Services /W3Svc /Parameters /ScriptMap.

  • On the edit menu select: New->String Value.

  • Type in the extension you wish to use for your php scripts. For example .php

  • Double click on the new string value and enter the path to php.exe in the value data field. ex: C:\php\php.exe for PHP 4, or C:\php\php-cgi.exe for PHP 5.

  • Repeat these steps for each extension you wish to associate with PHP scripts.

The following steps do not affect the web server installation and only apply if you want your PHP scripts to be executed when they are run from the command line (ex. run C:\myscripts\test.php) or by double clicking on them in a directory viewer window. You may wish to skip these steps as you might prefer the PHP files to load into a text editor when you double click on them.

  • Navigate to: HKEY_CLASSES_ROOT

  • On the edit menu select: New->Key.

  • Name the key to the extension you setup in the previous section. ex: .php

  • Highlight the new key and in the right side pane, double click the "default value" and enter phpfile.

  • Repeat the last step for each extension you set up in the previous section.

  • Now create another New->Key under HKEY_CLASSES_ROOT and name it phpfile.

  • Highlight the new key phpfile and in the right side pane, double click the "default value" and enter PHP Script.

  • Right click on the phpfile key and select New->Key, name it Shell.

  • Right click on the Shell key and select New->Key, name it open.

  • Right click on the open key and select New->Key, name it command.

  • Highlight the new key command and in the right side pane, double click the "default value" and enter the path to php.exe. ex: c:\php\php.exe -q %1. (don't forget the %1).

  • Exit Regedit.

  • If using PWS on Windows, reboot to reload the registry.

PWS and IIS 3 users now have a fully operational system. IIS 3 users can use a nifty tool from Steven Genusa to configure their script maps.


Windows and PWS 4 or newer

When installing PHP on Windows with PWS 4 or newer version, you have two options. One to set up the PHP CGI binary, the other is to use the ISAPI module DLL.

If you choose the CGI binary, do the following:

  • Edit the enclosed pws-php4cgi.reg / pws-php5cgi.reg file (look into the SAPI folder for PHP 4, or in the main folder for PHP 5) to reflect the location of your php.exe / php-cgi.exe. Backslashes should be escaped, for example: [HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\w3svc\parameters\Script Map] ".php"="C:\\php\\php.exe" (change to C:\\php\\php-cgi.exe if you are using PHP 5) Now merge this registery file into your system; you may do this by double-clicking it.

  • In the PWS Manager, right click on a given directory you want to add PHP support to, and select Properties. Check the 'Execute' checkbox, and confirm.

If you choose the ISAPI module, do the following:

  • Edit the enclosed pws-php4isapi.reg / pws-php5isapi.reg file (look into the SAPI folder for PHP 4, or in the main folder for PHP 5) to reflect the location of your php4isapi.dll / php5isapi.dll. Backslashes should be escaped, for example: [HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\w3svc\parameters\Script Map] ".php"="C:\\php\\sapi\\php4isapi.dll" (or C:\\php\\php5isapi.dll for PHP 5) Now merge this registery file into your system; you may do this by double-clicking it.

  • In the PWS Manager, right click on a given directory you want to add PHP support to, and select Properties. Check the 'Execute' checkbox, and confirm.


Windows NT/2000/XP and IIS 4 or newer

To install PHP on an NT/2000/XP Server running IIS 4 or newer, follow these instructions. You have two options to set up PHP, using the CGI binary (php.exe in PHP 4, or php-cgi.exe in PHP 5) or with the ISAPI module.

In either case, you need to start the Microsoft Management Console (may appear as 'Internet Services Manager', either in your Windows NT 4.0 Option Pack branch or the Control Panel=>Administrative Tools under Windows 2000/XP). Then right click on your Web server node (this will most probably appear as 'Default Web Server'), and select 'Properties'.

If you want to use the CGI binary, do the following:

  • Under 'Home Directory', 'Virtual Directory', or 'Directory', click on the 'Configuration' button, and then enter the App Mappings tab.

  • Click Add, and in the Executable box, type: C:\php\php.exe for PHP 4 or C:\php\php-cgi.exe for PHP 5 (assuming that you have unziped PHP in c:\php\).

  • In the Extension box, type the file name extension you want associated with PHP scripts. Leave 'Method exclusions' blank, and check the 'Script engine' checkbox. You may also like to check the 'check that file exists' box - for a small performance penalty, IIS (or PWS) will check that the script file exists and sort out authentication before firing up PHP. This means that you will get sensible 404 style error messages instead of CGI errors complaining that PHP did not output any data.

    You must start over from the previous step for each extension you want associated with PHP scripts. .php and .phtml are common, although .php3 may be required for legacy applications.

  • Set up the appropriate security. (This is done in Internet Service Manager), and if your NT Server uses NTFS file system, add execute rights for I_USR_ to the directory that contains php.exe / php-cgi.exe.

To use the ISAPI module, do the following:

  • If you don't want to perform HTTP Authentication using PHP, you can (and should) skip this step. Under ISAPI Filters, add a new ISAPI filter. Use PHP as the filter name, and supply a path to the php4isapi.dll / php5isapi.dll.

  • Under 'Home Directory', click on the 'Configuration' button. Add a new entry to the Application Mappings. Use the path to the php4isapi.dll / php5isapi.dll as the Executable, supply .php as the extension, leave 'Method exclusions' blank, and check the 'Script engine' checkbox.

  • Stop IIS completely (NET STOP iisadmin)

  • Start IIS again (NET START w3svc)

If you experience 100% CPU usage after some time, turn off the IIS setting Cache ISAPI Application.


Apache 1.3.x on Microsoft Windows

This section contains notes and hints specific to Apache 1.3.x installs of PHP on Microsoft Windows systems. There are also instructions and notes for Apache 2 on a separate page.

Nota: Please read the manual installation steps first!

There are two ways to set up PHP to work with Apache 1.3.x on Windows. One is to use the CGI binary (php.exe for PHP 4 and php-cgi.exe for PHP 5), the other is to use the Apache Module DLL. In either case you need to edit your httpd.conf to configure Apache to work with PHP, and then restart the server.

It is worth noting here that now the SAPI module has been made more stable under Windows, we recommend it's use above the CGI binary, since it is more transparent and secure.

Although there can be a few variations of configuring PHP under Apache, these are simple enough to be used by the newcomer. Please consult the Apache Documentation for further configuration directives.

After changing the configuration file, remember to restart the server, for example, NET STOP APACHE followed by NET START APACHE, if you run Apache as a Windows Service, or use your regular shortcuts.

Nota: Remember that when adding path values in the Apache configuration files on Windows, all backslashes such as c:\directory\file.ext must be converted to forward slashes, as c:/directory/file.ext.


Installing as an Apache module

You should add the following lines to your Apache httpd.conf file:

Esempio 6-3. PHP as an Apache 1.3.x module

This assumes PHP is installed to c:\php. Adjust the path if this is not the case.

For PHP 4:

# Add to the end of the LoadModule section
# Don't forget to copy this file from the sapi directory!
LoadModule php4_module "C:/php/php4apache.dll"

# Add to the end of the AddModule section
AddModule mod_php4.c

For PHP 5:

# Add to the end of the LoadModule section
LoadModule php5_module "C:/php/php5apache.dll"

# Add to the end of the AddModule section
AddModule mod_php5.c

For both:

# Add this line inside the <IfModule mod_mime.c> conditional brace
AddType application/x-httpd-php .php

# For syntax highlighted .phps files, also add
AddType application/x-httpd-php-source .phps


Installing as a CGI binary

If you unzipped the PHP package to C:\php\ as described in the Manual Installation Steps section, you need to insert these lines to your Apache configuration file to set up the CGI binary:

Esempio 6-4. PHP and Apache 1.3.x as CGI

ScriptAlias /php/ "c:/php/"
AddType application/x-httpd-php .php

# For PHP 4
Action application/x-httpd-php "/php/php.exe"

# For PHP 5
Action application/x-httpd-php "/php/php-cgi.exe"

# specify the directory where php.ini is
SetEnv PHPRC C:/php
Note that the second line in the list above can be found in the actual versions of httpd.conf, but it is commented out. Remember also to substitute the c:/php/ for your actual path to PHP.

Avvertimento

By using the CGI setup, your server is open to several possible attacks. Please read our CGI security section to learn how to defend yourself from those attacks.

If you would like to present PHP source files syntax highlighted, there is no such convenient option as with the module version of PHP. If you chose to configure Apache to use PHP as a CGI binary, you will need to use the highlight_file() function. To do this simply create a PHP script file and add this code: <?php highlight_file('some_php_script.php'); ?>.


Apache 2.0.x on Microsoft Windows

This section contains notes and hints specific to Apache 2.0.x installs of PHP on Microsoft Windows systems. We also have instructions and notes for Apache 1.3.x users on a separate page.

Nota: You should read the manual installation steps first!

Avvertimento

We do not recommend using a threaded MPM in production with Apache2. Use the prefork MPM instead, or use Apache1. For information on why, read the following FAQ entry

You are highly encouraged to take a look at the Apache Documentation to get a basic understanding of the Apache 2.0.x Server. Also consider to read the Windows specific notes for Apache 2.0.x before reading on here.

PHP and Apache 2.0.x compatibility notes: The following versions of PHP are known to work with the most recent version of Apache 2.0.x:

These versions of PHP are compatible to Apache 2.0.40 and later.

Apache 2.0 SAPI-support started with PHP 4.2.0. PHP 4.2.3 works with Apache 2.0.39, don't use any other version of Apache with PHP 4.2.3. However, the recommended setup is to use PHP 4.3.0 or later with the most recent version of Apache2.

All mentioned versions of PHP will work still with Apache 1.3.x.

Avvertimento

Apache 2.0.x is designed to run on Windows NT 4.0, Windows 2000 or Windows XP. At this time, support for Windows 9x is incomplete. Apache 2.0.x is not expected to work on those platforms at this time.

Download the most recent version of Apache 2.0.x and a fitting PHP version. Follow the Manual Installation Steps and come back to go on with the integration of PHP and Apache.

There are two ways to set up PHP to work with Apache 2.0.x on Windows. One is to use the CGI binary the other is to use the Apache module DLL. In either case you need to edit your httpd.conf to configure Apache to work with PHP and then restart the server.

Nota: Remember that when adding path values in the Apache configuration files on Windows, all backslashes such as c:\directory\file.ext must be converted to forward slashes, as c:/directory/file.ext.


Installing as a CGI binary

You need to insert these three lines to your Apache httpd.conf configuration file to set up the CGI binary:

Esempio 6-5. PHP and Apache 2.0 as CGI

ScriptAlias /php/ "c:/php/"
AddType application/x-httpd-php .php

# For PHP 4
Action application/x-httpd-php "/php/php.exe"

# For PHP 5
Action application/x-httpd-php "/php/php-cgi.exe"

Avvertimento

By using the CGI setup, your server is open to several possible attacks. Please read our CGI security section to learn how to defend yourself from those attacks.


Installing as an Apache module

You need to insert these two lines to your Apache httpd.conf configuration file to set up the PHP module for Apache 2.0:

Esempio 6-6. PHP and Apache 2.0 as Module

# For PHP 4 do something like this:
LoadModule php4_module "c:/php/php4apache2.dll"
# Don't forget to copy the php4apache2.dll file from the sapi directory!
AddType application/x-httpd-php .php

# For PHP 5 do something like this:
LoadModule php5_module "c:/php/php5apache2.dll"
AddType application/x-httpd-php .php

# configure the path to php.ini
PHPIniDir "C:/php"

Nota: Remember to substitute the c:/php/ for your actual path to PHP in the above examples. Take care to use either php4apache2.dll or php5apache2.dll in your LoadModule directive and not php4apache.dll or php5apache.dll as the latter ones are designed to run with Apache 1.3.x.

Nota: If you want to use content negotiation, read related FAQ.

Avvertimento

Don't mix up your installation with DLL files from different PHP versions. You have the only choice to use the DLL's and extensions that ship with your downloaded PHP version.


Sun, iPlanet and Netscape servers on Microsoft Windows

This section contains notes and hints specific to Sun Java System Web Server, Sun ONE Web Server, iPlanet and Netscape server installs of PHP on Windows.

From PHP 4.3.3 on you can use PHP scripts with the NSAPI module to generate custom directory listings and error pages. Additional functions for Apache compatibility are also available. For support in current webservers read the note about subrequests.


CGI setup on Sun, iPlanet and Netscape servers

To install PHP as a CGI handler, do the following:

  • Copy php4ts.dll to your systemroot (the directory where you installed Windows)

  • Make a file association from the command line. Type the following two lines:
    assoc .php=PHPScript
    ftype PHPScript=c:\php\php.exe %1 %*

  • In the Netscape Enterprise Administration Server create a dummy shellcgi directory and remove it just after (this step creates 5 important lines in obj.conf and allow the web server to handle shellcgi scripts).

  • In the Netscape Enterprise Administration Server create a new mime type (Category: type, Content-Type: magnus-internal/shellcgi, File Suffix:php).

  • Do it for each web server instance you want PHP to run

More details about setting up PHP as a CGI executable can be found here: http://benoit.noss.free.fr/php/install-php.html


NSAPI setup on Sun, iPlanet and Netscape servers

To install PHP with NSAPI, do the following:

  • Copy php4ts.dll to your systemroot (the directory where you installed Windows)

  • Make a file association from the command line. Type the following two lines:
    assoc .php=PHPScript
    ftype PHPScript=c:\php\php.exe %1 %*

  • In the Netscape Enterprise Administration Server create a new mime type (Category: type, Content-Type: magnus-internal/x-httpd-php, File Suffix: php).

  • Edit magnus.conf (for servers >= 6) or obj.conf (for servers < 6) and add the following: You should place the lines after mime types init.
    Init fn="load-modules" funcs="php4_init,php4_execute,php4_auth_trans" shlib="c:/php/sapi/php4nsapi.dll"
    Init fn="php4_init" LateInit="yes" errorString="Failed to initialise PHP!" [php_ini="c:/path/to/php.ini"]
    (PHP >= 4.3.3) The php_ini parameter is optional but with it you can place your php.ini in your webserver config directory.

  • Configure the default object in obj.conf (for virtual server classes [Sun Web Server 6.0+] in their vserver.obj.conf): In the <Object name="default"> section, place this line necessarily after all 'ObjectType' and before all 'AddLog' lines:
    Service fn="php4_execute" type="magnus-internal/x-httpd-php" [inikey=value inikey=value ...]
    (PHP >= 4.3.3) As additional parameters you can add some special php.ini-values, for example you can set a docroot="/path/to/docroot" specific to the context php4_execute is called. For boolean ini-keys please use 0/1 as value, not "On","Off",... (this will not work correctly), e.g. zlib.output_compression=1 instead of zlib.output_compression="On"

  • This is only needed if you want to configure a directory that only consists of PHP scripts (same like a cgi-bin directory):
    <Object name="x-httpd-php">
    ObjectType fn="force-type" type="magnus-internal/x-httpd-php"
    Service fn=php4_execute [inikey=value inikey=value ...]
    </Object>
    After that you can configure a directory in the Administration server and assign it the style x-httpd-php. All files in it will get executed as PHP. This is nice to hide PHP usage by renaming files to .html.

  • Restart your web service and apply changes

  • Do it for each web server instance you want PHP to run

Nota: More details about setting up PHP as an NSAPI filter can be found here: http://benoit.noss.free.fr/php/install-php4.html

Nota: The stacksize that PHP uses depends on the configuration of the webserver. If you get crashes with very large PHP scripts, it is recommended to raise it with the Admin Server (in the section "MAGNUS EDITOR").


CGI environment and recommended modifications in php.ini

Important when writing PHP scripts is the fact that Sun JSWS/Sun ONE WS/iPlanet/Netscape is a multithreaded web server. Because of that all requests are running in the same process space (the space of the webserver itself) and this space has only one environment. If you want to get CGI variables like PATH_INFO, HTTP_HOST etc. it is not the correct way to try this in the old PHP 3.x way with getenv() or a similar way (register globals to environment, $_ENV). You would only get the environment of the running webserver without any valid CGI variables!

Nota: Why are there (invalid) CGI variables in the environment?

Answer: This is because you started the webserver process from the admin server which runs the startup script of the webserver, you wanted to start, as a CGI script (a CGI script inside of the admin server!). This is why the environment of the started webserver has some CGI environment variables in it. You can test this by starting the webserver not from the administration server. Use the command line as root user and start it manually - you will see there are no CGI-like environment variables.

Simply change your scripts to get CGI variables in the correct way for PHP 4.x by using the superglobal $_SERVER. If you have older scripts which use $HTTP_HOST, etc., you should turn on register_globals in php.ini and change the variable order too (important: remove "E" from it, because you do not need the environment here):
variables_order = "GPCS"
register_globals = On


Special use for error pages or self-made directory listings (PHP >= 4.3.3)

You can use PHP to generate the error pages for "404 Not Found" or similar. Add the following line to the object in obj.conf for every error page you want to overwrite:
Error fn="php4_execute" code=XXX script="/path/to/script.php" [inikey=value inikey=value...]
where XXX is the HTTP error code. Please delete any other Error directives which could interfere with yours. If you want to place a page for all errors that could exist, leave the code parameter out. Your script can get the HTTP status code with $_SERVER['ERROR_TYPE'].

Another possibility is to generate self-made directory listings. Just create a PHP script which displays a directory listing and replace the corresponding default Service line for type="magnus-internal/directory" in obj.conf with the following:
Service fn="php4_execute" type="magnus-internal/directory" script="/path/to/script.php" [inikey=value inikey=value...]
For both error and directory listing pages the original URI and translated URI are in the variables $_SERVER['PATH_INFO'] and $_SERVER['PATH_TRANSLATED'].


Note about nsapi_virtual() and subrequests (PHP >= 4.3.3)

The NSAPI module now supports the nsapi_virtual() function (alias: virtual()) to make subrequests on the webserver and insert the result in the webpage. The problem is, that this function uses some undocumented features from the NSAPI library.

Under Unix this is not a problem, because the module automatically looks for the needed functions and uses them if available. If not, nsapi_virtual() is disabled.

Under Windows limitations in the DLL handling need the use of a automatic detection of the most recent ns-httpdXX.dll file. This is tested for servers till version 6.1. If a newer version of the Sun server is used, the detection fails and nsapi_virtual() is disabled.

If this is the case, try the following: Add the following parameter to php4_init in magnus.conf/obj.conf:
Init fn=php4_init ... server_lib="ns-httpdXX.dll"
where XX is the correct DLL version number. To get it, look in the server-root for the correct DLL name. The DLL with the biggest filesize is the right one.

You can check the status by using the phpinfo() function.

Nota: But be warned: Support for nsapi_virtual() is EXPERIMENTAL!!!


OmniHTTPd Server

This section contains notes and hints specific to OmniHTTPd on Windows.

Nota: You should read the manual installation steps first!

Avvertimento

By using the CGI setup, your server is open to several possible attacks. Please read our CGI security section to learn how to defend yourself from those attacks.

You need to complete the following steps to make PHP work with OmniHTTPd. This is a CGI executable setup. SAPI is supported by OmniHTTPd, but some tests have shown that it is not so stable to use PHP as an ISAPI module.

Important for CGI users: Read the faq on cgi.force_redirect for important details. This directive needs to be set to 0.

  1. Install OmniHTTPd server.

  2. Right click on the blue OmniHTTPd icon in the system tray and select Properties

  3. Click on Web Server Global Settings

  4. On the 'External' tab, enter: virtual = .php | actual = c:\php\php.exe (use php-cgi.exe if installing PHP 5), and use the Add button.

  5. On the Mime tab, enter: virtual = wwwserver/stdcgi | actual = .php, and use the Add button.

  6. Click OK

Repeat steps 2 - 6 for each extension you want to associate with PHP.

Nota: Some OmniHTTPd packages come with built in PHP support. You can choose at setup time to do a custom setup, and uncheck the PHP component. We recommend you to use the latest PHP binaries. Some OmniHTTPd servers come with PHP 4 beta distributions, so you should choose not to set up the built in support, but install your own. If the server is already on your machine, use the Replace button in Step 4 and 5 to set the new, correct information.


Sambar Server on Microsoft Windows

This section contains notes and hints specific to the Sambar Server for Windows.

Nota: You should read the manual installation steps first!

This list describes how to set up the ISAPI module to work with the Sambar server on Windows.

  • Find the file called mappings.ini (in the config directory) in the Sambar install directory.

  • Open mappings.ini and add the following line under [ISAPI]:

    Esempio 6-7. ISAPI configuration of Sambar

    #for PHP 4
    *.php = c:\php\php4isapi.dll
    
    #for PHP 5
    *.php = c:\php\php5isapi.dll
    (This line assumes that PHP was installed in c:\php.)

  • Now restart the Sambar server for the changes to take effect.


Xitami on Microsoft Windows

This section contains notes and hints specific to Xitami on Windows.

Nota: You should read the manual installation steps first!

This list describes how to set up the PHP CGI binary to work with Xitami on Windows.

Important for CGI users: Read the faq on cgi.force_redirect for important details. This directive needs to be set to 0. If you want to use $_SERVER['PHP_SELF'] you have to enable the cgi.fix_pathinfo directive.

Avvertimento

By using the CGI setup, your server is open to several possible attacks. Please read our CGI security section to learn how to defend yourself from those attacks.

  • Make sure the webserver is running, and point your browser to xitamis admin console (usually http://127.0.0.1/admin), and click on Configuration.

  • Navigate to the Filters, and put the extension which PHP should parse (i.e. .php) into the field File extensions (.xxx).

  • In Filter command or script put the path and name of your PHP CGI executable i.e. C:\php\php.exe for PHP 4, or C:\php\php-cgi.exe for PHP 5.

  • Press the 'Save' icon.

  • Restart the server to reflect changes.


Building from source

Before getting started, it is worthwhile answering the question: "Why is building on Windows so hard?" Two reasons come to mind:

  1. Windows does not (yet) enjoy a large community of developers who are willing to freely share their source. As a direct result, the necessary investment in infrastructure required to support such development hasn't been made. By and large, what is available has been made possible by the porting of necessary utilities from Unix. Don't be surprised if some of this heritage shows through from time to time.

  2. Pretty much all of the instructions that follow are of the "set and forget" variety. So sit back and try follow the instructions below as faithfully as you can.


Requisiti

To compile and build PHP you need a Microsoft Development Environment. Microsoft Visual C++ 6.0 is recommended. To extract the downloaded files you need a extraction utility (e.g.: Winzip). If you don't already have an unzip utility, you can get a free version from InfoZip.

Before you get started, you have to download...

Finally, you are going to need the source to PHP itself. You can get the latest development version using anonymous CVS, a snapshot or the most recent released source tarball.


Putting it all together

After downloading the required packages you have to extract them in a proper place.

  • Create a working directory where all files end up after extracting, e.g: C:\work.

  • Create the directory win32build under your working directory (C:\work) and unzip win32build.zip into it.

  • Create the directory bindlib_w32 under your working directory (C:\work) and unzip bindlib_w32.zip into it.

  • Extract the downloaded PHP source code into your working directory (C:\work).

Following this steps your directory structure looks like this:

+--c:\work
|  |
|  +--bindlib_w32
|  |  |
|  |  +--arpa
|  |  |
|  |  +--conf
|  |  |
|  |  +--...
|  |
|  +--php-4.x.x
|  |  |
|  |  +--build
|  |  |
|  |  +--...
|  |  |
|  |  +--win32
|  |  |
|  |  +--...
|  |
|  +--win32build
|  |  |
|  |  +--bin
|  |  |
|  |  +--include
|  |  |
|  |  +--lib

Create the directories c:\usr\local\lib. Copy bison.simple from c:\work\win32build\bin to c:\usr\local\lib.

Nota: Cygwin users may omit the last step. A properly installed Cygwin environment provides the mandatory files bison.simple and bison.exe.


Configure MVC ++

The next step is to configure MVC ++ to prepare for compiling. Launch Microsoft Visual C++, and from the menu select Tools => Options. In the dialog, select the directories tab. Sequentially change the dropdown to Executables, Includes, and Library files. Your entries should look like this:

  • Executable files: c:\work\win32build\bin, Cygwin users: cygwin\bin

  • Include files: c:\work\win32build\include

  • Library files: c:\work\win32build\lib


Build resolv.lib

You must build the resolv.lib library. Decide whether you want to have debug symbols available (bindlib - Win32 Debug) or not (bindlib - Win32 Release). Build the appropriate configuration:

  • For GUI users, launch VC++, and then select File => Open Workspace, navigate to c:\work\bindlib_w32 and select bindlib.dsw. Then select Build=>Set Active Configuration and select the desired configuration. Finally select Build=>Rebuild All.

  • For command line users, make sure that you either have the C++ environment variables registered, or have run vcvars.bat, and then execute one of the following commands:

    • msdev bindlib.dsp /MAKE "bindlib - Win32 Debug"

    • msdev bindlib.dsp /MAKE "bindlib - Win32 Release"

At this point, you should have a usable resolv.lib in either your c:\work\bindlib_w32\Debug or Release subdirectories. Copy this file into your c:\work\win32build\lib directory over the file by the same name found in there.


Compiling

The best way to get started is to build the CGI version.

  • For GUI users, launch VC++, and then select File => Open Workspace and select c:\work\php-4.x.x\win32\php4ts.dsw . Then select Build=>Set Active Configuration and select the desired configuration, either php4ts - Win32 Debug_TS or php4ts - Win32 Release_TS. Finally select Build=>Rebuild All.

  • For command line users, make sure that you either have the C++ environment variables registered, or have run vcvars.bat, and then execute one of the following commands from the c:\work\php-4.x.x\win32 directory:

    • msdev php4ts.dsp /MAKE "php4ts - Win32 Debug_TS"

    • msdev php4ts.dsp /MAKE "php4ts - Win32 Release_TS"

    • At this point, you should have a usable php.exe in either your c:\work\php-4.x.x.\Debug_TS or Release_TS subdirectories.

It is possible to do minor customization to the build process by editing the main/config.win32.h file. For example you can change the default location of php.ini, the built-in extensions, and the default location for your extensions.

Next you may want to build the CLI version which is designed to use PHP from the command line. The steps are the same as for building the CGI version, except you have to select the php4ts_cli - Win32 Debug_TS or php4ts_cli - Win32 Release_TS project file. After a successful compiling run you will find the php.exe in either the directory Release_TS\cli\ or Debug_TS\cli\.

Nota: If you want to use PEAR and the comfortable command line installer, the CLI-SAPI is mandatory. For more information about PEAR and the installer read the documentation at the PEAR website.

In order to build the SAPI module (php4isapi.dll) for integrating PHP with Microsoft IIS, set your active configuration to php4isapi-whatever-config and build the desired dll.


Installation of extensions on Windows

After installing PHP and a webserver on Windows, you will probably want to install some extensions for added functionality. You can choose which extensions you would like to load when PHP starts by modifying your php.ini. You can also load a module dynamically in your script using dl().

The DLLs for PHP extensions are prefixed with php_.

Nota: In PHP 4.3.1 BCMath, Calendar, COM, Ctype, FTP, MySQL, ODBC, Overload, PCRE, Session, Tokenizer, WDDX, XML and Zlib support is built in. You don't need to load any additional extensions in order to use these functions. See your distributions README.txt or install.txt or this table for a list of built in modules.

The default location PHP searches for extensions is c:\php4\extensions in PHP 4 and c:\php5 in PHP 5. To change this setting to reflect your setup of PHP edit your php.ini file:

  • You will need to change the extension_dir setting to point to the directory where your extensions lives, or where you have placed your php_*.dll files. Please do not forget the last backslash. For example:

    extension_dir = c:/php/extensions/

  • Enable the extension(s) in php.ini you want to use by uncommenting the extension=php_*.dll lines in php.ini. This is done by deleting the leading ; from the extension you want to load.

    Esempio 6-8. Enable Bzip2 extension for PHP-Windows

    // change the following line from ...
    ;extension=php_bz2.dll
    
    // ... to
    extension=php_bz2.dll

  • Some of the extensions need extra DLLs to work. Couple of them can be found in the distribution package, in the C:\php\dlls\ folder in PHP 4 or in the main folder in PHP 5, but some, for example Oracle (php_oci8.dll) require DLLs which are not bundled with the distribution package. If you are installing PHP 4, copy the bundled DLLs from C:\php\dlls folder to the main C:\php folder. Don't forget to include C:\php in the system PATH (this process is explained in a separate FAQ entry).

  • Some of these DLLs are not bundled with the PHP distribution. See each extensions documentation page for details. Also, read the manual section titled Installation of PECL extensions for details on PECL. An increasingly large number of PHP extensions are found in PECL, and these extensions require a separate download.

Nota: If you are running a server module version of PHP remember to restart your webserver to reflect your changes to php.ini.

The following table describes some of the extensions available and required additional dlls.

Tabella 6-1. PHP Extensions

ExtensionDescriptionNotes
php_bz2.dllbzip2 compression functionsNone
php_calendar.dllCalendar conversion functionsBuilt in since PHP 4.0.3
php_cpdf.dllClibPDF functionsNone
php_crack.dllCrack functionsNone
php_ctype.dllctype family functionsBuilt in since PHP 4.3.0
php_curl.dllCURL, Client URL library functionsRequires: libeay32.dll, ssleay32.dll (bundled)
php_cybercash.dllCybercash payment functionsPHP <= 4.2.0
php_db.dllDBM functionsDeprecated. Use DBA instead (php_dba.dll)
php_dba.dllDBA: DataBase (dbm-style) Abstraction layer functionsNone
php_dbase.dlldBase functionsNone
php_dbx.dlldbx functions 
php_domxml.dllDOM XML functions PHP <= 4.2.0 requires: libxml2.dll (bundled) PHP >= 4.3.0 requires: iconv.dll (bundled)
php_dotnet.dll.NET functionsPHP <= 4.1.1
php_exif.dllEXIF functions php_mbstring.dll. And, php_exif.dll must be loaded after php_mbstring.dll in php.ini.
php_fbsql.dllFrontBase functionsPHP <= 4.2.0
php_fdf.dllFDF: Forms Data Format functions.Requires: fdftk.dll (bundled)
php_filepro.dllfilePro functionsRead-only access
php_ftp.dllFTP functionsBuilt-in since PHP 4.0.3
php_gd.dllGD library image functions Removed in PHP 4.3.2. Also note that truecolor functions are not available in GD1, instead, use php_gd2.dll.
php_gd2.dllGD library image functionsGD2
php_gettext.dllGettext functions PHP <= 4.2.0 requires gnu_gettext.dll (bundled), PHP >= 4.2.3 requires libintl-1.dll, iconv.dll (bundled).
php_hyperwave.dllHyperWave functionsNone
php_iconv.dllICONV characterset conversionRequires: iconv-1.3.dll (bundled), PHP >=4.2.1 iconv.dll
php_ifx.dllInformix functionsRequires: Informix libraries
php_iisfunc.dllIIS management functionsNone
php_imap.dllIMAP POP3 and NNTP functionsNone
php_ingres.dllIngres II functionsRequires: Ingres II libraries
php_interbase.dllInterBase functionsRequires: gds32.dll (bundled)
php_java.dllJava functionsPHP <= 4.0.6 requires: jvm.dll (bundled)
php_ldap.dllLDAP functions PHP <= 4.2.0 requires libsasl.dll (bundled), PHP >= 4.3.0 requires libeay32.dll, ssleay32.dll (bundled)
php_mbstring.dllMulti-Byte String functionsNone
php_mcrypt.dllMcrypt Encryption functionsRequires: libmcrypt.dll
php_mhash.dllMhash functionsPHP >= 4.3.0 requires: libmhash.dll (bundled)
php_mime_magic.dllMimetype functionsRequires: magic.mime (bundled)
php_ming.dllMing functions for FlashNone
php_msql.dllmSQL functionsRequires: msql.dll (bundled)
php_mssql.dllMSSQL functionsRequires: ntwdblib.dll (bundled)
php_mysql.dllMySQL functionsPHP >= 5.0.0, requires libmysql.dll (bundled)
php_mysqli.dllMySQLi functionsPHP >= 5.0.0, requires libmysql.dll (libmysqli.dll in PHP <= 5.0.2) (bundled)
php_oci8.dllOracle 8 functionsRequires: Oracle 8.1+ client libraries
php_openssl.dllOpenSSL functionsRequires: libeay32.dll (bundled)
php_oracle.dllOracle functionsRequires: Oracle 7 client libraries
php_overload.dllObject overloading functionsBuilt in since PHP 4.3.0
php_pdf.dllPDF functionsNone
php_pgsql.dllPostgreSQL functionsNone
php_printer.dllPrinter functionsNone
php_shmop.dllShared Memory functionsNone
php_snmp.dllSNMP get and walk functionsNT only!
php_soap.dllSOAP functionsPHP >= 5.0.0
php_sockets.dllSocket functionsNone
php_sybase_ct.dllSybase functionsRequires: Sybase client libraries
php_tidy.dllTidy functionsPHP >= 5.0.0
php_tokenizer.dllTokenizer functionsBuilt in since PHP 4.3.0
php_w32api.dllW32api functionsNone
php_xmlrpc.dllXML-RPC functionsPHP >= 4.2.1 requires: iconv.dll (bundled)
php_xslt.dllXSLT functions PHP <= 4.2.0 requires sablot.dll, expat.dll (bundled). PHP >= 4.2.1 requires sablot.dll, expat.dll, iconv.dll (bundled).
php_yaz.dllYAZ functionsRequires: yaz.dll (bundled)
php_zip.dllZip File functionsRead only access
php_zlib.dllZLib compression functionsBuilt in since PHP 4.3.0


Capitolo 7. Installation of PECL extensions

Introduction to PECL Installations

PHP extensions may be installed in a variety of ways. PECL is a repository of PHP extensions living within the PEAR structure, and the following demonstrates how to install these extensions.

These instructions assume /your/phpsrcdir/ is the path to the PHP source, and extname is the name of the PECL extension. Adjust accordingly. These instructions also assume a familiarity with the pear command.

Shared extensions may be installed by including them inside of php.ini using the extension PHP directive. See also the extensions_dir directive, and dl(). The installation methods described below do not automatically configure PHP to include these extensions, this step must be done manually.

When building PHP modules, it's important to have the appropriate versions of the required tools (autoconf, automake, libtool, etc.) See the Anonymous CVS Instructions for details on the required tools, and required versions.


Downloading PECL extensions

There are several options for downloading PECL extensions, such as:

  • http://pecl.php.net

    Listed here is information like the ChangeLog, release information, requirements, revisions, etc. Although not every PECL extension has a webpage, most do.

  • pear download extname

    The pear command may also be used to download source files. Specific revisions may also be specified.

  • CVS

    All PECL files reside in CVS. A web-based view may be seen at http://cvs.php.net/pecl/. To download straight from CVS, consider the following where phpfi is the password for user cvsread:

    $ cvs -d:pserver:cvsread@cvs.php.net:/repository login 
    $ cvs -d:pserver:cvsread@cvs.php.net:/repository co pecl/extname

  • Windows downloads

    Windows users may find compiled PECL binaries by downloading the Collection of PECL modules from the PHP Downloads page, and by retrieving a PECL Snapshot. To compile PHP under Windows, read the Win32 Build README.


PECL for Windows users

Like with any other PHP extension DLL, to install move the PECL extension DLLs into the extension_dir folder and include them within php.ini. For example:

extension=php_extname.dll

After doing this, restart the web server.


Compiling shared PECL extensions with PEAR

PEAR makes it easy to create shared PHP extensions. Using the pear command, do the following:

$ pear install extname

That will download the source for extname, and compile it on the system. This results in an extname.so file that may then be included in php.ini

In case the systems preferred_state is set higher than an available extname version, like it's set to stable and the extension is still in beta, either alter the preferred_state via pear config-set or specify a specific version of the PECL extension. For example:

$ pear install extname-0.1.1

Regardless, pear will copy this extname.so into the extensions directory. Adjust php.ini accordingly.


Compiling shared PECL extensions with phpize

If using pear is not an option, like for building shared PECL extensions from CVS, or for unreleased PECL packages, then creating a shared extension may also be done by manually using the phpize command. The pear command essentially does this but it may also be done manually. Assuming the source file is named extname.tgz, and that it was downloaded into the current directory, consider the following:

$ pear download extname
$ gzip -d < extname.tgz | tar -xvf -
$ cd extname
$ phpize
$ ./configure && make

Upon success, this will create extname.so and put it into the modules/ and/or .libs/ directory within the extname/ source. Move this shared extension (extname.so) into the PHP extensions directory, and adjust php.ini accordingly.


Compiling PECL extensions statically into PHP

To statically include the extension within the PHP build, put the extensions source into the ext/ directory found in the PHP source. For example:

$ cd /your/phpsrcdir/ext
$ pear download extname
$ gzip -d < extname.tgz | tar -xvf -
$ mv extname-x.x.x extname
$ rm package.xml

This will result in the following directory:

/your/phpsrcdir/ext/extname

From here, build PHP as normal:

$ cd /your/phpsrcdir 
$ ./buildconf
$ ./configure --help
$ ./configure --with-extname --enable-someotherext --with-foobar
$ make
$ make install

Whether --enable-extname or --with-extname is used depends on the extension. Typically an extension that does not require external libraries uses --enable. To be sure, run the following after buildconf:

$ ./configure --help | grep extname


Capitolo 8. Problems?

Read the FAQ

Some problems are more common than others. The most common ones are listed in the PHP FAQ, part of this manual.


Other problems

If you are still stuck, someone on the PHP installation mailing list may be able to help you. You should check out the archive first, in case someone already answered someone else who had the same problem as you. The archives are available from the support page on http://www.php.net/support.php. To subscribe to the PHP installation mailing list, send an empty mail to php-install-subscribe@lists.php.net. The mailing list address is php-install@lists.php.net.

If you want to get help on the mailing list, please try to be precise and give the necessary details about your environment (which operating system, what PHP version, what web server, if you are running PHP as CGI or a server module, safe mode, etc...), and preferably enough code to make others able to reproduce and test your problem.


Bug reports

If you think you have found a bug in PHP, please report it. The PHP developers probably don't know about it, and unless you report it, chances are it won't be fixed. You can report bugs using the bug-tracking system at http://bugs.php.net/. Please do not send bug reports in mailing list or personal letters. The bug system is also suitable to submit feature requests.

Read the How to report a bug document before submitting any bug reports!


Capitolo 9. Runtime Configuration

The configuration file

The configuration file (called php3.ini in PHP 3, and simply php.ini as of PHP 4) is read when PHP starts up. For the server module versions of PHP, this happens only once when the web server is started. For the CGI and CLI version, it happens on every invocation.

The default location of php.ini is a compile time option (see the FAQ entry), but can be changed for the CGI and CLI version with the -c command line switch, see the chapter about using PHP from the command line. You can also use the environment variable PHPRC for an additional path to search for a php.ini file.

If php-SAPI.ini exists (where SAPI is used SAPI, so the filename is e.g. php-cli.ini or php-apache.ini), it's used instead of php.ini.

Nota: The Apache web server changes the directory to root at startup causing PHP to attempt to read php.ini from the root filesystem if it exists.

The php.ini directives handled by extensions are documented respectively on the pages of the extensions themselves. The list of the core directives is available in the appendix. Probably not all the PHP directives are documented in the manual though. For a completel list of directives available in your PHP version, please read your well commented php.ini file. Alternatively, you may find the the latest php.ini from CVS helpful too.

Esempio 9-1. php.ini example

; any text on a line after an unquoted semicolon (;) is ignored
[php] ; section markers (text within square brackets) are also ignored
; Boolean values can be set to either:
;    true, on, yes
; or false, off, no, none
register_globals = off
track_errors = yes

; you can enclose strings in double-quotes
include_path = ".:/usr/local/lib/php"

; backslashes are treated the same as any other character
include_path = ".;c:\php\lib"


How to change configuration settings

Running PHP as an Apache module

When using PHP as an Apache module, you can also change the configuration settings using directives in Apache configuration files (e.g. httpd.conf) and .htaccess files. You will need "AllowOverride Options" or "AllowOverride All" privileges to do so.

With PHP 4 and PHP 5, there are several Apache directives that allow you to change the PHP configuration from within the Apache configuration files. For a listing of which directives are PHP_INI_ALL, PHP_INI_PERDIR, or PHP_INI_SYSTEM, have a look at Appendice H.

Nota: With PHP 3, there are Apache directives that correspond to each configuration setting in the php3.ini name, except the name is prefixed by "php3_".

php_value name value

Sets the value of the specified directive. Can be used only with PHP_INI_ALL and PHP_INI_PERDIR type directives. To clear a previously set value use none as the value.

Nota: Don't use php_value to set boolean values. php_flag (see below) should be used instead.

php_flag name on|off

Used to set a boolean configuration directive. Can be used only with PHP_INI_ALL and PHP_INI_PERDIR type directives.

php_admin_value name value

Sets the value of the specified directive. This can not be used in .htaccess files. Any directive type set with php_admin_value can not be overridden by .htaccess or virtualhost directives. To clear a previously set value use none as the value.

php_admin_flag name on|off

Used to set a boolean configuration directive. This can not be used in .htaccess files. Any directive type set with php_admin_flag can not be overridden by .htaccess or virtualhost directives.

Esempio 9-2. Apache configuration example

<IfModule mod_php5.c>
  php_value include_path ".:/usr/local/lib/php"
  php_admin_flag safe_mode on
</IfModule>
<IfModule mod_php4.c>
  php_value include_path ".:/usr/local/lib/php"
  php_admin_flag safe_mode on
</IfModule>
<IfModule mod_php3.c>
  php3_include_path ".:/usr/local/lib/php"
  php3_safe_mode on
</IfModule>

Attenzione

PHP constants do not exist outside of PHP. For example, in httpd.conf you can not use PHP constants such as E_ALL or E_NOTICE to set the error_reporting directive as they will have no meaning and will evaluate to 0. Use the associated bitmask values instead. These constants can be used in php.ini


Changing PHP configuration via the Windows registry

When running PHP on Windows, the configuration values can be modified on a per-directory basis using the Windows registry. The configuration values are stored in the registry key HKLM\SOFTWARE\PHP\Per Directory Values, in the sub-keys corresponding to the path names. For example, configuration values for the directory c:\inetpub\wwwroot would be stored in the key HKLM\SOFTWARE\PHP\Per Directory Values\c\inetpub\wwwroot. The settings for the directory would be active for any script running from this directory or any subdirectory of it. The values under the key should have the name of the PHP configuration directive and the string value. PHP constants in the values are not parsed.


Other interfaces to PHP

Regardless of how you run PHP, you can change certain values at runtime of your scripts through ini_set(). See the documentation on the ini_set() page for more information.

If you are interested in a complete list of configuration settings on your system with their current values, you can execute the phpinfo() function, and review the resulting page. You can also access the values of individual configuration directives at runtime using ini_get() or get_cfg_var().


Capitolo 10. Sintassi Fondamentale

Modi per uscire dalla modalità HTML

Quando il PHP inizia a esaminare un file, visualizzerà il contenuto del file sino a quando non incontra uno dei tag speciali indicanti l'inizio del codice da interpretare come istruzioni PHP. A questo punto il parser eseguirà tutto il codice trovato sino a quando non incontrerà i tag di chiusura, che indicano al parser di tornare alla modalità di visualizzazione. Questo meccanismo permette di inserire codice PHP all'interno di codice HTML: tutto ciò che si trova all'esterno dei tag PHP sarà lasciato inalterato, mentre tutto ciò che si trova all'interno sarà eseguito come codice PHP.

Esistono 4 set di tag che possono essere utilizzati per delimitare blocchi di codice PHP. Soltanto due di questi (<?php. . .?> e <script language="php">. . .</script>) sono sempre disponibili; gli altri possono essere attivati o disattivati tramite il file di configurazione php.ini. Sebbene i tag brevi o quelli in stile ASP possano essere pratici, il supporto di questi non è garantito in tutte le versioni. Quindi, se si intende inserire codice PHP all'interno di testi XMl o XHTML, occorre utilizzare <?php. . .?> per essere conformi allo standard XML.  

I tag supportati dal PHP sono:     

Esempio 10-1. Metodi per uscire dalla modalità HTML

1.  <?php echo("se si vogliono produrre documenti XHTML o XML, si utilizzi questo modo\n"); ?>

2.  <? echo ("questo è il più semplice, ovvero come istruzione SGML\n"); ?>
    <?= espressione ?>  Questa è un'abbreviazione per "<? echo espressione ?>"
 
3.  <script language="php">
        echo ("alcuni editor (tipo FrontPage) non 
               amano le istruzioni di elaborazione");
    </script>

4.  <% echo ("Opzionalmente puoi utilizzare tag nello stile ASP"); %>
    <%= $variable; # Questo &egrave; una abbreviazione per "<%echo .." %>

Il primo, <?php. . .?>, è il metodo preferenziale, dato che permette l'utilizzo del PHP all'interno di codice conforme a specifiche XML come XHTML.

Il secondo metodo è disponibile solo se sono stati abilitati i tags abbreviati. Ciò può essere impostato sia utilizzando la funzione short_tags() (solo PHP 3), sia abilitando nel file di configurazione del PHP l'opzione short_open_tag, oppure compilando il PHP utilizzando l'opzione --enable-short-tags nel comando configure. Sebbene siano abilitati nel php.ini-dist riilasciato, l'uso dei tag brevi è vivamente sconsigliato.

Il quarto modo è disponibile solo se sono stati attivati nel file di configurazione i tag in stile ASP tramite l'opzione asp_tags.

Nota: Il supporto per i tag nello stile ASP è stato aggiunto nella versione 3.0.4.

Nota:      L'utilizzo dei tag brevi dovrebbe essere evitato nello sviluppo di applicazioni o librerie destinate alla distribuzione o destinati a server di produzione PHP di cui non si ha il controllo poichè questi tag potrebbero non essere attivi sul server di destinazione. Per avere maggiore portabilità, codice redistribuibile, occorre essere certi di non utilizzare i tag brevi.    

Il tag di chiusura di un blocco include il carattere di 'a capo' immediatamente seguente, se presente. Inoltre, il tag di chiusura viene considerato automaticamente come punto e virgola; pertanto non occorre inserire il punto e virgola alla fine dell'ultima riga del blocco php.      

Il PHP permette strutture tipo le seguenti:

Esempio 10-2. Modi avanzati per uscire dalla modalità HTML

<?php
if ($expression) {
    ?>
    <strong>Questa è vera.</strong>
    <?php
} else {
    ?>
    <strong>Questa è falsa.</strong>
    <?php
}
?>
Questo esempio agisce come atteso, poichè il PHP rileva il tag di chiusura ?>, e da questo punto, inizia a dare in output tutto ciò che trova fino a quando non rileva un'altro tag di apertura. Certamente l'esempio dato è macchinoso, ma per l'output di grossi blocchi di testo, l'uscire dalla modalità di parsing PHP, è generalmente più efficiente piuttosto che inviare il testo tramite ripetute funzioni echo() o print().


Separazione delle istruzioni

Le istruzioni sono separate come nel C o in Perl - ogni istruzione termina con un punto e virgola.

Il tag di chiusura (?>) implica anche la fine di un'istruzione, perciò le seguenti sono equivalenti:

<?php
    echo "Questo &grave; un test";
?>
<?php echo "Questo &grave; un test" ?>


Commenti

Il PHP supporta i commenti dei linguaggi 'C', 'C++' e della shell Unix. Per esempio:

<?php
    echo "Questo &grave; un test"; // Questo &egrave; un commento su una linea nella stile c++ 
    /* Questo &egrave; un commento su pi&ugrave; linee
       ancora un'altra linea di commento */
    echo "Questo &egrave; un altro test";
    echo "Un ultimo test"; # Questo &egrave; un commento stile shell Unix 
?>

Lo stile di commento su "una linea", attualmente commenta solo fino alla fine della linea o del blocco corrente di codice PHP.

<h1>Questo &egrave; un <?# echo "semplice";?> esempio.</h1>
<p>L'intestazione qui sopra dir&agrave; 'Questo &egrave; un esempio'.

Occorre fare attenzione nel non annidare i commenti di stile C, situazione che si presenta quando si commentano larghi blocchi di codice.

<?php
 /* 
    echo "Questo &egrave; un test"; /* Questo commento causer&agrave; dei problemi */
 */
?>

  Lo stile di commento su linea singola commenta il testo fino alla fine della riga oppure alla fine del blocco di codice PHP, dipende da cosa si incontra prima. Questo significa che il codice HTML posizionato dopo // ?> SARA' visualizzato: ?> indica di uscire dal modo PHP e di ritornare in modalità HTML, e, quindi, // non hanno più effetto.     


Capitolo 11. Types

Introduction

PHP supports eight primitive types.

Four scalar types:

Two compound types:

And finally two special types:

This manual also introduces some pseudo-types for readability reasons:

You may also find some references to the type "double". Consider double the same as float, the two names exist only for historic reasons.

The type of a variable is usually not set by the programmer; rather, it is decided at runtime by PHP depending on the context in which that variable is used.

Nota: If you want to check out the type and value of a certain expression, use var_dump().

Nota: If you simply want a human-readable representation of the type for debugging, use gettype(). To check for a certain type, do not use gettype(), but use the is_type functions. Some examples:

<?php
$bool = TRUE;   // a boolean
$str  = "foo";  // a string
$int  = 12;     // an integer

echo gettype($bool); // prints out "boolean"
echo gettype($str);  // prints out "string"

// If this is an integer, increment it by four
if (is_int($int)) {
    $int += 4;
}

// If $bool is a string, print it out
// (does not print out anything)
if (is_string($bool)) {
    echo "String: $bool";
}
?>

If you would like to force a variable to be converted to a certain type, you may either cast the variable or use the settype() function on it.

Note that a variable may be evaluated with different values in certain situations, depending on what type it is at the time. For more information, see the section on Type Juggling. Also, you may be interested in viewing the type comparison tables, as they show examples of various type related comparisons.


Booleans

This is the easiest type. A boolean expresses a truth value. It can be either TRUE or FALSE.

Nota: The boolean type was introduced in PHP 4.


Syntax

To specify a boolean literal, use either the keyword TRUE or FALSE. Both are case-insensitive.

<?php
$foo = True; // assign the value TRUE to $foo
?>

Usually you use some kind of operator which returns a boolean value, and then pass it on to a control structure.

<?php
// == is an operator which test
// equality and returns a boolean
if ($action == "show_version") {
    echo "The version is 1.23";
}

// this is not necessary...
if ($show_separators == TRUE) {
    echo "<hr>\n";
}

// ...because you can simply type
if ($show_separators) {
    echo "<hr>\n";
}
?>


Converting to boolean

To explicitly convert a value to boolean, use either the (bool) or the (boolean) cast. However, in most cases you do not need to use the cast, since a value will be automatically converted if an operator, function or control structure requires a boolean argument.

See also Type Juggling.

When converting to boolean, the following values are considered FALSE:

Every other value is considered TRUE (including any resource).

Avvertimento

-1 is considered TRUE, like any other non-zero (whether negative or positive) number!

<?php
var_dump((bool) "");        // bool(false)
var_dump((bool) 1);         // bool(true)
var_dump((bool) -2);        // bool(true)
var_dump((bool) "foo");     // bool(true)
var_dump((bool) 2.3e5);     // bool(true)
var_dump((bool) array(12)); // bool(true)
var_dump((bool) array());   // bool(false)
var_dump((bool) "false");   // bool(true)
?>


Integers

An integer is a number of the set Z = {..., -2, -1, 0, 1, 2, ...}.

See also: Arbitrary length integer / GMP, Floating point numbers, and Arbitrary precision / BCMath


Syntax

Integers can be specified in decimal (10-based), hexadecimal (16-based) or octal (8-based) notation, optionally preceded by a sign (- or +).

If you use the octal notation, you must precede the number with a 0 (zero), to use hexadecimal notation precede the number with 0x.

Esempio 11-1. Integer literals

<?php
$a = 1234; // decimal number
$a = -123; // a negative number
$a = 0123; // octal number (equivalent to 83 decimal)
$a = 0x1A; // hexadecimal number (equivalent to 26 decimal)
?>
Formally the possible structure for integer literals is:

decimal     : [1-9][0-9]*
            | 0

hexadecimal : 0[xX][0-9a-fA-F]+

octal       : 0[0-7]+

integer     : [+-]?decimal
            | [+-]?hexadecimal
            | [+-]?octal

The size of an integer is platform-dependent, although a maximum value of about two billion is the usual value (that's 32 bits signed). PHP does not support unsigned integers.

Avvertimento

If an invalid digit is passed to octal integer (i.e. 8 or 9), the rest of the number is ignored.

Esempio 11-2. Octal weirdness

<?php
var_dump(01090); // 010 octal = 8 decimal
?>


Integer overflow

If you specify a number beyond the bounds of the integer type, it will be interpreted as a float instead. Also, if you perform an operation that results in a number beyond the bounds of the integer type, a float will be returned instead.

<?php
$large_number =  2147483647;
var_dump($large_number);
// output: int(2147483647)

$large_number =  2147483648;
var_dump($large_number);
// output: float(2147483648)

// this goes also for hexadecimal specified integers:
var_dump( 0x80000000 );
// output: float(2147483648)

$million = 1000000;
$large_number =  50000 * $million;
var_dump($large_number);
// output: float(50000000000)
?>

Avvertimento

Unfortunately, there was a bug in PHP so that this does not always work correctly when there are negative numbers involved. For example: when you do -50000 * $million, the result will be -429496728. However, when both operands are positive there is no problem.

This is solved in PHP 4.1.0.

There is no integer division operator in PHP. 1/2 yields the float 0.5. You can cast the value to an integer to always round it downwards, or you can use the round() function.

<?php
var_dump(25/7);         // float(3.5714285714286) 
var_dump((int) (25/7)); // int(3)
var_dump(round(25/7));  // float(4) 
?>


Converting to integer

To explicitly convert a value to integer, use either the (int) or the (integer) cast. However, in most cases you do not need to use the cast, since a value will be automatically converted if an operator, function or control structure requires an integer argument. You can also convert a value to integer with the function intval().

See also type-juggling.


From booleans

FALSE will yield 0 (zero), and TRUE will yield 1 (one).


From floating point numbers

When converting from float to integer, the number will be rounded towards zero.

If the float is beyond the boundaries of integer (usually +/- 2.15e+9 = 2^31), the result is undefined, since the float hasn't got enough precision to give an exact integer result. No warning, not even a notice will be issued in this case!

Avvertimento

Never cast an unknown fraction to integer, as this can sometimes lead to unexpected results.

<?php
echo (int) ( (0.1+0.7) * 10 ); // echoes 7!
?>

See for more information the warning about float-precision.


From other types

Attenzione

Behaviour of converting to integer is undefined for other types. Currently, the behaviour is the same as if the value was first converted to boolean. However, do not rely on this behaviour, as it can change without notice.


Floating point numbers

Floating point numbers (AKA "floats", "doubles" or "real numbers") can be specified using any of the following syntaxes:

<?php
$a = 1.234; 
$b = 1.2e3; 
$c = 7E-10;
?>

Formally:

LNUM          [0-9]+
DNUM          ([0-9]*[\.]{LNUM}) | ({LNUM}[\.][0-9]*)
EXPONENT_DNUM ( ({LNUM} | {DNUM}) [eE][+-]? {LNUM})

The size of a float is platform-dependent, although a maximum of ~1.8e308 with a precision of roughly 14 decimal digits is a common value (that's 64 bit IEEE format).

Floating point precision

It is quite usual that simple decimal fractions like 0.1 or 0.7 cannot be converted into their internal binary counterparts without a little loss of precision. This can lead to confusing results: for example, floor((0.1+0.7)*10) will usually return 7 instead of the expected 8 as the result of the internal representation really being something like 7.9999999999....

This is related to the fact that it is impossible to exactly express some fractions in decimal notation with a finite number of digits. For instance, 1/3 in decimal form becomes 0.3333333. . ..

So never trust floating number results to the last digit and never compare floating point numbers for equality. If you really need higher precision, you should use the arbitrary precision math functions or gmp functions instead.


Converting to float

For information on when and how strings are converted to floats, see the section titled String conversion to numbers. For values of other types, the conversion is the same as if the value would have been converted to integer and then to float. See the Converting to integer section for more information. As of PHP 5, notice is thrown if you try to convert object to float.


Strings

A string is series of characters. In PHP, a character is the same as a byte, that is, there are exactly 256 different characters possible. This also implies that PHP has no native support of Unicode. See utf8_encode() and utf8_decode() for some Unicode support.

Nota: It is no problem for a string to become very large. There is no practical bound to the size of strings imposed by PHP, so there is no reason at all to worry about long strings.


Syntax

A string literal can be specified in three different ways.


Single quoted

The easiest way to specify a simple string is to enclose it in single quotes (the character ').

To specify a literal single quote, you will need to escape it with a backslash (\), like in many other languages. If a backslash needs to occur before a single quote or at the end of the string, you need to double it. Note that if you try to escape any other character, the backslash will also be printed! So usually there is no need to escape the backslash itself.

Nota: In PHP 3, a warning will be issued at the E_NOTICE level when this happens.

Nota: Unlike the two other syntaxes, variables and escape sequences for special characters will not be expanded when they occur in single quoted strings.

<?php
echo 'this is a simple string';

echo 'You can also have embedded newlines in 
strings this way as it is
okay to do';

// Outputs: Arnold once said: "I'll be back"
echo 'Arnold once said: "I\'ll be back"';

// Outputs: You deleted C:\*.*?
echo 'You deleted C:\\*.*?';

// Outputs: You deleted C:\*.*?
echo 'You deleted C:\*.*?';

// Outputs: This will not expand: \n a newline
echo 'This will not expand: \n a newline';

// Outputs: Variables do not $expand $either
echo 'Variables do not $expand $either';
?>


Double quoted

If the string is enclosed in double-quotes ("), PHP understands more escape sequences for special characters:

Tabella 11-1. Escaped characters

sequencemeaning
\nlinefeed (LF or 0x0A (10) in ASCII)
\rcarriage return (CR or 0x0D (13) in ASCII)
\thorizontal tab (HT or 0x09 (9) in ASCII)
\\backslash
\$dollar sign
\"double-quote
\[0-7]{1,3} the sequence of characters matching the regular expression is a character in octal notation
\x[0-9A-Fa-f]{1,2} the sequence of characters matching the regular expression is a character in hexadecimal notation

Again, if you try to escape any other character, the backslash will be printed too!

But the most important feature of double-quoted strings is the fact that variable names will be expanded. See string parsing for details.


Heredoc

Another way to delimit strings is by using heredoc syntax ("<<<"). One should provide an identifier after <<<, then the string, and then the same identifier to close the quotation.

The closing identifier must begin in the first column of the line. Also, the identifier used must follow the same naming rules as any other label in PHP: it must contain only alphanumeric characters and underscores, and must start with a non-digit character or underscore.

Avvertimento

It is very important to note that the line with the closing identifier contains no other characters, except possibly a semicolon (;). That means especially that the identifier may not be indented, and there may not be any spaces or tabs after or before the semicolon. It's also important to realize that the first character before the closing identifier must be a newline as defined by your operating system. This is \r on Macintosh for example.

If this rule is broken and the closing identifier is not "clean" then it's not considered to be a closing identifier and PHP will continue looking for one. If in this case a proper closing identifier is not found then a parse error will result with the line number being at the end of the script.

Heredoc text behaves just like a double-quoted string, without the double-quotes. This means that you do not need to escape quotes in your here docs, but you can still use the escape codes listed above. Variables are expanded, but the same care must be taken when expressing complex variables inside a here doc as with strings.

Esempio 11-3. Heredoc string quoting example

<?php
$str = <<<EOD
Example of string
spanning multiple lines
using heredoc syntax.
EOD;

/* More complex example, with variables. */
class foo
{
    var $foo;
    var $bar;

    function foo()
    {
        $this->foo = 'Foo';
        $this->bar = array('Bar1', 'Bar2', 'Bar3');
    }
}

$foo = new foo();
$name = 'MyName';

echo <<<EOT
My name is "$name". I am printing some $foo->foo.
Now, I am printing some {$foo->bar[1]}.
This should print a capital 'A': \x41
EOT;
?>

Nota: Heredoc support was added in PHP 4.


Variable parsing

When a string is specified in double quotes or with heredoc, variables are parsed within it.

There are two types of syntax: a simple one and a complex one. The simple syntax is the most common and convenient. It provides a way to parse a variable, an array value, or an object property.

The complex syntax was introduced in PHP 4, and can be recognised by the curly braces surrounding the expression.


Simple syntax

If a dollar sign ($) is encountered, the parser will greedily take as many tokens as possible to form a valid variable name. Enclose the variable name in curly braces if you want to explicitly specify the end of the name.

<?php
$beer = 'Heineken';
echo "$beer's taste is great"; // works, "'" is an invalid character for varnames
echo "He drank some $beers";   // won't work, 's' is a valid character for varnames
echo "He drank some ${beer}s"; // works
echo "He drank some {$beer}s"; // works
?>

Similarly, you can also have an array index or an object property parsed. With array indices, the closing square bracket (]) marks the end of the index. For object properties the same rules apply as to simple variables, though with object properties there doesn't exist a trick like the one with variables.

<?php
// These examples are specific to using arrays inside of strings.
// When outside of a string, always quote your array string keys 
// and do not use {braces} when outside of strings either.

// Let's show all errors
error_reporting(E_ALL);

$fruits = array('strawberry' => 'red', 'banana' => 'yellow');

// Works but note that this works differently outside string-quotes
echo "A banana is $fruits[banana].";

// Works
echo "A banana is {$fruits['banana']}.";

// Works but PHP looks for a constant named banana first
// as described below.
echo "A banana is {$fruits[banana]}.";

// Won't work, use braces.  This results in a parse error.
echo "A banana is $fruits['banana'].";

// Works
echo "A banana is " . $fruits['banana'] . ".";

// Works
echo "This square is $square->width meters broad.";

// Won't work. For a solution, see the complex syntax.
echo "This square is $square->width00 centimeters broad.";
?>

For anything more complex, you should use the complex syntax.


Complex (curly) syntax

This isn't called complex because the syntax is complex, but because you can include complex expressions this way.

In fact, you can include any value that is in the namespace in strings with this syntax. You simply write the expression the same way as you would outside the string, and then include it in { and }. Since you can't escape '{', this syntax will only be recognised when the $ is immediately following the {. (Use "{\$" or "\{$" to get a literal "{$"). Some examples to make it clear:

<?php
// Let's show all errors
error_reporting(E_ALL);

$great = 'fantastic';

// Won't work, outputs: This is { fantastic}
echo "This is { $great}";

// Works, outputs: This is fantastic
echo "This is {$great}";
echo "This is ${great}";

// Works
echo "This square is {$square->width}00 centimeters broad."; 

// Works
echo "This works: {$arr[4][3]}";

// This is wrong for the same reason as $foo[bar] is wrong 
// outside a string.  In other words, it will still work but
// because PHP first looks for a constant named foo, it will
// throw an error of level E_NOTICE (undefined constant).
echo "This is wrong: {$arr[foo][3]}"; 

// Works.  When using multi-dimensional arrays, always use
// braces around arrays when inside of strings
echo "This works: {$arr['foo'][3]}";

// Works.
echo "This works: " . $arr['foo'][3];

echo "You can even write {$obj->values[3]->name}";

echo "This is the value of the var named $name: {${$name}}";
?>


String access and modification by character

Characters within strings may be accessed and modified by specifying the zero-based offset of the desired character after the string in curly braces.

Nota: For backwards compatibility, you can still use array-brackets for the same purpose. However, this syntax is deprecated as of PHP 4.

Esempio 11-4. Some string examples

<?php
// Get the first character of a string
$str = 'This is a test.';
$first = $str{0};

// Get the third character of a string
$third = $str{2};

// Get the last character of a string.
$str = 'This is still a test.';
$last = $str{strlen($str)-1}; 

// Modify the last character of a string
$str = 'Look at the sea';
$str{strlen($str)-1} = 'e';
          
?>


Useful functions and operators

Strings may be concatenated using the '.' (dot) operator. Note that the '+' (addition) operator will not work for this. Please see String operators for more information.

There are a lot of useful functions for string modification.

See the string functions section for general functions, the regular expression functions for advanced find&replacing (in two tastes: Perl and POSIX extended).

There are also functions for URL-strings, and functions to encrypt/decrypt strings (mcrypt and mhash).

Finally, if you still didn't find what you're looking for, see also the character type functions.


Converting to string

You can convert a value to a string using the (string) cast, or the strval() function. String conversion is automatically done in the scope of an expression for you where a string is needed. This happens when you use the echo() or print() functions, or when you compare a variable value to a string. Reading the manual sections on Types and Type Juggling will make the following clearer. See also settype().

A boolean TRUE value is converted to the string "1", the FALSE value is represented as "" (empty string). This way you can convert back and forth between boolean and string values.

An integer or a floating point number (float) is converted to a string representing the number with its digits (including the exponent part for floating point numbers).

Arrays are always converted to the string "Array", so you cannot dump out the contents of an array with echo() or print() to see what is inside them. To view one element, you'd do something like echo $arr['foo']. See below for tips on dumping/viewing the entire contents.

Objects are always converted to the string "Object". If you would like to print out the member variable values of an object for debugging reasons, read the paragraphs below. If you would like to find out the class name of which an object is an instance of, use get_class(). As of PHP 5, __toString() method is used if applicable.

Resources are always converted to strings with the structure "Resource id #1" where 1 is the unique number of the resource assigned by PHP during runtime. If you would like to get the type of the resource, use get_resource_type().

NULL is always converted to an empty string.

As you can see above, printing out the arrays, objects or resources does not provide you any useful information about the values themselves. Look at the functions print_r() and var_dump() for better ways to print out values for debugging.

You can also convert PHP values to strings to store them permanently. This method is called serialization, and can be done with the function serialize(). You can also serialize PHP values to XML structures, if you have WDDX support in your PHP setup.


String conversion to numbers

When a string is evaluated as a numeric value, the resulting value and type are determined as follows.

The string will evaluate as a float if it contains any of the characters '.', 'e', or 'E'. Otherwise, it will evaluate as an integer.

The value is given by the initial portion of the string. If the string starts with valid numeric data, this will be the value used. Otherwise, the value will be 0 (zero). Valid numeric data is an optional sign, followed by one or more digits (optionally containing a decimal point), followed by an optional exponent. The exponent is an 'e' or 'E' followed by one or more digits.

<?php
$foo = 1 + "10.5";                // $foo is float (11.5)
$foo = 1 + "-1.3e3";              // $foo is float (-1299)
$foo = 1 + "bob-1.3e3";           // $foo is integer (1)
$foo = 1 + "bob3";                // $foo is integer (1)
$foo = 1 + "10 Small Pigs";       // $foo is integer (11)
$foo = 4 + "10.2 Little Piggies"; // $foo is float (14.2)
$foo = "10.0 pigs " + 1;          // $foo is float (11)
$foo = "10.0 pigs " + 1.0;        // $foo is float (11)     
?>

For more information on this conversion, see the Unix manual page for strtod(3).

If you would like to test any of the examples in this section, you can cut and paste the examples and insert the following line to see for yourself what's going on:

<?php
echo "\$foo==$foo; type is " . gettype ($foo) . "<br />\n";
?>

Do not expect to get the code of one character by converting it to integer (as you would do in C for example). Use the functions ord() and chr() to convert between charcodes and characters.


Arrays

An array in PHP is actually an ordered map. A map is a type that maps values to keys. This type is optimized in several ways, so you can use it as a real array, or a list (vector), hashtable (which is an implementation of a map), dictionary, collection, stack, queue and probably more. Because you can have another PHP array as a value, you can also quite easily simulate trees.

Explanation of those data structures is beyond the scope of this manual, but you'll find at least one example for each of them. For more information we refer you to external literature about this broad topic.


Syntax

Specifying with array()

An array can be created by the array() language-construct. It takes a certain number of comma-separated key => value pairs.

array( [key =>] value
     , ...
     )
// key may be an integer or string
// value may be any value

<?php
$arr = array("foo" => "bar", 12 => true);

echo $arr["foo"]; // bar
echo $arr[12];    // 1
?>

A key may be either an integer or a string. If a key is the standard representation of an integer, it will be interpreted as such (i.e. "8" will be interpreted as 8, while "08" will be interpreted as "08"). There are no different indexed and associative array types in PHP; there is only one array type, which can both contain integer and string indices.

A value can be of any PHP type.

<?php
$arr = array("somearray" => array(6 => 5, 13 => 9, "a" => 42));

echo $arr["somearray"][6];    // 5
echo $arr["somearray"][13];   // 9
echo $arr["somearray"]["a"];  // 42
?>

If you do not specify a key for a given value, then the maximum of the integer indices is taken, and the new key will be that maximum value + 1. If you specify a key that already has a value assigned to it, that value will be overwritten.

<?php
// This array is the same as ...
array(5 => 43, 32, 56, "b" => 12);

// ...this array
array(5 => 43, 6 => 32, 7 => 56, "b" => 12);
?>

Avvertimento

As of PHP 4.3.0, the index generation behaviour described above has changed. Now, if you append to an array in which the current maximum key is negative, then the next key created will be zero (0). Before, the new index would have been set to the largest existing key + 1, the same as positive indices are.

Using TRUE as a key will evaluate to integer 1 as key. Using FALSE as a key will evaluate to integer 0 as key. Using NULL as a key will evaluate to the empty string. Using the empty string as key will create (or overwrite) a key with the empty string and its value; it is not the same as using empty brackets.

You cannot use arrays or objects as keys. Doing so will result in a warning: Illegal offset type.


Creating/modifying with square-bracket syntax

You can also modify an existing array by explicitly setting values in it.

This is done by assigning values to the array while specifying the key in brackets. You can also omit the key, add an empty pair of brackets ("[]") to the variable name in that case.
$arr[key] = value;
$arr[] = value;
// key may be an integer or string
// value may be any value
If $arr doesn't exist yet, it will be created. So this is also an alternative way to specify an array. To change a certain value, just assign a new value to an element specified with its key. If you want to remove a key/value pair, you need to unset() it.

<?php
$arr = array(5 => 1, 12 => 2);

$arr[] = 56;    // This is the same as $arr[13] = 56;
                // at this point of the script

$arr["x"] = 42; // This adds a new element to
                // the array with key "x"
                
unset($arr[5]); // This removes the element from the array

unset($arr);    // This deletes the whole array
?>

Nota: As mentioned above, if you provide the brackets with no key specified, then the maximum of the existing integer indices is taken, and the new key will be that maximum value + 1 . If no integer indices exist yet, the key will be 0 (zero). If you specify a key that already has a value assigned to it, that value will be overwritten.

Avvertimento

As of PHP 4.3.0, the index generation behaviour described above has changed. Now, if you append to an array in which the current maximum key is negative, then the next key created will be zero (0). Before, the new index would have been set to the largest existing key + 1, the same as positive indices are.

Note that the maximum integer key used for this need not currently exist in the array. It simply must have existed in the array at some time since the last time the array was re-indexed. The following example illustrates:

<?php
// Create a simple array.
$array = array(1, 2, 3, 4, 5);
print_r($array);

// Now delete every item, but leave the array itself intact:
foreach ($array as $i => $value) {
    unset($array[$i]);
}
print_r($array);

// Append an item (note that the new key is 5, instead of 0 as you
// might expect).
$array[] = 6;
print_r($array);

// Re-index:
$array = array_values($array);
$array[] = 7;
print_r($array);
?>

The above example will output:

Array
(
    [0] => 1
    [1] => 2
    [2] => 3
    [3] => 4
    [4] => 5
)
Array
(
)
Array
(
    [5] => 6
)
Array
(
    [0] => 6
    [1] => 7
)


Useful functions

There are quite a few useful functions for working with arrays. See the array functions section.

Nota: The unset() function allows unsetting keys of an array. Be aware that the array will NOT be reindexed. If you only use "usual integer indices" (starting from zero, increasing by one), you can achieve the reindex effect by using array_values().

<?php
$a = array(1 => 'one', 2 => 'two', 3 => 'three');
unset($a[2]);
/* will produce an array that would have been defined as
   $a = array(1 => 'one', 3 => 'three');
   and NOT
   $a = array(1 => 'one', 2 =>'three');
*/

$b = array_values($a);
// Now $b is array(0 => 'one', 1 =>'three')
?>

The foreach control structure exists specifically for arrays. It provides an easy way to traverse an array.


Array do's and don'ts

Why is $foo[bar] wrong?

You should always use quotes around a string literal array index. For example, use $foo['bar'] and not $foo[bar]. But why is $foo[bar] wrong? You might have seen the following syntax in old scripts:

<?php
$foo[bar] = 'enemy';
echo $foo[bar];
// etc
?>

This is wrong, but it works. Then, why is it wrong? The reason is that this code has an undefined constant (bar) rather than a string ('bar' - notice the quotes), and PHP may in future define constants which, unfortunately for your code, have the same name. It works because PHP automatically converts a bare string (an unquoted string which does not correspond to any known symbol) into a string which contains the bare string. For instance, if there is no defined constant named bar, then PHP will substitute in the string 'bar' and use that.

Nota: This does not mean to always quote the key. You do not want to quote keys which are constants or variables, as this will prevent PHP from interpreting them.

<?php
error_reporting(E_ALL);
ini_set('display_errors', true);
ini_set('html_errors', false);
// Simple array:
$array = array(1, 2);
$count = count($array);
for ($i = 0; $i < $count; $i++) {
    echo "\nChecking $i: \n";
    echo "Bad: " . $array['$i'] . "\n";
    echo "Good: " . $array[$i] . "\n";
    echo "Bad: {$array['$i']}\n";
    echo "Good: {$array[$i]}\n";
}
?>

Nota: The above example will output:

Checking 0: 
Notice: Undefined index:  $i in /path/to/script.html on line 9
Bad: 
Good: 1
Notice: Undefined index:  $i in /path/to/script.html on line 11
Bad: 
Good: 1

Checking 1: 
Notice: Undefined index:  $i in /path/to/script.html on line 9
Bad: 
Good: 2
Notice: Undefined index:  $i in /path/to/script.html on line 11
Bad: 
Good: 2

More examples to demonstrate this fact:

<?php
// Let's show all errors
error_reporting(E_ALL);

$arr = array('fruit' => 'apple', 'veggie' => 'carrot');

// Correct
print $arr['fruit'];  // apple
print $arr['veggie']; // carrot

// Incorrect.  This works but also throws a PHP error of
// level E_NOTICE because of an undefined constant named fruit
// 
// Notice: Use of undefined constant fruit - assumed 'fruit' in...
print $arr[fruit];    // apple

// Let's define a constant to demonstrate what's going on.  We
// will assign value 'veggie' to a constant named fruit.
define('fruit', 'veggie');

// Notice the difference now
print $arr['fruit'];  // apple
print $arr[fruit];    // carrot

// The following is okay as it's inside a string.  Constants are not
// looked for within strings so no E_NOTICE error here
print "Hello $arr[fruit]";      // Hello apple

// With one exception, braces surrounding arrays within strings
// allows constants to be looked for
print "Hello {$arr[fruit]}";    // Hello carrot
print "Hello {$arr['fruit']}";  // Hello apple

// This will not work, results in a parse error such as:
// Parse error: parse error, expecting T_STRING' or T_VARIABLE' or T_NUM_STRING'
// This of course applies to using autoglobals in strings as well
print "Hello $arr['fruit']";
print "Hello $_GET['foo']";

// Concatenation is another option
print "Hello " . $arr['fruit']; // Hello apple
?>

When you turn error_reporting() up to show E_NOTICE level errors (such as setting it to E_ALL) then you will see these errors. By default, error_reporting is turned down to not show them.

As stated in the syntax section, there must be an expression between the square brackets ('[' and ']'). That means that you can write things like this:

<?php
echo $arr[somefunc($bar)];
?>

This is an example of using a function return value as the array index. PHP also knows about constants, as you may have seen the E_* ones before.

<?php
$error_descriptions[E_ERROR]   = "A fatal error has occured";
$error_descriptions[E_WARNING] = "PHP issued a warning";
$error_descriptions[E_NOTICE]  = "This is just an informal notice";
?>

Note that E_ERROR is also a valid identifier, just like bar in the first example. But the last example is in fact the same as writing:

<?php
$error_descriptions[1] = "A fatal error has occured";
$error_descriptions[2] = "PHP issued a warning";
$error_descriptions[8] = "This is just an informal notice";
?>

because E_ERROR equals 1, etc.

As we already explained in the above examples, $foo[bar] still works but is wrong. It works, because bar is due to its syntax expected to be a constant expression. However, in this case no constant with the name bar exists. PHP now assumes that you meant bar literally, as the string "bar", but that you forgot to write the quotes.


So why is it bad then?

At some point in the future, the PHP team might want to add another constant or keyword, or you may introduce another constant into your application, and then you get in trouble. For example, you already cannot use the words empty and default this way, since they are special reserved keywords.

Nota: To reiterate, inside a double-quoted string, it's valid to not surround array indexes with quotes so "$foo[bar]" is valid. See the above examples for details on why as well as the section on variable parsing in strings.


Converting to array

For any of the types: integer, float, string, boolean and resource, if you convert a value to an array, you get an array with one element (with index 0), which is the scalar value you started with.

If you convert an object to an array, you get the properties (member variables) of that object as the array's elements. The keys are the member variable names.

If you convert a NULL value to an array, you get an empty array.


Comparing

It is possible to compare arrays by array_diff() and by Array operators.


Examples

The array type in PHP is very versatile, so here will be some examples to show you the full power of arrays.

<?php
// this
$a = array( 'color' => 'red',
            'taste' => 'sweet',
            'shape' => 'round',
            'name'  => 'apple',
                       4        // key will be 0
          );

// is completely equivalent with
$a['color'] = 'red';
$a['taste'] = 'sweet';
$a['shape'] = 'round';
$a['name']  = 'apple';
$a[]        = 4;        // key will be 0

$b[] = 'a';
$b[] = 'b';
$b[] = 'c';
// will result in the array array(0 => 'a' , 1 => 'b' , 2 => 'c'),
// or simply array('a', 'b', 'c')
?>

Esempio 11-5. Using array()

<?php
// Array as (property-)map
$map = array( 'version'    => 4,
              'OS'         => 'Linux',
              'lang'       => 'english',
              'short_tags' => true
            );
            
// strictly numerical keys
$array = array( 7,
                8,
                0,
                156,
                -10
              );
// this is the same as array(0 => 7, 1 => 8, ...)

$switching = array(         10, // key = 0
                    5    =>  6,
                    3    =>  7, 
                    'a'  =>  4,
                            11, // key = 6 (maximum of integer-indices was 5)
                    '8'  =>  2, // key = 8 (integer!)
                    '02' => 77, // key = '02'
                    0    => 12  // the value 10 will be overwritten by 12
                  );
                  
// empty array
$empty = array();         
?>

Esempio 11-6. Collection

<?php
$colors = array('red', 'blue', 'green', 'yellow');

foreach ($colors as $color) {
    echo "Do you like $color?\n";
}

?>

The above example will output:

Do you like red?
Do you like blue?
Do you like green?
Do you like yellow?

Note that it is currently not possible to change the values of the array directly in such a loop. A workaround is the following:

Esempio 11-7. Collection

<?php
foreach ($colors as $key => $color) {
    // won't work:
    //$color = strtoupper($color);
    
    // works:
    $colors[$key] = strtoupper($color);
}
print_r($colors);
?>

The above example will output:

Array
(
    [0] => RED
    [1] => BLUE
    [2] => GREEN
    [3] => YELLOW
)

This example creates a one-based array.

Esempio 11-8. One-based index

<?php
$firstquarter  = array(1 => 'January', 'February', 'March');
print_r($firstquarter);
?>

The above example will output:

Array 
(
    [1] => 'January'
    [2] => 'February'
    [3] => 'March'
)

Esempio 11-9. Filling an array

<?php
// fill an array with all items from a directory
$handle = opendir('.');
while (false !== ($file = readdir($handle))) {
    $files[] = $file;
}
closedir($handle); 
?>

Arrays are ordered. You can also change the order using various sorting functions. See the array functions section for more information. You can count the number of items in an array using the count() function.

Esempio 11-10. Sorting an array

<?php
sort($files);
print_r($files);
?>

Because the value of an array can be anything, it can also be another array. This way you can make recursive and multi-dimensional arrays.

Esempio 11-11. Recursive and multi-dimensional arrays

<?php
$fruits = array ( "fruits"  => array ( "a" => "orange",
                                       "b" => "banana",
                                       "c" => "apple"
                                     ),
                  "numbers" => array ( 1,
                                       2,
                                       3,
                                       4,
                                       5,
                                       6
                                     ),
                  "holes"   => array (      "first",
                                       5 => "second",
                                            "third"
                                     )
                );

// Some examples to address values in the array above 
echo $fruits["holes"][5];    // prints "second"
echo $fruits["fruits"]["a"]; // prints "orange"
unset($fruits["holes"][0]);  // remove "first"

// Create a new multi-dimensional array
$juices["apple"]["green"] = "good"; 
?>

You should be aware that array assignment always involves value copying. You need to use the reference operator to copy an array by reference.

<?php
$arr1 = array(2, 3);
$arr2 = $arr1;
$arr2[] = 4; // $arr2 is changed,
             // $arr1 is still array(2, 3)
             
$arr3 = &$arr1;
$arr3[] = 4; // now $arr1 and $arr3 are the same
?>


Objects

Object Initialization

To initialize an object, you use the new statement to instantiate the object to a variable.

<?php
class foo
{
    function do_foo()
    {
        echo "Doing foo."; 
    }
}

$bar = new foo;
$bar->do_foo();
?>

For a full discussion, please read the section Classes and Objects.


Converting to object

If an object is converted to an object, it is not modified. If a value of any other type is converted to an object, a new instance of the stdClass built in class is created. If the value was null, the new instance will be empty. For any other value, a member variable named scalar will contain the value.

<?php
$obj = (object) 'ciao';
echo $obj->scalar;  // outputs 'ciao'
?>


Resource

A resource is a special variable, holding a reference to an external resource. Resources are created and used by special functions. See the appendix for a listing of all these functions and the corresponding resource types.

Nota: The resource type was introduced in PHP 4

See also get_resource_type().


Converting to resource

As resource types hold special handlers to opened files, database connections, image canvas areas and the like, you cannot convert any value to a resource.


Freeing resources

Due to the reference-counting system introduced with PHP 4's Zend Engine, it is automatically detected when a resource is no longer referred to (just like Java). When this is the case, all resources that were in use for this resource are made free by the garbage collector. For this reason, it is rarely ever necessary to free the memory manually by using some free_result function.

Nota: Persistent database links are special, they are not destroyed by the garbage collector. See also the section about persistent connections.


NULL

The special NULL value represents that a variable has no value. NULL is the only possible value of type NULL.

Nota: The null type was introduced in PHP 4.

A variable is considered to be NULL if

  • it has been assigned the constant NULL.

  • it has not been set to any value yet.

  • it has been unset().


Syntax

There is only one value of type NULL, and that is the case-insensitive keyword NULL.

<?php
$var = NULL;       
?>

See also is_null() and unset().


Pseudo-types used in this documentation

mixed

mixed indicates that a parameter may accept multiple (but not necessarily all) types.

gettype() for example will accept all PHP types, while str_replace() will accept strings and arrays.


number

number indicates that a parameter can be either integer or float.


callback

Some functions like call_user_func() or usort() accept user defined callback functions as a parameter. Callback functions can not only be simple functions but also object methods including static class methods.

A PHP function is simply passed by its name as a string. You can pass any builtin or user defined function with the exception of array(), echo(), empty(), eval(), exit(), isset(), list(), print() and unset().

A method of an instantiated object is passed as an array containing an object as the element with index 0 and a method name as the element with index 1.

Static class methods can also be passed without instantiating an object of that class by passing the class name instead of an object as the element with index 0.

Esempio 11-12. Callback function examples

<?php 
// An example callback function
function my_callback_function() {
    echo 'hello world!';
}

// An example callback method
class MyClass {
    function myCallbackMethod() {
        echo 'Hello World!';
    }
}

// Type 1: Simple callback
call_user_func('my_callback_function'); 

// Type 2: Static class method call
call_user_func(array('MyClass', 'myCallbackMethod')); 

// Type 3: Object method call
$obj = new MyClass();
call_user_func(array(&$obj, 'myCallbackMethod'));
?>


Type Juggling

PHP does not require (or support) explicit type definition in variable declaration; a variable's type is determined by the context in which that variable is used. That is to say, if you assign a string value to variable $var, $var becomes a string. If you then assign an integer value to $var, it becomes an integer.

An example of PHP's automatic type conversion is the addition operator '+'. If any of the operands is a float, then all operands are evaluated as floats, and the result will be a float. Otherwise, the operands will be interpreted as integers, and the result will also be an integer. Note that this does NOT change the types of the operands themselves; the only change is in how the operands are evaluated.

<?php
$foo = "0";  // $foo is string (ASCII 48)
$foo += 2;   // $foo is now an integer (2)
$foo = $foo + 1.3;  // $foo is now a float (3.3)
$foo = 5 + "10 Little Piggies"; // $foo is integer (15)
$foo = 5 + "10 Small Pigs";     // $foo is integer (15)
?>

If the last two examples above seem odd, see String conversion to numbers.

If you wish to force a variable to be evaluated as a certain type, see the section on Type casting. If you wish to change the type of a variable, see settype().

If you would like to test any of the examples in this section, you can use the var_dump() function.

Nota: The behaviour of an automatic conversion to array is currently undefined.

<?php
$a = "1";     // $a is a string
$a[0] = "f";  // What about string offsets? What happens?
?>

Since PHP (for historical reasons) supports indexing into strings via offsets using the same syntax as array indexing, the example above leads to a problem: should $a become an array with its first element being "f", or should "f" become the first character of the string $a?

The current versions of PHP interpret the second assignment as a string offset identification, so $a becomes "f", the result of this automatic conversion however should be considered undefined. PHP 4 introduced the new curly bracket syntax to access characters in string, use this syntax instead of the one presented above:

<?php
$a    = "abc"; // $a is a string
$a{1} = "f";   // $a is now "afc"
?>

See the section titled String access by character for more information.


Type Casting

Type casting in PHP works much as it does in C: the name of the desired type is written in parentheses before the variable which is to be cast.

<?php
$foo = 10;   // $foo is an integer
$bar = (boolean) $foo;   // $bar is a boolean
?>

The casts allowed are:

  • (int), (integer) - cast to integer

  • (bool), (boolean) - cast to boolean

  • (float), (double), (real) - cast to float

  • (string) - cast to string

  • (array) - cast to array

  • (object) - cast to object

Note that tabs and spaces are allowed inside the parentheses, so the following are functionally equivalent:

<?php
$foo = (int) $bar;
$foo = ( int ) $bar;
?>

Nota: Instead of casting a variable to string, you can also enclose the variable in double quotes.

<?php
$foo = 10;            // $foo is an integer
$str = "$foo";        // $str is a string
$fst = (string) $foo; // $fst is also a string

// This prints out that "they are the same"
if ($fst === $str) {
    echo "they are the same";
}
?>

It may not be obvious exactly what will happen when casting between certain types. For more info, see these sections:


Capitolo 12. Variables

Basics

Variables in PHP are represented by a dollar sign followed by the name of the variable. The variable name is case-sensitive.

Variable names follow the same rules as other labels in PHP. A valid variable name starts with a letter or underscore, followed by any number of letters, numbers, or underscores. As a regular expression, it would be expressed thus: '[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*'

Nota: For our purposes here, a letter is a-z, A-Z, and the ASCII characters from 127 through 255 (0x7f-0xff).

For information on variable related functions, see the Variable Functions Reference.

<?php
$var = 'Bob';
$Var = 'Joe';
echo "$var, $Var";      // outputs "Bob, Joe"

$4site = 'not yet';     // invalid; starts with a number
$_4site = 'not yet';    // valid; starts with an underscore
$täyte = 'mansikka';    // valid; 'ä' is (Extended) ASCII 228.
?>

In PHP 3, variables are always assigned by value. That is to say, when you assign an expression to a variable, the entire value of the original expression is copied into the destination variable. This means, for instance, that after assigning one variable's value to another, changing one of those variables will have no effect on the other. For more information on this kind of assignment, see the chapter on Expressions.

As of PHP 4, PHP offers another way to assign values to variables: assign by reference. This means that the new variable simply references (in other words, "becomes an alias for" or "points to") the original variable. Changes to the new variable affect the original, and vice versa. This also means that no copying is performed; thus, the assignment happens more quickly. However, any speedup will likely be noticed only in tight loops or when assigning large arrays or objects.

To assign by reference, simply prepend an ampersand (&) to the beginning of the variable which is being assigned (the source variable). For instance, the following code snippet outputs 'My name is Bob' twice:

<?php
$foo = 'Bob';              // Assign the value 'Bob' to $foo
$bar = &$foo;              // Reference $foo via $bar.
$bar = "My name is $bar";  // Alter $bar...
echo $bar;
echo $foo;                 // $foo is altered too.
?>

One important thing to note is that only named variables may be assigned by reference.

<?php
$foo = 25;
$bar = &$foo;      // This is a valid assignment.
$bar = &(24 * 7);  // Invalid; references an unnamed expression.

function test()
{
   return 25;
}

$bar = &test();    // Invalid.
?>


Predefined variables

PHP provides a large number of predefined variables to any script which it runs. Many of these variables, however, cannot be fully documented as they are dependent upon which server is running, the version and setup of the server, and other factors. Some of these variables will not be available when PHP is run on the command line. For a listing of these variables, please see the section on Reserved Predefined Variables.

Avvertimento

In PHP 4.2.0 and later, the default value for the PHP directive register_globals is off. This is a major change in PHP. Having register_globals off affects the set of predefined variables available in the global scope. For example, to get DOCUMENT_ROOT you'll use $_SERVER['DOCUMENT_ROOT'] instead of $DOCUMENT_ROOT, or $_GET['id'] from the URL http://www.example.com/test.php?id=3 instead of $id, or $_ENV['HOME'] instead of $HOME.

For related information on this change, read the configuration entry for register_globals, the security chapter on Using Register Globals , as well as the PHP 4.1.0 and 4.2.0 Release Announcements.

Using the available PHP Reserved Predefined Variables, like the superglobal arrays, is preferred.

From version 4.1.0 onward, PHP provides an additional set of predefined arrays containing variables from the web server (if applicable), the environment, and user input. These new arrays are rather special in that they are automatically global--i.e., automatically available in every scope. For this reason, they are often known as 'autoglobals' or 'superglobals'. (There is no mechanism in PHP for user-defined superglobals.) The superglobals are listed below; however, for a listing of their contents and further discussion on PHP predefined variables and their natures, please see the section Reserved Predefined Variables. Also, you'll notice how the older predefined variables ($HTTP_*_VARS) still exist. As of PHP 5.0.0, the long PHP predefined variable arrays may be disabled with the register_long_arrays directive.

Variable variables: Superglobals cannot be used as variable variables inside functions or class methods.

Nota: Even though both the superglobal and HTTP_*_VARS can exist at the same time; they are not identical, so modifying one will not change the other.

If certain variables in variables_order are not set, their appropriate PHP predefined arrays are also left empty.

PHP Superglobals

$GLOBALS

Contains a reference to every variable which is currently available within the global scope of the script. The keys of this array are the names of the global variables. $GLOBALS has existed since PHP 3.

$_SERVER

Variables set by the web server or otherwise directly related to the execution environment of the current script. Analogous to the old $HTTP_SERVER_VARS array (which is still available, but deprecated).

$_GET

Variables provided to the script via URL query string. Analogous to the old $HTTP_GET_VARS array (which is still available, but deprecated).

$_POST

Variables provided to the script via HTTP POST. Analogous to the old $HTTP_POST_VARS array (which is still available, but deprecated).

$_COOKIE

Variables provided to the script via HTTP cookies. Analogous to the old $HTTP_COOKIE_VARS array (which is still available, but deprecated).

$_FILES

Variables provided to the script via HTTP post file uploads. Analogous to the old $HTTP_POST_FILES array (which is still available, but deprecated). See POST method uploads for more information.

$_ENV

Variables provided to the script via the environment. Analogous to the old $HTTP_ENV_VARS array (which is still available, but deprecated).

$_REQUEST

Variables provided to the script via the GET, POST, and COOKIE input mechanisms, and which therefore cannot be trusted. The presence and order of variable inclusion in this array is defined according to the PHP variables_order configuration directive. This array has no direct analogue in versions of PHP prior to 4.1.0. See also import_request_variables().

Attenzione

Since PHP 4.3.0, FILE information from $_FILES does not exist in $_REQUEST.

Nota: When running on the command line , this will not include the argv and argc entries; these are present in the $_SERVER array.

$_SESSION

Variables which are currently registered to a script's session. Analogous to the old $HTTP_SESSION_VARS array (which is still available, but deprecated). See the Session handling functions section for more information.


Variable scope

The scope of a variable is the context within which it is defined. For the most part all PHP variables only have a single scope. This single scope spans included and required files as well. For example:

<?php
$a = 1;
include 'b.inc';
?>

Here the $a variable will be available within the included b.inc script. However, within user-defined functions a local function scope is introduced. Any variable used inside a function is by default limited to the local function scope. For example:

<?php
$a = 1; /* global scope */ 

function Test()
{ 
    echo $a; /* reference to local scope variable */ 
} 

Test();
?>

This script will not produce any output because the echo statement refers to a local version of the $a variable, and it has not been assigned a value within this scope. You may notice that this is a little bit different from the C language in that global variables in C are automatically available to functions unless specifically overridden by a local definition. This can cause some problems in that people may inadvertently change a global variable. In PHP global variables must be declared global inside a function if they are going to be used in that function.


The global keyword

First, an example use of global:

Esempio 12-1. Using global

<?php
$a = 1;
$b = 2;

function Sum()
{
    global $a, $b;

    $b = $a + $b;
} 

Sum();
echo $b;
?>

The above script will output "3". By declaring $a and $b global within the function, all references to either variable will refer to the global version. There is no limit to the number of global variables that can be manipulated by a function.

A second way to access variables from the global scope is to use the special PHP-defined $GLOBALS array. The previous example can be rewritten as:

Esempio 12-2. Using $GLOBALS instead of global

<?php
$a = 1;
$b = 2;

function Sum()
{
    $GLOBALS['b'] = $GLOBALS['a'] + $GLOBALS['b'];
} 

Sum();
echo $b;
?>

The $GLOBALS array is an associative array with the name of the global variable being the key and the contents of that variable being the value of the array element. Notice how $GLOBALS exists in any scope, this is because $GLOBALS is a superglobal. Here's an example demonstrating the power of superglobals:

Esempio 12-3. Example demonstrating superglobals and scope

<?php
function test_global()
{
    // Most predefined variables aren't "super" and require 
    // 'global' to be available to the functions local scope.
    global $HTTP_POST_VARS;
    
    echo $HTTP_POST_VARS['name'];
    
    // Superglobals are available in any scope and do 
    // not require 'global'. Superglobals are available 
    // as of PHP 4.1.0, and HTTP_POST_VARS is now
    // deemed deprecated.
    echo $_POST['name'];
}
?>


Using static variables

Another important feature of variable scoping is the static variable. A static variable exists only in a local function scope, but it does not lose its value when program execution leaves this scope. Consider the following example:

Esempio 12-4. Example demonstrating need for static variables

<?php
function Test()
{
    $a = 0;
    echo $a;
    $a++;
}
?>

This function is quite useless since every time it is called it sets $a to 0 and prints "0". The $a++ which increments the variable serves no purpose since as soon as the function exits the $a variable disappears. To make a useful counting function which will not lose track of the current count, the $a variable is declared static:

Esempio 12-5. Example use of static variables

<?php
function Test()
{
    static $a = 0;
    echo $a;
    $a++;
}
?>

Now, every time the Test() function is called it will print the value of $a and increment it.

Static variables also provide one way to deal with recursive functions. A recursive function is one which calls itself. Care must be taken when writing a recursive function because it is possible to make it recurse indefinitely. You must make sure you have an adequate way of terminating the recursion. The following simple function recursively counts to 10, using the static variable $count to know when to stop:

Esempio 12-6. Static variables with recursive functions

<?php
function Test()
{
    static $count = 0;

    $count++;
    echo $count;
    if ($count < 10) {
        Test();
    }
    $count--;
}
?>

Nota: Static variables may be declared as seen in the examples above. Trying to assign values to these variables which are the result of expressions will cause a parse error.

Esempio 12-7. Declaring static variables

<?php
function foo(){
    static $int = 0;          // correct 
    static $int = 1+2;        // wrong  (as it is an expression)
    static $int = sqrt(121);  // wrong  (as it is an expression too)

    $int++;
    echo $int;
}
?>


References with global and static variables

The Zend Engine 1, driving PHP 4, implements the static and global modifier for variables in terms of references. For example, a true global variable imported inside a function scope with the global statement actually creates a reference to the global variable. This can lead to unexpected behaviour which the following example addresses:

<?php
function test_global_ref() {
    global $obj;
    $obj = &new stdclass;
}

function test_global_noref() {
    global $obj;
    $obj = new stdclass;
}

test_global_ref();
var_dump($obj);
test_global_noref();
var_dump($obj);
?>

Executing this example will result in the following output:

NULL
object(stdClass)(0) {
}

A similar behaviour applies to the static statement. References are not stored statically:

<?php
function &get_instance_ref() {
    static $obj;

    echo 'Static object: ';
    var_dump($obj);
    if (!isset($obj)) {
        // Assign a reference to the static variable
        $obj = &new stdclass;
    }
    $obj->property++;
    return $obj;
}

function &get_instance_noref() {
    static $obj;

    echo 'Static object: ';
    var_dump($obj);
    if (!isset($obj)) {
        // Assign the object to the static variable
        $obj = new stdclass;
    }
    $obj->property++;
    return $obj;
}

$obj1 = get_instance_ref();
$still_obj1 = get_instance_ref();
echo "\n";
$obj2 = get_instance_noref();
$still_obj2 = get_instance_noref();
?>

Executing this example will result in the following output:

Static object: NULL
Static object: NULL

Static object: NULL
Static object: object(stdClass)(1) {
  ["property"]=>
  int(1)
}

This example demonstrates that when assigning a reference to a static variable, it's not remembered when you call the &get_instance_ref() function a second time.


Variable variables

Sometimes it is convenient to be able to have variable variable names. That is, a variable name which can be set and used dynamically. A normal variable is set with a statement such as:

<?php
$a = 'hello';
?>

A variable variable takes the value of a variable and treats that as the name of a variable. In the above example, hello, can be used as the name of a variable by using two dollar signs. i.e.

<?php
$$a = 'world';
?>

At this point two variables have been defined and stored in the PHP symbol tree: $a with contents "hello" and $hello with contents "world". Therefore, this statement:

<?php
echo "$a ${$a}";
?>

produces the exact same output as:

<?php
echo "$a $hello";
?>

i.e. they both produce: hello world.

In order to use variable variables with arrays, you have to resolve an ambiguity problem. That is, if you write $$a[1] then the parser needs to know if you meant to use $a[1] as a variable, or if you wanted $$a as the variable and then the [1] index from that variable. The syntax for resolving this ambiguity is: ${$a[1]} for the first case and ${$a}[1] for the second.

Avvertimento

Please note that variable variables cannot be used with PHP's Superglobal arrays within functions or class methods.


Variables from outside PHP

HTML Forms (GET and POST)

When a form is submitted to a PHP script, the information from that form is automatically made available to the script. There are many ways to access this information, for example:

Esempio 12-8. A simple HTML form

<form action="foo.php" method="post">
    Name:  <input type="text" name="username" /><br />
    Email: <input type="text" name="email" /><br />
    <input type="submit" name="submit" value="Submit me!" />
</form>

Depending on your particular setup and personal preferences, there are many ways to access data from your HTML forms. Some examples are:

Esempio 12-9. Accessing data from a simple POST HTML form

<?php 
// Available since PHP 4.1.0

   echo $_POST['username'];
   echo $_REQUEST['username'];

   import_request_variables('p', 'p_');
   echo $p_username;

// Available since PHP 3. As of PHP 5.0.0, these long predefined
// variables can be disabled with the register_long_arrays directive.

   echo $HTTP_POST_VARS['username'];

// Available if the PHP directive register_globals = on. As of 
// PHP 4.2.0 the default value of register_globals = off.
// Using/relying on this method is not preferred.

   echo $username;
?>

Using a GET form is similar except you'll use the appropriate GET predefined variable instead. GET also applies to the QUERY_STRING (the information after the '?' in a URL). So, for example, http://www.example.com/test.php?id=3 contains GET data which is accessible with $_GET['id']. See also $_REQUEST and import_request_variables().

Nota: Superglobal arrays, like $_POST and $_GET, became available in PHP 4.1.0

As shown, before PHP 4.2.0 the default value for register_globals was on. And, in PHP 3 it was always on. The PHP community is encouraging all to not rely on this directive as it's preferred to assume it's off and code accordingly.

Nota: The magic_quotes_gpc configuration directive affects Get, Post and Cookie values. If turned on, value (It's "PHP!") will automagically become (It\'s \"PHP!\"). Escaping is needed for DB insertion. See also addslashes(), stripslashes() and magic_quotes_sybase.

PHP also understands arrays in the context of form variables (see the related faq). You may, for example, group related variables together, or use this feature to retrieve values from a multiple select input. For example, let's post a form to itself and upon submission display the data:

Esempio 12-10. More complex form variables

<?php
if (isset($_POST['action']) && $_POST['action'] == 'submitted') {
    echo '<pre>';
    print_r($_POST);
    echo '<a href="'. $_SERVER['PHP_SELF'] .'">Please try again</a>';

    echo '</pre>';
} else {
?>
<form action="<?php echo $_SERVER['PHP_SELF']; ?>" method="post">
    Name:  <input type="text" name="personal[name]" /><br />
    Email: <input type="text" name="personal[email]" /><br />
    Beer: <br />
    <select multiple name="beer[]">
        <option value="warthog">Warthog</option>
        <option value="guinness">Guinness</option>
        <option value="stuttgarter">Stuttgarter Schwabenbräu</option>
    </select><br />
    <input type="hidden" name="action" value="submitted" />
    <input type="submit" name="submit" value="submit me!" />
</form>
<?php
}
?>

In PHP 3, the array form variable usage is limited to single-dimensional arrays. As of PHP 4, no such restriction applies.


IMAGE SUBMIT variable names

When submitting a form, it is possible to use an image instead of the standard submit button with a tag like:

<input type="image" src="image.gif" name="sub" />

When the user clicks somewhere on the image, the accompanying form will be transmitted to the server with two additional variables, sub_x and sub_y. These contain the coordinates of the user click within the image. The experienced may note that the actual variable names sent by the browser contains a period rather than an underscore, but PHP converts the period to an underscore automatically.


HTTP Cookies

PHP transparently supports HTTP cookies as defined by Netscape's Spec. Cookies are a mechanism for storing data in the remote browser and thus tracking or identifying return users. You can set cookies using the setcookie() function. Cookies are part of the HTTP header, so the SetCookie function must be called before any output is sent to the browser. This is the same restriction as for the header() function. Cookie data is then available in the appropriate cookie data arrays, such as $_COOKIE, $HTTP_COOKIE_VARS as well as in $_REQUEST. See the setcookie() manual page for more details and examples.

If you wish to assign multiple values to a single cookie variable, you may assign it as an array. For example:

<?php
  setcookie("MyCookie[foo]", 'Testing 1', time()+3600);
  setcookie("MyCookie[bar]", 'Testing 2', time()+3600);
?>

That will create two separate cookies although MyCookie will now be a single array in your script. If you want to set just one cookie with multiple values, consider using serialize() or explode() on the value first.

Note that a cookie will replace a previous cookie by the same name in your browser unless the path or domain is different. So, for a shopping cart application you may want to keep a counter and pass this along. i.e.

Esempio 12-11. A setcookie() example

<?php
if (isset($_COOKIE['count'])) {
    $count = $_COOKIE['count'] + 1;
} else {
    $count = 1;
}
setcookie('count', $count, time()+3600);
setcookie("Cart[$count]", $item, time()+3600);
?>

Dots in incoming variable names

Typically, PHP does not alter the names of variables when they are passed into a script. However, it should be noted that the dot (period, full stop) is not a valid character in a PHP variable name. For the reason, look at it:
<?php
$varname.ext;  /* invalid variable name */
?>
Now, what the parser sees is a variable named $varname, followed by the string concatenation operator, followed by the barestring (i.e. unquoted string which doesn't match any known key or reserved words) 'ext'. Obviously, this doesn't have the intended result.

For this reason, it is important to note that PHP will automatically replace any dots in incoming variable names with underscores.


Determining variable types

Because PHP determines the types of variables and converts them (generally) as needed, it is not always obvious what type a given variable is at any one time. PHP includes several functions which find out what type a variable is, such as: gettype(), is_array(), is_float(), is_int(), is_object(), and is_string(). See also the chapter on Types.


Capitolo 13. Costanti

Una costante è un identificatore (nome) per un valore. Come si può intuire, tale valore non può cambiare durante l'esecuzione dello script (fanno eccezione le costanti magiche, che, in realtà, non sono costanti). Una costante è "case-sensitive" per default. È convenzione comune che i nomi di costante siano sempre maiuscoli.

In PHP il nome di una costante segue le regole di qualsiasi "etichetta". Un nome di costante valido inizia con una lettera o underscore, seguita da un numero qualsiasi di caratteri alfanumerici o underscore. L'espressione regolare che esprime questa convenzione è: [a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*

Nota: In questo contesto una lettera è a-z, A-Z e i caratteri ASCII dal 127 al 255 (0x7f-0xff).

Come le superglobals, costante è sempre globale. Si può accedere alle costanti da qualsiasi punto dello script senza tenere conto della visibilità. Per maggiori dettagli sulla visibilità, leggere la sezione variable scope.


Sintassi

È possibile definire una variabile utilizzando la funzione define(). Una volta definita, a una costante non è possibile cambiare il valore o eliminarla.

Le costanti possono contenere solo dati di tipo scalare (boolean, integer, float e string).

Per ottenere il valore di una costante è sufficiente specificarne il nome. A differenza delle variabili, non è necessario anteporre il simbolo $ al nome di una variabile. Si può anche utilizzare la funzione constant(), per leggere il valore di una costante, nel caso in cui se ne ottenga dinamicamente il nome. Si utilizzi get_defined_constants() per ottenere una lista delle variabili definite.

Nota: Costanti e variabili (globali) si trovano in un "namespace" differente. Questo implica che generalmente TRUE e $TRUE sono differenti.

Se si utilizza il nome di una costante che non è definita, PHP assume che detto valore sia il nome della costante stessa, come se si fosse inserito il testo nel nome . Quando ciò accade PHP segnala il problema con un E_NOTICE. Vedere anche il capitolo del manuale sul perchè $foo[bar] è errata (a meno che prima non definisca bar come costante con define()). Per sapere se una costante è definita, si può utilizzare la funzione defined().

Di seguito sono riportate le principali differenze rispetto le variabili:

  • Le costanti non iniziano con il segno del dollaro ($);

  • Le costanti possono essere definite solo con la funzione define() e non tramite assegnazione;

  • Le costanti possono essere definite e utilizzate ovunque senza seguire le regole di visibilità;

  • Una volta impostate, le costanti non posso essere redefinite e ne annullate;

  • Le costanti possono essere solo valori scalari;

Esempio 13-1. Definizione di costanti

<?php
define("COSTANTE", "Ciao mondo.");
echo COSTANTE; // stampa "Ciao mondo."
echo Costante; // stampa "Costante" e genera una notice.
?>


Costanti predefinite

Il PHP mette a disposizione ad ogni script diverse costanti predefinite. Alcune di queste, tuttavia, sono create dai vari moduli, e, pertanto, saranno disponibili solo quando questi moduli sono caricati, sia dinamicamente sia staticamente.

Esistono quattro costanti magiche il cui valore cambia in base al contesto in cui sono utilizzate. Ad esempio, il valore di __LINE__ dipende da quale linea si trova nel momento in cui è richiamata. Queste costanti speciali sono 'case-insensitive' e sono:

Tabella 13-1. Le costanti "magiche" del PHP

NomeDescrizione
__LINE__ Il numero di linea corrente.
__FILE__ Il nome e percorso assoluto del file.
__FUNCTION__ Nome della funzione. (Aggiunta nel PHP 4.3.0.)
__CLASS__ Nome della classe. (Aggiunta nel PHP 4.3.0.)
__METHOD__ Nome del metodo della classe (Aggiunta nel PHP 5.0.0.)

La lista di tutte le costanti predefinite è presente nella sezione reserved predefined constants.


Capitolo 14. Expressions

Expressions are the most important building stones of PHP. In PHP, almost anything you write is an expression. The simplest yet most accurate way to define an expression is "anything that has a value".

The most basic forms of expressions are constants and variables. When you type "$a = 5", you're assigning '5' into $a. '5', obviously, has the value 5, or in other words '5' is an expression with the value of 5 (in this case, '5' is an integer constant).

After this assignment, you'd expect $a's value to be 5 as well, so if you wrote $b = $a, you'd expect it to behave just as if you wrote $b = 5. In other words, $a is an expression with the value of 5 as well. If everything works right, this is exactly what will happen.

Slightly more complex examples for expressions are functions. For instance, consider the following function:

<?php
function foo ()
{
    return 5;
}
?>

Assuming you're familiar with the concept of functions (if you're not, take a look at the chapter about functions), you'd assume that typing $c = foo() is essentially just like writing $c = 5, and you're right. Functions are expressions with the value of their return value. Since foo() returns 5, the value of the expression 'foo()' is 5. Usually functions don't just return a static value but compute something.

Of course, values in PHP don't have to be integers, and very often they aren't. PHP supports four scalar value types: integer values, floating point values (float), string values and boolean values (scalar values are values that you can't 'break' into smaller pieces, unlike arrays, for instance). PHP also supports two composite (non-scalar) types: arrays and objects. Each of these value types can be assigned into variables or returned from functions.

PHP takes expressions much further, in the same way many other languages do. PHP is an expression-oriented language, in the sense that almost everything is an expression. Consider the example we've already dealt with, '$a = 5'. It's easy to see that there are two values involved here, the value of the integer constant '5', and the value of $a which is being updated to 5 as well. But the truth is that there's one additional value involved here, and that's the value of the assignment itself. The assignment itself evaluates to the assigned value, in this case 5. In practice, it means that '$a = 5', regardless of what it does, is an expression with the value 5. Thus, writing something like '$b = ($a = 5)' is like writing '$a = 5; $b = 5;' (a semicolon marks the end of a statement). Since assignments are parsed in a right to left order, you can also write '$b = $a = 5'.

Another good example of expression orientation is pre- and post-increment and decrement. Users of PHP and many other languages may be familiar with the notation of variable++ and variable--. These are increment and decrement operators. In PHP/FI 2, the statement '$a++' has no value (is not an expression), and thus you can't assign it or use it in any way. PHP enhances the increment/decrement capabilities by making these expressions as well, like in C. In PHP, like in C, there are two types of increment - pre-increment and post-increment. Both pre-increment and post-increment essentially increment the variable, and the effect on the variable is identical. The difference is with the value of the increment expression. Pre-increment, which is written '++$variable', evaluates to the incremented value (PHP increments the variable before reading its value, thus the name 'pre-increment'). Post-increment, which is written '$variable++' evaluates to the original value of $variable, before it was incremented (PHP increments the variable after reading its value, thus the name 'post-increment').

A very common type of expressions are comparison expressions. These expressions evaluate to either FALSE or TRUE. PHP supports > (bigger than), >= (bigger than or equal to), == (equal), != (not equal), < (smaller than) and <= (smaller than or equal to). The language also supports a set of strict equivalence operators: === (equal to and same type) and !== (not equal to or not same type). These expressions are most commonly used inside conditional execution, such as if statements.

The last example of expressions we'll deal with here is combined operator-assignment expressions. You already know that if you want to increment $a by 1, you can simply write '$a++' or '++$a'. But what if you want to add more than one to it, for instance 3? You could write '$a++' multiple times, but this is obviously not a very efficient or comfortable way. A much more common practice is to write '$a = $a + 3'. '$a + 3' evaluates to the value of $a plus 3, and is assigned back into $a, which results in incrementing $a by 3. In PHP, as in several other languages like C, you can write this in a shorter way, which with time would become clearer and quicker to understand as well. Adding 3 to the current value of $a can be written '$a += 3'. This means exactly "take the value of $a, add 3 to it, and assign it back into $a". In addition to being shorter and clearer, this also results in faster execution. The value of '$a += 3', like the value of a regular assignment, is the assigned value. Notice that it is NOT 3, but the combined value of $a plus 3 (this is the value that's assigned into $a). Any two-place operator can be used in this operator-assignment mode, for example '$a -= 5' (subtract 5 from the value of $a), '$b *= 7' (multiply the value of $b by 7), etc.

There is one more expression that may seem odd if you haven't seen it in other languages, the ternary conditional operator:

<?php
$first ? $second : $third
?>

If the value of the first subexpression is TRUE (non-zero), then the second subexpression is evaluated, and that is the result of the conditional expression. Otherwise, the third subexpression is evaluated, and that is the value.

The following example should help you understand pre- and post-increment and expressions in general a bit better:

<?php
function double($i)
{
    return $i*2;
}
$b = $a = 5;        /* assign the value five into the variable $a and $b */
$c = $a++;          /* post-increment, assign original value of $a 
                       (5) to $c */
$e = $d = ++$b;     /* pre-increment, assign the incremented value of 
                       $b (6) to $d and $e */

/* at this point, both $d and $e are equal to 6 */

$f = double($d++);  /* assign twice the value of $d before
                       the increment, 2*6 = 12 to $f */
$g = double(++$e);  /* assign twice the value of $e after
                       the increment, 2*7 = 14 to $g */
$h = $g += 10;      /* first, $g is incremented by 10 and ends with the 
                       value of 24. the value of the assignment (24) is 
                       then assigned into $h, and $h ends with the value 
                       of 24 as well. */
?>

Some expressions can be considered as statements. In this case, a statement has the form of 'expr' ';' that is, an expression followed by a semicolon. In '$b=$a=5;', $a=5 is a valid expression, but it's not a statement by itself. '$b=$a=5;' however is a valid statement.

One last thing worth mentioning is the truth value of expressions. In many events, mainly in conditional execution and loops, you're not interested in the specific value of the expression, but only care about whether it means TRUE or FALSE. The constants TRUE and FALSE (case-insensitive) are the two possible boolean values. When necessary, an expression is automatically converted to boolean. See the section about type-casting for details about how.

PHP provides a full and powerful implementation of expressions, and documenting it entirely goes beyond the scope of this manual. The above examples should give you a good idea about what expressions are and how you can construct useful expressions. Throughout the rest of this manual we'll write expr to indicate any valid PHP expression.


Capitolo 15. Operatori


Precedenza degli operatori

La precedenza di un operatore specifica come esso tenga legate assieme "strettamente" due espressioni. Per esempio, nell'espressione 1 + 5 * 3, la risposta è 16 e non 18 perché l'operatore di moltiplicazione ("*") ha una precedenza più alta rispetto all'operatore di addizione ("+"). Le parentesi possono essere usate per forzare la precedenza, se necessario. Per esempio: (1 + 5) * 3 viene valutata 18.

La seguente tabella fornisce una lista della precedenza degli operatori con gli operatori a più bassa precedenza listati prima.

Tabella 15-1. Precedenza degli operatori

AssociativitàOperatori
sinistra,
sinistraor
sinistraxor
sinistraand
destraprint
sinistra = += -= *= /= .= %= &= |= ^= ~= <<= >>=
sinistra? :
sinistra||
sinistra&&
sinistra|
sinistra^
sinistra&
non associativi== != === !==
non associativi< <= > >=
sinistra<< >>
sinistra+ - .
sinistra* / %
destra! ~ ++ -- (int) (float) (string) (array) (object) @
destra[
non associativinew


Operatori aritmetici

Ricordate l'aritmetica di base dalla scuola? Questi funzionano proprio come quelli.

Tabella 15-2. Operatori aritmetici

EsempioNomeRisultato
$a + $bAddizioneLa somma di $a e $b.
$a - $bSottrazioneLa differenza di $a e $b.
$a * $bMoltiplicazioneil prodotto di $a e $b.
$a / $bDivisioneQuoziente di $a e $b.
$a % $bModuloIl resto di $a diviso da $b.

L'operatore di divisione ("/") restituisce un valore float in ogni caso, anche se i due operandi sono interi (oppure stringhe che vengono convertite in interi).


Operatori di assegnazione

L'operatore di base dell'assegnazione è "=". La vostra prima inclinazione potrebbe essere di pensare che ciò sia come "uguale a". No. Esso significa realmente che l'operando a sinistra assume il valore dell'espressione a destra (ciò significa, "assegna il valore a").

Il valore di un'espressione di assegnazione è il valore assegnato. Cioè il valore di "$a = 3" è 3. Questo vi permette di fare qualche trucchetto:

$a = ($b = 4) + 5; // $a è uguale a 9 ora, e $b è stato impostato a 4.

In aggiunta all'operatore di base dell'assegnazione, ci sono gli "operatori combinati" per tutta l'aritmetica binaria e gli operatori di stringa che vi consentono di usare un valore in un'espressione e poi impostare il suo valore al risultato di quell'espressione. Per esempio:

$a = 3;
$a += 5; // imposta $a a 8, come se avessimo detto: $a = $a + 5;
$b = "Ciao ";
$b .= "Lì!"; // imposta $b a "Ciao Lì!", proprio come $b = $b . "Lì!";

Notare che l'assegnazione copia la variabile originale alla nuova (assegnazione per valore), così i cambiamenti ad una non si verificheranno nell' altra. Ciò può anche avere rilevanza se avete bisogno di copiare qualcosa come un grande array in un ciclo molto stretto. PHP 4 supporta l'assegnazione per riferimento, usando la sintassi $var = &$othervar;, ma ciò non è possibile in PHP 3. 'L'assegnazione per riferimento' vuol dire che entrambe le variabili finiscono con il puntare agli stessi dati, e nulla è copiato in nessun posto. Per ulteriori approfondimenti sui riferimenti, consultare References explained.


Operatori bitwise

Gli operatori bitwise vi permettono di alterare bit specifici in posizione on oppure off. Se entrambi i parametri di sinistra e destra sono stringhe, l'operatore bitwise opererà sui caratteri di questa stringa.

<?php
    echo 12 ^ 9; // L'output è '5'

    echo "12" ^ "9"; // L'output è il carattere Backspace (ascii 8)
                     // ('1' (ascii 49)) ^ ('9' (ascii 57)) = #8

    echo "hallo" ^ "hello"; // L'output è il valore ascii #0 #4 #0 #0 #0
                            // 'a' ^ 'e' = #4
?>

Tabella 15-3. Operatori bitwise

EsempioNomeRisultato
$a & $bAndSono impostati ad ON i bit che sono ON sia in $a che in $b.
$a | $bOrSono impostati ad ON i bit che sono ON in $a oppure in $b.
$a ^ $bXor Sono impostati ad ON i bit che sono ON in $a oppure in $b na non quelli che sono entrambi ON.
~ $aNot Sono impostati ad ON i bit che sono OFF in $a, e viceversa.
$a << $bShift left Sposta i bit di $a a sinistra di $b passi (ogni passo significa "moltiplica per due")
$a >> $bShift right Sposta i bit di $a a destra di $b passi (ogni passo significa "dividi per due")

Operatori di confronto

Gli operatori di confronto, come suggerisce il loro nome, permettono di confrontare due valori.

Tabella 15-4. Operatori di confronto

EsempioNomeRisultato
$a == $bUgualeTRUE se $a è uguale a $b.
$a === $bIdentico TRUE se $a è uguale a $b, ed essi sono dello stesso tipo. (Solo PHP 4)
$a != $bDiversiTRUE se $a è diverso da $b.
$a <> $bDiversiTRUE se $a è diverso da $b.
$a !== $bNon identici TRUE se $a è diverso da $b, o se essi non sono dello stesso tipo. (Solo PHP 4)
$a < $bMinoreTRUE se $a è strettamente minore di $b.
$a > $bMaggioreTRUE se $a è strettamente maggiore di $b.
$a <= $bMinore o ugualeTRUE se $a è minore o uguale a $b.
$a >= $bMaggiore o ugualeTRUE se $a è maggiore o uguale a $b.

Un altro operatore condizionale è l'operatore "?:" (o ternario), che opera come in C e molti altri linguaggi.

(espressione1) ? (espressione2) : (espressione3);

Questa espressione vale espressione2 se espressione1 è TRUE, e espressione3 se espressione1 è FALSE.


Operatori di controllo errori

PHP supporta un operatore di controllo dell'errore: il carattere at (@). Quando prefisso ad una espressione in PHP, qualunque messaggio di errore che potesse essere generato da quella espressione sarà ignorato.

Se la caratteristica track_errors è abilitata, qualsiasi messaggio di errore generato dall'espressione sarà salvato nella variabile globale $php_errormsg. Questa variabile sarà sovrascritta ad ogni errore, così controllatela subito se volete usarla.

<?php
/* Errore di file intenzionale */
$my_file = @file ('file_inesistente') or
    die ("Apertura del file fallita: l'errore è '$php_errormsg'");

// questo funziona per qualsiasi espressione, non solo funzioni:
$value = @$cache[$key];
// non verrà generata una notifica se l'indice $key non esiste.

?>

Nota: L'operatore @ funziona solo sulle espressioni. Una semplice regola di thumb è: se potete prendere il valore di qualcosa, potete anteporre ad esso l'operatore @. Per esempio, potete anteporre esso a variabili, funzioni e chiamate ad include(), costanti, e così via. non potete anteporre esso a definizioni di funzioni o classi, o strutture condizionali come if e foreach, e così via.

Vedere anche error_reporting().

Avvertimento

Attualmente il prefisso operatore di controllo dell'errore "@" disabiliterà la restituzione di errori per errori critici che interromperanno l'esecuzione dello script. Tra le altre cose, questo significa che se state usando "@" per sopprimere errori da una certa funzione ed essa non è disponibile oppure è stata scritta male, lo script terminerà senza dare indicazioni sul perché.


Operatori di esecuzione

PHP supporta un operatore di esecuzione: backticks (``). Notare che quelli non sono apostrofi! PHP cercherà di eseguire il contenuto dei backticks come comando di shell; sarà restituito l'output (i.e., non sarà semplicemente esportato come output; può essere assegnato ad una variabile).

$output = `ls -al`;
echo "<pre>$output</pre>";

Nota: L'operatore backtick è disabilitato quando è abilitata safe mode oppure quando è disabilitata shell_exec().

Vedere anche escapeshellcmd(), exec(), passthru(), popen(), shell_exec() e system().


Operatori di incremento/decremento

PHP supporta lo stile C degli operatori di pre- e post-incremento e decremento.

Tabella 15-5. Operatori di incremento/decremento

EsempioNomeEffetto
++$aPre-incrementoIncrementa $a di una unità, inoltre restituisce $a.
$a++Post-incrementoRestituisce $a, inoltre incrementa $a di una unità.
--$aPre-decrementoDecrementa $a di una unità, inoltre restituisce $a.
$a--Post-decrementoRestituisce $a, inoltre decrementa $a di una unità.

Qui c'è un semplice script di esempio:

<?php
echo "<h3&gt;Post-incremento</h3&gt;";
$a = 5;
echo "Dovrebbe essere 5: " . $a++ . "<br>\n";
echo "Dovrebbe essere 6: " . $a . "<br>\n";

echo "<h3>Pre-incremento</h3>";
$a = 5;
echo "Dovrebbe essere 6: " . ++$a . "<br>\n";
echo "Dovrebbe essere 6: " . $a . "<br>\n";

echo "<h3>Post-decremento</h3>";
$a = 5;
echo "Dovrebbe essere 5: " . $a-- . "<br>\n";
echo "Dovrebbe essere 4: " . $a . "<br>\n";

echo "<h3>Pre-decremento</h3>";
$a = 5;
echo "Dovrebbe essere 4: " . --$a . "<br>\n";
echo "Dovrebbe essere 4: " . $a . "<br>\n";
?>


Operatori logici

Tabella 15-6. Operatori logici

EsempioNomeRisultato
$a and $bAndTRUE se entrambi $a e $b sono TRUE.
$a or $bOrTRUE se uno tra $a o $b è TRUE.
$a xor $bXorTRUE se uno tra $a o $b è TRUE, ma non entrambi.
! $aNotTRUE se $a non è TRUE.
$a && $bAndTRUE se entrambi $a e $b sono TRUE.
$a || $bOrTRUE se uno tra $a o $b è TRUE.

La ragione per le due differenti variazioni degli operatori "and" e "or" è che essi operano con differenti precedenze. (Vedere Precedenza degli operatori.)


Operatori di stringa

Ci sono due operatori di stringa. Il primo è l'operatore di concatenazione ('.'), che restituisce la concatenazione dei suoi argomenti a destra e a sinistra. Il secondo è l'operatore di assegnazione concatenata ('.='), che aggiunge alla fine dell'argomento sul lato destro l'argomento sul lato sinistro. Per favore consultare Operatori di assegnazione per maggiori informazioni.

$a = "Ciao ";
$b = $a . "Mondo!"; // ora $b contiene "Ciao Mondo!"

$a = "Ciao ";
$a .= "Mondo!";     // ora $a contiene "Ciao Mondo!"


Capitolo 16. Strutture di controllo

Qualsiasi script PHP è costituito da una serie di istruzioni. Una istruzione può essere un'assegnazione, una chiamata di funzione, un loop, una istruzione condizionale che non fa nulla (istruzione vuota). Le istruzioni terminano con un punto e virgola. Inoltre, le istruzioni si possono raggruppare in blocchi di istruzioni racchiudendole tra parentesi graffa. Un gruppo di istruzioni è, a sua volta, un'istruzione. Il presente capitolo descrive i differenti tipi di istruzioni.


if

Il costrutto if è una delle più importanti caratteristiche di qualsiasi linguaggio, incluso PHP. Permette l'esecuzione condizionata di frammenti di codice. La struttura di controllo if di PHP è simile a quella del linguaggio C:

if (espressione)
    istruzione

Come descritto nella sezione sulle espressioni, espressione restiruirà il suo valore booleano. Se espressione vale TRUE, PHP eseguirà istruzione, e se essa vale FALSE - la ignorerà. Più informazioni riguardo i valori valutati FALSE possono essere trovati nella sezione 'Conversione in booleano' .

L'esempio che segue visualizzerà a è maggiore di b se $a sarà maggiore di $b:

if ($a > $b)
    print "a è maggiore di b";

Spesso sarà necessario eseguire più di una istruzione condizionale. Naturalmente non è necessario, utilizzare una singola clausola if per ciascuna istruzione. Si possono raggruppare diverse istruzioni in un singolo gruppo di istruzioni. Per esempio, il codice che segue visualizzerà a è maggiore di b se $a è maggiore di $b, e successivamente assegnerà il valore della variabile $a alla variabile $b:

if ($a > $b) {
    print "a è maggiore di b";
    $b = $a;
}

Si possono annidare indefinitamente istruzioni if, la qual cosa fornisce piena flessibilità per l'esecuzione di istruzioni condizionali in diversi punti del programma.


else

Spesso è necessario eseguire un'istruzione se una proposizione è vera e un'altra istruzione se la proposizione è falsa. Per questo si usa la clausola else. else estende il costrutto if aggiungendo la possibilità di eseguire un'istruzione se l'espressione nel ramo if è FALSE. L'esempio che segue visualizzerà a è maggiore di b se $a è maggiore di $b e a NON è maggiore di b altrimenti:

if ($a > $b) {
    print "a è maggiore di b";
} else {
    print "a NON è maggiore di b";
}

Il ramo else viene eseguito solo se l'espressione nel ramo if è FALSE, e, nel caso ci fossero delle clausole elseif, solamente se le espressioni in esse contenute fossero anch'esse FALSE (vedere elseif).


elseif

elseif, come è facile intuire, è una combinazione di if ed else. Analogamente ad else, estende if aggiungendo la possibilità di eseguire un'altra istruzione nel caso in cui l'espressione contenuta nel ramo if sia FALSE. Però, a differenza di else, si eseguirà l'istruzione alternativa solamente se l'espressione contenuta nel ramo elseif sarà TRUE. L'esempio che segue, visualizzerà a è maggiore di b, a è uguale a b oppure a è minore di b:

if ($a > $b) {
    print "a è maggiore di b";
} elseif ($a == $b) {
    print "a è uguale a b";
} else {
    print "a è minore di b";
}

Nel medesimo blocco if possono essere presenti più di una clausola elseif. Verrà eseguita l'istruzione del primo ramo elseif la cui espressione sia TRUE. In PHP è possibile scrivere 'else if' (due parole) e il significato sarà lo stesso di 'elseif' (una sola parola). Il significato sintattico è leggermente differente (se si ha familiarità con il linguaggio C, esso ha lo stesso comportamento) però al lato pratico l'effetto è il medesimo.

L'istruzione di un ramo elseif verrà eseguita solo se l'espressione del ramo if e le espressioni dei rami elseif precedenti sono FALSE, e se l'espressione del ramo elseif è TRUE.


Sintassi alternativa per le strutture di controllo

PHP offre una sintassi alternativa per alcune delle sue strutture di controllo; vale a dire, if, while, for, foreach e switch. Fondamentalmente la sintassi alternativa consiste nel sostituire la prima parentesi graffa con il carattere "duepunti" (:) e la seconda parentesi graffa con endif;, endwhile;, endfor;, endforeach;, oppure endswitch;, rispettivamente.

<?php if ($a == 5): ?>
a è uguale a 5
<?php endif; ?>

Nell'esempio precedente, il blocco HTML "a è uguale a 5" è incluso nel ramo if scritto utilizzando la sintassi alternativa. Il blocco HTML verrà visualizzato solamente se $a è uguale a 5.

La sintassi alternativa si applica anche ad else ed elseif. Nell'esempio che segue si mostra come utilizzare la sintassi alternativa nel caso di un if con elseif ed else:

if ($a == 5):
    print "a è uguale a 5";
    print "...";
elseif ($a == 6):
    print "a è uguale a 6";
    print "!!!";
else:
    print "a non è nè 5 nè 6";
endif;

Vedere anche while, for, e if per ulteriori esempi.


while

Il ciclo while è la forma di ciclo più semplice tra quelle possibili in PHP. Si comporta come la sua controparte nel linguaggio C. La forma di base di un ciclo while è la seguente:

while (espressione) istruzione

Il significato di un ciclo while è semplice. Istruisce l'interprete PHP perchè esegua l'istruzione (o le istruzioni) in esso racchiuse, ripetutamente, fintanto che l'espressione contenuta nella clausola while ha valore TRUE. Il valore dell'espressione viene verificato ogni volta che il ciclo si ripete (iterazione), così che anche se il valore dell'espressione cambia durante l'esecuzione dell'istruzione, il ciclo non termina fino all'iterazione successiva. Ovviamente, se l'espressione nella clausola while ha valore FALSE dall'inizio, l'istruzione racchiusa nel blocco non verrà eseguita nemmeno una volta.

Come nel caso della struttura di controllo if, si possono raggruppare più istruzioni nello medesimo ciclo while racchiudendo le istruzioni in parentesi graffa, oppure utilizzando la sintassi alternativa:

while (espressione): istruzione ... endwhile;

Gli esempi seguenti sono identici e entrambi visualizzano i numeri da 1 a 10:

/* esempio 1 */

$i = 1;
while ($i <= 10) {
    print $i++;  /* Il valore visualizzato è il valore della
                    variabile $i prima dell'incremento
                    (post-incremento) */
}

/* esempio 2 */

$i = 1;
while ($i <= 10):
    print $i;
    $i++;
endwhile;


do..while

Il ciclo do..while è simile al ciclo while, con l'unica differenza che il valore dell'espressione viene controllato alla fine di ogni iterazione anzichè all'inizio. La differenza più importante rispetto a while è che la prima iterazione di un blocco do..while verrà sempre eseguita (il valore dell'espressione viene controllato alla fine del ciclo), mentre non sarà necessariamente eseguito in un ciclo while (il valore dell'espressione viene controllato all'inizio del ciclo, e se tale valore è FALSE dall'inizio, l'esecuzione del ciclo termina immediatamente).

È ammessa una sola sintassi per il ciclo do..while:

$i = 0;
do {
   print $i;
} while ($i>0);

Il ciclo precedente verrà eseguito un'unica volta, dal momento che alla prima iterazione, quando si controlla l'espressione, il suo valore sarà FALSE ($i non è maggiore di 0) e il ciclo di esecuzioni, termina.

Chi ha utilizzato il linguaggio C conosce probabilmente un'altro modo di utilizzare il ciclo do..while, che permette di terminare l'esecuzione delle istruzioni durante l'esecuzione stessa, utilizzando do..while(0), e usando l'istruzione break. Il codice che segue esemplifica questa possibilità:

do {
    if ($i < 5) {
        print "i non è abbastanza grande";
        break;
    }
    $i *= $factor;
    if ($i < $minimum_limit) {
        break;
    }
    print "i è ok";

     ...processa i...

} while(0);

Non vi preoccupate se l'esempio non è sufficientemente chiaro. Si possono scrivere ottimi programmi PHP anche senza far ricorso a questa 'possibilità'.


for

Il ciclo for è il ciclo più complesso tra quelli disponibili in PHP. Si comporta come la sua controparte nel linguaggio C. La sintassi di un clico for è:

for (espressione1; espressione2; espressione3) istruzione

Il valore della prima espressione (espressione1) viene verificato (eseguito) una sola volta incondizionatamente all'inizio del ciclo.

Ad ogni iterazione, si controlla il valore di espressione2. Se è TRUE, il ciclo prosegue e viene eseguita l'istruzione (o le istruzioni) contenuta nel blocco; se è FALSE, l'esecuzione del ciclo termina.

Al termine di ogni iterazione, si verifica (si esegue) il valore di espressione3.

Le due espressioni possono anche non essere presenti. Se non esiste espressione2 significa che il ciclo deve essere eseguito indefinitamente (PHP considera implicitamente che il suo valore è TRUE, come in C). Questa possibilità in fondo non è utile come può sembrare perchè obbliga a terminare il ciclo utilizzando l'istruzione break invece di utilizzare le espressioni booleane del ciclo for .

Si considerino gli esempi seguenti. In ciascun caso si visualizzeranno i numeri da 1 a 10:

/* esempio 1 */

for ($i = 1; $i <= 10; $i++) {
    print $i;
}

/* esempio 2 */

for ($i = 1;;$i++) {
    if ($i > 10) {
        break;
    }
    print $i;
}

/* esempio 3 */

$i = 1;
for (;;) {
    if ($i > 10) {
        break;
    }
    print $i;
    $i++;
}

/* esempio 4 */

for ($i = 1; $i <= 10; print $i, $i++) ;

Naturalmente il primo esempio sembra il migliore (o forse il quarto), ma l'uso del ciclo for senza espressioni può essere utile in molti casi.

PHP offre una sintassi alternativa (con i "punto e virgola") per i cicli for.

for (espressione1; espressione2; espressione3): istruzione; ...; endfor;

Alcuni linguaggi permettono l'uso della struttura di controllo foreach per attraversare un array o una tabella hash. PHP 3 non premette l'uso di tale ciclo mentre PHP 4 si (vedere foreach). In PHP 3 è possibile combinare while con la funzione list() e each() per ottenere la stessa funzionalià. Si veda la documentazione di queste funzioni per ulteriori esempi.


foreach

PHP 4 (non PHP 3) permette l'uso della struttura di controllo foreach, alla stessa maniera del linguaggio Perl e altri. Ciò semplicemente fornisce una facile metodo per attraversare un array. Esistono due possibili notazioni sintattiche; la seconda è un'utile estensione della prima:

foreach(array_expression as $value) istruzione
foreach(array_expression as $key => $value) istruzione

La prima attraversa l'array dato da array_expression. Ad ogni ciclo, si assegna il valore dell'elemento corrente a $value e il puntatore interno avanza di una posizione (in modo tale che al ciclo successivo l'elemento corrente sarà il successivo elemento dell'array).

La seconda esegue lo stesso ciclo con la differenza che il valore dell'indice corrente viene assegnato ad ogni ciclo, alla variabile $key.

Nota: All'inizio dell'esecuzione di un ciclo foreach il puntatore interno viene automaticamente posizionato nella prima posizione. Questo significa che non è necessario utilizzare la funzione reset() prima di un ciclo foreach.

Nota: È importante notare che foreach opera su una copia dell'array, non sull'array stesso, pertanto il puntatore dell'array originale non viene modificato come accade utilizzando la funzione each() e le modifiche agli elementi dell'array non appaiono nell'array originale.

Nota: foreach non offre la possibilità di annullare la generazione di messaggi d'errore utilizzando il carattere '@'.

Avete probabilmente notato che i due cicli seguenti sono identici da un punto di vista funzionale:

reset ($arr);
while (list(, $value) = each ($arr)) {
    echo "Valore: $value<br>\n";
}

foreach ($arr as $value) {
    echo "Valore: $value<br>\n";
}

Allo stesso modo i due cicli seguenti sono identici:

reset ($arr);
while (list($key, $value) = each ($arr)) {
    echo "Chiave: $key; Valore: $value<br>\n";
}

foreach ($arr as $key => $value) {
    echo "Chiave: $key; Valore: $value<br>\n";
}

Di seguito, altri esempi per mostrare possibili utilizzi:

/* esempio 1 foreach: solo il valore */

$a = array (1, 2, 3, 17);

foreach ($a as $v) {
   print "Valore corrente di \$a: $v.\n";
}

/* esempio 2 foreach: valore (con la chiave stampata) */

$a = array (1, 2, 3, 17);

$i = 0; /* solo per un proposito illustrativo */

foreach($a as $v) {
    print "\$a[$i] => $v.\n";
    $i++;
}

/* esempio 3 foreach: chiave e valore */

$a = array (
    "uno" => 1,
    "due" => 2,
    "tre" => 3,
    "diciassette" => 17
);

foreach($a as $k => $v) {
    print "\$a[$k] => $v.\n";
}

/* esempio 4 foreach: array multidimensionali */

$a[0][0] = "a";
$a[0][1] = "b";
$a[1][0] = "y";
$a[1][1] = "z";

foreach($a as $v1) {
    foreach ($v1 as $v2) {
        print "$v2\n";
    }
}

/* esempio 5 foreach: array dinamici */

foreach(array(1, 2, 3, 4, 5) as $v) {
    print "$v\n";
}


break

break termina l'esecuzione di una struttura for, foreach while, do..while o switch.

break accetta un argomento opzionale che definisce, nel caso di cicli annidati, il livello del ciclo che è da interrompere.

$arr = array ('uno', 'due', 'tre', 'quattro', 'stop', 'cinque');
while (list (, $val) = each ($arr)) {
    if ($val == 'stop') {
        break;    /* Qui si può anche usare 'break 1;'. */
    }
    echo "$val<br>\n";
}

/* Uso dell'argomento opzionale. */

$i = 0;
while (++$i) {
    switch ($i) {
    case 5:
        echo "At 5<br>\n";
        break 1;  /* Interrompe solo awitch. */
    case 10:
        echo "At 10; quitting<br>\n";
        break 2;  /* Interrompe switch e while. */
    default:
        break;
    }
}


continue

continue si utilizza per interrompere l'esecuzione del ciclo corrente e continuare con l'esecuzione all'inizio del ciclo successivo.

continue accetta un argomento numerico opzionale che definisce, nel caso di cicli annidati, il numero di cicli da interrompere e da cui iniziare l'esecuzione dell'iterazione successiva.

while (list ($key, $value) = each ($arr)) {
    if (!($key % 2)) { // salta odd members
        continue;
    }
    do_something_odd ($value);
}

$i = 0;
while ($i++ < 5) {
    echo "Esterno<br>\n";
    while (1) {
        echo "&nbsp;&nbsp;Centrale<br>\n";
        while (1) {
            echo "&nbsp;&nbsp;Interno<br>\n";
            continue 3;
        }
        echo "Questo non sarà mai stampato.<br>\n";
    }
    echo "Nemmeno questo.<br>\n";
}


switch

switch è simile a una serie di if sulla stessa espressione. In molti casi può essere necessario confrontare una variabile (o espressione) con differenti valori ed eseguire un differente blocco di istruzioni a seconda del valore di detta variabile. Questo è esattamente quello che fa la struttura di controllo switch.

Gli esempi seguenti mostrano due maniere differenti di scrivere la stessa cosa, uno utilizzando una serie di if, l'altro utilizzando switch :

if ($i == 0) {
    print "i è uguale a 0";
}
if ($i == 1) {
    print "i è uguale a 1";
}
if ($i == 2) {
    print "i è uguale a 2";
}

switch ($i) {
    case 0:
        print "i è uguale a 0";
        break;
    case 1:
        print "i è uguale a 1";
        break;
    case 2:
        print "i è uguale a 2";
        break;
}

È importante comprendere esattamente come viene eseguita la clausola switch per evitare errori. Un'istruzione switch esegue linea dopo linea le istruzioni in essa contenuta. All'inizio non viene eseguito alcun codice. Solamente quando incontra una clausola case il cui valore è uguale al valore della viariabile, PHP inizia ad eseguire le istruzioni contenute nel blocco case. PHP continua l'esecuzione delle istruzioni fino alla termine del blocco switch, o quando incontra un'istruzione break. Se non esiste alcuna istruzione break al termine di un blocco case PHP continuerà l'esecuzione delle istruzioni del blocco case successivo. Per esempio:

switch ($i) {
    case 0:
        print "i è uguale a 0";
    case 1:
        print "i è uguale a 1";
    case 2:
        print "i è uguale a 2";
}

In questo caso se $i è uguale a 0, PHP eseguirà tutte le istruzioni contenute nei blocchi case. Se $i è uguale a 1, PHP eseguirà le istruzioni degli ultimi due blocchi case e solamente se $i è uguale a 2 otterremo il risultato voluto e si visualizzerà solo '$i è uguale a 2'. Pertanto è importante non dimenticare l'istruzione break (anche se in alcuni casi potrà essere necessario non utilizzarla).

In un'istruzione switch, la condizione in parentesi viene valutata una sola volta e il risultato viene confrontato con ciascun ramo case. Utilizzando elseif, la condizione viene valutata una seconda volta. Se tale condizione è più complessa di un semplice confronto e/o è in un ciclo piuttosto pesante, l'uso di switch dovrebbe garantire un minor tempo di esecuzione.

Un blocco case può anche non contenere istruzioni, nel qual caso il controllo passa semplicemente al successivo blocco case.

switch ($i) {
    case 0:
    case 1:
    case 2:
        print "i è minore di 3 ma non negativo";
        break;
    case 3:
        print "i è 3";
}

Un blocco case speciale è il il blocco case di default. Uguaglia tutte le condizioni non uguagliate nei blocchi case precedenti e dev'essere l'ultimo blocco case. Per esempio:

switch ($i) {
    case 0:
        print "i è uguale a 0";
        break;
    case 1:
        print "i è uguale a 1";
        break;
    case 2:
        print "i è uguale a 2";
        break;
    default:
        print "i è diverso da 0, 1 o 2";
}

L'espressione in un ramo case può essere qualsiasi espressione il cui valore sarà di tipo intero, decimale, numerico e stringa. Array e oggetti (objects) non sono ammessi a meno che non siano dereferenziati a un tipo di dato semplice tra quelli precedentemente elencati.

Come per altre strutture di controllo è possibile utilizzare una sintassi alternativa. Si veda Sintassi alternativa per le strutture di controllo per ulteriori esempi.

switch ($i):
    case 0:
        print "i è uguale a 0";
        break;
    case 1:
        print "i è uguale a 1";
        break;
    case 2:
        print "i è uguale a 2";
        break;
    default:
        print "i è diverso da 0, 1 o 2";
endswitch;


declare

Il costrutto declare si usa per definire direttive di esecuzione per blocchi di istruzioni. La sintassi è simile alla sintassi di altre strutture di controllo:

declare (direttiva) istruzione

La sezione direttiva permette di impostare il comportamento del blocco declare . Attualmente è riconosciuta una sola direttiva: la direttiva ticks. (Fare riferimento più in basso per ulteriori informazioni relative alla direttiva ticks)

Verrà eseguita la parte istruzione del blocco declare - come verrà eseguita e quali effetti collaterali emergeranno durante l'esecuzione potrà dipendere dalla direttiva impostata nel blocco direttiva.


Ticks

Un tick è un evento che si verifica per ogni N istruzioni di basso livello eseguite dal parser all'interno del blocco declare. Il valore per N viene specificato usando ticks=N all'interno della sezione direttiva del blocco declare.

L'evento (o gli eventi) che si verifica su ogni tick è specificato usando register_tick_function(). Vedere l'esempio più in basso per ulteriori dettagli. Notare che può verificarsi più di un evento per ogni tick.

Esempio 16-1. Segue una sezione di codice PHP

<?php
// Una funzione che registra il tempo quando viene chiamata
function profile ($dump = FALSE)
{
    static $profile;

    // Restituisce il tempo immagazinato in $profile, successivamente lo cancella
    if ($dump) {
        $temp = $profile;
        unset ($profile);
        return ($temp);
    }

    $profile[] = microtime ();
}

// Imposta un tick handler
register_tick_function("profile");

// Inizializza la funzione prima del blocco declare
profile ();

// Esegue un blocco di codice, attraverso un tick ogni seconda istruzione
declare (ticks = 2) {
    for ($x = 1; $x < 50; ++$x) {
        echo similar_text (md5($x), md5($x*$x)), "<br />";
    }
}

// Mostra i dati immagazionati nel profilo
print_r (profile (TRUE));
?>
L'esempio descrive il codice PHP all'interno del blocco 'declare', registrando il tempo in cui è stata eseguita ogni seconda istruzione di basso livello. Questa informazione può poi essere usata per trovare le aree lente all'interno di particolari segmenti di codice. Questo processo può essere ottimizzato usando altri metodi: usando i tick è più conveniente e facile da implementare.

I tick sono ben adeguati per il debugging, l'implementazione di semplici multitasking, backgrounded I/O e molti altri compiti.

Vedere anche register_tick_function() e unregister_tick_function().


return

Se viene chiamato all'interno di una funzione, l'istruzione return() termina immediatamente l'esecuzione della funzione corrente, e restituisce il suo argomento come valore della funzione chiamata. return() terminerà anche l'esecuzione di un'istruzione eval() o di un file di script.

Se viene chiamato in uno scope globale, allora verrà terrminata l'esecuzione del file di script corrente. Nel caso in cui il file di script corrente sia un file chiamato da include() o require(), il controllo viene passato al file chiamante. Ciononostante, se il file di script corrente è un file chiamato da include(), allora il valore dato da return() verrà restituito come valore della chiamata include(). Se viene chiamato return() all'interno del file di script principale, allora l'esecuzione dello script terminerà. Se il file di script corrente è stato nominato da auto_prepend_file o auto_append_file con le opzioni di configurazione nel file di configurazione, allora l'esecuzione di quello script termina.

Per maggiori informazioni, consultare Valori restituiti.

Nota: Notate che poichè return() è un costrutto di linguaggio e non una funzione, le parentesi che circondano i suoi argomenti non sono richieste --infatti, è più comune evitarle che usarle, nonostante ciò non c'è motivo di preferire un modo o l'altro.


require()

L'istruzione require() include e valuta il file specifico.

require() include e valuta uno specifico file. Informazioni dettagliate su come funziona quest'inclusione sono descritte nella documentazione di include().

require() e include() sono identiche in ogni senso eccetto per come esse trattano gli errori. include() produce un Warning mentre require() restituisce un Fatal Error. In altre parole, non esitate ad usare require() se volete che un file mancante fermi l'esecuzione della pagina. include() non si comporta in questo modo, lo script continuerà nonostante tutto. Assicuratevi di avere un appropriato include_path impostato a dovere.

Esempio 16-2. Esempio di base con require()

<?php

require 'prepend.php';

require $qualche_file;

require ('qualche_file.txt');

?>

Vedere la documentazione di include() per più esempi.

Nota: Prima di PHP 4.0.2, si applica la seguente logica: require() tenterà sempre di leggere il file chiamato, anche se la riga su cui si trova non verrà mai eseguita. L'istruzione condizionale non avrà effetto su require(). Comunque, se la riga su cui si verifica require() non viene eseguita, non sarà eseguito nemmeno il codice del file incluso. Similmente, le strutture cicliche non avranno effetto sul comportamento di require(). Sebbene il codice contenuto nel file incluso è ancora soggetto a ciclo, require() stesso si verifica solo una volta.

Vedere anche include(), require_once(), include_once(), eval(), file(), readfile(), virtual() e include_path.


include()

L'istruzione include() include e valuta il file specificato.

La documentazione seguente si applica anche a require(). I due costrutti sono identici in ogni aspetto eccetto per come essi trattano gli errori. include() produce un Warning mentre require() restituisce un Fatal Error. In altre parole, usate require() se volete che un file mancante fermi l'esecuzione della pagina. include() non si comporta in questo modo, lo script continuerà nonostante tutto. Assicuratevi di avere un appropriato include_path impostato a dovere.

Quando un file viene incluso, il codice che esso contiene eredita lo scope delle variabili della riga in cui si verifica l'inclusione. Qualsiasi variabile disponibile in quella riga nella chiamata al file sarà disponibile all'interno del file chiamato, da quel punto in avanti.

Esempio 16-3. Esempio di base con include()

vars.php
<?php

$colore = 'verde';
$frutto = 'mela';

?>

test.php
<?php

echo "Una $frutto $colore"; // Una

include 'vars.php';

echo "Una $frutto $colore"; // Una mela verde

?>

Se l'inclusione si verifica dentro una funzione all'interno del file chiamato, allora tutto il codice contenuto nel file chiamato si comporterà come se esso sia stato definito all'interno di una funzione. Così, esso seguirà lo scope delle variabili di quella funzione.

Esempio 16-4. Inclusione all'interno di funzioni

<?php

function foo()
{
global $frutto;

    include 'vars.php';

    echo "Una $frutto $colore";
}

/* vars.php è nello scope di foo() così    *
 * $colore NON è disponibile fuori di      *
 * questo scope. $frutto si perchè è stato *
 * dichiarato globale.                     */

foo();                        // Una mela verde
echo "Una $frutto $colore";   // Una mela

?>

Quando un file viene incluso, il parsing esce dalla modalità PHP e entra in modalità HTML all'inizio del file incluso, e riprende alla fine. Per questa ragione, qualunque codice all'interno del file incluso che dovrebbe essere eseguito come codice PHP deve essere incluso all'interno dei tag PHP validi di apertura e chiusura.

Se "URL fopen wrappers" nel PHP sono abilitati (come nella configurazione di default), potete specificare il file da includere usando un URL (via HTTP) invece che un percorso locale. Se il server chiamato interpreta il file incluso come codice PHP, le variabili possono essere passate al file incluso usando una stringa di richiesta URL come con l'utilizzo di HTTP GET. Non è proprio parlare della stessa cosa includere il file e averlo ereditato dallo scope di variabili del file chiamante; lo script è stato attualmente eseguito su un server remoto e il risultato è poi stato incluso nello script locale.

Esempio 16-5. include() attraverso HTTP

<?php

/* Questo esempio assume che www.example.com è configurato per eseguire file *
 * .php e non file .txt. Anche, 'Funziona' qui significa che le variabili    *
 * $foo e $bar sono disponibili all'interno del file incluso.                */

// Non funzionerà; file.txt non è stato trattato da www.example.com come PHP
include 'http://www.example.com/file.txt?foo=1&bar=2';

// Non funzionerà; cercare un file chiamato'file.php?foo=1&bar=2' nel
// filesystem locale.
include 'file.php?foo=1&bar=2';

// Funziona.
include 'http://www.example.com/file.php?foo=1&bar=2';

$foo = 1;
$bar = 2;
include 'file.txt';  // Funziona.
include 'file.php';  // Funziona.

?>
Vedere anche Remote files, fopen() e file() per informazioni correlate.

Poichè include() e require() sono speciali costrutti di linguaggio, dovete includerli all'interno di blocchi di istruzioni se si trovano in un blocco condizionale.

Esempio 16-6. include() e i blocchi condizionali

<?php

// Questo NON VA BENE e non funzionerà come desiderato.
if ($condizione)
    include $file;
else
    include $un_altro;


// Questo è CORRETTO.
if ($condizione) {
    include $file;
} else {
    include $un_altro;
}

?>

Trattamento dei valori restituiti: È possibile eseguire un'istruzione return() in un file incluso per terminare l'esecuzione di quel file e restituirlo allo script che l'ha chiamato. È anche possibile restituire valori dai file inclusi. Potete prendere il valore di una chiamata di inclusione come fareste con una normale funzione.

Nota: In PHP 3, return potrebbe non apparire in un blocco a meno che esso sia un blocco di funzione, nel qual caso return() si applica a quella funzione e non all'intero file.

Esempio 16-7. include() and the return() statement

return.php
<?php

$var = 'PHP';

return $var;

?>

noreturn.php
<?php

$var = 'PHP';

?>

testreturns.php
<?php

$foo = include 'return.php';

echo $foo; // stampa 'PHP'

$bar = include 'noreturn.php';

echo $bar; // stampa 1

?>

$bar ha valore 1 perchè l'inclusione è stata eseguita con successo. Notare la differenza tra gli esempi sopra. Il primo usa return() all'interno di un file incluso mentre l'altro no. Pochi altri modi di "includere" file in variabili sono con fopen(), file() o usando include() insieme con Output Control Functions.

Vedere anche require(), require_once(), include_once(), readfile(), virtual(), e include_path.


require_once()

L'istruzione require_once() include e valuta il file specificato durante l'esecuzione dello script. È un comportamento simile all'istruzione require(), con la sola differenza che se il codice di un file è stato già incluso, esso non sarà incluso nuovamente. Vedere la documentazione di require() per maggiori informazioni su come funziona quest'istruzione.

require_once() dovrebbe essere usato nei casi dove lo stesso file potrebbe essere incluso e valutato più di una volta durante una particolare esecuzione di uno script, e volete essere sicuri che esso sia incluso esattamente una volta per evitare problemi con la ridefinizione di funzioni, riassegnazione di valori a variabili, etc.

Per esempi sull'utilizzo di require_once() e include_once(), consultare il codice PEAR incluso nell'ultima distribuzione del codice sorgente di PHP.

Nota: require_once() è stato aggiunto in PHP 4.0.1pl2

Vedere anche: require(), include(), include_once(), get_required_files(), get_included_files(), readfile(), e virtual().


include_once()

L'istruzione include_once() include e valuta il file specificato durante l'esecuzione dello script. È un comportamento simile all'istruzione include(), con la sola differenza che se il codice di un file è stato già incluso, esso non sarà incluso nuovamente. Come suggerisce il nome, esso sarà incluso solo una volta.

include_once() dovrebbe essere usato nei casi dove lo stesso file potrebbe essere incluso e valutato più di una volta durante una particolare esecuzione di uno script, e volete essere sicuri che esso sia incluso esattamente una volta per evitare problemi con la ridefinizione di funzioni, riassegnazione di valori a variabili, etc.

Per maggiori esempi sull'utilizzo di require_once() e include_once(), consultare il codice PEAR incluso nell'ultima distribuzione del codice sorgente di PHP.

Nota: include_once() è stato aggiunto in PHP 4.0.1pl2

Vedere anche include(), require(), require_once(), get_required_files(), get_included_files(), readfile() e virtual().


Capitolo 17. Funzioni

Funzioni definite dall'utente

Una funzione può essere definita usando la seguente sintassi:

function foo ($arg_1, $arg_2, ..., $arg_n)
{
    echo "Funzione di esempio.\n";
    return $retval;
}

All'interno di una funzione può apparire qualunque codice PHP valido, persino altre funzioni e definizioni di classe.

In PHP 3, le funzioni devono essere definite prima di essere referenziate. Non esiste nessun requisito in PHP 4.

PHP non supporta l'overloading di funzioni, non è possibile indefinire o ridefinire funzioni precedentemente dichiarate.

PHP 3 non supporta un numero variabile di argomenti per le funzioni, sebbene siano supportati gli argomenti di default (vedere Argomenti con valori di default per maggiori informazioni). PHP 4 li supporta entrambi: vedere Liste di argomenti a lunghezza variabile e i riferimenti alle funzioni func_num_args(), func_get_arg() e func_get_args() per maggiori informazioni.


Argomenti delle funzioni

L'informazione può essere passata alle funzioni tramite la lista degli argomenti, che sono liste di variabili e/o costanti delimitati dalla virgola.

PHP supporta il passaggio di argomenti per valore (comportamento di default), il passaggio per riferimento, e i valori di default degli argomenti. Le liste di argomenti di lunghezza varabile sono supportate solo in PHP 4 e successivi; vedere Liste di argomenti a lunghezza variabile e i riferimenti alle funzioni func_num_args(), func_get_arg(), e func_get_args() per maggiori informazioni. Un effetto simile può essere ottenuto in PHP 3 passando una array di argomenti alla funzione.

function prende_array($input)
{
    echo "$input[0] + $input[1] = ", $input[0]+$input[1];
}


Costruire argomenti passati per riferimento

Di default, gli argomenti della funzione sono passati per valore (così se cambiate il valore dell'argomento all'interno della funzione , esso non cambierà fuori della funzione). Se volete permettere ad una funzione di modificare i suoi argomenti, dovete passarli per riferimento.

Se volete che una argomento sia passato sempre per riferimento ad una funzione, dovete anteporre un ampersand (&) al nome dell'argomento nella definizione della funzione:

function aggiungi_qualcosa(&$string)
{
    $string .= 'e qualche altra cosa.';
}
$str = 'Questa è una stringa, ';
aggiungi_qualcosa($str);
echo $str;    // l'output sarà 'Questa è una stringa, e qualche altra cosa.'


Valori predefiniti degli argomenti

Una funzione può definire valori predefiniti in stile C++ per argomenti scalari come segue:

function fare_il_caffe ($tipo = "cappuccino")
{
    return "Sto facendo una tazza di $tipo.\n";
}
echo fare_il_caffe ();
echo fare_il_caffe ("espresso");

L'output dal frammento di sopra è:
Sto facendo una tazza di cappuccino.
Sto facendo una tazza di espresso.

Il valore predefinito deve essere un'espressione costante, non (per esempio) una variabile o un membro di classe.

Da notare che quando vengono usati argomenti predefiniti, qualunque argomento predefinito dovrebbe essere a destra degli argomenti non-predefiniti; diversamente, le cose non funzioneranno come ci si aspetti. Si consideri il seguente frammento di codice:

function fare_lo_yogurt ($tipo = "yogurt", $gusto)
{
    return "Fare una vaschetta di $tipo a $gusto.\n";
}

echo fare_lo_yogurt ("fragola");   // non funziona come si aspetta

L'output dell'esempio di sopra è:
Warning: Missing argument 2 in call to fare_lo_yogurt() in
/usr/local/etc/httpd/htdocs/php3test/functest.html on line 41
Fare una vaschetta di fragola a.

Ora, si confronti il codice di sopra con questo:

function fare_lo_yogurt ($gusto, $tipo = "yogurt")
{
    return "Fare una vaschetta di $tipo a $gusto.\n";
}

echo fare_lo_yogurt ("fragola");   // funziona come si aspetta

L'output di questo esempio è:
Fare una vaschetta di yogurt a fragola.


Liste di argomenti a lunghezza variabile

PHP 4 ha il supporto per le liste di argomenti a lunghezza variabile nelle funzioni definite dall'utente. Ciò è realmente abbastanza semplice, usando le funzioni func_num_args(), func_get_arg(), e func_get_args().

Non è richiesta una speciale sintassi, e le liste di argomenti possono ancora essere provviste esplicitamente con le definizioni di funzioni e si comporteranno normalmente.


Valori restituiti

I valori vengono restituiti usando l'istruzione opzionale return. Può essere restituito qualsiasi tipo, incluse liste ed oggetti. Ciò provoca l'interruzione dell'esecuzione della funzione immediatamente e la restituzione del controllo alla linea da cui è stata chiamata. Vedere return() per maggiori informazioni.

function quadrato ($num)
{
    return $num * $num;
}
echo quadrato (4);   // L'output è '16'.

Non possono essere restituiti valori multipli da una funzione, ma risultati simili possono essere ottenuti restituendo una lista.

function numeri_piccoli()
{
    return array (0, 1, 2);
}
list ($zero, $uno, $due) = numeri_piccoli();

Per restituire un riferimento da una funzione, è necessario usare l'operatore di passaggio per riferimento & in entrambe le dichiarazioni di funzioni e quando viene assegnato il valore restituito ad una variabile:

function &restituisce_riferimento()
{
    return $un_riferimento;
}

$nuovo_riferimento =& restituisce_riferimento();

Per maggiori informazioni sui riferimenti, consultare References Explained.


old_function

L'istruzione old_function permette di dichiarare una funzione usando una sintassi identica a PHP/FI2 (eccetto il dover sostituire 'function' con 'old_function'.

Questa è una caratteristica deprecata, e dovrebbe essere usata solo da convertitori PHP/FI2->PHP 3.

Avvertimento

Le funzioni dichiarate come old_function non possono essere chiamate da codice interno di PHP. Tra le altre cose, questo significa che non possono essere usate in funzioni come usort(), array_walk(), e register_shutdown_function(). Si può aggirare questa limitazione scrivendo una funzione contenitore (nel normale stile di PHP 3) per chiamare la old_function.


Funzioni variabili

PHP supporta il concetto di funzioni variabili. Ciò significa che se un nome di variabile ha le parentesi accodate ad esso, PHP cercherà una funzione con lo stesso nome del valore della variabile, e cercherà di eseguirla. Tra le altre cose, ciò puo essere usato per implementare delle callbacks, tabelle di funzioni e così via.

Le funzioni variabili non funzionano con costrutti di linguaggio come echo(), unset(), isset(), empty() e include(). Ad ogni modo, il costrutto print() è un'eccezione e funzionerà. Questa è una delle maggiori differenze tra le funzioni PHP e i costrutti di linguaggio.

Esempio 17-1. Esempio di funzioni variabili

<?php
function foo()
{
    echo "In foo()<br>\n";
}

function bar($arg = '')
{
    echo "In bar(); l'argomento era '$arg'.<br>\n";
}

$func = 'foo';
$func();
$func = 'bar';
$func('test');
?>

Vedere anche variabili variabili e function_exists().


Capitolo 18. Classi e Oggetti

Classi

Una classe è una collezione di variabili e funzioni che utilizzano queste variabili. Una classe si definisce usando la seguente sintassi:

<?php
class Cart
{
    var $items;  // Articoli nel carrello
   
    // Aggiunge $num articoli di $artnr nel carrello
 
    function add_item ($artnr, $num)
    {
        $this->items[$artnr] += $num;
    }
   
    // Prende $num articoli di $artnr e li rimuove dal carrello
 
    function remove_item ($artnr, $num)
    {
        if ($this->items[$artnr] > $num) {
            $this->items[$artnr] -= $num;
            return true;
        } else {
            return false;
        }   
    }
}
?>

Il codice definisce una classe chiamata Cart composta da un array associativo che archivia gli articoli nel carrello e due funzioni per aggiungere e rimuovere gli articoli dal carrello stesso.

Avvertimento

NON spezzate una definizione di classe in più file o in più blocchi PHP. Il seguente codice non funziona:

<?php
class test {
?>
<?php
    function test() {
        print 'OK';
    }
}
?>

Le seguenti note cautelative sono valide per PHP 4.

Attenzione

Il nome stdClass è usato esclusivamente da Zend ed è riservato. Non è quindi possibile creare una classe chiamata stdClass in PHP.

Attenzione

I nomi di funzione __sleep e __wakeup sono riservati e magici nelle classi PHP. Non è possibile creare funzioni con questi nomi nelle classi definite dall'utente, a meno che non sia desiderata la funzionalità magica connessa a questi nomi. Si veda sotto per avere più informazioni.

Attenzione

PHP riserva tutti i nomi di funzione che iniziano con __ a funzioni magiche. Si suggerisce di non usare nomi di funzioni che utilizzano con i caratteri __ in PHP a meno che non si desideri implementare una funzionalità magica.

In PHP 4, sono permesse inizializzazioni di variabili con valori costanti solamente grazie all'uso di var. Per inizializzare variabili con valori non-costanti, bisogna creare una funzione d'inizializzazione che è chiamata automaticamente all'istanziazione di un oggetto da una classe. Questo tipo di funzione si chiama costruttore (vedi sotto).

<?php
/* questo non funziona in PHP 4. */
class Cart
{
    var $todays_date = date("Y-m-d");
    var $name = $firstname;
    var $owner = 'Fred ' . 'Jones';
    var $items = array("VCR", "TV");
}

/* Questo è corretto. */
class Cart
{
    var $todays_date;
    var $name;
    var $owner;
    var $items;

    function Cart()
    {
        $this->todays_date = date("Y-m-d");
        $this->name = $GLOBALS['firstname'];
        /* etc ... */
    }
}
?>

Le classi sono tipi del linguaggio, e sono modelli per variabili reali. Per creare una variabile oggetto si usa l'operatore new.

<?php
$cart = new Cart;
$cart->add_item("10", 1);

$another_cart = new Cart;
$another_cart->add_item("0815", 3);
?>

Il codice sopra, genera gli oggetti $cart e $another_cart, dalla classe Cart. La funzione add_item() dell'oggetto $cart è chiamata per aggiungere una ricorrenza dell'articolo numero 10 a $cart. Ad $another_cart sono aggiunte 3 ricorrenze dell'articolo numero 0815.

Sia $cart che $another_cart dispongono delle funzioni add_item(), remove_item() e della variabile $items, ma per ogni oggetto queste sono funzioni e variabili sono distinte. Potete pensare agli oggetti come a qualcosa di simile alle directories di un filesystem. In un filesystem si possono avere due diversi files README.TXT, purchè siano in directories differenti. Così come in un filesystem dovete digitare il nome (percorso) completo per raggiungere un determinato file partendo da una directory toplevel, così dovete specificare il nome completo di una funzione o variabile che desiderate richiamare da un oggetto. Per PHP, la directory toplevel è il namespace globale dell'oggetto ed il separatore del pathname (/) è ->. Così $cart->items e $another_cart->items sono due diverse variabili che differiscono per il nome. Si noti che la variabile si chiama $cart->items, e non $cart->$items, questo perchè le variabili il PHP si scrivono con un unico simbolo di dollaro.

<?php
// corretto con un singolo $
$cart->items = array("10" => 1); 

// non valido, perchè $cart->$items diventa $cart->""
$cart->$items = array("10" => 1);

// corretto, ma non sempre può funzionare:
// $cart->$myvar diventa $cart->items
$myvar = 'items';
$cart->$myvar = array("10" => 1);  
?>

Quando si definisce una classe, non è possibile prevedere quale nome avrà l'oggetto istanziato nel programma. Quando la classe Cart è stata scritta, non si poteva prevedere che l'oggetto istanziato da essa si sarebbe potuto chiamare $cart o $another_cart. Quindi non è possibile scrivere $cart->items all'interno della classe Cart in fase di progettazione. Per poter accedere alle funzioni e alle variabili interne di una classe perciò si usa la pseudo-variabile $this che può essere letta come 'la mia\il mio' o 'di questo oggetto'. Quindi, '$this->items[$artnr] += $num' può essere letto come 'aggiungi $num al contatore $artnr al del mio array degli articoli' o 'aggiungi $num al contatore $artnr dell'array degli articoli di questo oggetto'.

Nota: Ci sono molte utili funzioni per manipolare classi ed oggetti. Se desiderate conoscerle potete dare un'occhiata alle Class/Object Functions


extends

Spesso si ha bisogno di avere classi con variabili e funzioni simili ad altre classi. É buona norma definire una classe in modo generico, sia per poterla riutilizzare spesso, sia per poterla adattare a scopi specifici.Per facilitare questa operazione, è possibile generare classi per estensione di altre classi. Una classe estesa o derivata ha tutte le variabili e le funzioni della classe di base (questo fenomeno è chiamato 'eredità', anche se non muore nessuno) più tutto ciò che viene aggiunto dall'estensione. Non è possibile che una sottoclasse, ridefinisca variabili e funzioni di una classe madre. Una classe estesa dipende sempre da una singola classe di base: l'eredità multipla non è supportata. Le classi si estendono usando la parola chiave 'extends'.

<?php
class Named_Cart extends Cart
{
    var $owner;
  
    function set_owner ($name)
    {
        $this->owner = $name;
    }
}
?>

Qui viene definita una classe Named_Cart che ha tutte le funzioni e variabili di Cart più la variabile $owner e la funzione set_owner(). Viene creato un carrello con nome con il metodo usato in precedenza, in più la classe estesa permette di settare o leggere il nome del carrello. Si possono usare variabili e funzioni sia di Cart che della sua estensione:

<?php
$ncart = new Named_Cart;    // Crea un carrello con nome
$ncart->set_owner("kris");  // Assegna il nome al carrello
print $ncart->owner;        // stampa il nome del proprietario
$ncart->add_item("10", 1);  // (funzionalità ereditata da Cart)
?>

La relazione mostrata è chiamata relazione "genitore-figlio". Si crea una classe di base, poi utilizzando extends si crea una nuova classe basata sulla classe genitore: la classe figlia. Successivamente si può usare la classe figlia come classe base per un'altra classe.

Nota: Una classe deve essere definita prima di essere utilizzata! Se si vuole la classe Named_Cart che estende la classe Cart, bisogna definire una classe Cart prima. Se si vuole creare un'altra classe chiamata Yellow_named_cart basata sulla classe Named_Cart bisogna definire la classe Named_Cart prima. Per farla breve: l'ordine di definizione delle classi è importante.


Costruttori

Attenzione

In PHP 3 i costruttori si comportano diversamente rispetto a PHP 4. La semantica di PHP 4 è decisamente da preferire.

I costruttori sono funzioni che esistono in una classe e che sono chiamate automaticamente quando si crea una nuova istanza di una classe con new. In PHP 3, una funzione si transforma in in un costruttore quando ha lo stesso nome di una classe. In PHP 4, una funzione diventa un costruttore, quando ha lo stesso nome di una classe ed è definita all'interno della classe stessa - la differenza è sottile, ma cruciale (si veda sotto).

<?php
// Funziona in PHP 3 e PHP 4.
class Auto_Cart extends Cart
{
    function Auto_Cart()
    {
        $this->add_item ("10", 1);
    }
}
?>

Questo codice definisce una classe Auto_Cart, che non è altro che Cart più un costruttore che inizializza il carrello con una occorrenza dell'articolo numero "10" ogni volta che un nuovo Auto_Cart è creato con "new". I costruttori possono avere degli argomenti, e gli argomenti possono essere facoltativi, questo li rende molto versatili. Per poter usare una classe senza specificare parametri, tutti i parametri del costruttore devono essere resi facoltativi con valori di default.

<?php
// Funziona in PHP 3 and PHP 4.
class Constructor_Cart extends Cart
{
    function Constructor_Cart($item = "10", $num = 1)
    {
        $this->add_item ($item, $num);
    }
}
 
// Istanzia il vecchio e noioso carrello.
 
$default_cart = new Constructor_Cart;
 
// Un carrello nuovo ...
 
$different_cart = new Constructor_Cart("20", 17);
?>

E possibile utilizzare l'operatore @ per inibire gli errori provocati dal costruttore, es: @new.

Attenzione

In PHP 3, le classi e i costruttori derivati presentano un certo numero di limitazioni. I seguenti esempi dovrebbero essere letti con attenzione per capire queste limitazioni.

<?php
class A
{
    function A()
    {
      echo "Sono il costtruttore di A.<br>\n";
    }
}

class B extends A
{
    function C()
    {
        echo "Sono una normale funzione.<br>\n";
    }
}

// nessun costruttore è chiamato in PHP 3.
$b = new B;
?>

In PHP 3, nessun costruttore è stato chiamanto nel suddetto esempio. La regola in PHP 3 è: 'un costruttore è una funzione che ha lo stesso nome di una classe'. Il nome della classe è B e non c'è nessuna funzione B() nella classe B.

Questa regola è stata cambiata in PHP 4, la nuova regola dice: 'Se una classe non ha un costruttore proprio, verrà chiamato il costruttore della classe base, se esiste'. Il suddetto esempio avrebbe stampato 'Sono il costruttore di A.' in PHP 4.

<?php
class A
{
    function A()
    {
        echo "Sono il costruttore di A.<br>\n";
    }

    function B()
    {
        echo "Sono una normale funzione di nome B della classe A.<br>\n";
        echo "Non sono il costruttore di A.<br>\n";
    }
}

class B extends A
{
    function C()
    {
        echo "Sono una normale funzione.<br>\n";
    }
}

// This will call B() as a constructor.
$b = new B;
?>

In PHP 3, la funzione B() della classe A si transformerà improvvisamente in un costruttore per la classe B, anche se questo non era previsto. La regola in PHP 3 è: 'un costruttore è una funzione che ha lo stesso nome di una classe'. PHP 3 non si preoccupa se la funzione è stata definita nella classe B o se è stata ereditata.

La regola è stata corretta in PHP 4 ed è diventata: 'un costruttore è una funzione con lo stesso nome della classe in cui è definita'. Così in PHP 4, la classe B non avendo una funzione costruttore avrebbe richiamato il costruttore della sua classe base, e sarebbe stato stampato 'io sono il costruttore di A.'.

Attenzione

Nè PHP 3 nè PHP 4 chiamano costruttori di una classe base automaticamente da un costruttore di una classe derivata. È responsabilità del programmatore propagare la chiamata ai costruttori dove è necessario.

Nota: Non ci sono distruttori in PHP 3 o in PHP 4. Potete usare register_shutdown_function() per simulare la maggior parte degli effetti dei distruttori.

I distruttori sono funzioni che sono chiamate automaticamente quando una variabile è distrutta con unset() o semplicemente uscendo dal suo ambito. Non ci sono distruttori in PHP.


::

Attenzione

Ciò che segue è valido soltanto per PHP 4.

A volte è utile riferirsi alle funzioni ed alle variabili di classi base o riferirsi alle funzioni di classi senza istanziarle. L'operatore :: è usato per questi scopi.

<?php
class A
{
    function example()
    {
        echo "Sono la funzione originale A::example().<br>\n";
    }
}

class B extends A
{
    function example()
    {
        echo "Sono la funzione ridefinita B::example().<br>\n";
        A::example();
    }
}

// non viene istanziato nessun oggetto dalla classe A.
// ma il codice stampa
//   Sono la funzione originale A::example().<br>
A::example();

// crea un oggetto dalla classe B.
$b = new B;

// questo codice stampa
//   Sono la funzione ridefinita B::example().<br>
//   Sono la funzione originale A::example().<br>
$b->example();
?>

L'esempio chiama la funzione example() della classe A, ma senza creare un'istanza di A, di modo che la funzione non si possa richiamare con $a->example(). example() è chiamata come 'funzione della classe', e non come funzione di un oggetto della classe.

Si possono usare funzioni della classe, ma non le variabili della classe. Infatti, non esiste nessun oggetto nel momento della chiamata della funzione. Quindi, la funzione della classe non può usare le variabili dell'oggetto (ma può usare le variabili locali e globali) e $this non può essere usato.

Nel suddetto esempio, la classe B ridefinisce la funzione example(). La funzione originale definita nella classe A è adombrata e non più disponibile, a meno che voi non chiamiate esplicitamente con l'operatore :: scrivendo A::example() per richiamare la funzione (è possibile anche scrivere parent::example(), come mostra la sezione seguente).

In questo contesto, c'è un oggetto corrente che può avere determinate variabili. Una volta usate da parte di una funzione dell'oggetto, potete usare $this per le variabili dell'oggetto.


parent

E possibile ritrovarsi a scrivere classi con codice che si riferisce a variabili e funzioni di classi base. Ciò è particolarmente VERO se una classe derivata è un perfezionamento o una specializzazione di una classe base.

Invece di usare il nome letterale della classe, bisognerebbe usare il nome speciale parent, che si riferisce al nome della classe base definita nella dichiarazione di extends. Usando questo metodo, si evita di usare il nome della classe base nel codice scritto. Se l'albero di eredità cambiasse durante lo sviluppo della classe, il cambiamento si ridurrebbe semplicemente alla modifica della dichiarazione extends della classe.

<?php
class A
{
    function example()
    {
        echo "Sono A::example() e fornisco una funzionalità di base.<br>\n";
    }
}

class B extends A
{
    function example()
    {
        echo "Sono B::example() e fornisco una funzionalità aggiuntiva.<br>\n";
        parent::example();
    }
}

$b = new B;

// Il codice chiama B::example(), che a sua volta chiama A::example().
$b->example();
?>


Serializzare oggetti - oggetti nelle sessioni

Nota: In PHP 3, gli oggetti perdono la loro associazione di classe durante il processo di serializzazione e di deserializzazione. La variabile risultante è di tipo oggetto, ma non ha classe e metodi, e diventa inutile (come un buffo array).

Attenzione

Le seguenti informazioni sono valide soltanto per PHP 4.

serialize() restituisce una stringa che contiene una rappresentazione byte-stream di tutti i valori che possono essere memorizzati in PHP. unserialize() può usare questa stringa per ricreare i valori variabili utilizzabili. Usando serialize() per salvare un oggetto si salveranno tutte le variabili dell'oggetto. Le funzioni dell'oggetto non sono salvate, viene salvato solo il nome della classe.

Per potere usare unserialize() su un oggetto, la classe dell'oggetto deve essere definita. Cioè se avete un oggetto $a della classe A su una pagina di nome page1.php e usate serialize(), otterrete una stringa che si riferisce alla classe A e contiene tutti i valori delle variabili contenute in $a. Se desiderate potere deserializzare l'oggetto in un'altra pagina chiamata page2.php, dovete ricreare $a dalla classe A, la definizione della classe A perciò deve essere presente nella pagina page2.php. Questo può essere fatto per esempio memorizzando la definizione della classe A in un file che viene incluso sia in page1.php che in page2.php.

<?php
// classa.inc:
  
  class A 
  {
      var $one = 1;
    
      function show_one()
      {
          echo $this->one;
      }
  }
  
// page1.php:
  include("classa.inc");
  
  $a = new A;
  $s = serialize($a);
  // memorizzare $s in qualche posto della page2.
  $fp = fopen("store", "w");
  fputs($fp, $s);
  fclose($fp);

// page2.php:

  // questo è necessario perchè unserialize() funzioni correttamente.
  include("classa.inc");

  $s = implode("", @file("store"));
  $a = unserialize($s);

  // ora usiamo la function show_one() dell'oggetto $a.  
  $a->show_one();
?>

Se state usando le sessioni ed usate session_register() per registrare oggetti, questi oggetti vengono serializzati automaticamente alla fine di ogni pagina PHP e sono deserializzate automaticamente su ogni pagina della sessione. Ciò significa che gli oggetti possono mostrarsi in ogni pagina e che sono parte integrante della sessione.

Si suggerisce vivamente di includere le definizioni delle classi degli oggetti registrati su tutte le pagine, anche se le classi non sono usate su tutte le pagine. Se un oggetto viene deserializzato senza la relativa definizione della classe, perderà l'associazione ad essa e si transformerà in in un oggetto della classe stdClass senza nessuna funzione disponibile, diventando inutile.

Così se nell'esempio qui sopra $a diventasse parte di una sessione e fosse registrato con session_register("a"), dovreste includere un file classa.inc su tutte le pagine in cui è valida la sessione, non soltanto nella page1.php e nella page2.php.


Le funzioni magiche __sleep e __wakeup

serialize() controlla se la vostra classe ha una funzione dal nome magico __sleep. In caso affermativo, quella funzione viene eseguita prima di qualsiasi serializzazione. La funzione può pulire l'oggetto e restituire un array con i nomi di tutte le variabili di quell' oggetto che dovrebbero essere serializzate.

Si intende usare __sleep quando chiudendo un collegamento ad un database l'oggetto può avere dati pendenti e l'oggetto ha bisogno di essere ripulito. Inoltre, la funzione è utile se avete oggetti molto grandi che non devono essere salvati completamente.

Per contro, unserialize() controlla per vedere se c'è nella classe una funzione dal nome magico __wakeup. Se è presente questa funzione può ricostruire qualunque risorsa che l'oggetto aveva.

L'intento di __wakeup è quello di ristabilire le connessioni ai database che possono esser state persi durante la serializzazione ed effettuare altre mansioni reinizializzazione.


Riferimenti all'interno del costruttore

La creazione di riferimenti con costruttori può condurre a risultati confusi. Questa sezione in stile Tutorial vi aiuterà ad evitare problemi.

<?php
class Foo
{
    function Foo($name)
    {
        // crea un riferimento all'interno della variabile $globalref
        global $globalref;
        $globalref[] = &$this;
        // setta Name con il valore passato
        $this->setName($name);
        // e lo manda all'output
        $this->echoName();
    }

    function echoName()
    {
        echo "<br>",$this->name;
    }
	
    function setName($name)
    {
        $this->name = $name;
    }
}
?>

Verifichiamo se c'è una differenza fra $bar1 che è stato creato usando l'operatore = e $bar2 che è stato creato usando l'operatore di riferimento =& ...

<?php
$bar1 = new Foo('set in constructor');
$bar1->echoName();
$globalref[0]->echoName();

/* output:
imposta nel costruttore
imposta nel costruttore
imposta nel costruttore */

$bar2 =& new Foo('set in constructor');
$bar2->echoName();
$globalref[1]->echoName();

/* output:
imposta nel costruttore
imposta nel costruttore
imposta nel costruttore */
?>

Apparentemente non c'è differenza, ed in effetti questo è molto significativo: $bar1 e $globalref[0] _ NON _ sono riferimenti, ma sono due variabili diverse. Questo succede perché "new" non restituisce per default un riferimento, ma restituisce una copia.

Nota: Non c'è perdita di prestazioni (da php 4 in su si usa il riferimento) ad istanziare copie per riferimento. Al contrario spesso è meglio lavorare con copie istanziate per riferimento, perché creare copie reali richiede un certo tempo, mentre creare riferimenti virtuali è immediato, (a meno che non si parli di un grande array o un oggetto che viene modificato in modo successivo, allora sarebbe saggio usare i riferimenti per cambiargli tutti i valori simultaneamente).

Per dimostrare quello che è scritto sopra guardate il codice qui sotto.

<?php
// ora cambieremo il nome che cosa vi aspettate?
// potreste prevedere che $bar e $globalref[0] cambino i loro nomi ...
$bar1->setName('set from outside');

// come accennato prima ecco il risultato.
$bar1->echoName();
$globalref[0]->echoName();

/* output:
set from outside
set in constructor */

// vediamo le differenze tra $bar2 e $globalref[1] 
$bar2->setName('set from outside');

// fortunatamen sono solo uguali, ma sono la stessa variabile
// $bar2->name e $globalref[1]->name sono la stessa cosa
$bar2->echoName();
$globalref[1]->echoName();

/* output:
set from outside
set from outside */
?>

Un esempio finale, prova a farvi capire.

<?php
class A
{
    function A($i)
    {
        $this->value = $i;
        // provare a capire perchè qui non abbiamo bisogno d'un riferimento 
        $this->b = new B($this);
    }

    function createRef()
    {
        $this->c = new B($this);
    }

    function echoValue()
    {
        echo "<br>","class ",get_class($this),': ',$this->value;
    }
}


class B
{
    function B(&$a)
    {
        $this->a = &$a;
    }

    function echoValue()
    {
        echo "<br>","class ",get_class($this),': ',$this->a->value;
    }
}

// prova a capire perchè usando una semplice copia si avrebbe
// in un risultato indesiderato nella riga segnata con *
$a =& new A(10);
$a->createRef();

$a->echoValue();
$a->b->echoValue();
$a->c->echoValue();

$a->value = 11;

$a->echoValue();
$a->b->echoValue(); // *
$a->c->echoValue();

/*
output:
class A: 10
class B: 10
class B: 10
class A: 11
class B: 11
class B: 11
*/
?>


Confronto di oggetti in PHP 4

In PHP 4, gli oggetti sono confrontati semplicemente, cioè: due istanze di oggetto sono uguali se hanno gli stessi attributi e valori, e sono istanze della stessa classe. Questa regola regola è applicata anche nel confronto di due oggetti utilizzando l'operatore di identità (===).

Eseguendo il codice seguente:

Esempio 18-1. Esempio di confronto di oggetti in PHP 4

<?php
function bool2str($bool) {
    if ($bool === false) {
            return 'FALSE';
    } else {
            return 'TRUE';
    }
}

function compareObjects(&$o1, &$o2) {
    echo 'o1 == o2 : '.bool2str($o1 == $o2)."\n";
    echo 'o1 != o2 : '.bool2str($o1 != $o2)."\n";
    echo 'o1 === o2 : '.bool2str($o1 === $o2)."\n";
    echo 'o1 !== o2 : '.bool2str($o1 !== $o2)."\n";
}

class Flag {
    var $flag;

    function Flag($flag=true) {
            $this->flag = $flag;
    }
}

class SwitchableFlag extends Flag {

    function turnOn() {
        $this->flag = true;
    }

    function turnOff() {
        $this->flag = false;
    }
}

$o = new Flag();
$p = new Flag(false);
$q = new Flag();

$r = new SwitchableFlag();

echo "Confronto di istanze create con gli stessi parametri\n";
compareObjects($o, $q);

echo "\nConfronto di istanze create con parametri diversi\n";
compareObjects($o, $p);

echo "\nConfronto di un'istanza della classe genitore con una sottoclasse\n";
compareObjects($o, $r);
?>
Si ha:
Confronto di istanze create con gli stessi parametri
o1 == o2 : TRUE
o1 != o2 : FALSE
o1 === o2 : TRUE
o1 !== o2 : FALSE

Confronto di istanze create con parametri diversi
o1 == o2 : FALSE
o1 != o2 : TRUE
o1 === o2 : FALSE
o1 !== o2 : TRUE

Confronto di un'istanza della classe genitore con una sottoclasse
o1 == o2 : FALSE
o1 != o2 : TRUE
o1 === o2 : FALSE
o1 !== o2 : TRUE
Questo è l'output che si ottiene secondo le regole di confronto descritte sopra. Solo le istanze con gli stessi valori per gli attributi e derivanti dalla stessa classe sono considerate uguali ed identiche.

Anche nei casi in cui l'oggetto è composto si applicano le stesse regole di confronto. Nell'esempio seguente creiamo una classe contenitore che archivia nell'array associativo Flag altri oggetti.

Esempio 18-2. Confronto di oggetti composti in PHP 4

<?php
class FlagSet {
    var $set;

    function FlagSet($flagArr = array()) {
        $this->set = $flagArr;
    }

    function addFlag($name, $flag) {
        $this->set[$name] = $flag;
    }

    function removeFlag($name) {
        if (array_key_exists($name, $this->set)) {
            unset($this->set[$name]);
        }
    }
}


$u = new FlagSet();
$u->addFlag('flag1', $o);
$u->addFlag('flag2', $p);
$v = new FlagSet(array('flag1'=>$q, 'flag2'=>$p));
$w = new FlagSet(array('flag1'=>$q));

echo "\nOggetti composti u(o,p) e v(q,p)\n";
compareObjects($u, $v);

echo "\nu(o,p) and w(q)\n";
compareObjects($u, $w);
?>
L'output previsto è:
Oggetti composti u(o,p) e v(q,p)
o1 == o2 : TRUE
o1 != o2 : FALSE
o1 === o2 : TRUE
o1 !== o2 : FALSE

u(o,p) and w(q)
o1 == o2 : FALSE
o1 != o2 : TRUE
o1 === o2 : FALSE
o1 !== o2 : TRUE


Confronto di oggetti in PHP 5

Avvertimento

Questo modulo è SPERIMENTALE. Ovvero, il comportamento di queste funzioni, i nomi di queste funzioni, in definitiva tutto ciò che è documentato qui può cambiare nei futuri rilasci del PHP senza preavviso. Siete avvisati, l'uso di questo modulo è a vostro rischio.

In PHP 5, il confronto tra oggetti è più complicato che in PHP 4, ed è in armonia con quello che ci si può aspettare da un linguaggio orientato agli oggetti (non che PHP 5 lo sia veramente).

Quando si usa l'operatore di confronto (==), le variabili oggetto sono confrontate in modo semplice, cioè: due istanze di oggetto sono uguali se hanno gli stessi attributi e valori, e sono istanze della stessa classe, definita nello stesso spazio dei nomi.

Diversamente, quando usiamo l'operatore di identità (===), le variabili oggetto sono identiche se e solo se si riferiscono alla stessa istanza della stessa classe (in un particolare spazio dei nomi).

Un esempio chiarirà questa regola.

Esempio 18-3. Esempio di confronto di oggetti in PHP 5

<?php
function bool2str($bool) {
    if ($bool === false) {
            return 'FALSE';
    } else {
            return 'TRUE';
    }
}

function compareObjects(&$o1, &$o2) {
    echo 'o1 == o2 : '.bool2str($o1 == $o2)."\n";
    echo 'o1 != o2 : '.bool2str($o1 != $o2)."\n";
    echo 'o1 === o2 : '.bool2str($o1 === $o2)."\n";
    echo 'o1 !== o2 : '.bool2str($o1 !== $o2)."\n";
}

class Flag {
    var $flag;

    function Flag($flag=true) {
            $this->flag = $flag;
    }
}

namespace Other {

    class Flag {
        var $flag;

        function Flag($flag=true) {
                $this->flag = $flag;
        }
    }

}

$o = new Flag();
$p = new Flag();
$q = $o;
$r = new Other::Flag();

echo "Due istanze della stessa classe\n";
compareObjects($o, $p);

echo "\nDue riferimenti alla stessa istanza\n";
compareObjects($o, $q);

echo "\nIstanze di classi di diversi spazi dei nomi e simili nomi di classe\n";
compareObjects($o, $r);
?>
L'esempio stampa:
Due istanze della stessa classe
o1 == o2 : TRUE
o1 != o2 : FALSE
o1 === o2 : FALSE
o1 !== o2 : TRUE

Due riferimenti alla stessa istanza
o1 == o2 : TRUE
o1 != o2 : FALSE
o1 === o2 : TRUE
o1 !== o2 : FALSE

Istanze di classi di diversi spazi dei nomi e simili nomi di classe
o1 == o2 : FALSE
o1 != o2 : TRUE
o1 === o2 : FALSE
o1 !== o2 : TRUE


Capitolo 19. Classes and Objects (PHP 5)

Introduction

In PHP 5 there is a new Object Model. PHP's handling of objects has been completely rewritten, allowing for better performance and more features.


The Basics

class

Every class definition begins with the keyword class, followed by a class name, which can be any name that isn't a reserved word in PHP. Followed by a pair of curly braces, of which contains the definition of the classes members and methods. A pseudo-variable, $this is available when a method is called from within an object context. $this is a reference to the calling object (usually the object to which the method belongs, but can be another object, if the method is called statically from the context of a secondary object). This is illustrated in the following example:

<?php
class A
{
    function foo()
    {
        if (isset($this)) {
            echo '$this is defined (';
            echo get_class($this);
            echo ")\n";
        } else {
            echo "\$this is not defined.\n";
        }
    }
}

class B
{
    function bar()
    {
        A::foo();
    }
}

$a = new A();
$a->foo();
A::foo();
$b = new B();
$b->bar();
B::bar();
?>

The above example will output:

$this is defined (a)
$this is not defined.
$this is defined (b)
$this is not defined.

Esempio 19-1. Simple Class definition

<?php
class SimpleClass
{
    // member declaration
    public $var = 'a default value';

    // method declaration
    public function displayVar() {
        echo $this->var;
    }
}
?>

new

To create an instance of an object, a new object must be created and assigned to a variable. An object will always be assigned when creating a new object unless the object has a constructor defined that throws an exception on error.

Esempio 19-2. Creating an instance

<?php
$instance = new SimpleClass()
?>

When assigning an already created instance of an object to a new variable, the new variable will access the same instance as the object that was assigned. This behaviour is the same when passing instances to a function. A new instance of an already created object can be made by cloning it.

Esempio 19-3. Object Assignment

<?php
$assigned   =  $instance;
$reference  =& $instance;

$instance->var = '$assigned will have this value';

$instance = null; // $instance and $reference become null

var_dump($instance);
var_dump($reference);
var_dump($assigned);
?>

The above example will output:

NULL
NULL
object(SimpleClass)#1 (1) {
   ["var"]=>
     string(30) "$assigned will have this value"
}

extends

A class can inherit methods and members of another class by using the extends keyword in the declaration. It is not possible to extend multiple classes, a class can only inherit one base class.

The inherited methods and members can be overridden, unless the parent class has defined a method as final, by redeclaring them within the same name defined in the parent class. It is possible to access the overrided method or members by referencing them with parent::

Esempio 19-4. Simple Class Inherintance

<?php
class ExtendClass extends SimpleClass
{
    // Redefine the parent method
    function displayVar()
    {
        echo "Extending class\n";
        parent::displayVar();
    }
}

$extended = new ExtendClass();
$extended->displayVar();
?>

The above example will output:

Extending class
a default value

Autoloading Objects

Many developers writing object-oriented applications create one PHP source file per-class definition. One of the biggest annoyances is having to write a long list of needed includes at the beginning of each script (one for each class).

In PHP 5, this is no longer necessary. You may define an __autoload function which is automatically called in case you are trying to use a class which hasn't been defined yet. By calling this function the scripting engine is given a last chance to load the class before PHP fails with an error.

Nota: Exceptions thrown in __autoload function cannot be caught in the catch block and results in a fatal error.

Esempio 19-5. Autoload example

This example attempts to load the classes MyClass1 and MyClass2 from the files MyClass1.php and MyClass2.php respectively.

<?php
function __autoload($class_name) {
    require_once $class_name . '.php';
}

$obj  = new MyClass1();
$obj2 = new MyClass2(); 
?>


Constructors and Destructors

Constructor

void __construct ( [mixed args [, ...]] )

PHP 5 allows developers to declare constructor methods for classes. Classes which have a constructor method call this method on each newly-created object, so it is suitable for any initialization that the object may need before it is used.

Nota: Parent constructors are not called implicitly if the child class defines a constructor. In order to run a parent constructor, a call to parent::__construct() within the child constructor is required.

Esempio 19-6. using new unified constructors

<?php
class BaseClass {
   function __construct() {
       print "In BaseClass constructor\n";
   }
}

class SubClass extends BaseClass {
   function __construct() {
       parent::__construct();
       print "In SubClass constructor\n";
   }
}

$obj = new BaseClass();
$obj = new SubClass();
?>

For backwards compatibility, if PHP 5 cannot find a __construct() function for a given class, it will search for the old-style constructor function, by the name of the class. Effectively, it means that the only case that would have compatibility issues is if the class had a method named __construct() which was used for different semantics.


Destructor

void __destruct ( void )

PHP 5 introduces a destructor concept similar to that of other object-oriented languages, such as C++. The destructor method will be called as soon as all references to a particular object are removed or when the object is explicitly destroyed.

Esempio 19-7. Destructor Example

<?php
class MyDestructableClass {
   function __construct() {
       print "In constructor\n";
       $this->name = "MyDestructableClass";
   }

   function __destruct() {
       print "Destroying " . $this->name . "\n";
   }
}

$obj = new MyDestructableClass();
?>

Like constructors, parent destructors will not be called implicitly by the engine. In order to run a parent destructor, one would have to explicitly call parent::__destruct() in the destructor body.


Visibility

The visibility of a property or method can be defined by prefixing the declaration with the keywords: public, protected or private. Public declared items can be accessed everywhere. Protected limits access to inherited classes (and to the class that defines the item). Private limits visibility only to the class that defines the item.


Members Visibility

Class members must be defined with public, private, or protected.

Esempio 19-8. Member declaration

<?php
/**
 * Define MyClass
 */
class MyClass
{
    public $public = 'Public';
    protected $protected = 'Protected';
    private $private = 'Private';

    function printHello()
    {
        echo $this->public;
        echo $this->protected;
        echo $this->private;
    }
}

$obj = new MyClass();
echo $obj->public; // Works
echo $obj->protected; // Fatal Error
echo $obj->private; // Fatal Error
$obj->printHello(); // Shows Public, Protected and Private


/**
 * Define MyClass2
 */
class MyClass2 extends MyClass
{
    // We can redeclare the public and protected method, but not private
    protected $protected = 'Protected2';

    function printHello()
    {
        echo $this->public;
        echo $this->protected;
        echo $this->private;
    }
}

$obj2 = new MyClass2();
echo $obj->public; // Works
echo $obj2->private; // Undefined
echo $obj2->protected; // Fatal Error
$obj2->printHello(); // Shows Public, Protected2, not Private

?>

Nota: The PHP 4 method of declaring a variable with the var keyword is no longer valid for PHP 5 objects. For compatibility a variable declared in php will be assumed with public visibility, and a E_STRICT warning will be issued.


Method Visibility

Class methods must be defined with public, private, or protected. Methods without any declaration are defined as public.

Esempio 19-9. Method Declaration

<?php
/**
 * Define MyClass
 */
class MyClass
{
    // Contructors must be public
    public function __construct() { }

    // Declare a public method
    public function MyPublic() { }

    // Declare a protected method
    protected function MyProtected() { }

    // Declare a private method
    private function MyPrivate() { }

    // This is public
    function Foo()
    {
        $this->MyPublic();
        $this->MyProtected();
        $this->MyPrivate();
    }
}

$myclass = new MyClass;
$myclass->MyPublic(); // Works
$myclass->MyProtected(); // Fatal Error
$myclass->MyPrivate(); // Fatal Error
$myclass->Foo(); // Public, Protected and Private work


/**
 * Define MyClass2
 */
class MyClass2 extends MyClass
{
    // This is public
    function Foo2()
    {
        $this->MyPublic();
        $this->MyProtected();
        $this->MyPrivate(); // Fatal Error
    }
}

$myclass2 = new MyClass2;
$myclass2->MyPublic(); // Works
$myclass2->Foo2(); // Public and Protected work, not Private
?>


Scope Resolution Operator (::)

The Scope Resolution Operator (also called Paamayim Nekudotayim) or in simpler terms, the double colon, is a token that allows access to static, constant, and overridden members or methods of a class.

When referencing these items from outside the class definition, use the name of the class.

Paamayim Nekudotayim would, at first, seem like a strange choice for naming a double-colon. However, while writing the Zend Engine 0.5 (which powers PHP 3), that's what the Zend team decided to call it. It actually does mean double-colon - in Hebrew!

Esempio 19-10. :: from outside the class definition

<?php
class MyClass {
    const CONST_VALUE = 'A constant value';
}

echo MyClass::CONST_VALUE;
?>

Two special keywords self and parent are used to access members or methods from inside the class definition.

Esempio 19-11. :: from inside the class definition

<?php
class OtherClass extends MyClass
{
    public static $my_static = 'static var';

    public static function doubleColon() {
        echo parent::CONST_VALUE . "\n";
        echo self::$my_static . "\n";
    }
}

OtherClass::doubleColon();
?>

When an extending class overrides the parents definition of a method, PHP will not call the parent's method. It's up to the extended class on whether or not the parent's method is called. This also applies to Constructors and Destructors, Overloading, and Magic method definitions.

Esempio 19-12. Calling a parent's method

<?php
class MyClass
{
    protected function myFunc() {
        echo "MyClass::myFunc()\n";
    }
}

class OtherClass extends MyClass
{
    // Override parent's definition
    public function myFunc()
    {
        // But still call the parent function
        parent::myFunc();
        echo "OtherClass::myFunc()\n";
    }
}

$class = new OtherClass();
$class->myFunc();
?>

Static Keyword

Declaring class members or methods as static, makes them callable from outside the object context. A member or method declared with static can not be accessed with a variable that is an instance of the object and cannot be re-defined in an extending class.

The static declaration must be after the visibility declaration. For compatibility with PHP 4, if no visibility declaration is used, then the member or method will be treated as if it was declared as public static.

Because static methods are callable without an instance of the object created, the pseudo variable $this is not available inside the method declared as static.

In fact static method calls are resolved at compile time. When using an explicit class name the method is already identified completley and no inheritance rules apply. If the call is done by self then self is translated to the current class, that is the class the code belongs to. Here also no inheritance rules apply.

Static properties cannot be accessed through the object using the arrow operator ->.

Esempio 19-13. Static member example

<?php
class Foo
{
    public static $my_static = 'foo';

    public function staticValue() {
        return self::$my_static;
    }
}

class Bar extends Foo
{
    public function fooStatic() {
        return parent::$my_static;
    }
}


print Foo::$my_static . "\n";

$foo = new Foo();
print $foo->staticValue() . "\n";
print $foo->my_static . "\n";      // Undefined "Property" my_static 

// $foo::my_static is not possible

print Bar::$my_static . "\n";
$bar = new Bar();
print $bar->fooStatic() . "\n";
?>

Esempio 19-14. Static method example

<?php
class Foo {
    public static function aStaticMethod() {
        // ...
    }
}

Foo::aStaticMethod();
?>

Object Constants

It is possible to define constant values on a per-class basis remaining the same and unchangeable. Constants differ from normal variables in that you don't use the $ symbol to declare or use them. Like static members, constant values can not be accessed from an instance of the object.

Esempio 19-15. Defining and using a constant

<?php
class MyClass
{
    const constant = 'constant value';

    function showConstant() {
        echo  self::constant . "\n";
    }
}

echo MyClass::constant . "\n";

$class = new MyClass();
$class->showConstant();
// echo $class::constant;  is not allowed
?>

Object Abstraction

PHP 5 introduces abstract classes and methods. It is not allowed to create an instance of a class that has been defined as abstract. Any class that contains at least one abstract method must also be abstract. Methods defined as abstract simply declare the method's signature they cannot define the implementation.

The class that implements the abstract method must define with the same visibillity or weaker. If the abstract method is defined as protected, the function implementation must be defined as either protected or public.

Esempio 19-16. Abstract class example

<?php
abstract class AbstractClass
{
    // Force Extending class to define this method
    abstract protected function getValue();

    // Common method
    public function printOut() {
        print $this->getValue();
    }
}

class ConcreteClass1 extends AbstractClass
{
    protected function getValue() {
        return "ConcreteClass1";
    }
}

class ConcreteClass2 extends AbstractClass
{
    protected function getValue() {
        return "ConcreteClass2";
    }

}

$class1 = new ConcreteClass1;
$class1->printOut();

$class2 = new ConcreteClass2;
$class2->printOut();
?>

Old code that has no user-defined classes or functions named 'abstract' should run without modifications.


Object Interfaces

Object interfaces allow you to create code which specifies which methods a class must implement, without having to define how these methods are handled.

Interfaces are defined using the interface keyword, in the same way as a standard class, but without any of the methods having their contents defined. Classes which implement an interface should do so using the implements keyword, and must have definitions for all the methods listed in the interface. Classes may implement more than one interface if desired by listing each interface split by a comma.

All methods declared in an interface must be public, this is the nature of an interface.

Stating that a class implements an interface, and then not implementing all the methods in the interface will result in a fatal error telling you which methods have not been implemented.

Esempio 19-17. Interface example

<?php
// Declare the interface 'iTemplate'
interface iTemplate
{
    public function setVariable($name, $var);
    public function getHtml($template);
}

// Implement the interface
// This will work
class Template implements iTemplate
{
    private $vars = array();
  
    public function setVariable($name, $var)
    {
        $this->vars[$name] = $var;
    }
  
    public function getHtml($template)
    {
        foreach($this->vars as $name => $value) {
            $template = str_replace('{' . $name . '}', $value, $template);
        }
 
        return $template;
    }
}

// This will not work
// Fatal error: Class BadTemplate contains 1 abstract methods
// and must therefore be declared abstract (iTemplate::getHtml)
class BadTemplate implements iTemplate
{
    private $vars = array();
  
    public function setVariable($name, $var)
    {
        $this->vars[$name] = $var;
    }
}

?>

Overloading

Both method calls and member accesses can be overloaded via the __call, __get and __set methods. These methods will only be triggered when your object or inherited object doesn't contain the member or method you're trying to access.


Member overloading

void __set ( string name, mixed value )

mixed __get ( mixed name )

Class members can be overloaded to run custom code defined in your class by defining these specially named methods. The $name parameter used is the name of the variable that should be set or retrieved. The __set() method's $value parameter specifies the value that the object should set set the $name.

Esempio 19-18. overloading with __get and __set example

<?php
class Setter
{
    public $n;
    private $x = array("a" => 1, "b" => 2, "c" => 3);

    function __get($nm)
    {
        print "Getting [$nm]\n";

        if (isset($this->x[$nm])) {
            $r = $this->x[$nm];
            print "Returning: $r\n";
            return $r;
        } else {
            echo "Nothing!\n";
        }
    }

    function __set($nm, $val)
    {
        print "Setting [$nm] to $val\n";

        if (isset($this->x[$nm])) {
            $this->x[$nm] = $val;
            echo "OK!\n";
        } else {
            echo "Not OK!\n";
        }
    }
}

$foo = new Setter();
$foo->n = 1;
$foo->a = 100;
$foo->a++;
$foo->z++;
var_dump($foo);
?>

The above example will output:

Setting [a] to 100
OK!
Getting [a]
Returning: 100
Setting [a] to 101
OK!
Getting [z]
Nothing!
Setting [z] to 1
Not OK!
object(Setter)#1 (2) {
    ["n"]=>
    int(1)
    ["x:private"]=>
    array(3) {
        ["a"]=>
        int(101)
        ["b"]=>
        int(2)
        ["c"]=>
        int(3)
    }
}

Method overloading

mixed __call ( string name, array arguments )

Class methods can be overloaded to run custom code defined in your class by defining this specially named method. The $name parameter used is the name as the function name that was requested to be used. The arguments that were passed in the function will be defined as an array in the $arguments parameter. The value returned from the __call() method will be returned to the caller of the method.

Esempio 19-19. overloading with __call example

<?php
class Caller
{
    private $x = array(1, 2, 3);

    function __call($m, $a)
    {
        print "Method $m called:\n";
        var_dump($a);
        return $this->x;
    }
}

$foo = new Caller();
$a = $foo->test(1, "2", 3.4, true);
var_dump($a);
?>

The above example will output:

Method test called:
array(4) {
    [0]=>
    int(1)
    [1]=>
    string(1) "2"
    [2]=>
    float(3.4)
    [3]=>
    bool(true)
}
array(3) {
    [0]=>
    int(1)
    [1]=>
    int(2)
    [2]=>
    int(3)
}

Object Iteration

PHP 5 provides a way for objects to be defined so it is possible to iterate through a list of items, with, for example a foreach statement. By default, all visible properties will be used for the iteration.

Esempio 19-20. Simple Object Iteration

<?php
class MyClass
{
    public $var1 = 'value 1';
    public $var2 = 'value 2';
    public $var3 = 'value 3';

    protected $protected = 'protected var';
    private   $private   = 'private var';

    function iterateVisible() {
       echo "MyClass::iterateVisible:\n";
       foreach($this as $key => $value) {
           print "$key => $value\n";
       }
    }
}

$class = new MyClass();

foreach($class as $key => $value) {
    print "$key => $value\n";
}
echo "\n";


$class->iterateVisible();

?>

The above example will output:

var1 => value 1
var2 => value 2
var3 => value 3

MyClass::iterateVisible:
var1 => value 1
var2 => value 2
var3 => value 3
protected => protected var
private => private var

As the output shows, the foreach iterated through all visible variables that can be accessed. To take it a step further you can implement one of PHP 5's internal interface named Iterator. This allows the object to decide what and how the object will be iterated.

Esempio 19-21. Object Iteration implementing Iterator

<?php
class MyIterator implements Iterator
{
    private $var = array();

    public function __construct($array)
    {
        if (is_array($array)) {
            $this->var = $array;
        }
    }

    public function rewind() {
        echo "rewinding\n";
        reset($this->var);
    }

    public function current() {
        $var = current($this->var);
        echo "current: $var\n";
        return $var;
    }

    public function key() {
        $var = key($this->var);
        echo "key: $var\n";
        return $var;
    }

    public function next() {
        $var = next($this->var);
        echo "next: $var\n";
        return $var;
    }

    public function valid() {
        $var = $this->current() !== false;
        echo "valid: {$var}\n";
        return $var;
    }
}

$values = array(1,2,3);
$it = new MyIterator($values);

foreach ($it as $a => $b) {
    print "$a: $b\n";
}
?>

The above example will output:

rewinding
current: 1
valid: 1
current: 1
key: 0
0: 1
next: 2
current: 2
valid: 1
current: 2
key: 1
1: 2
next: 3
current: 3
valid: 1
current: 3
key: 2
2: 3
next:
current:
valid:

You can also define your class so that it doesn't have to define all the Iterator functions by simply implementing the PHP 5 IteratorAggregate interface.

Esempio 19-22. Object Iteration implementing IteratorAggregate

<?php
class MyCollection implements IteratorAggregate
{
    private $items = array();
    private $count = 0;

    // Required definition of interface IteratorAggregate
    public function getIterator() {
        return new MyIterator($this->items);
    }

    public function add($value) {
        $this->items[$this->count++] = $value;
    }
}

$coll = new MyCollection();
$coll->add('value 1');
$coll->add('value 2');
$coll->add('value 3');

foreach ($coll as $key => $val) {
    echo "key/value: [$key -> $val]\n\n";
}
?>

The above example will output:

rewinding
current: value 1
valid: 1
current: value 1
key: 0
key/value: [0 -> value 1]

next: value 2
current: value 2
valid: 1
current: value 2
key: 1
key/value: [1 -> value 2]

next: value 3
current: value 3
valid: 1
current: value 3
key: 2
key/value: [2 -> value 3]

next:
current:
valid:

Nota: For more examples of iterators, see the SPL Extension.


Patterns

Patterns are ways to describe best practices and good designs. They show a flexible solution to common programming problems.


Factory

The Factory pattern allows for the instantiation of objects at runtime. It is called a Factory Pattern since it is responsible for "manufacturing" an object.

Esempio 19-23. Factory Method

<?php
class Example
{
    // The factory method
    public static function factory($type)
    {
        if (include_once 'Drivers/' . $type . '.php') {
            $classname = 'Driver_' . $type;
            return new $classname;
        } else {
            throw new Exception ('Driver not found');
        }
    }
}
?>

Defining this method in a class allows drivers to be loaded on the fly. If the Example class was a database abstraction class, loading a MySQL and SQLite driver could be done as follows:

<?php
// Load a MySQL Driver
$mysql = Example::factory('MySQL');

// Load a SQLite Driver
$sqlite = Example::factory('SQLite');
?>

Singleton

The Singleton pattern applies to situations in which there needs to be a single instance of a class. The most common example of this is a database connection. Implementing this pattern allows a programmer to make this single instance easily accessible by many other objects.

Esempio 19-24. Singleton Function

<?php
class Example
{
    // Hold an instance of the class
    private static $instance;
    
    // A private constructor; prevents direct creation of object
    private function __construct() 
    {
        echo 'I am constructed';
    }

    // The singleton method
    public static function singleton() 
    {
        if (!isset(self::$instance)) {
            $c = __CLASS__;
            self::$instance = new $c;
        }

        return self::$instance;
    }
    
    // Example method
    public function bark()
    {
        echo 'Woof!';
    }

    // Prevent users to clone the instance
    public function __clone()
    {
        trigger_error('Clone is not allowed.', E_USER_ERROR);
    }

}

?>

This allows a single instance of the Example class to be retrieved.

<?php
// This would fail because the constructor is private
$test = new Example;

// This will always retrieve a single instance of the class
$test = Example::singleton();
$test->bark();

// This will issue an E_USER_ERROR.
$test_clone = clone($test);

?>

Magic Methods

The function names __construct, __destruct (see Constructors and Destructors), __call, __get, __set (see Overloading), __sleep, __wakeup, and __toString are magical in PHP classes. You cannot have functions with these names in any of your classes unless you want the magic functionality associated with them.

Attenzione

PHP reserves all function names starting with __ as magical. It is recommended that you do not use function names with __ in PHP unless you want some documented magic functionality.


__sleep and __wakeup

serialize() checks if your class has a function with the magic name __sleep. If so, that function is executed prior to any serialization. It can clean up the object and is supposed to return an array with the names of all variables of that object that should be serialized.

The intended use of __sleep is to close any database connections that the object may have, commit pending data or perform similar cleanup tasks. Also, the function is useful if you have very large objects which do not need to be saved completely.

Conversely, unserialize() checks for the presence of a function with the magic name __wakeup. If present, this function can reconstruct any resources that the object may have.

The intended use of __wakeup is to reestablish any database connections that may have been lost during serialization and perform other reinitialization tasks.


__toString

The __toString method allows a class to decide how it will react when it is converted to a string.

Esempio 19-25. Simple example

<?php
// Declare a simple class
class TestClass
{
    public $foo;

    public function __construct($foo) {
        $this->foo = $foo;
    }

    public function __toString() {
        return $this->foo;
    }
}

$class = new TestClass('Hello');
echo $class;
?>

The above example will output:

Hello

It is worth noting that the __toString method will only be called when it is directly combined with echo() or print().

Esempio 19-26. Cases where __toString is called

<?php
// __toString called
echo $class;

// __toString called (still a normal parameter for echo)
echo 'text', $class;

// __toString not called (concatenation operator used first)
echo 'text' . $class;

// __toString not called (cast to string first)
echo (string) $class;

// __toString not called (cast to string first)
echo "text $class";
?>

Final Keyword

PHP 5 introduces the final keyword, which prevents child classes from overriding a method by prefixing the definition with final. If the class itself is being defined final then it cannot be extended.

Esempio 19-27. Final methods example

<?php
class BaseClass {
   public function test() {
       echo "BaseClass::test() called\n";
   }
   
   final public function moreTesting() {
       echo "BaseClass::moreTesting() called\n";
   }
}

class ChildClass extends BaseClass {
   public function moreTesting() {
       echo "ChildClass::moreTesting() called\n";
   }
}
// Results in Fatal error: Cannot override final method BaseClass::moreTesting()
?>

Esempio 19-28. Final class example

<?php
final class BaseClass {
   public function test() {
       echo "BaseClass::test() called\n";
   }

   // Here it doesn't matter if you specify the function as final or not
   final public function moreTesting() {
       echo "BaseClass::moreTesting() called\n";
   }
}

class ChildClass extends BaseClass {
}
// Results in Fatal error: Class ChildClass may not inherit from final class (BaseClass)
?>

Object cloning

Creating a copy of an object with fully replicated properties is not always the wanted behavior. A good example of the need for copy constructors, is if you have an object which represents a GTK window and the object holds the resource of this GTK window, when you create a duplicate you might want to create a new window with the same properties and have the new object hold the resource of the new window. Another example is if your object holds a reference to another object which it uses and when you replicate the parent object you want to create a new instance of this other object so that the replica has its own separate copy.

An object copy is created by using the clone keyword (which calls the object's __clone() method if possible). An object's __clone() method cannot be called directly.

$copy_of_object = clone $object;

When an object is cloned, PHP 5 will perform a shallow copy of all of the object's properties. Any properties that are references to other variables, will remain references. If a __clone() method is defined, then the newly created object's __clone() method will be called, to allow any necessary properties that need to be changed.

Esempio 19-29. Cloning an object

<?php
class SubObject
{
    static $instances = 0;
    public $instance;

    public function __construct() {
        $this->instance = ++self::$instances;
    }

    public function __clone() {
        $this->instance = ++self::$instances;
    }
}

class MyCloneable
{
    public $object1;
    public $object2;

    function __clone()
    {
        // Force a copy of this->object, otherwise
        // it will point to same object.
        $this->object1 = clone($this->object1);
    }
}

$obj = new MyCloneable();

$obj->object1 = new SubObject();
$obj->object2 = new SubObject();

$obj2 = clone $obj;


print("Original Object:\n");
print_r($obj);

print("Cloned Object:\n");
print_r($obj2);

?>

The above example will output:

Original Object:
MyCloneable Object
(
    [object1] => SubObject Object
        (
            [instance] => 1
        )

    [object2] => SubObject Object
        (
            [instance] => 2
        )

)
Cloned Object:
MyCloneable Object
(
    [object1] => SubObject Object
        (
            [instance] => 3
        )

    [object2] => SubObject Object
        (
            [instance] => 2
        )

)

Comparing objects

In PHP 5, object comparison is more complicated than in PHP 4 and more in accordance to what one will expect from an Object Oriented Language (not that PHP 5 is such a language).

When using the comparison operator (==), object variables are compared in a simple manner, namely: Two object instances are equal if they have the same attributes and values, and are instances of the same class.

On the other hand, when using the identity operator (===), object variables are identical if and only if they refer to the same instance of the same class.

An example will clarify these rules.

Esempio 19-30. Example of object comparison in PHP 5

<?php
function bool2str($bool)
{
    if ($bool === false) {
        return 'FALSE';
    } else {
        return 'TRUE';
    }
}

function compareObjects(&$o1, &$o2)
{
    echo 'o1 == o2 : ' . bool2str($o1 == $o2) . "\n";
    echo 'o1 != o2 : ' . bool2str($o1 != $o2) . "\n";
    echo 'o1 === o2 : ' . bool2str($o1 === $o2) . "\n";
    echo 'o1 !== o2 : ' . bool2str($o1 !== $o2) . "\n";
}

class Flag
{
    public $flag;

    function Flag($flag = true) {
        $this->flag = $flag;
    }
}

class OtherFlag
{
    public $flag;

    function OtherFlag($flag = true) {
        $this->flag = $flag;
    }
}

$o = new Flag();
$p = new Flag();
$q = $o;
$r = new OtherFlag();

echo "Two instances of the same class\n";
compareObjects($o, $p);

echo "\nTwo references to the same instance\n";
compareObjects($o, $q);

echo "\nInstances of two different classes\n";
compareObjects($o, $r);
?>

The above example will output:

Two instances of the same class
o1 == o2 : TRUE
o1 != o2 : FALSE
o1 === o2 : FALSE
o1 !== o2 : TRUE

Two references to the same instance
o1 == o2 : TRUE
o1 != o2 : FALSE
o1 === o2 : TRUE
o1 !== o2 : FALSE

Instances of two different classes
o1 == o2 : FALSE
o1 != o2 : TRUE
o1 === o2 : FALSE
o1 !== o2 : TRUE


Reflection

Introduction

PHP 5 comes with a complete reflection API that adds the ability to reverse-engineer classes, interfaces, functions and methods as well as extensions. Additionally, the reflection API also offers ways of retrieving doc comments for functions, classes and methods.

The reflection API is an object-oriented extension to the Zend Engine, consisting of the following classes:

<?php
class Reflection { }
interface Reflector { }
class ReflectionException extends Exception { }
class ReflectionFunction implements Reflector { }
class ReflectionParameter implements Reflector { }
class ReflectionMethod extends ReflectionFunction { }
class ReflectionClass implements Reflector { }
class ReflectionObject extends ReflectionClass { }
class ReflectionProperty implements Reflector { }
class ReflectionExtension implements Reflector { }
?>

Nota: For details on these classes, have a look at the next chapters.

If we were to execute the code in the example below:

Esempio 19-31. Basic usage of the reflection API

<?php
Reflection::export(new ReflectionClass('Exception'));
?>

The above example will output:

Class [ <internal> class Exception ] {

  - Constants [0] {
  }

  - Static properties [0] {
  }

  - Static methods [0] {
  }

  - Properties [6] {
    Property [ <default> protected $message ]
    Property [ <default> private $string ]
    Property [ <default> protected $code ]
    Property [ <default> protected $file ]
    Property [ <default> protected $line ]
    Property [ <default> private $trace ]
  }

  - Methods [9] {
    Method [ <internal> final private method __clone ] {
    }

    Method [ <internal> <ctor> public method __construct ] {

      - Parameters [2] {
        Parameter #0 [ <required> $message ]
        Parameter #1 [ <required> $code ]
      }
    }

    Method [ <internal> final public method getMessage ] {
    }

    Method [ <internal> final public method getCode ] {
    }

    Method [ <internal> final public method getFile ] {
    }

    Method [ <internal> final public method getLine ] {
    }

    Method [ <internal> final public method getTrace ] {
    }

    Method [ <internal> final public method getTraceAsString ] {
    }

    Method [ <internal> public method __toString ] {
    }
  }
}


ReflectionFunction

The ReflectionFunction class lets you reverse-engineer functions.

<?php
class ReflectionFunction implements Reflector
{
    final private __clone()
    public object __construct(string name)
    public string __toString()
    public static string export()
    public string getName()
    public bool isInternal()
    public bool isUserDefined()
    public string getFileName()
    public int getStartLine()
    public int getEndLine()
    public string getDocComment()
    public array getStaticVariables()
    public mixed invoke(mixed* args)
    public mixed invokeArgs(array args)
    public bool returnsReference()
    public ReflectionParameter[] getParameters()
    public int getNumberOfParameters()
    public int getNumberOfRequiredParameters()
}
?>

Nota: invokeArgs() was added in PHP 5.1.0.

To introspect a function, you will first have to create an instance of the ReflectionFunction class. You can then call any of the above methods on this instance.

Esempio 19-32. Using the ReflectionFunction class

<?php
/**
 * A simple counter
 *
 * @return    int
 */
function counter() 
{
    static $c = 0;
    return $c++;
}

// Create an instance of the Reflection_Function class
$func = new ReflectionFunction('counter');

// Print out basic information
printf(
    "===> The %s function '%s'\n".
    "     declared in %s\n".
    "     lines %d to %d\n",
    $func->isInternal() ? 'internal' : 'user-defined',
    $func->getName(),
    $func->getFileName(),
    $func->getStartLine(),
    $func->getEndline()
);

// Print documentation comment
printf("---> Documentation:\n %s\n", var_export($func->getDocComment(), 1));

// Print static variables if existant
if ($statics = $func->getStaticVariables())
{
    printf("---> Static variables: %s\n", var_export($statics, 1));
}

// Invoke the function
printf("---> Invokation results in: ");
var_dump($func->invoke());


// you may prefer to use the export() method
echo "\nReflectionFunction::export() results:\n";
echo ReflectionFunction::export('counter');
?>

Nota: The method invoke() accepts a variable number of arguments which are passed to the function just as in call_user_func().


ReflectionParameter

The ReflectionParameter class retrieves information about a function's or method's parameters.

<?php
class ReflectionParameter implements Reflector
{
    final private __clone()
    public object __construct(string name)
    public string __toString()
    public static string export()
    public string getName()
    public bool isPassedByReference()
    public ReflectionClass getClass()
    public bool allowsNull()
    public bool isOptional()
    public bool isDefaultValueAvailable()
    public mixed getDefaultValue()
}
?>

Nota: getDefaultValue(), isDefaultValueAvailable(), isOptional() were added in PHP 5.1.0.

To introspect function parameters, you will first have to create an instance of the ReflectionFunction or ReflectionMethod classes and then use their getParameters() method to retrieve an array of parameters.

Esempio 19-33. Using the ReflectionParameter class

<?php
function foo($a, $b, $c) { }
function bar(Exception $a, &$b, $c) { }
function baz(ReflectionFunction $a, $b = 1, $c = null) { }
function abc() { }

// Create an instance of Reflection_Function with the
// parameter given from the command line.    
$reflect = new ReflectionFunction($argv[1]);

echo $reflect;

foreach ($reflect->getParameters() as $i => $param) {
    printf(
        "-- Parameter #%d: %s {\n".
        "   Class: %s\n".
        "   Allows NULL: %s\n".
        "   Passed to by reference: %s\n".
        "   Is optional?: %s\n".
        "}\n",
        $i, 
        $param->getName(),
        var_export($param->getClass(), 1),
        var_export($param->allowsNull(), 1),
        var_export($param->isPassedByReference(), 1),
        $param->isOptional() ? 'yes' : 'no'
    );
}
?>

ReflectionClass

The ReflectionClass class lets you reverse-engineer classes.

<?php
class ReflectionClass implements Reflector
{
    final private __clone()
    public object __construct(string name)
    public string __toString()
    public static string export()
    public string getName()
    public bool isInternal()
    public bool isUserDefined()
    public bool isInstantiable()
    public bool hasConstant(string name)
    public bool hasMethod(string name)
    public bool hasProperty(string name)
    public string getFileName()
    public int getStartLine()
    public int getEndLine()
    public string getDocComment()
    public ReflectionMethod getConstructor()
    public ReflectionMethod getMethod(string name)
    public ReflectionMethod[] getMethods()
    public ReflectionProperty getProperty(string name)
    public ReflectionProperty[] getProperties()
    public array getConstants()
    public mixed getConstant(string name)
    public ReflectionClass[] getInterfaces()
    public bool isInterface()
    public bool isAbstract()
    public bool isFinal()
    public int getModifiers()
    public bool isInstance(stdclass object)
    public stdclass newInstance(mixed* args)
    public ReflectionClass getParentClass()
    public bool isSubclassOf(ReflectionClass class)
    public array getStaticProperties()
    public array getDefaultProperties()
    public bool isIterateable()
    public bool implementsInterface(string name)
    public ReflectionExtension getExtension()
    public string getExtensionName()
}
?>

Nota: hasConstant(), hasMethod(), hasProperty() were added in PHP 5.1.0.

To introspect a class, you will first have to create an instance of the ReflectionClass class. You can then call any of the above methods on this instance.

Esempio 19-34. Using the ReflectionClass class

<?php
interface Serializable
{
    // ...
}

class Object
{
    // ...
}

/**
 * A counter class
 */
class Counter extends Object implements Serializable 
{
    const START = 0;
    private static $c = Counter::START;

    /**
     * Invoke counter
     *
     * @access  public
     * @return  int
     */
    public function count() {
        return self::$c++;
    }
}

// Create an instance of the ReflectionClass class
$class = new ReflectionClass('Counter');

// Print out basic information
printf(
    "===> The %s%s%s %s '%s' [extends %s]\n" .
    "     declared in %s\n" .
    "     lines %d to %d\n" .
    "     having the modifiers %d [%s]\n",
        $class->isInternal() ? 'internal' : 'user-defined',
        $class->isAbstract() ? ' abstract' : '',
        $class->isFinal() ? ' final' : '',
        $class->isInterface() ? 'interface' : 'class',
        $class->getName(),
        var_export($class->getParentClass(), 1),
        $class->getFileName(),
        $class->getStartLine(),
        $class->getEndline(),
        $class->getModifiers(),
        implode(' ', Reflection::getModifierNames($class->getModifiers()))
);

// Print documentation comment
printf("---> Documentation:\n %s\n", var_export($class->getDocComment(), 1));

// Print which interfaces are implemented by this class
printf("---> Implements:\n %s\n", var_export($class->getInterfaces(), 1));

// Print class constants
printf("---> Constants: %s\n", var_export($class->getConstants(), 1));

// Print class properties
printf("---> Properties: %s\n", var_export($class->getProperties(), 1));

// Print class methods
printf("---> Methods: %s\n", var_export($class->getMethods(), 1));

// If this class is instantiable, create an instance
if ($class->isInstantiable()) {
    $counter = $class->newInstance();

    echo '---> $counter is instance? '; 
    echo $class->isInstance($counter) ? 'yes' : 'no';

    echo "\n---> new Object() is instance? ";
    echo $class->isInstance(new Object()) ? 'yes' : 'no';
}
?>

Nota: The method newInstance() accepts a variable number of arguments which are passed to the function just as in call_user_func().

Nota: $class = new ReflectionClass('Foo'); $class->isInstance($arg) is equivalent to $arg instanceof Foo or is_a($arg, 'Foo').


ReflectionMethod

The ReflectionMethod class lets you reverse-engineer class methods.

<?php
class ReflectionMethod extends ReflectionFunction
{
    public __construct(mixed class, string name)
    public string __toString()
    public static string export()
    public mixed invoke(stdclass object, mixed* args)
    public moxed invokeArgs(stdclass object, array args)
    public bool isFinal()
    public bool isAbstract()
    public bool isPublic()
    public bool isPrivate()
    public bool isProtected()
    public bool isStatic()
    public bool isConstructor()
    public bool isDestructor()
    public int getModifiers()
    public ReflectionClass getDeclaringClass()

    // Inherited from ReflectionFunction
    final private __clone()
    public string getName()
    public bool isInternal()
    public bool isUserDefined()
    public string getFileName()
    public int getStartLine()
    public int getEndLine()
    public string getDocComment()
    public array getStaticVariables()
    public bool returnsReference()
    public ReflectionParameter[] getParameters()
    public int getNumberOfParameters()
    public int getNumberOfRequiredParameters()
}
?>

To introspect a method, you will first have to create an instance of the ReflectionMethod class. You can then call any of the above methods on this instance.

Esempio 19-35. Using the ReflectionMethod class

<?php
class Counter
{
    private static $c = 0;

    /**
     * Increment counter
     *
     * @final
     * @static
     * @access  public
     * @return  int
     */
    final public static function increment()
    {
        return ++self::$c;
    }
}

// Create an instance of the Reflection_Method class
$method = new ReflectionMethod('Counter', 'increment');

// Print out basic information
printf(
    "===> The %s%s%s%s%s%s%s method '%s' (which is %s)\n" .
    "     declared in %s\n" .
    "     lines %d to %d\n" .
    "     having the modifiers %d[%s]\n",
        $method->isInternal() ? 'internal' : 'user-defined',
        $method->isAbstract() ? ' abstract' : '',
        $method->isFinal() ? ' final' : '',
        $method->isPublic() ? ' public' : '',
        $method->isPrivate() ? ' private' : '',
        $method->isProtected() ? ' protected' : '',
        $method->isStatic() ? ' static' : '',
        $method->getName(),
        $method->isConstructor() ? 'the constructor' : 'a regular method',
        $method->getFileName(),
        $method->getStartLine(),
        $method->getEndline(),
        $method->getModifiers(),
        implode(' ', Reflection::getModifierNames($method->getModifiers()))
);

// Print documentation comment
printf("---> Documentation:\n %s\n", var_export($method->getDocComment(), 1));

// Print static variables if existant
if ($statics= $method->getStaticVariables()) {
    printf("---> Static variables: %s\n", var_export($statics, 1));
}

// Invoke the method
printf("---> Invokation results in: ");
var_dump($method->invoke(NULL));
?>

Nota: Trying to invoke private, protected or abstract methods will result in an exception being thrown from the invoke() method.

Nota: For static methods as seen above, you should pass NULL as the first argument to invoke(). For non-static methods, pass an instance of the class.


ReflectionProperty

The ReflectionProperty class lets you reverse-engineer class properties.

<?php
class ReflectionProperty implements Reflector
{
    final private __clone()
    public __construct(mixed class, string name)
    public string __toString()
    public static string export()
    public string getName()
    public bool isPublic()
    public bool isPrivate()
    public bool isProtected()
    public bool isStatic()
    public bool isDefault()
    public int getModifiers()
    public mixed getValue(stdclass object)
    public void setValue(stdclass object, mixed value)
    public ReflectionClass getDeclaringClass()
}
?>

To introspect a property, you will first have to create an instance of the ReflectionProperty class. You can then call any of the above methods on this instance.

Esempio 19-36. Using the ReflectionProperty class

<?php
class String
{
    public $length  = 5;
}

// Create an instance of the ReflectionProperty class
$prop = new ReflectionProperty('String', 'length');

// Print out basic information
printf(
    "===> The%s%s%s%s property '%s' (which was %s)\n" .
    "     having the modifiers %s\n",
        $prop->isPublic() ? ' public' : '',
        $prop->isPrivate() ? ' private' : '',
        $prop->isProtected() ? ' protected' : '',
        $prop->isStatic() ? ' static' : '',
        $prop->getName(),
        $prop->isDefault() ? 'declared at compile-time' : 'created at run-time',
        var_export(Reflection::getModifierNames($prop->getModifiers()), 1)
);

// Create an instance of String
$obj= new String();

// Get current value
printf("---> Value is: ");
var_dump($prop->getValue($obj));

// Change value
$prop->setValue($obj, 10);
printf("---> Setting value to 10, new value is: ");
var_dump($prop->getValue($obj));

// Dump object
var_dump($obj);
?>

Nota: Trying to get or set private or protected class property's values will result in an exception being thrown.


ReflectionExtension

The ReflectionExtension class lets you reverse-engineer extensions. You can retrieve all loaded extensions at runtime using the get_loaded_extensions().

<?php
class ReflectionExtension implements Reflector {
    final private __clone()
    public __construct(string name)
    public string __toString()
    public static string export()
    public string getName()
    public string getVersion()
    public ReflectionFunction[] getFunctions()
    public array getConstants()
    public array getINIEntries()
    public ReflectionClass[] getClasses()
    public array getClassNames()
}
?>

To introspect an extension, you will first have to create an instance of the ReflectionExtension class. You can then call any of the above methods on this instance.

Esempio 19-37. Using the ReflectionExtension class

<?php
// Create an instance of the ReflectionProperty class
$ext = new ReflectionExtension('standard');

// Print out basic information
printf(
    "Name        : %s\n" .
    "Version     : %s\n" .
    "Functions   : [%d] %s\n" .
    "Constants   : [%d] %s\n" .
    "INI entries : [%d] %s\n" .
    "Classes     : [%d] %s\n",
        $ext->getName(),
        $ext->getVersion() ? $ext->getVersion() : 'NO_VERSION',
        sizeof($ext->getFunctions()),
        var_export($ext->getFunctions(), 1),

        sizeof($ext->getConstants()),
        var_export($ext->getConstants(), 1),

        sizeof($ext->getINIEntries()),
        var_export($ext->getINIEntries(), 1),

        sizeof($ext->getClassNames()),
        var_export($ext->getClassNames(), 1)
);
?>

Extending the reflection classes

In case you want to create specialized versions of the built-in classes (say, for creating colorized HTML when being exported, having easy-access member variables instead of methods or having utility methods), you may go ahead and extend them.

Esempio 19-38. Extending the built-in classes

<?php
/**
 * My Reflection_Method class
 */
class My_Reflection_Method extends ReflectionMethod
{
    public $visibility = '';

    public function __construct($o, $m)
    {
        parent::__construct($o, $m);
        $this->visibility= Reflection::getModifierNames($this->getModifiers());
    }
}

/**
 * Demo class #1
 *
 */
class T {
    protected function x() {}
}

/**
 * Demo class #2
 *
 */
class U extends T {
    function x() {}
}

// Print out information
var_dump(new My_Reflection_Method('U', 'x'));
?>

Nota: Caution: If you're overwriting the constructor, remember to call the parent's constructor _before_ any code you insert. Failing to do so will result in the following: Fatal error: Internal error: Failed to retrieve the reflection object


Type Hinting

PHP 5 introduces Type Hinting. Functions are now able to force parameters to be objects by specifying the name of the class in the function prototype.

Esempio 19-39. Type Hinting example

<?php
// An example class
class MyClass
{
    /**
     * A test function
     *
     * First parameter must be an object of type OtherClass
     */
    public function test(OtherClass $otherclass) {
        echo $otherclass->var;
    }
}

// Another example class
class OtherClass {
    public $var = 'Hello World';
}
?>

Failing to satisfy the type hint results in a fatal error.

<?php
// An instance of each class
$myclass = new MyClass;
$otherclass = new OtherClass;

// Fatal Error: Argument 1 must be an object of class OtherClass
$myclass->test('hello');

// Fatal Error: Argument 1 must be an instance of OtherClass
$foo = new stdClass;
$myclass->test($foo);

// Fatal Error: Argument 1 must not be null
$myclass->test(null);

// Works: Prints Hello World
$myclass->test($otherclass);
?>

Type hinting also works with functions:

<?php
// An example class
class MyClass {
    public $var = 'Hello World';
}

/**
 * A test function
 *
 * First parameter must be an object of type MyClass
 */
function MyFunction (MyClass $foo) {
    echo $foo->var;
}

// Works
$myclass = new MyClass;
MyFunction($myclass);
?>

Type Hints can only be of the object type. Traditional type hinting with int and string are not supported.


Capitolo 20. Exceptions

PHP 5 has an exception model similar to that of other programming languages. An exception can be thrown, try and caught within PHP. A Try block must include at least one catch block. Multiple catch blocks can be used to catch different classtypes; execution will continue after that last catch block defined in sequence. Exceptions can be thrown within catch blocks.

When an exception is thrown, code following the statement will not be executed and PHP will attempt to find the first matching catch block. If an exception is not caught a PHP Fatal Error will be issued with an Uncaught Exception message, unless there has been a handler defined with set_exception_handler().

Esempio 20-1. Throwing an Exception

<?php
try {
    $error = 'Always throw this error';
    throw new Exception($error);

    // Code following an exception is not executed.
    echo 'Never executed';

} catch (Exception $e) {
    echo 'Caught exception: ',  $e->getMessage(), "\n";
}

// Continue execution
echo 'Hello World';
?>

Extending Exceptions

A User defined Exception class can be defined by extending the built-in Exception class. The members and properties below, show what is accessible within the child class that derives from the built-in Exception class.

Esempio 20-2. The Built in Exception class

<?php
class Exception
{
    protected $message = 'Unknown exception';   // exception message
    protected $code = 0;                        // user defined exception code
    protected $file;                            // source filename of exception
    protected $line;                            // source line of exception

    function __construct($message = null, $code = 0);

    final function getMessage();                // message of exception 
    final function getCode();                   // code of exception
    final function getFile();                   // source filename
    final function getLine();                   // source line
    final function getTrace();                  // an array of the backtrace()
    final function getTraceAsString();          // formated string of trace

    /* Overrideable */
    function __toString();                       // formated string for display
}
?>

If a class extends the built-in Exception class and re-defines the constructor, it is highly recomended that it also call parent::__construct() to ensure all available data has been properly assigned. The __toString() method can be overriden to provide a custom output when the object is presented as a string.

Esempio 20-3. Extending the Exception class

<?php
/**
 * Define a custom exception class
 */
class MyException extends Exception
{
    // Redefine the exception so message isn't optional
    public function __construct($message, $code = 0) {
        // some code
    
        // make sure everything is assigned properly
        parent::__construct($message, $code);
    }

    // custom string representation of object */
    public function __toString() {
        return __CLASS__ . ": [{$this->code}]: {$this->message}\n";
    }

    public function customFunction() {
        echo "A Custom function for this type of exception\n";
    }
}


/**
 * Create a class to test the exception
 */
class TestException
{
    public $var;

    const THROW_NONE    = 0;
    const THROW_CUSTOM  = 1;
    const THROW_DEFAULT = 2;

    function __construct($avalue = self::THROW_NONE) {

        switch ($avalue) {
            case self::THROW_CUSTOM:
                // throw custom exception
                throw new MyException('1 is an invalid parameter', 5);
                break;

            case self::THROW_DEFAULT:
                // throw default one.
                throw new Exception('2 isnt allowed as a parameter', 6);
                break;

            default: 
                // No exception, object will be created.
                $this->var = $avalue;
                break;
        }
    }
}


// Example 1
try {
    $o = new TestException(TestException::THROW_CUSTOM);
} catch (MyException $e) {      // Will be caught
    echo "Caught my exception\n", $e;
    $e->customFunction();
} catch (Exception $e) {        // Skipped
    echo "Caught Default Exception\n", $e;
}

// Continue execution
var_dump($o);
echo "\n\n";


// Example 2
try {
    $o = new TestException(TestException::THROW_DEFAULT);
} catch (MyException $e) {      // Doesn't match this type
    echo "Caught my exception\n", $e;
    $e->customFunction();
} catch (Exception $e) {        // Will be caught
    echo "Caught Default Exception\n", $e;
}

// Continue execution
var_dump($o);
echo "\n\n";


// Example 3
try {
    $o = new TestException(TestException::THROW_CUSTOM);
} catch (Exception $e) {        // Will be caught
    echo "Default Exception caught\n", $e;
}

// Continue execution
var_dump($o);
echo "\n\n";


// Example 4
try {
    $o = new TestException();
} catch (Exception $e) {        // Skipped, no exception
    echo "Default Exception caught\n", $e;
}

// Continue execution
var_dump($o);
echo "\n\n";
?>

Capitolo 21. Spiegazioni sui riferimenti

Cosa sono i riferimenti

I riferimenti in PHP sono il mezzo per accedere ad uno stesso contenuto di variabile utilizzando diversi nomi. Non si sta parlando di puntatori come in C, ma di alias nella tabella dei simboli. Si noti che in PHP, il nome delle variabili e il loro contenuto sono cose diverse, uno stesso contenuto infatti può avere nomi diversi. L'analogia più prossima è quella con i nomi dei file e i file stessi in Unix - i nomi delle variabili sono come directory, mentre il contenuto delle variabili è il file stesso. I riferimenti possono essere pensati come hardlink del filesystem Unix.


Che cosa fanno i riferimenti

I riferimenti permettono di creare due o più variabili che si riferiscono allo stesso contenuto. Questo significa, che scrivendo:

$a =& $b

$a e $b puntano alla stessa variabile.

Nota: $a e $b sono completamente uguali, ma $a non è un puntatore a $b o vice versa, $a e $b puntano semplicemente nello stesso posto.

Questa sintassi si può usare con le funzioni, nella restituzione per riferimento, e con l'operatore new (da PHP 4.0.4 in poi):

$bar =& new fooclass();
$foo =& find_var ($bar);

Nota: Se non si usa l'operatore & l'oggeto appena creato viene copiato. Usando $this in una classe, opererà sulla sua istanza corrente. L'assegnazione senza & copia perciò l'istanza (l'oggetto) e $this opera sulla copia, che non è sempre ciò che si desidera. Normalmente si lavora su una singola istanza di oggetto, sia per motivi di prestazioni che di consumo di memoria.

Utilizzando l'operatore @ con new, si sopprimono gli errori nel costruttore in questo modo @new, il metodo però non funziona se si usa l'istruzione &new. Questa è una limitazione dello Zend Engine e provoca un parser error.

Il secondo utilizzo del riferimento è il passaggio di una variabile per riferimento. Questo si fa dichiarando una variabile locale di una funzione e una variabile nell'ambito della chiamata del riferimento con lo stesso contenuto. Esempio:

function foo(&$var)
{
    $var++;
}

$a=5;
foo($a);

$a assume il valore 6. Questo accade perchè nella funzione foo, la variabile $var si riferisce allo stesso contenuto di $a. Si vedano le spiegazioni più dettagliate per passaggio per riferimento.

Il terzo utilizzo del riferimento è il ritorno per riferimento.


Cosa i riferimenti non sono

Come detto prima, i riferimenti non sono puntatori. Questo significa, che il seguente costrutto non fà quello che ci si aspetterebbe:

function foo (&$var)
{
    $var =& $GLOBALS["baz"];
}
foo($bar);

Nell'esempio $var in foo viene scambiato con $bar nella chiamata, e poi riscambiato con $GLOBALS["baz"]. Questo non è il modo per collegare $bar nell'ambito della chiamata con qualcos'altro usando il meccanismo di riferimento, poichè $bar non è disponibile nella funzione foo (è rappresentato da $var, ma $var possiede soltanto il contenuto della variabile e non il nome del valore collegato nella tabella dei simboli).


Passaggio per riferimento

Si può passare una variabile ad una funzione per riferimento, modificandone gli argomenti. La sintassi è la seguente:

function foo(&$var)
{
    $var++;
}

$a=5;
foo($a);
// $a adesso è 6

Nota che non si usa il segno di riferimento nella chiamata della funzione, ma solo nella definizione. La definizione della funzione basta da sola per passare correttamente un argomento per riferimento.

Le seguenti cose possono essere passate per riferimento:

  • Variabili, es. foo($a)

  • Operatore New, es. foo(new foobar())

  • Riferimento restituito da una funazione, es.

    function &bar()
    {
        $a = 5;
        return $a;
    }
    foo(bar());

    Vedi anche le spiegazioni sulla restituzione per riferimento.

Qualunque altra cosa non dovrebbe essere passata per riferimento, poichè il risultato sarebbe indefinito. Per esempio, il seguente passaggio per riferimento non è valido:

function bar() // Nota l'assenza di &
{
    $a = 5;
    return $a;
}

foo(bar());
foo($a = 5) // Expressione: non una variabile
foo(5) // Constante: non una variabile

Questi requisiti sono validi per PHP 4.0.4 e seguenti.


Restituzione per riferimento

La restituzione per riferimento è utile quando si vuole usare una funzione per trovare quale variabile un riferimento dovrebbe limitare. Per restituire per riferimento, si usa questa sintassi:

function &find_var($param)
{
    ...codice...
    return $found_var;
}

$foo =& find_var($bar);
$foo->x = 2;

In questo esempio, la proprietà dell'oggetto restituito dalla funzione find_var viene impostata, non la copia, come sarebbe stato senza l'uso della sintassi del riferimento.

Nota: Diversamente dal passaggio di un parametro, bisogna utilizzare & in entrambi i posti - nella dichiarazione per indicare che si vuole restituire per riferimento, e non per copia come di consueto, e per indicare nella chiamata, il collegamento del riferimento, piuttosto che l'usuale assegnazione che verrebbe fatta per $foo.


Cancellare riferimenti

Quando si cancella un riferimento, si rompe il collegamento tra il nome della variabile e il contenuto della variabile. Questo non significa che il contenuto della variabile venga distrutto. Per esempio:

$a = 1;
$b =& $a;
unset ($a);

non cancella $b, ma solo $a.

Di nuovo, può essere utile pensare a questo con un'analogia col comendo Unix unlink.


Spotting References

Diversi costrutti in PHP sono implementati attraverso il meccanismo dei riferimenti, dove ogni cosa detta precedentemente, si applica anche a questi costrutti. Alcuni, come il passaggio e la restituzione per riferimento, sono stati menzionati sopra, gli altri sono:


Il riferimento global

Quando si dichiara una variabile come global $var di fatto si crea un riferimento ad una variabile globale. Questo ha lo stesso significato, dell'espressione:

$var =& $GLOBALS["var"];

Questo significa, per esempio, che cancellando $var non si cancella la variabile globale.


$this

In un metodo di un oggetto, $this è sempre un riferimento all'oggetto chiamante.


Capitolo 22. Introduction

PHP is a powerful language and the interpreter, whether included in a web server as a module or executed as a separate CGI binary, is able to access files, execute commands and open network connections on the server. These properties make anything run on a web server insecure by default. PHP is designed specifically to be a more secure language for writing CGI programs than Perl or C, and with correct selection of compile-time and runtime configuration options, and proper coding practices, it can give you exactly the combination of freedom and security you need.

As there are many different ways of utilizing PHP, there are many configuration options controlling its behaviour. A large selection of options guarantees you can use PHP for a lot of purposes, but it also means there are combinations of these options and server configurations that result in an insecure setup.

The configuration flexibility of PHP is equally rivalled by the code flexibility. PHP can be used to build complete server applications, with all the power of a shell user, or it can be used for simple server-side includes with little risk in a tightly controlled environment. How you build that environment, and how secure it is, is largely up to the PHP developer.

This chapter starts with some general security advice, explains the different configuration option combinations and the situations they can be safely used, and describes different considerations in coding for different levels of security.


Capitolo 23. General considerations

A completely secure system is a virtual impossibility, so an approach often used in the security profession is one of balancing risk and usability. If every variable submitted by a user required two forms of biometric validation (such as a retinal scan and a fingerprint), you would have an extremely high level of accountability. It would also take half an hour to fill out a fairly complex form, which would tend to encourage users to find ways of bypassing the security.

The best security is often unobtrusive enough to suit the requirements without the user being prevented from accomplishing their work, or over-burdening the code author with excessive complexity. Indeed, some security attacks are merely exploits of this kind of overly built security, which tends to erode over time.

A phrase worth remembering: A system is only as good as the weakest link in a chain. If all transactions are heavily logged based on time, location, transaction type, etc. but the user is only verified based on a single cookie, the validity of tying the users to the transaction log is severely weakened.

When testing, keep in mind that you will not be able to test all possibilities for even the simplest of pages. The input you may expect will be completely unrelated to the input given by a disgruntled employee, a cracker with months of time on their hands, or a housecat walking across the keyboard. This is why it's best to look at the code from a logical perspective, to discern where unexpected data can be introduced, and then follow how it is modified, reduced, or amplified.

The Internet is filled with people trying to make a name for themselves by breaking your code, crashing your site, posting inappropriate content, and otherwise making your day interesting. It doesn't matter if you have a small or large site, you are a target by simply being online, by having a server that can be connected to. Many cracking programs do not discern by size, they simply trawl massive IP blocks looking for victims. Try not to become one.


Capitolo 24. Installed as CGI binary

Possible attacks

Using PHP as a CGI binary is an option for setups that for some reason do not wish to integrate PHP as a module into server software (like Apache), or will use PHP with different kinds of CGI wrappers to create safe chroot and setuid environments for scripts. This setup usually involves installing executable PHP binary to the web server cgi-bin directory. CERT advisory CA-96.11 recommends against placing any interpreters into cgi-bin. Even if the PHP binary can be used as a standalone interpreter, PHP is designed to prevent the attacks this setup makes possible:

  • Accessing system files: http://my.host/cgi-bin/php?/etc/passwd

    The query information in a URL after the question mark (?) is passed as command line arguments to the interpreter by the CGI interface. Usually interpreters open and execute the file specified as the first argument on the command line.

    When invoked as a CGI binary, PHP refuses to interpret the command line arguments.

  • Accessing any web document on server: http://my.host/cgi-bin/php/secret/doc.html

    The path information part of the URL after the PHP binary name, /secret/doc.html is conventionally used to specify the name of the file to be opened and interpreted by the CGI program. Usually some web server configuration directives (Apache: Action) are used to redirect requests to documents like http://my.host/secret/script.php to the PHP interpreter. With this setup, the web server first checks the access permissions to the directory /secret, and after that creates the redirected request http://my.host/cgi-bin/php/secret/script.php. Unfortunately, if the request is originally given in this form, no access checks are made by web server for file /secret/script.php, but only for the /cgi-bin/php file. This way any user able to access /cgi-bin/php is able to access any protected document on the web server.

    In PHP, compile-time configuration option --enable-force-cgi-redirect and runtime configuration directives doc_root and user_dir can be used to prevent this attack, if the server document tree has any directories with access restrictions. See below for full the explanation of the different combinations.


Case 1: only public files served

If your server does not have any content that is not restricted by password or ip based access control, there is no need for these configuration options. If your web server does not allow you to do redirects, or the server does not have a way to communicate to the PHP binary that the request is a safely redirected request, you can specify the option --enable-force-cgi-redirect to the configure script. You still have to make sure your PHP scripts do not rely on one or another way of calling the script, neither by directly http://my.host/cgi-bin/php/dir/script.php nor by redirection http://my.host/dir/script.php.

Redirection can be configured in Apache by using AddHandler and Action directives (see below).


Case 2: using --enable-force-cgi-redirect

This compile-time option prevents anyone from calling PHP directly with a URL like http://my.host/cgi-bin/php/secretdir/script.php. Instead, PHP will only parse in this mode if it has gone through a web server redirect rule.

Usually the redirection in the Apache configuration is done with the following directives:

Action php-script /cgi-bin/php
AddHandler php-script .php

This option has only been tested with the Apache web server, and relies on Apache to set the non-standard CGI environment variable REDIRECT_STATUS on redirected requests. If your web server does not support any way of telling if the request is direct or redirected, you cannot use this option and you must use one of the other ways of running the CGI version documented here.


Case 3: setting doc_root or user_dir

To include active content, like scripts and executables, in the web server document directories is sometimes considered an insecure practice. If, because of some configuration mistake, the scripts are not executed but displayed as regular HTML documents, this may result in leakage of intellectual property or security information like passwords. Therefore many sysadmins will prefer setting up another directory structure for scripts that are accessible only through the PHP CGI, and therefore always interpreted and not displayed as such.

Also if the method for making sure the requests are not redirected, as described in the previous section, is not available, it is necessary to set up a script doc_root that is different from web document root.

You can set the PHP script document root by the configuration directive doc_root in the configuration file, or you can set the environment variable PHP_DOCUMENT_ROOT. If it is set, the CGI version of PHP will always construct the file name to open with this doc_root and the path information in the request, so you can be sure no script is executed outside this directory (except for user_dir below).

Another option usable here is user_dir. When user_dir is unset, only thing controlling the opened file name is doc_root. Opening a URL like http://my.host/~user/doc.php does not result in opening a file under users home directory, but a file called ~user/doc.php under doc_root (yes, a directory name starting with a tilde [~]).

If user_dir is set to for example public_php, a request like http://my.host/~user/doc.php will open a file called doc.php under the directory named public_php under the home directory of the user. If the home of the user is /home/user, the file executed is /home/user/public_php/doc.php.

user_dir expansion happens regardless of the doc_root setting, so you can control the document root and user directory access separately.


Case 4: PHP parser outside of web tree

A very secure option is to put the PHP parser binary somewhere outside of the web tree of files. In /usr/local/bin, for example. The only real downside to this option is that you will now have to put a line similar to:

#!/usr/local/bin/php

as the first line of any file containing PHP tags. You will also need to make the file executable. That is, treat it exactly as you would treat any other CGI script written in Perl or sh or any other common scripting language which uses the #! shell-escape mechanism for launching itself.

To get PHP to handle PATH_INFO and PATH_TRANSLATED information correctly with this setup, the PHP parser should be compiled with the --enable-discard-path configure option.


Capitolo 25. Installed as an Apache module

When PHP is used as an Apache module it inherits Apache's user permissions (typically those of the "nobody" user). This has several impacts on security and authorization. For example, if you are using PHP to access a database, unless that database has built-in access control, you will have to make the database accessible to the "nobody" user. This means a malicious script could access and modify the database, even without a username and password. It's entirely possible that a web spider could stumble across a database administrator's web page, and drop all of your databases. You can protect against this with Apache authorization, or you can design your own access model using LDAP, .htaccess files, etc. and include that code as part of your PHP scripts.

Often, once security is established to the point where the PHP user (in this case, the apache user) has very little risk attached to it, it is discovered that PHP is now prevented from writing any files to user directories. Or perhaps it has been prevented from accessing or changing databases. It has equally been secured from writing good and bad files, or entering good and bad database transactions.

A frequent security mistake made at this point is to allow apache root permissions, or to escalate apache's abilities in some other way.

Escalating the Apache user's permissions to root is extremely dangerous and may compromise the entire system, so sudo'ing, chroot'ing, or otherwise running as root should not be considered by those who are not security professionals.

There are some simpler solutions. By using open_basedir you can control and restrict what directories are allowed to be used for PHP. You can also set up apache-only areas, to restrict all web based activity to non-user, or non-system, files.


Capitolo 26. Filesystem Security

PHP is subject to the security built into most server systems with respect to permissions on a file and directory basis. This allows you to control which files in the filesystem may be read. Care should be taken with any files which are world readable to ensure that they are safe for reading by all users who have access to that filesystem.

Since PHP was designed to allow user level access to the filesystem, it's entirely possible to write a PHP script that will allow you to read system files such as /etc/passwd, modify your ethernet connections, send massive printer jobs out, etc. This has some obvious implications, in that you need to ensure that the files that you read from and write to are the appropriate ones.

Consider the following script, where a user indicates that they'd like to delete a file in their home directory. This assumes a situation where a PHP web interface is regularly used for file management, so the Apache user is allowed to delete files in the user home directories.

Esempio 26-1. Poor variable checking leads to....

<?php
// remove a file from the user's home directory
$username = $_POST['user_submitted_name'];
$homedir = "/home/$username";
$file_to_delete = "$userfile";
unlink ("$homedir/$userfile");
echo "$file_to_delete has been deleted!";
?>
Since the username is postable from a user form, they can submit a username and file belonging to someone else, and delete files. In this case, you'd want to use some other form of authentication. Consider what could happen if the variables submitted were "../etc/" and "passwd". The code would then effectively read:

Esempio 26-2. ... A filesystem attack

<?php
// removes a file from anywhere on the hard drive that
// the PHP user has access to. If PHP has root access:
$username = "../etc/";
$homedir = "/home/../etc/";
$file_to_delete = "passwd";
unlink ("/home/../etc/passwd");
echo "/home/../etc/passwd has been deleted!";
?>
There are two important measures you should take to prevent these issues.

  • Only allow limited permissions to the PHP web user binary.

  • Check all variables which are submitted.

Here is an improved script:

Esempio 26-3. More secure file name checking

<?php
// removes a file from the hard drive that
// the PHP user has access to.
$username = $_SERVER['REMOTE_USER']; // using an authentication mechanisim

$homedir = "/home/$username";

$file_to_delete = basename("$userfile"); // strip paths
unlink ($homedir/$file_to_delete);

$fp = fopen("/home/logging/filedelete.log","+a"); //log the deletion
$logstring = "$username $homedir $file_to_delete";
fwrite ($fp, $logstring);
fclose($fp);

echo "$file_to_delete has been deleted!";
?>
However, even this is not without it's flaws. If your authentication system allowed users to create their own user logins, and a user chose the login "../etc/", the system is once again exposed. For this reason, you may prefer to write a more customized check:

Esempio 26-4. More secure file name checking

<?php
$username = $_SERVER['REMOTE_USER']; // using an authentication mechanisim
$homedir = "/home/$username";

if (!ereg('^[^./][^/]*$', $userfile))
     die('bad filename'); //die, do not process

if (!ereg('^[^./][^/]*$', $username))
     die('bad username'); //die, do not process
//etc...
?>

Depending on your operating system, there are a wide variety of files which you should be concerned about, including device entries (/dev/ or COM1), configuration files (/etc/ files and the .ini files), well known file storage areas (/home/, My Documents), etc. For this reason, it's usually easier to create a policy where you forbid everything except for what you explicitly allow.


Capitolo 27. Database Security

Nowadays, databases are cardinal components of any web based application by enabling websites to provide varying dynamic content. Since very sensitive or secret information can be stored in a database, you should strongly consider protecting your databases.

To retrieve or to store any information you need to connect to the database, send a legitimate query, fetch the result, and close the connection. Nowadays, the commonly used query language in this interaction is the Structured Query Language (SQL). See how an attacker can tamper with an SQL query.

As you can surmise, PHP cannot protect your database by itself. The following sections aim to be an introduction into the very basics of how to access and manipulate databases within PHP scripts.

Keep in mind this simple rule: defense in depth. The more places you take action to increase the protection of your database, the less probability of an attacker succeeding in exposing or abusing any stored information. Good design of the database schema and the application deals with your greatest fears.


Designing Databases

The first step is always to create the database, unless you want to use one from a third party. When a database is created, it is assigned to an owner, who executed the creation statement. Usually, only the owner (or a superuser) can do anything with the objects in that database, and in order to allow other users to use it, privileges must be granted.

Applications should never connect to the database as its owner or a superuser, because these users can execute any query at will, for example, modifying the schema (e.g. dropping tables) or deleting its entire content.

You may create different database users for every aspect of your application with very limited rights to database objects. The most required privileges should be granted only, and avoid that the same user can interact with the database in different use cases. This means that if intruders gain access to your database using your applications credentials, they can only effect as many changes as your application can.

You are encouraged not to implement all the business logic in the web application (i.e. your script), instead do it in the database schema using views, triggers or rules. If the system evolves, new ports will be intended to open to the database, and you have to re-implement the logic in each separate database client. Over and above, triggers can be used to transparently and automatically handle fields, which often provides insight when debugging problems with your application or tracing back transactions.


Connecting to Database

You may want to establish the connections over SSL to encrypt client/server communications for increased security, or you can use ssh to encrypt the network connection between clients and the database server. If either of these is used, then monitoring your traffic and gaining information about your database will be difficult for a would-be attacker.


Encrypted Storage Model

SSL/SSH protects data travelling from the client to the server, SSL/SSH does not protect the persistent data stored in a database. SSL is an on-the-wire protocol.

Once an attacker gains access to your database directly (bypassing the webserver), the stored sensitive data may be exposed or misused, unless the information is protected by the database itself. Encrypting the data is a good way to mitigate this threat, but very few databases offer this type of data encryption.

The easiest way to work around this problem is to first create your own encryption package, and then use it from within your PHP scripts. PHP can assist you in this with several extensions, such as Mcrypt and Mhash, covering a wide variety of encryption algorithms. The script encrypts the data before inserting it into the database, and decrypts it when retrieving. See the references for further examples of how encryption works.

In case of truly hidden data, if its raw representation is not needed (i.e. not be displayed), hashing may also be taken into consideration. The well-known example for the hashing is storing the MD5 hash of a password in a database, instead of the password itself. See also crypt() and md5().

Esempio 27-1. Using hashed password field

<?php

// storing password hash
$query  = sprintf("INSERT INTO users(name,pwd) VALUES('%s','%s');",
            addslashes($username), md5($password));
$result = pg_query($connection, $query);

// querying if user submitted the right password
$query = sprintf("SELECT 1 FROM users WHERE name='%s' AND pwd='%s';",
            addslashes($username), md5($password));
$result = pg_query($connection, $query);

if (pg_num_rows($result) > 0) {
    echo 'Welcome, $username!';
} else {
    echo 'Authentication failed for $username.';
}

?>

SQL Injection

Many web developers are unaware of how SQL queries can be tampered with, and assume that an SQL query is a trusted command. It means that SQL queries are able to circumvent access controls, thereby bypassing standard authentication and authorization checks, and sometimes SQL queries even may allow access to host operating system level commands.

Direct SQL Command Injection is a technique where an attacker creates or alters existing SQL commands to expose hidden data, or to override valuable ones, or even to execute dangerous system level commands on the database host. This is accomplished by the application taking user input and combining it with static parameters to build a SQL query. The following examples are based on true stories, unfortunately.

Owing to the lack of input validation and connecting to the database on behalf of a superuser or the one who can create users, the attacker may create a superuser in your database.

Esempio 27-2. Splitting the result set into pages ... and making superusers (PostgreSQL)

<?php

$offset = $argv[0]; // beware, no input validation!
$query  = "SELECT id, name FROM products ORDER BY name LIMIT 20 OFFSET $offset;";
$result = pg_query($conn, $query);

?>
Normal users click on the 'next', 'prev' links where the $offset is encoded into the URL. The script expects that the incoming $offset is a decimal number. However, what if someone tries to break in by appending a urlencode()'d form of the following to the URL

0;
insert into pg_shadow(usename,usesysid,usesuper,usecatupd,passwd)
    select 'crack', usesysid, 't','t','crack'
    from pg_shadow where usename='postgres';
--

If it happened, then the script would present a superuser access to him. Note that 0; is to supply a valid offset to the original query and to terminate it.

Nota: It is common technique to force the SQL parser to ignore the rest of the query written by the developer with -- which is the comment sign in SQL.

A feasible way to gain passwords is to circumvent your search result pages. The only thing the attacker needs to do is to see if there are any submitted variables used in SQL statements which are not handled properly. These filters can be set commonly in a preceding form to customize WHERE, ORDER BY, LIMIT and OFFSET clauses in SELECT statements. If your database supports the UNION construct, the attacker may try to append an entire query to the original one to list passwords from an arbitrary table. Using encrypted password fields is strongly encouraged.

Esempio 27-3. Listing out articles ... and some passwords (any database server)

<?php

$query  = "SELECT id, name, inserted, size FROM products
                  WHERE size = '$size'
                  ORDER BY $order LIMIT $limit, $offset;";
$result = odbc_exec($conn, $query);

?>
The static part of the query can be combined with another SELECT statement which reveals all passwords:

'
union select '1', concat(uname||'-'||passwd) as name, '1971-01-01', '0' from usertable;
--

If this query (playing with the ' and --) were assigned to one of the variables used in $query, the query beast awakened.

SQL UPDATE's are also susceptible to attack. These queries are also threatened by chopping and appending an entirely new query to it. But the attacker might fiddle with the SET clause. In this case some schema information must be possessed to manipulate the query successfully. This can be acquired by examining the form variable names, or just simply brute forcing. There are not so many naming conventions for fields storing passwords or usernames.

Esempio 27-4. From resetting a password ... to gaining more privileges (any database server)

<?php
$query = "UPDATE usertable SET pwd='$pwd' WHERE uid='$uid';";
?>
But a malicious user sumbits the value ' or uid like'%admin%'; -- to $uid to change the admin's password, or simply sets $pwd to "hehehe', admin='yes', trusted=100 " (with a trailing space) to gain more privileges. Then, the query will be twisted:

<?php

// $uid == ' or uid like'%admin%'; --
$query = "UPDATE usertable SET pwd='...' WHERE uid='' or uid like '%admin%'; --";

// $pwd == "hehehe', admin='yes', trusted=100 "
$query = "UPDATE usertable SET pwd='hehehe', admin='yes', trusted=100 WHERE
...;";

?>

A frightening example how operating system level commands can be accessed on some database hosts.

Esempio 27-5. Attacking the database hosts operating system (MSSQL Server)

<?php

$query  = "SELECT * FROM products WHERE id LIKE '%$prod%'";
$result = mssql_query($query);

?>
If attacker submits the value a%' exec master..xp_cmdshell 'net user test testpass /ADD' -- to $prod, then the $query will be:

<?php

$query  = "SELECT * FROM products
                    WHERE id LIKE '%a%'
                    exec master..xp_cmdshell 'net user test testpass /ADD'--";
$result = mssql_query($query);

?>

MSSQL Server executes the SQL statements in the batch including a command to add a new user to the local accounts database. If this application were running as sa and the MSSQLSERVER service is running with sufficient privileges, the attacker would now have an account with which to access this machine.

Nota: Some of the examples above is tied to a specific database server. This does not mean that a similar attack is impossible against other products. Your database server may be similarly vulnerable in another manner.


Avoiding techniques

You may plead that the attacker must possess a piece of information about the database schema in most examples. You are right, but you never know when and how it can be taken out, and if it happens, your database may be exposed. If you are using an open source, or publicly available database handling package, which may belong to a content management system or forum, the intruders easily produce a copy of a piece of your code. It may be also a security risk if it is a poorly designed one.

These attacks are mainly based on exploiting the code not being written with security in mind. Never trust any kind of input, especially that which comes from the client side, even though it comes from a select box, a hidden input field or a cookie. The first example shows that such a blameless query can cause disasters.

  • Never connect to the database as a superuser or as the database owner. Use always customized users with very limited privileges.

  • Check if the given input has the expected data type. PHP has a wide range of input validating functions, from the simplest ones found in Variable Functions and in Character Type Functions (e.g. is_numeric(), ctype_digit() respectively) and onwards to the Perl compatible Regular Expressions support.

  • If the application waits for numerical input, consider verifying data with is_numeric(), or silently change its type using settype(), or use its numeric representation by sprintf().

    Esempio 27-6. A more secure way to compose a query for paging

    <?php
    
    settype($offset, 'integer');
    $query = "SELECT id, name FROM products ORDER BY name LIMIT 20 OFFSET $offset;";
    
    // please note %d in the format string, using %s would be meaningless
    $query = sprintf("SELECT id, name FROM products ORDER BY name LIMIT 20 OFFSET %d;",
                     $offset);
    
    ?>

  • Quote each non numeric user supplied value that is passed to the database with the database-specific string escape function (e.g. mysql_escape_string(), sql_escape_string(), etc.). If a database-specific string escape mechanism is not available, the addslashes() and str_replace() functions may be useful (depending on database type). See the first example. As the example shows, adding quotes to the static part of the query is not enough, making this query easily crackable.

  • Do not print out any database specific information, especially about the schema, by fair means or foul. See also Error Reporting and Error Handling and Logging Functions.

  • You may use stored procedures and previously defined cursors to abstract data access so that users do not directly access tables or views, but this solution has another impacts.

Besides these, you benefit from logging queries either within your script or by the database itself, if it supports logging. Obviously, the logging is unable to prevent any harmful attempt, but it can be helpful to trace back which application has been circumvented. The log is not useful by itself, but through the information it contains. More detail is generally better than less.


Capitolo 28. Error Reporting

With PHP security, there are two sides to error reporting. One is beneficial to increasing security, the other is detrimental.

A standard attack tactic involves profiling a system by feeding it improper data, and checking for the kinds, and contexts, of the errors which are returned. This allows the system cracker to probe for information about the server, to determine possible weaknesses. For example, if an attacker had gleaned information about a page based on a prior form submission, they may attempt to override variables, or modify them:

Esempio 28-1. Attacking Variables with a custom HTML page

<form method="post" action="attacktarget?username=badfoo&amp;password=badfoo">
<input type="hidden" name="username" value="badfoo" />
<input type="hidden" name="password" value="badfoo" />
</form>

The PHP errors which are normally returned can be quite helpful to a developer who is trying to debug a script, indicating such things as the function or file that failed, the PHP file it failed in, and the line number which the failure occurred in. This is all information that can be exploited. It is not uncommon for a php developer to use show_source(), highlight_string(), or highlight_file() as a debugging measure, but in a live site, this can expose hidden variables, unchecked syntax, and other dangerous information. Especially dangerous is running code from known sources with built-in debugging handlers, or using common debugging techniques. If the attacker can determine what general technique you are using, they may try to brute-force a page, by sending various common debugging strings:

Esempio 28-2. Exploiting common debugging variables

<form method="post" action="attacktarget?errors=Y&amp;showerrors=1&amp;debug=1">
<input type="hidden" name="errors" value="Y" />
<input type="hidden" name="showerrors" value="1" />
<input type="hidden" name="debug" value="1" />
</form>

Regardless of the method of error handling, the ability to probe a system for errors leads to providing an attacker with more information.

For example, the very style of a generic PHP error indicates a system is running PHP. If the attacker was looking at an .html page, and wanted to probe for the back-end (to look for known weaknesses in the system), by feeding it the wrong data they may be able to determine that a system was built with PHP.

A function error can indicate whether a system may be running a specific database engine, or give clues as to how a web page or programmed or designed. This allows for deeper investigation into open database ports, or to look for specific bugs or weaknesses in a web page. By feeding different pieces of bad data, for example, an attacker can determine the order of authentication in a script, (from the line number errors) as well as probe for exploits that may be exploited in different locations in the script.

A filesystem or general PHP error can indicate what permissions the webserver has, as well as the structure and organization of files on the web server. Developer written error code can aggravate this problem, leading to easy exploitation of formerly "hidden" information.

There are three major solutions to this issue. The first is to scrutinize all functions, and attempt to compensate for the bulk of the errors. The second is to disable error reporting entirely on the running code. The third is to use PHP's custom error handling functions to create your own error handler. Depending on your security policy, you may find all three to be applicable to your situation.

One way of catching this issue ahead of time is to make use of PHP's own error_reporting(), to help you secure your code and find variable usage that may be dangerous. By testing your code, prior to deployment, with E_ALL, you can quickly find areas where your variables may be open to poisoning or modification in other ways. Once you are ready for deployment, you should either disable error reporting completely by setting error_reporting() to 0, or turn off the error display using the php.ini option display_errors, to insulate your code from probing. If you choose to do the latter, you should also define the path to your log file using the error_log ini directive, and turn log_errors on.

Esempio 28-3. Finding dangerous variables with E_ALL

<?php
if ($username) {  // Not initialized or checked before usage
    $good_login = 1;
}
if ($good_login == 1) { // If above test fails, not initialized or checked before usage
    readfile ("/highly/sensitive/data/index.html");
}
?>


Capitolo 29. Using Register Globals

Perhaps the most controversial change in PHP is when the default value for the PHP directive register_globals went from ON to OFF in PHP 4.2.0. Reliance on this directive was quite common and many people didn't even know it existed and assumed it's just how PHP works. This page will explain how one can write insecure code with this directive but keep in mind that the directive itself isn't insecure but rather it's the misuse of it.

When on, register_globals will inject (poison) your scripts will all sorts of variables, like request variables from HTML forms. This coupled with the fact that PHP doesn't require variable initialization means writing insecure code is that much easier. It was a difficult decision, but the PHP community decided to disable this directive by default. When on, people use variables yet really don't know for sure where they come from and can only assume. Internal variables that are defined in the script itself get mixed up with request data sent by users and disabling register_globals changes this. Let's demonstrate with an example misuse of register_globals:

Esempio 29-1. Example misuse with register_globals = on

<?php
// define $authorized = true only if user is authenticated
if (authenticated_user()) {
    $authorized = true;
}

// Because we didn't first initialize $authorized as false, this might be
// defined through register_globals, like from GET auth.php?authorized=1
// So, anyone can be seen as authenticated!
if ($authorized) {
    include "/highly/sensitive/data.php";
}
?>

When register_globals = on, our logic above may be compromised. When off, $authorized can't be set via request so it'll be fine, although it really is generally a good programming practice to initialize variables first. For example, in our example above we might have first done $authorized = false. Doing this first means our above code would work with register_globals on or off as users by default would be unauthorized.

Another example is that of sessions. When register_globals = on, we could also use $username in our example below but again you must realize that $username could also come from other means, such as GET (through the URL).

Esempio 29-2. Example use of sessions with register_globals on or off

<?php
// We wouldn't know where $username came from but do know $_SESSION is
// for session data
if (isset($_SESSION['username'])) {

    echo "Hello <b>{$_SESSION['username']}</b>";

} else {

    echo "Hello <b>Guest</b><br />";
    echo "Would you like to login?";

}
?>

It's even possible to take preventative measures to warn when forging is being attempted. If you know ahead of time exactly where a variable should be coming from, you can check to see if the submitted data is coming from an inappropriate kind of submission. While it doesn't guarantee that data has not been forged, it does require an attacker to guess the right kind of forging. If you don't care where the request data comes from, you can use $_REQUEST as it contains a mix of GET, POST and COOKIE data. See also the manual section on using variables from outside of PHP.

Esempio 29-3. Detecting simple variable poisoning

<?php
if (isset($_COOKIE['MAGIC_COOKIE'])) {

    // MAGIC_COOKIE comes from a cookie.
    // Be sure to validate the cookie data!

} elseif (isset($_GET['MAGIC_COOKIE']) || isset($_POST['MAGIC_COOKIE'])) {

   mail("admin@example.com", "Possible breakin attempt", $_SERVER['REMOTE_ADDR']);
   echo "Security violation, admin has been alerted.";
   exit;

} else {

   // MAGIC_COOKIE isn't set through this REQUEST

}
?>

Of course, simply turning off register_globals does not mean your code is secure. For every piece of data that is submitted, it should also be checked in other ways. Always validate your user data and initialize your variables! To check for uninitialized variables you may turn up error_reporting() to show E_NOTICE level errors.

For information about emulating register_globals being On or Off, see this FAQ.

Matrici superglobali: note di disponibilità: A partire da PHP 4.1.0, sono disponibili le matrici superglobali quali $_GET , $_POST, e $_SERVER, ecc. Per maggiori dettagli, si rimanda al capitolo superglobals del manuale


Capitolo 30. User Submitted Data

The greatest weakness in many PHP programs is not inherent in the language itself, but merely an issue of code not being written with security in mind. For this reason, you should always take the time to consider the implications of a given piece of code, to ascertain the possible damage if an unexpected variable is submitted to it.

Esempio 30-1. Dangerous Variable Usage

<?php
// remove a file from the user's home directory... or maybe
// somebody else's?
unlink ($evil_var);

// Write logging of their access... or maybe an /etc/passwd entry?
fwrite ($fp, $evil_var);

// Execute something trivial.. or rm -rf *?
system ($evil_var);
exec ($evil_var);

?>
You should always carefully examine your code to make sure that any variables being submitted from a web browser are being properly checked, and ask yourself the following questions:

  • Will this script only affect the intended files?

  • Can unusual or undesirable data be acted upon?

  • Can this script be used in unintended ways?

  • Can this be used in conjunction with other scripts in a negative manner?

  • Will any transactions be adequately logged?

By adequately asking these questions while writing the script, rather than later, you prevent an unfortunate re-write when you need to increase your security. By starting out with this mindset, you won't guarantee the security of your system, but you can help improve it.

You may also want to consider turning off register_globals, magic_quotes, or other convenience settings which may confuse you as to the validity, source, or value of a given variable. Working with PHP in error_reporting(E_ALL) mode can also help warn you about variables being used before they are checked or initialized (so you can prevent unusual data from being operated upon).


Capitolo 31. Magic Quotes

Magic Quotes is a process that automagically escapes incoming data to the PHP script. It's preferred to code with magic quotes off and to instead escape the data at runtime, as needed.


What are Magic Quotes

When on, all ' (single-quote), " (double quote), \ (backslash) and NULL characters are escaped with a backslash automatically. This is identical to what addslashes() does.

There are three magic quote directives:

  • magic_quotes_gpc

    Affects HTTP Request data (GET, POST, and COOKIE). Cannot be set at runtime, and defaults to on in PHP.

    See also get_magic_quotes_gpc().

  • magic_quotes_runtime

    If enabled, most functions that return data from an external source, including databases and text files, will have quotes escaped with a backslash. Can be set at runtime, and defaults to on in PHP.

    See also set_magic_quotes_runtime() and get_magic_quotes_runtime().

  • magic_quotes_sybase

    If enabled, a single-quote is escaped with a single-quote instead of a backslash. If on, it completely overrides magic_quotes_gpc. Having both directives enabled means only single quotes are escaped as ''. Double quotes, backslashes and NULL's will remain untouched and unescaped.

    See also ini_get() for retrieving its value.


Why use Magic Quotes

  • Useful for beginners

    Magic quotes are implemented in PHP to help code written by beginners from being dangerous. Although SQL Injection is still possible with magic quotes on, the risk is reduced.

  • Convenience

    For inserting data into a database, magic quotes essentially runs addslashes() on all Get, Post, and Cookie data, and does so automagically.


Why not to use Magic Quotes

  • Portability

    Assuming it to be on, or off, affects portability. Use get_magic_quotes_gpc() to check for this, and code accordingly.

  • Performance

    Because not every piece of escaped data is inserted into a database, there is a performance loss for escaping all this data. Simply calling on the escaping functions (like addslashes()) at runtime is more efficient.

    Although php.ini-dist enables these directives by default, php.ini-recommended disables it. This recommendation is mainly due to performance reasons.

  • Inconvenience

    Because not all data needs escaping, it's often annoying to see escaped data where it shouldn't be. For example, emailing from a form, and seeing a bunch of \' within the email. To fix, this may require excessive use of stripslashes().


Disabling Magic Quotes

The magic_quotes_gpc directive may only be disabled at the system level, and not at runtime. In otherwords, use of ini_set() is not an option.

Esempio 31-1. Disabling magic quotes server side

An example that sets the value of these directives to Off in php.ini. For additional details, read the manual section titled How to change configuration settings.

; Magic quotes
;

; Magic quotes for incoming GET/POST/Cookie data.
magic_quotes_gpc = Off

; Magic quotes for runtime-generated data, e.g. data from SQL, from exec(), etc.
magic_quotes_runtime = Off

; Use Sybase-style magic quotes (escape ' with '' instead of \').
magic_quotes_sybase = Off

If access to the server configuration is unavailable, use of .htaccess is also an option. For example:

php_flag magic_quotes_gpc Off

In the interest of writing portable code (code that works in any environment), like if setting at the server level is not possible, here's an example to disable magic_quotes_gpc at runtime. This method is inefficient so it's preferred to instead set the appropriate directives elsewhere.

Esempio 31-2. Disabling magic quotes at runtime

<?php
if (get_magic_quotes_gpc()) {
    function stripslashes_deep($value)
    {
        $value = is_array($value) ?
                    array_map('stripslashes_deep', $value) :
                    stripslashes($value);

        return $value;
    }

    $_POST = array_map('stripslashes_deep', $_POST);
    $_GET = array_map('stripslashes_deep', $_GET);
    $_COOKIE = array_map('stripslashes_deep', $_COOKIE);
}
?>


Capitolo 32. Hiding PHP

In general, security by obscurity is one of the weakest forms of security. But in some cases, every little bit of extra security is desirable.

A few simple techniques can help to hide PHP, possibly slowing down an attacker who is attempting to discover weaknesses in your system. By setting expose_php = off in your php.ini file, you reduce the amount of information available to them.

Another tactic is to configure web servers such as apache to parse different filetypes through PHP, either with an .htaccess directive, or in the apache configuration file itself. You can then use misleading file extensions:

Esempio 32-1. Hiding PHP as another language

# Make PHP code look like other code types
AddType application/x-httpd-php .asp .py .pl
Or obscure it completely:

Esempio 32-2. Using unknown types for PHP extensions

# Make PHP code look like unknown types
AddType application/x-httpd-php .bop .foo .133t
Or hide it as HTML code, which has a slight performance hit because all HTML will be parsed through the PHP engine:

Esempio 32-3. Using HTML types for PHP extensions

# Make all PHP code look like HTML
AddType application/x-httpd-php .htm .html
For this to work effectively, you must rename your PHP files with the above extensions. While it is a form of security through obscurity, it's a minor preventative measure with few drawbacks.


Capitolo 33. Keeping Current

PHP, like any other large system, is under constant scrutiny and improvement. Each new version will often include both major and minor changes to enhance and repair security flaws, configuration mishaps, and other issues that will affect the overall security and stability of your system.

Like other system-level scripting languages and programs, the best approach is to update often, and maintain awareness of the latest versions and their changes.


Capitolo 34. Autenticazione HTTP usando PHP

I meccanismi di Autenticazione HTTP sono disponibili in PHP solo quando questo viene usato come un modulo di Apache ed esso non è quindi disponibile nella versione CGI. In uno script PHP modulo di Apache, è possibile usare la funzione header() per inviare un messaggio di "Authentication Required" al browser dell'utente, provocando quindi l'apertura di una finestra contenente una richiesta di Nome utente/Password. Una volta che l'utente ha compilato i campi nome utente e password, l'URL contenente lo script PHP verrà richiamato nuovamente usando le variabili predefinite, PHP_AUTH_USER, PHP_AUTH_PW e AUTH_TYPE impostate con, rispettivamente: nome, password e tipo di autenticazione. Queste variabili predefinite possono essere trovate negli array $_SERVER e $HTTP_SERVER_VARS. Solamente il tipo di autenticazione "Basic" è al momento supportato. Fare riferimento alla funzione header() per ulteriori informazioni.

Nota sulla versione di PHP: Le variabili autoglobali, come $_SERVER, esistono a partire da PHP 4.1.0. $HTTP_SERVER_VARS è disponibile a partire da PHP 3.

Un frammento di script di esempio che richiede l'autenticazione da parte del browser su una pagina, potrebbe essere il seguente:

Esempio 34-1. Esempio di Autenticazione HTTP

<?php
  if (!isset($_SERVER['PHP_AUTH_USER'])) {
    header('WWW-Authenticate: Basic realm="Il mio realm"');
    header('HTTP/1.0 401 Unauthorized');
    echo 'Messaggio da inviare se si preme il tasto Cancel';
    exit;
  } else {
    echo "<p>Ciao {$_SERVER['PHP_AUTH_USER']}.</p>";
    echo "<p>Hai inserito {$_SERVER['PHP_AUTH_PW']} come tua password.</p>";
  }
?>

Note sulla compatibilità: Fare molta attenzione quando si scrive codice per le intestazioni HTTP. Per ottenere la massima compatibilità con tutti i client, la paorla-chiave "Basic" deve essere scritta con una "B" maiuscola, la stringa realm deve essere racchiusa in virgolette doppie (non singole), ed esattamente uno spazio deve precedere il codice 401 nella linea di intestazione HTTP/1.0 401.

Invece di stampare semplicemente PHP_AUTH_USER e PHP_AUTH_PW, probabilmente si vorrà controllare la validità dello username e della password. Probabilmente inviando una chiamata al database, o cercando un utente in un file dbm.

Si faccia attenzione ad alcune versioni di Internet Explorer. Sembra che siano molto schizzinosi riguardo all'ordine delle intestazioni. Inviare l'intestazione WWW-Authenticate prima dell'intestazione HTTP/1.0 401 sembra sistemare le cose per il momento.

A partire da PHP 4.3.0, al fine di prevenire che qualcuno scriva uno script che rivela la password di una pagina che era stata autenticata tramite un tradizionale meccanismo esterno, le variabili PHP_AUTH non verranno impostate se è abilitata l'autenticazione esterna per quella determinata pagina e safe mode è abilitato. Ciò nonostante, la variabile REMOTE_USER può essere usata per identificare un utente autenticato esternamente. Quindi, potete usare $_SERVER['REMOTE_USER'].

Nota sulla Configurazione: PHP usa la presenza di una direttiva AuthType per determinare se viene utilizzata l'autenticazione esterna.

Si fa notare, però, che quanto scritto sopra non impedisce a qualcuno che controlla un URL non autenticato di sottrarre password da URL autenticati presenti sullo stesso server.

Sia Netscape Navigator che Internet Explorer cancellano la cache locale della finestra del browser, per quanto riguarda il realm, al ricevimento di una risposta 401 da parte del server. Questo è effettivamente un meccanismo di "log out" per l'utente, che lo forza a reinserire lo username e la password. Alcune persone usano questo per fare il "time out" dei login, o per rendere disponibili bottoni di "log-out".

Esempio 34-2. Esempio di Autenticazione HTTP che impone l'inserimento di nuovo username/password

<?php
  function authenticate() {
    header('WWW-Authenticate: Basic realm="Prova del Sistema di Autenticazione"');
    header('HTTP/1.0 401 Unauthorized');
    echo "Per poter accedere a questa risorsa occorre inserire una coppia login e password valide\n";
    exit;
  }

  if (!isset($_SERVER['PHP_AUTH_USER']) ||
      ($_POST['SeenBefore'] == 1 && $_POST['OldAuth'] == $_SERVER['PHP_AUTH_USER'])) {
   authenticate();
  } 
  else {
   echo "<p>Benvenuto: {$_SERVER['PHP_AUTH_USER']}<br>";
   echo "Vecchio: {$_REQUEST['OldAuth']}";
   echo "<form action='{$_SERVER['PHP_SELF']}' METHOD='POST'>\n";
   echo "<input type='hidden' name='SeenBefore' value='1'>\n";
   echo "<input type='hidden' name='OldAuth' value='{$_SERVER['PHP_AUTH_USER']}'>\n";
   echo "<input type='submit' value='Ri autentifica'>\n";
   echo "</form></p>\n";
  }
?>

Questo comportamento non è richiesto dallo standard di autenticazione HTTP Basic, quindi non si dovrebbe mai fare affidamento su di esso. Test effettuati con Lynx mostrano che Lynx non cancella le credenziali di autenticazione al ricevimento del codice di risposta 401 da parte del server, quindi, premendo indietro e avanti nuovamente, darà nuovamente accesso alla risorsa, ammesso che le rispettive richieste di credenziali non siano cambiate. L'utente può però premere il tasto '_' al fine di cancellare le sue informazioni di autenticazione.

Si noti anche che questo non funziona con il server IIS di Microsoft e con la versione CGI di PHP a causa di una limitazione di IIS. Si noti anche che, prima di PHP 4.3.3, l'Autenticazione HTTP non funzionava usando il server IIS di Microsoft e con la versione CGI di PHP a causa di una limitazione di IIS. Al fine di farla funzionare in PHP 4.3.3+, si deve modificare la vostra configurazione di IIS "Directory Security". Cliccare su "Edit" e selezionare solo "Anonymous Access", tutti gli altri campi dovrebbero essere lasciati deselezionati.

Un'altra limitazione è che se si usa il modulo IIS (ISAPI) e PHP 4, non si possono usare le variabili PHP_AUTH_* ma, al contrario, la variabile HTTP_AUTHORIZATION è disponibile. Per esempio, si consideri il seguente codice: list($user, $pw) = explode(':', base64_decode(substr($_SERVER['HTTP_AUTHORIZATION'], 6)));

Nota su IIS:: Al fine di fare funzionare la Autenticazione HTTP con IIS, la direttiva PHP cgi.rfc2616_headers deve essere impostata al valore 0 (il valore predefinito).

Nota: Se è abilitato safe mode viene aggiunto lo uid dello script al realm dell'header WWW-Authenticate.


Capitolo 35. Cookies

PHP supporta in modo trasparente i cookies HTTP. I cookies sono un meccanismo per memorizzare dati nel browser remoto e tenere traccia degli utenti o identificarli al loro ritorno. I cookies possono essere impostati tramite le funzioni setcookie() oppure setrawcookie(). I cookies sono parte dell'intestazione HTTP, quindi setcookie() deve essere chiamata prima che qualsiasi output sia inviato al browser. Si tratta della stessa limitazione della funzione header(). Si può utilizzare la funzione di buffer dell'output per posticipare l'output dello script finchè non avete stabilito se impostare o meno qualsiasi cookies o l''invio di header.

Ogni cookie inviato dal client sarà automaticamente trasformato in una variabile PHP, come avviene nel caso di dati GET o POST, in base alle variabili di configurazione register_globals e variables_order. Se si vogliono assegnare più valori ad un singolo cookie, basta aggiungere [] al nome del cookie.

Nel PHP 4.1.0 e successivi, il vettore auto-globale $_COOKIE sarà sempre impostato con qualsiasi cookies inviati dal client. $HTTP_COOKIE_VARS è anch'essa impostata nelle versioni precedenti del PHP se è impostata la variabile di configurazione track_vars. (Questo parametro è sempre a on a partire da PHP 4.0.3.)

Per maggiori dettagli si vedano le funzioni setcookie() e setrawcookie().


Capitolo 36. Sessions

Session support in PHP consists of a way to preserve certain data across subsequent accesses. This enables you to build more customized applications and increase the appeal of your web site. All information is in the Session reference section.


Capitolo 37. Dealing with XForms

XForms defines a variation on traditional webforms which allows them to be used on a wider variety of platforms and browsers or even non-traditional media such as PDF documents.

The first key difference in XForms is how the form is sent to the client. XForms for HTML Authors contains a detailed description of how to create XForms, for the purpose of this tutorial we'll only be looking at a simple example.

Esempio 37-1. A simple XForms search form

<h:html xmlns:h="http://www.w3.org/1999/xhtml"
        xmlns="http://www.w3.org/2002/xforms">
<h:head>
 <h:title>Search</h:title>
 <model>
  <submission action="http://example.com/search"
              method="post" id="s"/>
 </model>
</h:head>
<h:body>
 <h:p>
  <input ref="q"><label>Find</label></input>
  <submit submission="s"><label>Go</label></submit>
 </h:p>
</h:body>
</h:html>

The above form displays a text input box (named q), and a submit button. When the submit button is clicked, the form will be sent to the page referred to by action.

Here's where it starts to look different from your web application's point of view. In a normal HTML form, the data would be sent as application/x-www-form-urlencoded, in the XForms world however, this information is sent as XML formatted data.

If you're choosing to work with XForms then you probably want that data as XML, in that case, look in $HTTP_RAW_POST_DATA where you'll find the XML document generated by the browser which you can pass into your favorite XSLT engine or document parser.

If you're not interested in formatting and just want your data to be loaded into the traditional $_POST variable, you can instruct the client browser to send it as application/x-www-form-urlencoded by changing the method attribute to urlencoded-post.

Esempio 37-2. Using an XForm to populate $_POST

<h:html xmlns:h="http://www.w3.org/1999/xhtml"
        xmlns="http://www.w3.org/2002/xforms">
<h:head>
 <h:title>Search</h:title>
 <model>
  <submission action="http://example.com/search"
              method="urlencoded-post" id="s"/>
 </model>
</h:head>
<h:body>
 <h:p>
  <input ref="q"><label>Find</label></input>
  <submit submission="s"><label>Go</label></submit>
 </h:p>
</h:body>
</h:html>

Nota: As of this writing, many browsers do not support XForms. Check your browser version if the above examples fails.


Capitolo 38. Caricare file

Metodo POST per caricamento di file

PHP è in grado di ricevere file caricati da qualsiasi browser compatibile con le specifiche RFC-1867 (che comprende Netscape Navigator 3 o successivo, Microsoft Internet Explorer 3 con una modifica di Microsoft, o versioni successive senza modifica). Questa caratteristica permette di caricare sia file di testo che binari. Utilizzando le funzioni di PHP per l'autenticazione e manipolazione dei file, è possibile avere pieno controllo su chi ha i permessi per caricare un file e su ciò che deve essere fatto una volta che il file è stato caricato.

Note relative alla configurazione: Si vedano i parametri file_uploads, upload_max_filesize, upload_tmp_dir, e post_max_size nel php.ini

Si noti che PHP permette l'upload di file con metodo PUT come utilizzato dai programmi Netscape Composer e W3C Amaya. Si veda Supporto per metodo PUT per maggiori dettagli.

La schermata di caricamento di un file può essere costruita con una form particolare, di questo tipo:

Esempio 38-1. Form di caricamento file

<form enctype="multipart/form-data" action="_URL_" method="post">
<input type="hidden" name="MAX_FILE_SIZE" value="30000">
Invia questo file: <input name="userfile" type="file">
<input type="submit" value="Invia File">
</form>
Il valore della action _URL_ dovrebbe puntare a un file PHP. Il campo nascosto MAX_FILE_SIZE deve precedere il campo di immissione del file e il suo valore è la dimensione massima accettata del file. Il valore è in byte.

Avvertimento

Il valore MAX_FILE_SIZE è consigliato al browser. E' facile aggirare questo valore, quindi non fate affidamento sul fatto che il navigatore si comporti come desiderato! L'impostazione PHP lato server per la dimensione massima non può comunque essere aggirata. Tuttavia si può comunque inserire MAX_FILE_SIZE per evitare all'utente di attendere il trasferimento di un file prima di scoprire che è di dimensioni eccessive.

Le variabili definite per i file inviati differiscono in base alla versione di PHP ed alla configurazione. La variabile globale $_FILES esiste a partire dalla versione 4.1.0 di PHP. La matrice $HTTP_POST_FILES esiste dalla versione 4.0.0. Tutte queste matrici conterranno tutte le informazioni dei file inviati. Si consiglia di preferire l'uso di $_FILES. Se il parametro register_globals è impostato a on, esisteranno anche le relative variabili. Attenzione che per default il parametro register_globals viene impostato a off dalla versione 4.2.0 di PHP.

Di seguito verrà illustrato il contenuto di $_FILES nel caso dell'esempio precedente. Si noti che si assume come nome del file inviato userfile, come nell'esempio precedente.

$_FILES['userfile']['name']

Il nome originale del file sulla macchina dell'utente.

$_FILES['userfile']['type']

Il mime-type del file, se il browser fornisce questa informazione. Un esempio potrebbe essere "image/gif".

$_FILES['userfile']['size']

La dimensione, in bytes, del file caricato.

$_FILES['userfile']['tmp_name']

Il nome del file temporaneo in cui il file caricato è salvato sul server.

$_FILES['userfile']['error']

Il codice di errore associato all'upload di questo file. Il campo ['error'] è stato aggiunto nella versione 4.2.0 di PHP.

Nota: Nelle versioni di PHP precedenti alla 4.1.0 questa variabile era chiamata $HTTP_POST_FILES e non era una variabile autoglobal come è $_FILES. La versione 3 di PHP non supporta $HTTP_POST_FILES.

Quando register_globals è impostato a on nel php.ini, sono disponibili variabili addizionali. Da esempio, $userfile_name sarà uguale a $_FILES['userfile']['name'], $userfile_type sarà uguale a $_FILES['userfile']['type'], eccetera. Si ricordi che a partire dalla versione 4.2.0 di PHP il parametro register_globals viene impostato a off per default. E' preferibile non fare affidamento su questo parametro.

I file sono, di default, salvati in una directory temporanea sul server, a meno che un diverso percorso sia specificato nella direttiva upload_tmp_dir nel file php.ini. La directory del server predefinita può essere cambiata impostando la variabile di ambiente TMPDIR in cui è in esecuzione PHP. Non è possibile impostare questa variabile utilizzando la funzione putenv() da uno script PHP. Questa variabile di ambiente può anche essere usata per assicurarsi che anche altre operazioni stiano lavorando sui file caricati.

Esempio 38-2. Verifica dell'upload di file

Si vedano le definizioni delle funzioni is_uploaded_file() e move_uploaded_file() per maggiori dettagli. L'esempio seguente illustra il processamento di un file inviato tramite un form.

<?php
// Nelle versioni di PHP precedenti alla 4.1.0 si deve utilizzare  $HTTP_POST_FILES anzichè $_FILES.
// Nelle versioni di PHP precedenti alla 4.0.3, si utilizzi copy() e is_uploaded_file() anzichè move_uploaded_file

$uploaddir = '/var/www/uploads/';
print "<pre>";
if (move_uploaded_file($_FILES['userfile']['tmp_name'], $uploaddir . $_FILES['userfile']['name'])) { 
    print "Il file è valido, e inviato con successo.  Ecco alcune informazioni:\n"; 
    print_r($_FILES);
} else {
    print "Possibile attacco tramite file upload! Alcune informazioni:\n"; 
    print_r($_FILES);
}
 
?>

Lo script PHP che riceve il file caricato dovrebbe implementare la logica necessaria per determinare cosa deve essere fatto con il file caricato. E' possibile, per esempio, utilizzare la variabile $_FILES['userfile']['size'] per eliminare file che siano troppo grandi o troppo piccoli. E' possibile utillizzare la variabile $_FILES['userfile']['type'] per eliminare tutti i file che non soddisfano certi criteri. A partire da PHP 4.2.0, si può utilizzare $_FILES['userfile']['error'] ed organizzare la logica in base ai codici di errore. Quale che sia la logica, bisognerebbe comunque sempre cancellare il file dalla directory temporanea e spostarlo da qualche altra parte.

Il file sarà eliminato dalla directory temporanea al termine della richiesta se non è stato mosso e rinominato.


Spiegazione dei messaggi di errore

Dalla versione 4.2.0, il PHP restituisce un codice di errore nella matrice del file. Il codice di errore si trova nell'indice ['error'] e viene valorizzato durante l'upload del file da parte del PHP. In altre parole l'errore può essere trovato in $_FILES['userfile']['error'].

UPLOAD_ERR_OK

Valore: 0; Non vi sono errori, l'upload è stato eseguito con successo.

UPLOAD_ERR_INI_SIZE

Valore: 1; Il file inviato eccede le dimensioni specificate nel parametro upload_max_filesize di php.ini.

UPLOAD_ERR_FORM_SIZE

Valore: 2; Il file inviato eccede le dimensioni specificate nel parametro MAX_FILE_SIZE del form.

UPLOAD_ERR_PARTIAL

Valore: 3; Upload eseguito parzialmente.

UPLOAD_ERR_NO_FILE

Valore: 4; Nessun file è stato inviato.

Nota: Questi valori sono diventate costanti PHP a partire dal PHP 4.3.0.


Common Pitfalls

La voce MAX_FILE_SIZE non può specificare una dimensione del file maggiore di quella impostata dal parametro upload_max_filesize del file php.ini. L'impostazione di default è 2 Megabytes.

Se si è impostato un limite di memoria memory_limit può essere necessario ampliarlo. Occorre essere certi di impostare memory_limit alle dimensioni appropriate.

Se max_execution_time è impostato ad un valore basso, l'esecuzione dello script può eccedere tale valore. Ampliare max_execution_time ad un tempo sufficiente per l'upload.

Nota: max_execution_time influisce solo sul tempo di esecuzione dello script. Il tempo utilizzato per attività esterno allo script, tipo le chiamate di sistema system(), o la funzione sleep(), le query nei database, il tempo inpiegato nell'upload del file non è considerato nel computo del tempo di esecuzione dello script.

Se post_max_size è impostato ad un valore troppo piccolo, non si può inviare file di grosse dimensioni. Impostare post_max_size alle dimensioni appropriate.

Non controllare il file su cui si sta operando potrebbe dare agli utenti accesso a informazioni sensibili contenute in altre directory.

Si noti che che il server http CERN sembra eliminare qualsiasi cosa a partire dal primo spazio nell'header mime content-type che riceve dal client. Fino a che questo si verificherà, il server http CERN non supporterà la possibilità di caricare file.

A causa della varietà di formati di directory, non si è in grado di garantire che nomi di file strani (ad esempio contenenti spazi) siano gestiti correttamente.


Caricamento di più file

E' possibile inviare più file contemporanemante utilizzando in input nomi differenti.

E' possibile caricare più file contemporaneamente e avere le informazioni organizzate automaticamente in array. Per questo è necessario utilizzare la medesima sintassi di invio di array da form HTML che è utilizzata con select e checkbox multipli:

Nota: Il supporto per il caricamento di file multipli è presente dalla versione 3.0.10.

Esempio 38-3. Caricamento di più file

<form action="file-upload.php" method="post" enctype="multipart/form-data">
  Send these files:<br>
  <input name="userfile[]" type="file"><br>
  <input name="userfile[]" type="file"><br>
  <input type="submit" value="Send files">
</form>

Quando la form è inviata, gli array $_FILES['userfile'], $_FILES['userfile']['name'], e $_FILES['userfile']['size'] saranno inizializzati (come sarà valorizzato $HTTP_POST_FILES per le versioni di PHP precedenti la 4.1.0). Quando il parametro register_globals è impostato a on saranno presenti anche le variabili globali. Ognuno di questi è un array indicizzato numericamente con i valori relativi ai diversi file caricati.

Per esempio, si supponga che i nomi di file /home/test/review.html e /home/test/xwp.out siano inviati. In questo caso, $_FILES['userfile']['name'][0] conterrebbe il valore review.html, e $_FILES['userfile']['name'][1] conterrebbe il valore xwp.out. Analogamente, $_FILES['userfile']['size'][0] conterrebbe la dimensione di review.html, e così via.

Anche $_FILES['userfile']['name'][0], $_FILES['userfile']['tmp_name'][0], $_FILES['userfile']['size'][0], e $_FILES['userfile']['type'][0] sono impostati.


Supporto per metodo PUT

Il supporto al metodo PUT è cambiato tra PHP 3 e PHP 4. In PHP 4 occorre utilizzare il flusso standard di input per leggere il contenuto di un PUT HTTP.

Esempio 38-4. Salvataggio di un file HTTP PUT con PHP 4

<?php
/* I dati PUT arrivano in stdin */
$putdata = fopen("php://stdin","r");
 
/* Apertura del file in scrittura */
$fp = fopen("myputfile.ext","w");
/* Lettura dei dati d 1kb alla volta e scrittura nel file */
while ($data = fread($putdata,1024))
  fwrite($fp,$data);
 
/* Chiusura */
fclose($fp);
fclose($putdata);
?>

Nota: Tutta la documentazione che segue si applica solo a PHP 3.

PHP fornisce supporto per il metodo HTTP PUT utilizzato da programmi come Netscape Composer e W3C Amaya. Le richieste PUT sono molto più semplici rispetto al caricamento di un file, e assomigliano a

PUT /percorso/nomefile.html HTTP/1.1

Questo significa che normalmente il programma remoto intende salvare il contenuto della richesta come : /percorso/nomefile.html nel filesystem sul server web. Non è ovviamente una buona idea per Apache o PHP lasciare a un qualsiasi utente la possibilità di sovrascrivere file sul server web. Quindi, per gestire questa richiesta si deve chiedere al server web che si vuole che sia un certo script PHP a gestire la richiesta stessa. In Apache si ottiene questo con la direttiva Script. Può essere posta quasi ovunque nel file di configurazione di Apache. Un posto frequente è all'interno di un blocco <Directory> oppurte all'interno del blocco <Virtualhost>. Un linea come la seguente è sufficiente:

Script PUT /put.php

Questo chiede ad Apache di inviare tutte le richieste PUT che soddisfano il contesto in cui si è inserito questo comando allo script put.php. Questo richiede, naturalmente, che sia abilitato PHP per l'estensione .php e che PHP sia attivo.

All'interno del file put.php si può inserire qualcosa del tipo:

<?php copy($PHP_UPLOADED_FILE_NAME,$DOCUMENT_ROOT.$REQUEST_URI); ?>

Questo copia il file nella posizione chiesta dal programma remoto. E' probabile che si vogliano effettuare dei controlli o autenticazioni dell'utente prima di effettuare questa copia. L'unica magia qui presente è che quando PHP vede una richiesta con metodo PUT memorizza il file caricato in un file temporaneo così come per i file caricati con il metodo POST. Quando la richiesta termina, questo file temporaneo è eliminato. Quindi il gestore della richiesta PUT deve copiare il file da qualche parte. Il nome del file temporaneo è memorizzato nella variabile $PHP_PUT_FILENAME, ed è possibile vedere il nome del file di destinazione nella variabile $REQUEST_URI (potrebbe variare su web server diversi da Apache). Qusto nome di file di destinazione è quello specificato dal client remoto. Non è necessario seguire le indicazioni del client. E' possibile, per esempio, copiare tutti i file caricati in una apposita directory.


Capitolo 39. Utilizzo di file remoti

Se allow_url_fopen è abilitato in php.ini, si possono usare gli URL HTTP e FTP con la maggior parte delle funzioni che richiedono nomi di file come parametri, incluse le funzioni require(), require_once(), include() e include_once(). Vedere Appendice L per maggiori dettagli sui protocolli supportati dal PHP.

Nota: In PHP 4.0.3 e precedenti, al fine di poter utilizzare gli URL wrapper, occorreva specificare l'opzione di configurazione --enable-url-fopen-wrapper.

Nota: Al momento, le versioni Windows di PHP precedenti la 4.3, non supportano l'accesso remoto ai file con le seguenti funzioni: include(), include_once(), require() e require_once() e le funzioni imagecreatefromXXX del modulo Riferimento LII, Funzioni per le immagini.

Per esempio, si può usare per aprire un file da un web server remoto, elaborare i dati presi da remoto, e usarli per effetuare delle query, o semplicemente visualizzarli con lo stile del proprio sito web.

Esempio 39-1. Leggere il titolo di una pagina web remota

<?php
$file = fopen ("http://www.example.com/", "r");
if (!$file) {
    echo "<p>Impossibile aprire il file remoto.\n";
    exit;
}
while (!feof ($file)) {
    $linea = fgets ($file, 1024);
    /* Funziona solo se title e i relativi tag sono sulla medesima riga */
    if (eregi ("<title>(.*)</title>", $linea, $out)) {
        $title = $out[1];
        break;
    }
}
fclose($file);
?>

Si può anche scrivere in un file remoto via FTP (se l'utente con cui ci si connette ha le autorizzazioni necessarie). Si possono solamente creare nuovi file usando questo metodo, se si prova a sovrascrivere un file che già esiste, fopen() non avrà successo.

Per connettersi con un utenti diversi da 'anonymous' si ha bisogno di specificare lo username (e la relativa password) assieme all'URL, in questo modo: 'ftp://user:password@ftp.example.com/directory/del/file'. (Si può usare lo stesso tipo di sintassi per accedere a file via HTTP quando richiedono autenticazione Basic).

Esempio 39-2. Salvataggio di dati su server remoto

<?php
$file = fopen ("ftp://ftp.example.com/incoming/outputfile", "w");
if (!$file) {
    echo "<p>Impossibile aprire il file remoto in scrittura.\n";
    exit;
}
/* Scrive i dati qui. */
fwrite ($file, $_SERVER['HTTP_USER_AGENT'] . "\n");
fclose ($file);
?>

Nota: Dall'esempio precedente ci si può fare un'idea di come usare questa tecnica per effettuare dei log in remoto, ma come già accennato, con questo sitema non è possibile scrivere con fopen() su file già esistenti. Per fare una procedura di log distribuito è più indicata la funzione syslog().


Capitolo 40. Gestione della connessione

Nota: Le seguenti note si applicano a partire dalla versione 3.0.7.

Internamente il PHP mantiene lo stato della connessione. Si hanno 3 possibili stati:

  • 0 - NORMAL

  • 1 - ABORTED

  • 2 - TIMEOUT

Quendo uno script PHP viene eseguito normalmente si trova nello stato NORMAL. Se il client remoto si disconnette viene attivato il flag ABORTED. La disconnessione di un client remoro è generalmente causata dalla pressione del tasto STOP da parte dell'utente. Se invece si raggiunge il limite di tempo imposto dal PHP (vedere set_time_limit()) si attiva lo stato TIMEOUT.

Si può decidere se la disconnessione del client debba fare abortire lo script o meno. In certi casi è più pratico lasciare finire lo script anche se non c'è più il browser remoto a ricevere i dati. Tuttavia il comportamento di default è di fare abortire lo script quando il client remoto si disconnette. Questo comportamento può essere impostato tramite la direttiva di php.ini ignore_user_abort oppure tramite la corrispondente direttiva "php_value ignore_user_abort" del file .conf di Apache oppure con la funzione ignore_user_abort(). Se non si segnala al PHP di ignorare la disconssessione dell'utente lo script sarà interrotto. Unica eccezione si ha con la registrazione di una funzione di chiusura utilizzando register_shutdown_function(). Con una funzione di shutdown, quando l'utente remoto preme il bottone di STOP, alla prima occasione in cui lo script tenterà di produrre un output, il PHP intercetterà che la connessione è interrotta e richiamerà la funzione di shutdown. Questa funzione sarà richiamata anche al normale termine dello script, pertanto per eseguire passi differenti in caso di disconnessione del client occorre utilizzare la funzione connection_aborted(). Questa funzione restituisce TRUE se la connessione è stata interrotta.

Uno script può essere fermato dal timer incorporato nel PHP. Per default il timeout è impostato a 30 secondi. Tale limite può essere variato agendo sulla direttiva max_execution_time nel php.ini o nel corrispondente parametro php_value max_execution_time nella configurazione di Apache, oppure con la funzione set_time_limit(). Quando termina il tempo impostato lo script viene interrotto, se è stata prevista una funzione di shutdown, questa verrà eseguita. All'interno di questa funzione si può discriminare se è stata attivata per lo scadere del timeout utilizzando la funzione connection_timeout(). Questa restituisce 2 se la funzione di shutdown è stata chiamata per lo scadere del tempo a disposizione.

Un aspetto che occorre notare sui stati ABORTED e TIMEOUT è che possono essere attivi contemporaneamente. Questo può accadere se si è impostato il PHP affinchè ignori le interruzioni da parte dell'utente. Infatti il PHP continua a tenere traccia della disconnessione dell'utente, ma, semplicemente, non viene interrotto lo script. Quindi, quando termina il tempo, lo script sarà interrotto e verrà richiamata la funzione di shutdown, se presente. In questa situazione si avrà che connection_status() restituirà 3.


Capitolo 41. Connessioni Persistenti ai Database

Connessioni persistenti sono collegamenti che non vengono chiusi quando l'esecusione di uno script viene terminata. Quando è richiesta una connessione persistente, PHP controlla se esiste già una identica connessione persistente (che è rimasta aperta da prima) - e se esiste, la usa. Se non esiste, crea il collegamento. Una connessione 'identica' è una connessione aperta verso lo stesso host, con lo stesso username e la stessa password (dove applicabile).

Chi non ha molta familiarità con il modo in cui lavorano i server web e di come essi distribuiscano il carico potrebbero confondere le connessioni permanenti per ciò che esse non sono. In particolare, non danno la possibilità di aprire 'sessioni utente' sullo stesso collegamento, non danno la possibilità di gestire una transazione in maniera efficiente e sopratutto non fanno molte altre cose. Infatti, per essere molto chiari su questo punto, le connessioni persistenti non hanno nessuna funzionalià che non era disponibile con le loro omonime non-persistenti.

Perché?

Questo ha a che fare con il modo in cui i server web operano. Ci sono tre modi in cui un server web può utilizzare PHP per generare le pagine web.

Il primo metodo ` quello di usare il PHP come un "wrapper" (involucro) CGI. Quando viene eseguito in questa modalità, per ogni pagina che viene richiesta al server web che contenga del codice PHP, viene creata e, alla fine dell'esecuzione, distrutta, una istanza dell'interprete PHP. Poiché viene distrutta alla fine di ogni richiesta, qualunque risorsa abbia acquisito (come ad esempio un collegamento ad un server di database SQL) verrà anch'essa distrutta. In questo caso, non vi è nessun guadagno nell'usare le connessioni persistenti -- semplicemente esse non persistono.

Il secondo, e più popolare, metodo è quello di eseguire il programma PHP come modulo in un server web multiprocesso, cosa che attualmente include solo Apache. Un server multiprocesso ha tipicamente un processo (il padre) che coordina un insieme di processi (i suoi figli) che sono quelli che generano le pagine web. Quando arriva una richiesta da parte di un client, questa è passata ad uno dei figli che in quel momento non è già occupato a servire un altro client. Questo significa che quando lo stesso client effettua una seconda richiesta al server, esso potrà essere servito da un diverso processo figlio rispetto a quello della prima volta. Quando si aprono delle connessioni persistenti, ciascuna pagina successiva che richiede dei servizi SQL, può riutilizzare la connessione al server SQL precedente.

L'ultimo metodo è quello di usare il PHP come una plug-in per un server web multithread. Attualmente PHP 4 supporta ISAPI, WSAPI e NSAPI (su piattaforma Windows), i quali permettono di usare PHP come una plug-in sui server web multithread come FastTrack (iPlanet) di Netscape, Internet Information Server (IIS) di Microsoft e WebSite Pro di O'Reilly. Il comportamento è essenzialmente lo stesso che si ha nel modello multiprocesso descritto prima. Si noti che il supporto SAPI non è disponibile in PHP 3.

Se le connessioni persistenti non hanno nessuna funzionalità aggiuntiva, perch´ usarle?

La risposta, in questo caso è estremamente semplice: efficienza. Le connessioni persistenti sono utili se il carico di lavoro necessario per aprire una connessione al server SQL è alto. Che il carico sia molto alto o meno dipende da molti fattori. Quali, il tipo di database che si utilizza, il fatto che esso si trovi sulla stessa macchina sulla quale si trova il server web, quanto carico di lavoro ha la macchina sulla quale si trova il server SQL, e molte altre ragioni. Il fatto importante è che se il carico di lavoro necessario per aprire le connessioni è alto, le connessioni persistenti possono aiutare in maniera considerevole. Fanno in modo che il processo figlio si colleghi semplicemente una volta durante la sua intera vita, invece di collegarsi ogni volta che processa una pagina che richiede una connessione al server SQL. Questo significa che per ogni figlio che ha aperto una connessione persistente, si avrà una nuova connessione persistente aperta verso il server. Per esempio, se si hanno 20 diversi processi figlio che eseguono uno script che crea una connessione persistente al server SQL server, si avranno 20 diverse connessioni al server SQL, una per ogni figlio.

Si fa notare, tuttavia, che questo può avere degli svantaggi se si fa uso di un database che ha un limite al numero di connessioni, minore rispetto al numero delle connessioni persistenti dei procesi figlio. Se per esempio di usa un database con 16 connessioni simultanee, e durante un periodo di intensa attività del web server, 17 processi figlio cercano di collegarsi, uno non sarà in grado di farlo. Se nei vostri script ci sono bug che non permettono alle connessioni di chiudersi in maniera regolare (come ad esempio un loop infinito), un database con sole 16 connessioni diventerà rapidamente saturo. Fare riferimento alla documentazione del database per informazioni su come gestire connessioni abbandonate o inattive.

Avvertimento

Ci sono un paio di altri caveat da tenere in considerazione quando si usano le connessioni persistenti. Uno è che quando si usa il table locking su una connessione persistente, se lo script, per una qualunque ragione non è in grado di rimuovere il blocco, allora i successivi script che useranno la stessa connessione rimarranno bloccati in maniera indefinita e potrebbe essre necessario riavviare il server httpd o il server database. Un altro è che quando si usano le transazioni, un transaction block verrà trasferito anche allo script successivo che usa la medesima connessione, se lo script in esecuzione termina prima che sia terminato il transaction block. In entrambi i casi, si può usare register_shutdown_function() per registrare una semplice funzione di pulizia per sbloccare le tabelle o effettuare il roll back delle transaczioni. Sarebbe meglio non dover affrontare il problema, semplicemente non usando le connessioni persistenti negli script che usano i lock delle tabelle o le transaczioni (si possono comunque usare in altre situazioni).

Sommario importante. Le connessioni persistenti sono state pensate per avere una mappatura uno-a-uno con le connessioni di tipo normale. Ciò significa che si dovrebbe sempre essere in grado di cambiare una connessione persistente con una connessione non-persistente, e che questo non dovrebbe cambiare il modo in cui lo script si comporta. Può (e probabilmente succederà) cambiare l'efficienza dello script, ma non il suo comportamento!

Vedere anche fbsql_pconnect(), ibase_pconnect(), ifx_pconnect(), ingres_pconnect(), msql_pconnect(), mssql_pconnect(), mysql_pconnect(), ocipLogon(), odbc_pconnect(), ora_pLogon(), pfsockopen(), pg_pconnect() e sybase_pconnect().


Capitolo 42. Modalità sicura (Safe mode)

La modalità Safe Mode è un tentativo di risolvere il problema di sicurezza derivante dalla condivisione del server. Dal punto di vista architetturale non è corretto cercare di risolvere questo problema al livello del PHP, ma poiché le alternative al livello del web server e del SO (Sistema Operativo) non sono realistiche, in molti, specialmente ISP (Internet Service Provider), utilizzano la modalità sicura.


Security and Safe Mode

Tabella 42-1. Direttive di configurazione della Modalità sicura e Sdella icurezza

NomeDefaultChangeableChangelog
safe_mode"0"PHP_INI_SYSTEM 
safe_mode_gid"0"PHP_INI_SYSTEMDisponibile dal PHP 4.1.0.
safe_mode_include_dirNULLPHP_INI_SYSTEMDisponibile dal PHP 4.1.0.
safe_mode_exec_dir""PHP_INI_SYSTEM 
safe_mode_allowed_env_vars"PHP_"PHP_INI_SYSTEM 
safe_mode_protected_env_vars"LD_LIBRARY_PATH"PHP_INI_SYSTEM 
open_basedirNULLPHP_INI_SYSTEM 
disable_functions""php.ini onlyDisponibile dal PHP 4.0.1.
disable_classes""php.ini onlyDisponibile dal PHP 4.3.2.
Per ulteriori dettagli e definizione delle costanti PHP_INI_* vedere ini_set().

Breve descrizione dei parametri di configurazione.

safe_mode boolean

Abilita o disabilita la modalità sicura di PHP's. Leggere il capitolo Sicurezza per ulteriori informazioni.

safe_mode_gid boolean

Di default, Safe Mode does a UID compare check when opening files. If you want to relax this to a GID compare, then turn on safe_mode_gid. Whether to use UID (FALSE) or GID (TRUE) checking upon file access.

safe_mode_include_dir string

UID/GID checks are bypassed when including files from this directory and its subdirectories (directory must also be in include_path or full path must including).

As of PHP 4.2.0, this directive can take a colon (semi-colon on Windows) separated path in a fashion similar to the include_path directive, rather than just a single directory.

The restriction specified is actually a prefix, not a directory name. This means that "safe_mode_include_dir = /dir/incl" also allows access to "/dir/include" and "/dir/incls" if they exist. When you want to restrict access to only the specified directory, end with a slash. For example: "safe_mode_include_dir = /dir/incl/"

safe_mode_exec_dir string

If PHP is used in safe mode, system() and the other functions executing system programs refuse to start programs that are not in this directory. You have to use / as directory separator on all environments including Windows.

safe_mode_allowed_env_vars string

Setting certain environment variables may be a potential security breach. This directive contains a comma-delimited list of prefixes. In Safe Mode, the user may only alter environment variables whose names begin with the prefixes supplied here. By default, users will only be able to set environment variables that begin with PHP_ (e.g. PHP_FOO=BAR).

Nota: If this directive is empty, PHP will let the user modify ANY environment variable!

safe_mode_protected_env_vars string

This directive contains a comma-delimited list of environment variables that the end user won't be able to change using putenv(). These variables will be protected even if safe_mode_allowed_env_vars is set to allow to change them.

open_basedir string

Limit the files that can be opened by PHP to the specified directory-tree, including the file itself. This directive is NOT affected by whether Safe Mode is turned On or Off.

When a script tries to open a file with, for example, fopen() or gzopen(), the location of the file is checked. When the file is outside the specified directory-tree, PHP will refuse to open it. All symbolic links are resolved, so it's not possible to avoid this restriction with a symlink.

The special value . indicates that the working directory of the script will be used as the base-directory. This is, however, a little dangerous as the working directory of the script can easily be changed with chdir().

In httpd.conf, open_basedir can be turned off (e.g. for some virtual hosts) the same way as any other configuration directive with "php_admin_value open_basedir none".

Under Windows, separate the directories with a semicolon. On all other systems, separate the directories with a colon. As an Apache module, open_basedir paths from parent directories are now automatically inherited.

The restriction specified with open_basedir is actually a prefix, not a directory name. This means that "open_basedir = /dir/incl" also allows access to "/dir/include" and "/dir/incls" if they exist. When you want to restrict access to only the specified directory, end with a slash. For example: "open_basedir = /dir/incl/"

Nota: Support for multiple directories was added in 3.0.7.

The default is to allow all files to be opened.

disable_functions string

This directive allows you to disable certain functions for security reasons. It takes on a comma-delimited list of function names. disable_functions is not affected by Safe Mode.

This directive must be set in php.ini For example, you cannot set this in httpd.conf.

disable_classes string

This directive allows you to disable certain classes for security reasons. It takes on a comma-delimited list of class names. disable_classes is not affected by Safe Mode.

This directive must be set in php.ini For example, you cannot set this in httpd.conf.

Availability note: This directive became available in PHP 4.3.2

See also: register_globals, display_errors, and log_errors

Le direttive di configurazione che controllano la modalità sicura sono:
safe_mode = Off 
open_basedir = 
safe_mode_exec_dir = 
safe_mode_allowed_env_vars = PHP_ 
safe_mode_protected_env_vars = LD_LIBRARY_PATH 
disable_functions =

Quando safe_mode è attiva (on), il PHP verifica se il proprietario dello script in esecuzione e il proprietario del file su cui si sta operando con una funzione sui file, coincidono. Per esempio:
-rw-rw-r--    1 rasmus   rasmus       33 Jul  1 19:20 script.php 
-rw-r--r--    1 root     root       1116 May 26 18:01 /etc/passwd
Eseguendo questo script.php
<?php
 readfile('/etc/passwd'); 
?>
results in this error when Safe Mode is enabled:
Warning: SAFE MODE Restriction in effect. The script whose uid is 500 is not 
allowed to access /etc/passwd owned by uid 0 in /docroot/script.php on line 2

Se, invece di safe_mode, viene definita una directory open_basedir allora tutte le operazioni sui file saranno limitate ai file sottostanti la directory specificata. Per esempio (nel file httpd.conf di Apache):
<Directory /docroot>
  php_admin_value open_basedir /docroot 
</Directory>
If you run the same script.php with this open_basedir setting then this is the result:
Warning: open_basedir restriction in effect. File is in wrong directory in 
/docroot/script.php on line 2

È possibile inoltre disabilitare le singole funzioni. Se si aggiunge la seguente riga al file php.ini:
disable_functions readfile,system
Then we get this output:
Warning: readfile() has been disabled for security reasons in 
/docroot/script.php on line 2


Funzioni limitate/disabilitate dalla modalità sicura (safe-mode)

Questo è un elenco probabilmente ancora incompleto e forse non esatto delle funzioni limitate da Safe Mode.

Tabella 42-2. Funzioni limitate dalla modalità sicura

FunzioniLimitazioni
dbmopen()Controlla che i file o le directory su cui si sta lavorando, abbiano lo stesso UID dello script che è in esecuzione.
dbase_open()Controlla che i file o le directory su cui si sta lavorando, abbiano lo stesso UID dello script che è in esecuzione.
filepro()Controlla che i file o le directory su cui si sta lavorando, abbiano lo stesso UID dello script che è in esecuzione.
filepro_rowcount()Controlla che i file o le directory su cui si sta lavorando, abbiano lo stesso UID dello script che è in esecuzione.
filepro_retrieve()Controlla che i file o le directory su cui si sta lavorando, abbiano lo stesso UID dello script che è in esecuzione.
ifx_*()sql_safe_mode restrictions, (!= Safe Mode)
ingres_*()sql_safe_mode restrictions, (!= Safe Mode)
mysql_*()sql_safe_mode restrictions, (!= Safe Mode)
pg_loimport()Controlla che i file o le directory su cui si sta lavorando, abbiano lo stesso UID dello script che è in esecuzione.
posix_mkfifo()Controlla che la directory su cui si sta lavorando, abbia lo stesso UID dello script che è in esecuzione.
putenv()Obbedisce le direttive del file ini safe_mode_protected_env_vars e safe_mode_allowed_env_vars. Vedere la documentazione relativa on putenv()
move_uploaded_file()Controlla che i file o le directory su cui si sta lavorando, abbiano lo stesso UID dello script che è in esecuzione.
chdir()Controlla che la directory su cui si sta lavorando, abbia lo stesso UID dello script che è in esecuzione.
dl()Questa funzione è disabilitata nella modalitàsafe-mode
backtick operatorQuesta funzione è disabilitata nella modalitàsafe-mode
shell_exec() (functional equivalent of backticks)Questa funzione è disabilitata nella modalitàsafe-mode
exec()You can only execute executables within the safe_mode_exec_dir. For practical reasons it's currently not allowed to have .. components in the path to the executable.
system()You can only execute executables within the safe_mode_exec_dir. For practical reasons it's currently not allowed to have .. components in the path to the executable.
passthru()You can only execute executables within the safe_mode_exec_dir. For practical reasons it's currently not allowed to have .. components in the path to the executable.
popen()You can only execute executables within the safe_mode_exec_dir. For practical reasons it's currently not allowed to have .. components in the path to the executable.
mkdir()Controlla che la directory su cui si sta lavorando, abbia lo stesso UID dello script che è in esecuzione.
rmdir()Controlla che i file o le directory su cui si sta lavorando, abbiano lo stesso UID dello script che è in esecuzione.
rename()Controlla che i file o le directory su cui si sta lavorando, abbiano lo stesso UID dello script che è in esecuzione. Controlla che la directory su cui si sta lavorando, abbia lo stesso UID dello script che è in esecuzione.
unlink()Controlla che i file o le directory su cui si sta lavorando, abbiano lo stesso UID dello script che è in esecuzione. Controlla che la directory su cui si sta lavorando, abbia lo stesso UID dello script che è in esecuzione.
copy()Controlla che i file o le directory su cui si sta lavorando, abbiano lo stesso UID dello script che è in esecuzione. Controlla che la directory su cui si sta lavorando, abbia lo stesso UID dello script che è in esecuzione. (on source and target)
chgrp()Controlla che i file o le directory su cui si sta lavorando, abbiano lo stesso UID dello script che è in esecuzione.
chown()Controlla che i file o le directory su cui si sta lavorando, abbiano lo stesso UID dello script che è in esecuzione.
chmod()Controlla che i file o le directory su cui si sta lavorando, abbiano lo stesso UID dello script che è in esecuzione. In addition, you cannot set the SUID, SGID and sticky bits
touch()Controlla che i file o le directory su cui si sta lavorando, abbiano lo stesso UID dello script che è in esecuzione. Controlla che la directory su cui si sta lavorando, abbia lo stesso UID dello script che è in esecuzione.
symlink()Controlla che i file o le directory su cui si sta lavorando, abbiano lo stesso UID dello script che è in esecuzione. Controlla che la directory su cui si sta lavorando, abbia lo stesso UID dello script che è in esecuzione. (note: only the target is checked)
link()Controlla che i file o le directory su cui si sta lavorando, abbiano lo stesso UID dello script che è in esecuzione. Controlla che la directory su cui si sta lavorando, abbia lo stesso UID dello script che è in esecuzione. (note: only the target is checked)
getallheaders()In Safe Mode, headers beginning with 'authorization' (case-insensitive) will not be returned. Warning: this is broken with the aol-server implementation of getallheaders()!
Qualsiasi funzione che utilizza php4/main/fopen_wrappers.c ??


Capitolo 43. Utilizzo di PHP da linea di comando

A partire dalla versione 4.3.0, il PHP supporta un nuovo tipo di SAPI (Server Application Programming Interface) chiamata CLI che significa Interfaccia per la Linea di Comando (Command Line Interface). Come il nome stesso suggerisce, questo tipo di SAPI è mirato allo sviluppo di applicazioni shell (o desktop) con PHP. Esistono alcune differenze tra la CLI SAPI e le altre SAPI; queste saranno illustrate nel corrente capitolo. Val la pena ricordare che CLI e CGI sono differenti SAPI sebbene condividano il medesimo comportamento in diverse situazioni.

La CLI SAPI è stata rilasciata per la prima volta con PHP 4.2.0, ma era ancora sperimentale e quindi doveva essere esplicitamente abilitata con --enable-cli nell'esecuzione di ./configure. A partire dal PHP 4.3.0 la CLI SAPI non viene più considerata sperimentale e quindi l'opzione --enable-cli è attivata per default. Vedere --disable-cli per disabilitare l'opzione.

Dal PHP 4.3.0, il nome, la posizione, e l'esistenza di eseguibili CLI/CGI differirà in base a come il PHP sarà installato sul sistema. Per default quando si esegue il make, si compila sia la versione CLI sia la versione CGI e saranno poste rispettivamente in sapi/cgi/php e sapi/cli/php a partire dalla directory dei sorgenti. Occorre notare che entrambi gli eseguibili sono chiamati php. Ciò che accade durante l'esecuzione di dipende dalla linea di configurazione. Se durante la configurazione si è scelto un modulo SAPI, tipo apxs, o si è attivato --disable-cgi, l'eseguibile CLI viene copiato in durante make install, altrimenti in questa cartella sarà posto l'eseguibile CGI. Così, per esempio, se si ha come parametro di configurazione --with--apxs allora l'eseguibile CLI sarà copiato in {PREFIX}/bin/php durante make install. Se si vuole evitare l'installazione dell'eseguibile CGI, utilizzare make install-cli dopo make install. In alternativa si può specificare --disable-cgi nella linea di configurazione.

Nota: Poichè sia --enable-cli sia --enable-cgi sono abilitati per default, avere semplicemente --enable-cli nella linea di configurazione non significa necessariamente che l'eseguibile CLI sia copiato come {PREFIX}/bin/php con l'esecuzione di make install.

Nel pacchetto per Windows, nelle versioni tra PHP 4.2.0 e PHP 4.2.3, l'eseguibile CLI era presente come php-cli.exe, nella medesima cartella della versione CGI php.exe. A partire dal PHP 4.3.0 nel pacchetto per Windows la versione CLI viene distribuita come php.exe in una cartella a parte chiamata cli, avendo perciò cli/php.exe. A partire dal PHP 5, la versione CLI viene inserita nella cartella principale, con il nome php.exe. La versione CGI sarà chiamata php-cgi.exe.

Sempre dal PHP 5, sarà introdotto un nuovo file chiamato php-win.exe. Questo è equivalente alla versione CLI, tranne che php-win non visualizzerà nulla e quindi non vi sarà la finestra di console (non compare la fienstra dos nello schermo). Questo comportamento è stato ripreso da php-gtk. Si dovrebbe configurare il PHP con --enable-cli-win32.

Quale SAPI ho?: Da shell, digitando php -v si avrà l'informazione di quale php si tratta, CGI o CLI. Vedere anche la funzione php_sapi_name()e la costante PHP_SAPI per dettagli.

Nota: Una pagina stile man di Unix è stata aggiunta in PHP 4.3.2. La si può visualizzare digitando man php da linea di comando.

Le principali differenze tra la CLI SAPI e le altre SAPI sono:

  • A differenza di CGI SAPI, non sono inviate in output delle intestazioni.

    Mentre nella CGI SAPI esiste un modo per sopprimere le intestazioni, nella CLI SAPI non si ha una opzione per abilitare le intestazioni.

    Per default CLI parte in modalità silenziosa, si è mantenuto, comunque, l'opzione -q e --no-header per motivi di compatibilità; in questo modo si possono utlizzare i vecchi script CGI.

    Non cambia la directory di lavoro in quella dello script. (E' rimasta l'opzione -C e --no-chdir per compatibilità)

    Messaggi di errore in formato testo (non formattati in HTML).

  • Esistono, inoltre, alcune direttive del php.ini che sono forzate nell'impostazione dalla CLI SAPI poichè non hanno senso nell'ambiente di shell:

    Tabella 43-1. Direttive del php.ini forzate

    DirettivaCLI SAPI valore di defaultCommento
    html_errorsFALSE E' difficile leggere i messaggi di errore nella shell quando sono affogati in tag HTML prive di significato; pertanto il default della direttiva è impostato a FALSE.
    implicit_flushTRUE E' desiderabile che ogni tipo di output proveniente da print(), echo() e simili sia scritto immediatamente e non venga bufferizzato. Tuttavia è ancora possibile utilizzare le funzioni di controllo dell'output se si desidera ritardare o manipolare lo standard output.
    max_execution_time0 (unlimited) Considerate le svariate possibilità offerte da PHP nell'ambiente di shell, il tempo massimo di esecuzione è stato impostato a infinito. Mentre nelle applicazione scritte per il web i tempi di esecuzione sono rapidi, le applicazioni di shell tendono ad avere tempi di esecuzione molto più lunghi.
    register_argc_argvTRUE

    Poichè è impostato a TRUE nella CLI SAPI si ha sempre la possibilità di accedere alla variabili argc (numero di argomenti passati all'applicazione) e argv (matrice degli argumenti).

    A partire da PHP 4.3.0, quando si utilizza la CLI SAPI le variabili PHP $argc e $argv sono sempre registrate e valorizzate in modo appropriato. Prima di questa versione la creazione di queste variabili era coerente con il comportamento delle versioni CGI e MODULO le quali richiedevano che la direttiva PHP register_globals fosse impostata a on. A prescindere dalla versione o dall'impostazione di register_globals si può sempre accedere alle variabili $_SERVER o $HTTP_SERVER_VARS. Esempio: $_SERVER['argv']

    Nota: Queste direttive non possono essere inizializate con altri valori dal file di configurazione php.ini o da uno personalizzato (se specifictao). Questa è una limitazione perchè questi valori di default sono applicati dopo avere esaminato tutti i file di configurazione. Tuttavia i loro valori possono essere cambiati durante l'esecuzione (operazione che non ha senso per queste direttive, ad esempio register_argc_argv).

  • Per potere lavorare meglio con le shell, sono state definite le seguenti costanti:

    Tabella 43-2. Costanti specifiche per CLI

    CostanteDescrizione
    STDIN Un flusso già aperto allo stdin. Questo evita di aprirlo con
    <?php
    $stdin = fopen('php://stdin', 'r');
    
    ?>
    Se si desidera leggere una singola linea dallo stdin, si può utilizzare
    <?php 
    $line = trim(fgets(STDIN)); // reads one line from STDIN 
    fscanf(STDIN, "%d\n", $number); // reads number from STDIN 
    ?>
    STDOUT Un flusso già aperto allo stdout. Questo evita di aprirlo con
    <?php
    
    $stdout = fopen('php://stdout', 'w');
    
    ?>
    STDERR Un flusso già aperto allo stderr. Questo evita di aprirlo con
    <?php
    
    $stderr = fopen('php://stderr', 'w');
    
    ?>

    Stante a quanto descritto non occorre più aprire in autonomia flussi per, ad esempio, lo stderr, ma semplicemente si può usare le costanti anzichè una nuova risorsa di flusso:
    php -r 'fwrite(STDERR, "stderr\n");'
    Non occorre chiudere esplicitamente questi flussi, saranno chiusi automaticamente dal PHP alla fine dello script.

  • La CLI SAPI non cambia la directory corrente in quella dello script eseguito!

    Il seguente esempio illustra la diferenza rispetto alla CGI SAPI:
    <?php
    // Semplice esempio di test chiamato test.php
    echo getcwd(), "\n";
    ?>

    Quando si usa la versione CGI, si avrà il seguente output:
    $ pwd
    /tmp
    
    $ php -q another_directory/test.php
    /tmp/another_directory
    Questo evidenzia chiaramente come il PHP cambi la directory corrente con quella in cui si trova lo script.

    Utilizzando la versione CLI SAPI abbiamo:
    $ pwd
    /tmp
    
    $ php -f another_directory/test.php
    /tmp
    Questo permette una grande flessibilità nello scrivere tools in PHP.

    Nota: La CGI SAPI supporta il comportamento della CLI SAPI attivando l'opzione -C quando viene eseguito da linea di comando.

L'elenco completo delle opzioni del PHP disponibili da linea di comando può essere visualizzato in qualsiasi momento eseguendo il PHP con l'opzione -h:
Usage: php [options] [-f] <file> [args...]
       php [options] -r <code> [args...]
       php [options] [-- args...]
  -s               Display colour syntax highlighted source.
  -w               Display source with stripped comments and whitespace.
  -f <file>        Parse <file>.
  -v               Version number
  -c <path>|<file> Look for php.ini file in this directory
  -a               Run interactively
  -d foo[=bar]     Define INI entry foo with value 'bar'
  -e               Generate extended information for debugger/profiler
  -z <file>        Load Zend extension <file>.
  -l               Syntax check only (lint)
  -m               Show compiled in modules
  -i               PHP information
  -r <code>        Run PHP <code> without using script tags <?..?>
  -h               This help

  args...          Arguments passed to script. Use -- args when first argument 
                   starts with - or script is read from stdin

La vesione CLI SAPI ha tre differenti modi per eseguire il codice PHP:

  1. Dire al PHP di eseguire certi file.

    php my_script.php
    
    php -f my_script.php
    Entrambi i metodi (con o senza l'opzione -f) eseguono il file my_script.php. Si può scegliere qualsiasi nome per lo script da eseguire - non è obbligatorio che gli script PHP finiscano con l'estensione .php, ma possono avere qualsiasi nome o estensione che si desideri.

  2. Passare il codice PHP da eseguire direttamente da linea di comando.

    php -r 'print_r(get_defined_constants());'
    Occorre prestare molta attenzione alla sostituzione delle variabili di shell e all'uso degli apici.

    Nota: Osservando con attenzione l'esempio si nota l'assenza dei tag di inizio e fine! L'opzione -r non li richiede. L'uso dei tag genera un errore di parsing.

  3. Si può passare il codice PHP da eseguire via standard input (stdin).

    Questo da la possibilità di generare dinamicamente del codice PHP e passarlo all'eseguibile, come illustrato nel seguente esempio (fittizio):
    $ some_application | some_filter | php | sort -u >final_output.txt

Non si possono combinare tra loro questi tre metodi di esecuzione del codice.

Come qualsiasi applicazione di shell, anche l'eseguibile PHP accetta diversi argomenti, ma anche lo script PHP può ricevere argomenti. Il numero degli argomenti passabili allo script non è limitato dal PHP (si rammenta che la shell ha un limite nel numero di caratteri che possono essere passati; solitamente non si raggiunte questo limite). Gli argomenti passati allo script sono disponibili nell'array $argv. L'indice zero contiene sempre il nome dello script (che è - nel caso in cui il codice PHP provenda o dallo standard input o dalla linea di comando con l'opzione -r). La seconda variabile globale registrata è $argc la quale contiene il numero degli elementi nella matrice $argv (non è il numero degli argomenti passati allo script).

Fino a quando gli argomenti passati allo script non iniziano con il carattere - non si deve prestare alcuna cautela. Tuttavia se si passa allo script argomenti che iniziano con - si hanno dei problemi perchè lo stesso PHP ritiene di doverli gestire. Per evitare ciò occorre utilizzare il separatore di argomenti --. Dopo che il PHP ha incontrato questo separatore, ogni argomento verrà passato direttamente allo script.

# Questo non visualizzerà il codice passato, ma l'elenco delle opzioni
$ php -r 'var_dump($argv);' -h
Usage: php [options] [-f] <file> [args...]
[...]

# Questo passerà il '-h'allo script ed eviterà al PHP di visualizzare le opzioni
$ php -r 'var_dump($argv);' -- -h
array(2) {
  [0]=>
  string(1) "-"
  [1]=>
  string(2) "-h"
}

Tuttvia esiste un'altro modo per eseguire gli script PHP. Si può scrivere uno script la cui prima riga inizi con #!/usr/bin/php. Seguendo questa regola si può posizionare il normale codice PHP tra i tag di apertura e chiusura del PHP. Una volta impostati correttamente gli attributi del file (ad esempio chmod +x test) lo script può essere eseguito come una normale shell o script perl:
#!/usr/bin/php
<?php
var_dump($argv);
?>
Assumento che questo file sia chiamato test nella directory corrente, si può eseguire:
$ chmod +x test
$ ./test -h -- foo
array(4) {
  [0]=>
  string(6) "./test"
  [1]=>
  string(2) "-h"
  [2]=>
  string(2) "--"
  [3]=>
  string(3) "foo"
}
Come si può notare in questo caso non vi è necessità di prestare attenzione nel passare i parametri che iniziano con -.

I parametro lunghi sono disponibili dal PHP 4.3.3.

Tabella 43-3. Opzioni della linea di comando,

ParametroParametro lungoDescrizione
-s--syntax-highlight

Visualizza il sorgente con sintassi colorata.

Questa opzione utilizza il meccanismo interno di parsing dei file e produce una versione HTML del sorgente e la dirige verso lo standard output. Occore notare che questa funzione genera dei blocchi di tag HTML <code> [...] </code> e non le intestazione HTML.

Nota: Questa opzione non funziona abbinata all'opzione -r.

-s--syntax-highlighting

Alias di --syntax-highlight.

-w--strip

Visualizza il sorgente senza gli spazi e i commenti.

Nota: Questa opzione non funziona abbinata all'opzione -r.

-f--file

Analizza ed esegue il file passato con l'opzione -f. Questo parametro è opzionale e può essere omesso. Basta fornire il nome del file da eseguire.

-v--version

Visualizza le versioni di PHP, PHP SAPI, e Zend nello standard output, ad esempio:
$ php -v
PHP 4.3.0 (cli), Copyright (c) 1997-2002 The PHP Group
Zend Engine v1.3.0, Copyright (c) 1998-2002 Zend Technologies

-c--php-ini

Con questa opzione si può sia specificare la directory in cui cercare il php.ini o si può specificare un file INI personalizzato (che non deve necessariamente chiamarsi php.ini), ad esempio:
$ php -c /custom/directory/ my_script.php

$ php -c /custom/directory/custom-file.ini my_script.php
Se non si specifica questa opzione, il file viene ricercato nelle directory di default.

-n--no-php-ini

Ignora del tutto il php.ini. Opzione disponibile dal PHP 4.3.0.

-d--define

Questa opzione permette di impostare valori personalizzati per qualsiasi delle direttive di configurazione previste in php.ini. La sintassi è:
-d configuration_directive[=value]

Esempi (le linee vanno a capo per motivi di layout):
# Omettendo il valore si imposta la direttiva data a "1"
$ php -d max_execution_time 
      -r '$foo = ini_get("max_execution_time"); var_dump($foo);'
string(1) "1"

# Passando un valore vuoto si imposta la direttiva a ""
php -d max_execution_time= 
    -r '$foo = ini_get("max_execution_time"); var_dump($foo);'
string(0) ""

# La direttiva di configurazione viene impostata a qualsiasi valore passato dopo il carattere '='
$  php -d max_execution_time=20 
       -r '$foo = ini_get("max_execution_time"); var_dump($foo);'
string(2) "20"
$  php 
       -d max_execution_time=doesntmakesense 
       -r '$foo = ini_get("max_execution_time"); var_dump($foo);'
string(15) "doesntmakesense"

-a--interactive

Esegue il PHP in modo interattivo.

-e--profile-info

Genera informazioni estese per il debugger/profiler.

-z--zend-extension

Carica l'estensione Zend. Soltano se si fornisce un nome di file, il PHP tenta di caricare l'estensione dal corrente percorso di default delle librerie (solitamente, sui sistemi Linux, /etc/ld.so.conf). Se si fornisce un nome di file con percorso assoluto, ls libreria non sarà cercata nella directory di default. Un nome di file con percorso relativo indica al PHP di tentare di caricare l'estensione con percorso relativo alla directory corrente.

-l--syntax-check

Questa opzione fornisce un metodo pratico per eseguire un controllo sintattico di un dato codice PHP. Se il controllo ha successo, verrà visualizzato il testo No syntax errors detected in <filename> e alla shell sarà restituito il codice 0. Se si rilevano errori si avrà il testo Errors parsing <filename>, inoltre si avranno anche i messaggi di errore del parser ed alla shell sarà restituito il codice 255.

Questa opzione non rileva errori fatali (tipo funzioni non definite). Occorre utilizzare l'opzione -f se si desidera rilevare gli errori fatali.

Nota: Questa opzione non è abbinabile all'opzione -r.

-m--modules

Utilizzare questa opzione per visualizzare i moduli PHP e di Zend integrati (e quindi caricati):
$ php -m
[PHP Modules]
xml
tokenizer
standard
session
posix
pcre
overload
mysql
mbstring
ctype

[Zend Modules]

-i--info Questa opzione della linea di comando richiama la funzione phpinfo(), e ne visualizza il risultato. Se il PHP non funziona correttamente, è opportuno utilizzare php -i per verificare se sono visualizzati messaggi di errore prima o al posto della tabella con le informazioni. Fare attenzione quando si usa la modalità CGI, l'output è in formato HTML e quindi abbastanza abbondante.
-r--run

Questa opzione permette l'esecuzione di codice PHP direttamente da linea di comando. I tag PHP di apertura e di chiusura (<?php e ?>) non sono necessari anzi, se presenti, causano un errore del parser.

Nota: Quando si utilizza questo metodo occorre prestare attenzione ad evitare collisioni con la sostituzione delle varibili eseguita dalla shell sulla linea di comando.

Ecco un esempio che visualizza un errore di parsing
$ php -r "$foo = get_defined_constants();"
Command line code(1) : Parse error - parse error, unexpected '='
In questo caso il problema è dovuto alla sostituzione della variabile eseguita da sh/bash anche quando si usano i doppi apici ". Poichè la viriabile $foo non è definita, essa verrà espansa con 'niente' generando il seguente codice PHP:
$ php -r " = get_defined_constants();"
Il metodo corretto richiede l'uso dell'apice singolo '. Le variabili racchiuse in stringhe delimite dall'apice singolo non vengono espanse da sh/bash.
$ php -r '$foo = get_defined_constants(); var_dump($foo);'
array(370) {
  ["E_ERROR"]=>
  int(1)
  ["E_WARNING"]=>
  int(2)
  ["E_PARSE"]=>
  int(4)
  ["E_NOTICE"]=>
  int(8)
  ["E_CORE_ERROR"]=>
  [...]
Se si utilizzano shell differenti rispetto a sh/bash, si potrebbe incorrere in altri problemi. In tal caso aprite una segnalazione di errore a http://bugs.php.net/ o inviate una mail a phpdoc@lists.php.net. Tuttavia si può facilmente incorrere in problemi nell'avere variabili di shell nel codice o nell'utilizzare le barre rovesciate (backslash) per l'escape. Siete avvertiti.

Nota: L'opzione -r è disponibile solo nella CLI SAPI e non nella CGI SAPI.

-h--help Con questa opzione si ha l'elenco dei comandi di linea ed una breve descrizione di questi.
-?--usage Alias di --help.

L'eseguibile PHP può essere utilizzato per eseguire script PHP in modo indipendente dal server web. Se ci si trova su sistemi Unix, si può aggiungere una prima linea speciale allo script PHP e renderlo eseguibile, in questo modo il sistema sa quale programma deve interpretare lo script. Sui sistemi Windows si può associare php.exe all'estensione .php, o si può scrivere un batch per eseguire gli script tramite PHP. La prima riga inserita per i sistemi Unix non crea problemi in Windows, in questo modo si possono scrivere batch multi-piattaforma. Seguirà un semplice esempio di programma PHP da linea di comando.

Esempio 43-1. Script sviluppato per essere esguito da linea di comando (script.php)

#!/usr/bin/php
<?php

if ($argc != 2 || in_array($argv[1], array('--help', '-help', '-h', '-?'))) {
?>

Questo è uno script PHP da linea di comando con una opzione.

  Utilizzo:
  <?php echo $argv[0]; ?> <opzione>

  <opzione> può essere qualsiasi parola che si desidera
  stampata. Con --help, -help, -h,
  o -? si ottiene questo aiuto.
<?php
} else {
    echo $argv[1];
}
?>

Nello script precedente, abbiamo utilizzato la prima riga per indicare che questo file deve essere interpretato dal PHP. Poichè qui lavoriamo con la versione CLI non vengono prodotte intestazioni HTTP. Esistono due variabili che si possono utilizzare nelle applicazioni PHP da linea di comando: $argc e $argv. La prima è il numero di argomenti più uno (il nome dello script). La seconda è una matrice contenente gli argomenti, iniziando dal nome dello script all'indice zero ($argv[0]).

Nel programma precedente abbiamo verificato se i parametri passati erano di più o di meno di uno. Inoltre se l'argomento è --help, -help, -h oppure -?, si visualizza un messaggio di aiuto, visualizzando in modo dinamico il nome dello script. Se si riceve un argomento differente questo sarà visualizzato.

Se si desidera eseguire lo script precedente su Unix, occorre, per prima cosa, renderlo eseguibile, e quindi richiamarlo con script.php echothis oppure script.php -h. Su Windows occorre scrivere un batch per ottenere questo risultato:

Esempio 43-2. File batch per eseguire uno script PHP da linea di comando (script.bat)

@c:\php\cli\php.exe script.php %1 %2 %3 %4

Assumendo che programma precedente sia chiamato script.php, che la versione CLI di php.exe sia in c:\php\cli\php.exe questo batch eseguirà lo script con le opzioni passate: script.bat echothis oppure script.bat -h.

Vedere anche la documentazione del modulo Readline per informazioni su funzioni che possono essere utilizzate per migliorare le applicazioni da linea di comando.

VI. Guida Funzioni

Sommario
I. Funzioni Apache
II. Advanced PHP debugger
III. Funzioni di Array
IV. Funzioni Aspell [deprecated]
V. Funzioni Matematiche BCMath a precisione arbitraria
VI. PHP bytecode Compiler
VII. Funzioni di compressione Bzip2
VIII. Funzioni Calendar
IX. Funzioni API CCVS [deprecate]
X. Classkit Functions
XI. Funzioni per Classi/Oggetti
XII. Funzioni di supporto COM per Windows
XIII. Funzioni ClibPDF
XIV. Funzioni di Crack
XV. Funzioni di tipo dei caratteri
XVI. Funzioni CURL, Client URL Library
XVII. Funzioni di pagamento Cybercash
XVIII. Funzioni di amministrazione Cyrus IMAP
XIX. Funzioni di Data e Ora
XX. Database (dbm-style) Abstraction Layer Functions
XXI. Funzioni dBase
XXII. Funzioni DBM
XXIII. DB++ Functions
XXIV. dbx Functions
XXV. Funzioni per l'IO diretto
XXVI. Funzioni per le directory
XXVII. Funzioni DOM
XXVIII. Funzioni DOM XML
XXIX. Funzioni .NET
XXX. Funzioni di gestione degli errori e di logging
XXXI. Funzioni per l'esecuzione di programmi
XXXII. Exif Functions
XXXIII. File Alteration Monitor Functions
XXXIV. FrontBase Functions
XXXV. Funzioni Forms Data Format
XXXVI. Funzioni filePro
XXXVII. Filesystem Functions
XXXVIII. Funzioni FriBiDi
XXXIX. Funzioni FTP
XL. Function Handling Functions
XLI. Gettext
XLII. Funzioni GMP
XLIII. Funzioni HTTP
XLIV. Hyperwave Functions
XLV. Hyperwave API Functions
XLVI. Funzioni Firebird/InterBase
XLVII. ICAP Functions [deprecated]
XLVIII. Iconv
XLIX. ID3 Functions
L. Informix Functions
LI. Funzioni di Amministrazione IIS
LII. Funzioni per le immagini
LIII. IMAP, POP3 and NNTP Functions
LIV. PHP Opzioni&Informazioni
LV. Ingres II Functions
LVI. IRC Gateway Functions
LVII. PHP / Java Integration
LVIII. LDAP Functions
LIX. libxml Functions
LX. Funzioni LZF
LXI. Funzioni di Mail
LXII. mailparse Functions
LXIII. Funzioni Matematiche
LXIV. MaxDB PHP Extension
LXV. Multibyte String Functions
LXVI. MCAL Functions
LXVII. Mcrypt Encryption Functions
LXVIII. MCVE Payment Functions
LXIX. Memcache Functions
LXX. Mhash Functions
LXXI. Mimetype Functions
LXXII. Ming functions for Flash
LXXIII. Miscellaneous Functions
LXXIV. mnoGoSearch Functions
LXXV. Mohawk Software Session Handler Functions
LXXVI. mSQL Functions
LXXVII. Funzioni per Microsoft SQL Server
LXXVIII. muscat Functions
LXXIX. MySQL Functions
LXXX. Improved MySQL Extension
LXXXI. Ncurses Terminal Screen Control Functions
LXXXII. Funzioni di rete
LXXXIII. YP/NIS Functions
LXXXIV. Lotus Notes Functions
LXXXV. NSAPI-specific Functions
LXXXVI. Object Aggregation/Composition Functions
LXXXVII. Funzioni Oracle 8
LXXXVIII. OpenAL Audio Bindings
LXXXIX. OpenSSL Functions
XC. Funzioni Oracle
XCI. Output Control Functions
XCII. Proprietà object e method call overloading
XCIII. Ovrimos SQL Functions
XCIV. Parsekit Functions
XCV. Process Control Functions
XCVI. Funzioni per le espressioni regolari (Perl compatibili)
XCVII. PDF functions
XCVIII. PDO Functions
XCIX. Verisign Payflow Pro Functions
C. Funzioni PostgreSQL
CI. Funzioni POSIX
CII. Funzioni per le Stampanti
CIII. Pspell Functions
CIV. Funzioni qtdom
CV. Rar Functions
CVI. GNU Readline
CVII. GNU Recode Functions
CVIII. Funzioni per le espressioni regolari (POSIX estesa)
CIX. Funzioni per i semafori, la memoria condivisa ed IPC
CX. SESAM Database Functions
CXI. Funzioni di gestione della sessione
CXII. Funzioni relative alla memoria condivisa
CXIII. SimpleXML functions
CXIV. Funzioni per SNMP
CXV. SOAP Functions
CXVI. Funzioni relative ai Socket
CXVII. Standard PHP Library (SPL) Functions
CXVIII. SQLite
CXIX. Secure Shell2 Functions
CXX. Stream Functions
CXXI. Stringhe
CXXII. Shockwave Flash Functions
CXXIII. Sybase Functions
CXXIV. TCP Wrappers Functions
CXXV. Tidy Functions
CXXVI. Tokenizer Functions
CXXVII. Funzioni ODBC (Unificate)
CXXVIII. URL Functions
CXXIX. Funzioni di Variabili
CXXX. Funzioni vpopmail
CXXXI. Funzioni W32api
CXXXII. WDDX Functions
CXXXIII. xattr Functions
CXXXIV. xdiff Functions
CXXXV. Funzioni relative al parser XML
CXXXVI. Funzioni XML-RPC
CXXXVII. XSL functions
CXXXVIII. Funzioni XSLT
CXXXIX. YAZ Functions
CXL. Funzioni per File Zip (Accesso di Sola Lettura)
CXLI. Funzioni di compressione Zlib

I. Funzioni Apache

Introduzione

Queste funzioni sono disponibili unicamente quando PHP è eseguito come modulo Apache.

Nota: A partire dal PHP 4.3.2, PATH_TRANSLATED non viene più impostata i mplicitamente sotto Apache 2 SAPI, diversamente da quanto accadeva in Apache 1, dove questa veniva impostata allo stesso valore di SCRIPT_FILENAME qualora non fosse già riempita. Questa modifica è stata fatta per adeguarsi allla specifica CGI che impone che PATH_TRANSLATED esista solo se PATH_INFO sia definita.

Gli utilizzatori di Apache 2 possono usare AcceptPathInfo = On in httpd.conf per definire PATH_INFO.


Installazione

Per l'installazione di PHP su Apache vedere il capitolo sull'installazione.


Configurazione di Runtime

Il comportamento del modulo Apache per PHP è influenzato dalle impostazioni in php.ini. Le impostazioni di configurazione del php.ini possono essere scavalcate attraverso le impostazioni php_flag nel file di configurazione del server o nei file .htaccess locali.

Esempio 1. disabilitazione dell'interprete PHP in una directory mediante .htaccess

php_flag engine off

Tabella 1. Opzioni di configurazione di Apache

NomeDefaultModificabileFunzione
engineOnPHP_INI_ALLaccende o spegne l'interprete PHP
child_terminateOffPHP_INI_ALL decide se gli script PHP possono richiedere la terminazione dei processi figli alla fine della richiesta HTTP, vedere anche apache_child_terminate()
last_modifiedOffPHP_INI_ALLmanda la data di modifica degli script nell'header Last-Modified:
xbithackOffPHP_INI_ALLinterpreta i file con il bit di esecuzione impostato, a prescindere dalla loro estensione

Breve descrizione dei parametri di configurazione.

engine boolean

Questa direttiva è utile solo nella versione di PHP compilata come modulo di Apache. Viene usata dai siti che vogliono spegnere e accendere il parsing PHP in base alla directory o al virtual server corrente. Inserendo engine off nel posto appropriato nel file httpd.conf, il PHP può essere abilitato o disabilitato.


Tipi di risorse

Questa estensione non definisce alcun tipo di risorsa.


Costanti predefinite

Questa estensione non definisce alcuna costante.

Sommario
apache_child_terminate -- Interrompe il processo apache dopo la presente richiesta
apache_get_modules --  Get a list of loaded Apache modules
apache_get_version --  Fetch Apache version
apache_getenv -- Get an Apache subprocess_env variable
apache_lookup_uri --  Esegue una richiesta parziale della URI specificata e restituisce tutte le informazioni
apache_note -- Ricava o imposta una variabile nella tabella notes di Apache
apache_request_headers -- Estrae tutti gli header della richiesta HTTP
apache_reset_timeout --  Reset the Apache write timer
apache_response_headers --  Estrae tutti gli header della risposta HTTP
apache_setenv -- Imposta una variabile Apache subprocess_env
ascii2ebcdic -- Traduce una stringa da ASCII a EBCDIC
ebcdic2ascii -- Traduce una stringa da string EBCDIC ad ASCII
getallheaders -- Estrae tutti gli header della richiesta HTTP
virtual -- Esegue una sotto-richiesta Apache

apache_child_terminate

(PHP 4 >= 4.0.5, PHP 5)

apache_child_terminate -- Interrompe il processo apache dopo la presente richiesta

Descrizione

bool apache_child_terminate ( void )

apache_child_terminate() informa il processo Apache che sta eseguendo la richiesta PHP corrente di terminare quando l'esecuzione del codice PHP è stata completata. Può essere usata per interrompere un processo dopo che sia stato eseguito uno script con alta occupazione di memoria dal momento che la memoria viene normalmente liberata internamente ma non restituita al sistema operativo.

Nota: La disponibilità di questa caratteristica è controllata dalal direttiva del php.ini child_terminate, che è impostata a off di default.

Questa caratteristica non è inoltre disponibile sulle versioni multithread di apache come, ad esempio, la versione win32.

Vedere anche exit().

apache_get_modules

(PHP 4 >= 4.3.2, PHP 5)

apache_get_modules --  Get a list of loaded Apache modules

Description

array apache_get_modules ( void )

This function returns an array with the loaded Apache modules.

Esempio 1. apache_get_modules() example

<?php
print_r(apache_get_modules());
?>

The above example will output something similar to:

Array
(
    [0] => core
    [1] => http_core
    [2] => mod_so
    [3] => sapi_apache2
    [4] => mod_mime
    [5] => mod_rewrite
)

Nota: This function is available only in Apache 2 handler. As of PHP 5, it is available also in Apache 2 filter and Apache 1.

apache_get_version

(PHP 4 >= 4.3.2, PHP 5)

apache_get_version --  Fetch Apache version

Description

string apache_get_version ( void )

apache_get_version() returns the version of Apache as string, or FALSE on failure.

Esempio 1. apache_get_version() example

<?php
$version = apache_get_version();
echo "$version\n";
?>

The above example will output something similar to:

Apache/1.3.29 (Unix) PHP/4.3.4

Nota: This function is available only in Apache 2 handler. As of PHP 4.3.4, it is available also in Apache 1 and as of PHP 5, it is available also in Apache 2 filter.

See also phpinfo().

apache_getenv

(PHP 4 >= 4.3.0, PHP 5)

apache_getenv -- Get an Apache subprocess_env variable

Description

string apache_getenv ( string variable [, bool walk_to_top] )

apache_getenv() returns the value of the Apache environment variable specified by variable, or FALSE on failure.

Nota: apache_getenv() is only defined when using Apache 2.

Esempio 1. apache_getenv() example

<?php
$ret = apache_getenv("SERVER_ADDR");
echo $ret;
?>

The example above shows how to retrieve the value of the Apache environment variable "SERVER_ADDR".

See also apache_setenv(), getenv() e Superglobals.

apache_lookup_uri

(PHP 3>= 3.0.4, PHP 4 , PHP 5)

apache_lookup_uri --  Esegue una richiesta parziale della URI specificata e restituisce tutte le informazioni

Descrizione

object apache_lookup_uri ( string nomefile )

Questa funzione esegue una richiesta parziale per una URI. Esegue l'operazione finché ottiene tutte le informazioni importanti sulla risorsa e restituisce queste informazioni in una classe. Le proprietà della classe restituita sono:

status
the_request
status_line
method
content_type
handler
uri
filename
path_info
args
boundary
no_cache
no_local_copy
allowed
send_bodyct
bytes_sent
byterange
clength
unparsed_uri
mtime
request_time

Esempio 1. esempio di apache_lookup_uri()

<?php
$info = apache_lookup_uri('index.php?var=value');
print_r($info);

if (file_exists($info->filename)) {
    echo 'file exists!';
}
?>

Questo esempio produrrà un risultato simile al seguente:

stdClass Object
(
    [status] => 200
    [the_request] => GET /dir/file.php HTTP/1.1
    [method] => GET
    [mtime] => 0
    [clength] => 0
    [chunked] => 0
    [content_type] => application/x-httpd-php
    [no_cache] => 0
    [no_local_copy] => 1
    [unparsed_uri] => /dir/index.php?var=value
    [uri] => /dir/index.php
    [filename] => /home/htdocs/dir/index.php
    [args] => var=value
    [allowed] => 0
    [sent_bodyct] => 0
    [bytes_sent] => 0
    [request_time] => 1074282764
)
file exists!

Nota: apache_lookup_uri() funziona solo quando PHP è installato come modulo Apache.

apache_note

(PHP 3>= 3.0.2, PHP 4 , PHP 5)

apache_note -- Ricava o imposta una variabile nella tabella notes di Apache

Descrizione

string apache_note ( string nome_nota [, string valore] )

apache_note() è una funzione specifica di Apache che ricava o imposta un valore nella tabella notes di una richiesta HTTP. Se viene invocata con un solo argomento restituisce il valore della nota nome_nota. Se viene chiamata con due argomenti, imposta il valore della nota nome_nota a valore e restituisce il valore precedente della nota nome_nota.

apache_request_headers

(PHP 4 >= 4.3.0, PHP 5)

apache_request_headers -- Estrae tutti gli header della richiesta HTTP

Descrizione

array apache_request_headers ( void )

apache_request_headers() restituisce un array associativo contenente tutti gli header HTTP nella richiesta corrente. Questa funzionalità è supportata solo quando PHP è un modulo di Apache.

Esempio 1. esempio di apache_request_headers()

<?php
$headers = apache_request_headers();

foreach ($headers as $header => $value) {
    echo "$header: $value <br />\n";
}
?>

Nota: Prima del PHP 4.3.0, apache_request_headers() si chiamava getallheaders(). Dopo il PHP 4.3.0, getallheaders() è un alias di apache_request_headers().

Nota: È possibile ottenere il valore delle variabili comuni CGI anche leggendole dalle variabili di ambiente; questo funziona indipendentemente dal fatto che si stia usando PHP come modulo Apache. Utilizzare phpinfo() per ottenere una lista di tutte le variabili d'ambiente disponibili.

Nota: Dal PHP 4.3.3 è possibile utilizzare questa funzione anche con il modulo server NSAPI dei server web Netscape/iPlanet/SunONE

Vedere anche apache_response_headers().

apache_reset_timeout

(no version information, might be only in CVS)

apache_reset_timeout --  Reset the Apache write timer

Description

bool apache_reset_timeout ( void )

apache_reset_timeout() resets the Apache write timer, which defaults to 300 seconds. With set_time_limit(0); ignore_user_abort(true) and periodic apache_reset_timeout() calls, Apache can theoretically run forever.

Restituisce TRUE in caso di successo, FALSE in caso di fallimento.

Nota: This functions is just available for Apache 1.

Nota: Questa funzione è disabilitata nella modalitàsafe-mode

apache_response_headers

(PHP 4 >= 4.3.0, PHP 5)

apache_response_headers --  Estrae tutti gli header della risposta HTTP

Descrizione

array apache_response_headers ( void )

Restituisce un array contenente tutti gli header della risposta HTTP di Apache. Questa funzione è disponibile solo nel PHP 4.3.0 o successivi.

Nota: Dal PHP 4.3.3 è possibile utilizzare questa funzione anche con il modulo server NSAPI dei server web Netscape/iPlanet/SunONE

Vedere anche getallheaders() e headers_sent().

apache_setenv

(PHP 4 >= 4.2.0, PHP 5)

apache_setenv -- Imposta una variabile Apache subprocess_env

Descrizione

int apache_setenv ( string varibile, string valore [, bool vai_in_cima] )

apache_setenv() imposta il valore della variabile di environment di Apache specificata da variabile.

Nota: Quando si imposta una variabile di environment di Apache, la corrispondente variabile $_SERVER non viene cambiata.

Esempio 1. Impostazione di una variabile di environment di Apache utilizzando apache_setenv()

<?php
apache_setenv("EXAMPLE_VAR", "Valore di prova");
?>

apache_setenv() può essere usata con apache_getenv() su pagine separate o impostare variabili da passare a Server Side Includes (.shtml) chr siano stati inclusi negli script PHP.

Vedere anche apache_getenv().

ascii2ebcdic

(PHP 3>= 3.0.17)

ascii2ebcdic -- Traduce una stringa da ASCII a EBCDIC

Descrizione

int ascii2ebcdic ( string ascii_str )

ascii2ebcdic() è una funzione Apache che è disponibile solo su sistemi operativi basati sull'EBCDIC (OS/390, BS2000). Traduce la stringa codificata in ASCII ascii_str nella sua rappresentazione equivalente EBCDIC (proteggendo i dati binari), e restituisce il risultato.

Vedere anche la funzione duale ebcdic2ascii()

ebcdic2ascii

(PHP 3>= 3.0.17)

ebcdic2ascii -- Traduce una stringa da string EBCDIC ad ASCII

Descrizione

int ebcdic2ascii ( string ebcdic_str )

ebcdic2ascii() è una funzione Apache che è disponibile solo su sistemi operativi basati su EBCDIC (OS/390, BS2000). Traduce la stringa codificata in EBCDIC ebcdic_str nella sua rappresentazione equivalente ASCII (proteggendo i dati binari), e restituisce il risultato.

Vedere anche la funzione duale ascii2ebcdic()

getallheaders

(PHP 3, PHP 4 , PHP 5)

getallheaders -- Estrae tutti gli header della richiesta HTTP

Descrizione

array getallheaders ( void )

getallheaders() è un alias di apache_request_headers(). Restituisce un array associativo contenente tutti gli header HTTP nella richiesta corrente. Leggere la documentazione di apache_request_headers() per ulteriori informazioni sul funzionamento.

Nota: Nel PHP 4.3.0 getallheaders() è diventata un alias di apache_request_headers(). In breve, è stata rinominata. Ciò dipende dal fatto che questa funzione è disponibile soltanto quando PHP è compilato come modulo di Apache.

Nota: Dal PHP 4.3.3 è possibile utilizzare questa funzione anche con il modulo server NSAPI dei server web Netscape/iPlanet/SunONE

Vedere anche apache_request_headers().

virtual

(PHP 3, PHP 4 , PHP 5)

virtual -- Esegue una sotto-richiesta Apache

Descrizione

int virtual ( string nomefile )

virtual() è una funzione specifica Apache che è equivalente a <!--#include virtual...--> in mod_include. Esegue una sotto-richiesta Apache. È utile ad includere script CGI o file .shtml, o qualsiasi altra cosa si voglia fa analizzarea ad Apache. Si noti che per uno script CGI, questo deve generare degli header CGI validi. Quindi, Come minimo deve generare un header Content-type.

Al fine di eseguire la sotto-richiesta, tutti i buffer vengono chiusi e svuotati verso il browser, e anche gli header in attesa vengono inviati.

Dal PHP 4.0.6, è possibile utilizzare virtual() sui file PHP. Comunque è preferibile usare include() o require() se è necessarei includere un altro file PHP.

Nota: Dal PHP 4.3.3 è possibile utilizzare questa funzione anche con il modulo server NSAPI dei server web Netscape/iPlanet/SunONE

II. Advanced PHP debugger

Introduzione

APD is the Advanced PHP Debugger. It was written to provide profiling and debugging capabilities for PHP code, as well as to provide the ability to print out a full stack backtrace. APD supports interactive debugging, but by default it writes data to trace files. It also offers event based logging so that varying levels of information (including function calls, arguments passed, timings, etc.) can be turned on or off for individual scripts.

Attenzione

APD is a Zend Extension, modifying the way the internals of PHP handle function calls, and thus may or may not be compatible with other Zend Extensions (for example Zend Optimizer).


Installazione

APD is currently available as a PECL extension from http://pecl.php.net/package/apd. Make sure you have installed the CGI version of PHP and it is available in your current path along with the phpize script.

Run the following command to download, build, and install the latest stable version of APD:
pear install apd

This automatically installs the APD Zend module into your PHP extensions directory. It is not mandatory to keep it there; you can store the module in any directory PHP can read as long as you set the zend_extension parameter accordingly.

Windows users can download the extension dll php_apd.dll from http://snaps.php.net/win32/PECL_STABLE/.

In your INI file, add the following lines:

zend_extension = /absolute/path/to/apd.so
apd.dumpdir = /absolute/path/to/trace/directory
apd.statement_trace = 0

Depending on your PHP build, the zend_extension directive can be one of the following:

zend_extension              (non ZTS, non debug build)
zend_extension_ts           (    ZTS, non debug build)
zend_extension_debug        (non ZTS,     debug build)
zend_extension_debug_ts     (    ZTS,     debug build)


Building on Win32

To build APD under Windows you need a working PHP compilation environment as described on http://php.net/ -- basically, it requires you to have Microsoft Visual C++, win32build.zip, bison/flex, and some know how to get it to work. Also ensure that adp.dsp has DOS line endings; if it has unix line endings, Microsoft Visual C++ will complain about it.


Configurazione di Runtime

Breve descrizione dei parametri di configurazione.

apd.dumpdir string

Sets the directory in which APD writes profile dump files. You can specify an absolute path or a relative path.

You can specify a different directory as an argument to apd_set_pprof_trace().

apd.statement_trace boolean

Specfies whether or not to do per-line tracings. Turning this on (1) will impact the performance of your application.


Tipi di risorse

Questa estensione non definisce alcun tipo di risorsa.


Costanti predefinite

Questa estensione non definisce alcuna costante.


How to use PHP-APD in your scripts

  1. As the first line of your PHP script, call the apd_set_pprof_trace() function to start the trace:

    apd_set_pprof_trace();

    You can insert the line anywhere in your script, but if you do not start tracing at the beginning of your script you discard profile data that might otherwise lead you to a performance bottleneck.

  2. Now run your script. The dump output will be written to apd.dumpdir/pprof_pid.ext.

    Suggerimento: If you're running the CGI version of PHP, you will need to add the '-e' flag to enable extended information for apd to work properly. For example: php -e -f script.php

  3. To display formatted profile data, issue the pprofp command with the sort and display options of your choice. The formatted output will look something like:
    bash-2.05b$ pprofp -R /tmp/pprof.22141.0
    
    Trace for /home/dan/testapd.php
    Total Elapsed Time = 0.00
    Total System Time  = 0.00
    Total User Time    = 0.00
    
    
    Real         User        System             secs/    cumm
    %Time (excl/cumm)  (excl/cumm)  (excl/cumm) Calls    call    s/call  Memory Usage Name
    --------------------------------------------------------------------------------------
    100.0 0.00 0.00  0.00 0.00  0.00 0.00     1  0.0000   0.0009            0 main
    56.9 0.00 0.00  0.00 0.00  0.00 0.00     1  0.0005   0.0005            0 apd_set_pprof_trace
    28.0 0.00 0.00  0.00 0.00  0.00 0.00    10  0.0000   0.0000            0 preg_replace
    14.3 0.00 0.00  0.00 0.00  0.00 0.00    10  0.0000   0.0000            0 str_replace

    The -R option used in this example sorts the profile table by the amount of real time the script spent executing a given function. The "cumm call" column reveals how many times each function was called, and the "s/call" column reveals how many seconds each call to the function required, on average.

  4. To generate a calltree file that you can import into the KCacheGrind profile analysis application, issue the pprof2calltree comand.


Contact information

If you have comments, bugfixes, enhancements or want to help developing this beast, you can send an mail to apd@mail.communityconnect.com. Any help is very welcome.

Sommario
apd_breakpoint -- Stops the interpreter and waits on a CR from the socket
apd_callstack -- Returns the current call stack as an array
apd_clunk -- Throw a warning and a callstack
apd_continue -- Restarts the interpreter
apd_croak -- Throw an error, a callstack and then exit
apd_dump_function_table -- Outputs the current function table
apd_dump_persistent_resources -- Return all persistent resources as an array
apd_dump_regular_resources -- Return all current regular resources as an array
apd_echo -- Echo to the debugging socket
apd_get_active_symbols -- Get an array of the current variables names in the local scope
apd_set_pprof_trace -- Starts the session debugging
apd_set_session_trace -- Starts the session debugging
apd_set_session -- Changes or sets the current debugging level
apd_set_socket_session_trace -- Starts the remote session debugging
override_function -- Overrides built-in functions
rename_function -- Renames orig_name to new_name in the global function_table

apd_breakpoint

(no version information, might be only in CVS)

apd_breakpoint -- Stops the interpreter and waits on a CR from the socket

Description

void apd_breakpoint ( int debug_level )

This can be used to stop the running of your script, and await responses on the connected socket. To step the program, just send enter (a blank line), or enter a php command to be executed. A typical session using tcplisten would look like this.

bash#tcplisten localhost 7777

APD - Advanced PHP Debugger Trace File
---------------------------------------------------------------------------
Process Pid (6118)
Trace Begun at Sun Mar 10 23:13:12 2002
---------------------------------------------------------------------------
(  0.000000): apd_set_session_trace called at /home/alan/Projects/project2/test. 
php:5
(  0.074824): apd_set_session_trace_socket() at /home/alan/Projects/project2/tes 
t.php:5 returned.  Elapsed (0.074824)
(  0.074918): apd_breakpoint() /home/alan/Projects/project2/test.php:7
              ++ argv[0] $(??) = 9
apd_breakpoint() at /home/alan/Projects/project2/test.php:7 returned.  Elapsed ( 
-2089521468.1073275368)
>\n 
statement: /home/alan/Projects/project2/test.php:8
>\n 
statement: /home/alan/Projects/project2/test.php:8
>\n 
statement: /home/alan/Projects/project2/test.php:10
>apd_echo($i);
EXEC: apd_echo($i);
0
>apd_echo(serialize(apd_get_active_symbols()));
EXEC:  apd_echo(serialize(apd_get_active_symbols()));
a:47:{i:0;s:4:"PWD";i:1;s:10:"COLORFGBG";i:2;s:11:"XAUTHORITY";i:3;s:14:"
COLORTERM_BCE";i:4;s:9:"WINDOWID";i:5;s:14:"ETERM_VERSION";i:6;s:16:"SE
SSION_MANAGER";i:7;s:4:"PS1";i:8;s:11:"GDMSESSION";i:9;s:5:"USER";i:10;s:5:"
MAIL";i:11;s:7:"OLDPWD";i:12;s:5:"LANG";i:13;s:10:"COLORTERM";i:14;s:8:"DISP
LAY";i:15;s:8:"LOGNAME";i:16;s:6:"
>apd_echo(system('ls /home/mydir'));
........
>apd_continue(0);

apd_callstack

(no version information, might be only in CVS)

apd_callstack -- Returns the current call stack as an array

Description

array apd_callstack ( void )

Returns the current call stack as an array

Esempio 1. apd_callstack() example

<?php
print_r(apd_callstack());
?>

apd_clunk

(no version information, might be only in CVS)

apd_clunk -- Throw a warning and a callstack

Description

void apd_clunk ( string warning [, string delimiter] )

Behaves like perl's Carp::cluck. Throw a warning and a callstack. The default line delimiter is "<BR />\n".

Esempio 1. apd_clunk() example

<?php
apd_clunk("Some Warning","<P>");
?>

apd_continue

(no version information, might be only in CVS)

apd_continue -- Restarts the interpreter

Description

void apd_continue ( int debug_level )

Usually sent via the socket to restart the interpreter.

Esempio 1. apd_continue() example

<?php
apd_continue(0);
?>

apd_croak

(no version information, might be only in CVS)

apd_croak -- Throw an error, a callstack and then exit

Description

void apd_croak ( string warning [, string delimiter] )

Behaves like perl's Carp::croak. Throw an error, a callstack and then exit. The default line delimiter is "<BR />\n".

Esempio 1. apd_croak() example

<?php
apd_croak("Some Warning","<P>");
?>

apd_dump_function_table

(no version information, might be only in CVS)

apd_dump_function_table -- Outputs the current function table

Description

void apd_dump_function_table ( void )

Outputs the current function table.

Esempio 1. apd_dump_function_table() example

<?php
apd_dump_function_table();
?>

apd_dump_persistent_resources

(no version information, might be only in CVS)

apd_dump_persistent_resources -- Return all persistent resources as an array

Description

array apd_dump_persistent_resources ( void )

Return all persistent resources as an array.

Esempio 1. apd_dump_persistent_resources() example

<?php
print_r(apd_dump_persistent_resources());
?>

apd_dump_regular_resources

(no version information, might be only in CVS)

apd_dump_regular_resources -- Return all current regular resources as an array

Description

array apd_dump_regular_resources ( void )

Return all current regular resources as an array.

Esempio 1. apd_dump_regular_resources() example

<?php
print_r(apd_dump_regular_resources());
?>

apd_echo

(no version information, might be only in CVS)

apd_echo -- Echo to the debugging socket

Description

void apd_echo ( string output )

Usually sent via the socket to request information about the running script.

Esempio 1. apd_echo() example

<?php
apd_echo($i);
?>

apd_get_active_symbols

(no version information, might be only in CVS)

apd_get_active_symbols -- Get an array of the current variables names in the local scope

Description

array apd_get_active_symbols ( )

Returns the names of all the variables defined in the active scope, (not their values)

Esempio 1. apd_get_active_symbols() example

<?php
apd_echo(apd_get_active_symbols());
?>

apd_set_pprof_trace

(no version information, might be only in CVS)

apd_set_pprof_trace -- Starts the session debugging

Description

void apd_set_pprof_trace ( [string dump_directory] )

Starts debugging to {dump_directory}/pprof_{process_id}, if dump_directory is not set, then the apd.dumpdir setting from the php.ini file is used.

Esempio 1. apd_set_pprof_trace() example

<?php
apd_set_pprof_trace();
?>

apd_set_session_trace

(no version information, might be only in CVS)

apd_set_session_trace -- Starts the session debugging

Description

void apd_set_session_trace ( int debug_level [, string dump_directory] )

Starts debugging to {dump_directory}/apd_dump_{process_id}, if dump_directory is not set, then the apd.dumpdir setting from the php.ini file is used.

debug_level is an integer which is formed by adding together the following values:

FUNCTION_TRACE      1
        ARGS_TRACE          2
        ASSIGNMENT_TRACE    4
        STATEMENT_TRACE     8
        MEMORY_TRACE        16
        TIMING_TRACE        32
        SUMMARY_TRACE       64

I would seriously not recommend using MEMORY_TRACE. It is very slow and does not appear to be accurate (great, huh?) also ASSIGNMENT_TRACE is not implemented. So, to turn on all functional traces (TIMING, FUNCTIONS, ARGS SUMMARY (like strace -c)) use the value 99

Esempio 1. apd_set_session_trace() example

<?php
apd_set_session_trace(99);
?>

apd_set_session

(no version information, might be only in CVS)

apd_set_session -- Changes or sets the current debugging level

Description

void apd_set_session ( int debug_level )

This can be used to increase or decrease debugging in a different area of your application,.debug_level is an integer which is formed by adding together the following values:

FUNCTION_TRACE      1
        ARGS_TRACE          2
        ASSIGNMENT_TRACE    4
        STATEMENT_TRACE     8
        MEMORY_TRACE        16
        TIMING_TRACE        32
        SUMMARY_TRACE       64

Esempio 1. apd_set_session() example

<?php
apd_set_session(9);
?>

apd_set_socket_session_trace

(no version information, might be only in CVS)

apd_set_socket_session_trace -- Starts the remote session debugging

Description

bool apd_set_socket_session_trace ( string ip_address_or_unix_socket_file, int socket_type, int port, int debug_level )

Connects to the tcp server (eg. tcplisten) specified IP or Unix Domain socket (like a file), and sends debugging data to the socket. You can use any port, but higher numbers are better as most of the lower numbers may be used by other system services.

the socket_type can be APD_AF_UNIX (for file based sockets) or APD_AF_INET (for standard tcp/ip)

debug_level is an integer which is formed by adding together the following values:

FUNCTION_TRACE      1
        ARGS_TRACE          2
        ASSIGNMENT_TRACE    4
        STATEMENT_TRACE     8
        MEMORY_TRACE        16
        TIMING_TRACE        32
        SUMMARY_TRACE       64

I would seriously not recommend setting the value to 'zero' to start with, and use the breakpoint methods to start debugging at a specific place in the file.

Esempio 1. apd_set_socket_session_trace() example

<?php
  apd_set_socket_session_trace("127.0.0.1",APD_AF_INET,7112,0);
?>

override_function

(no version information, might be only in CVS)

override_function -- Overrides built-in functions

Description

bool override_function ( string function_name, string function_args, string function_code )

Syntax similar to create_function(). Overrides built-in functions (replaces them in the symbol table).

Esempio 1. override_function() example

<?php
override_function('test', '$a,$b', 'echo "DOING TEST"; return $a * $b;');
?>

rename_function

(no version information, might be only in CVS)

rename_function -- Renames orig_name to new_name in the global function_table

Description

bool rename_function ( string original_name, string new_name )

Renames orig_name to new_name in the global function_table. Useful for temporarily overriding builtin functions.

Esempio 1. rename_function() example

<?php
rename_function('mysql_connect', 'debug_mysql_connect' );
?>

III. Funzioni di Array

Introduzione

Queste funzioni permettono di manipolare e interagire con gli array in vari modi. Gli array sono indispensabili per immagazzinare, mantenere e operare su gruppi di variabili.

Sono supportati sia array semplici che multi-dimensionali, che possono essere sia creati dall'utente che da funzioni. Ci sono specifiche funzioni di database per riempire gli array a partire da interrogazioni sui dati, e parecchie funzioni restituiscono array.

Vedere la sezione Array del manuale per una spiegazione dettagliata di come gli array siano implementati ed usati in PHP. Vedere anche per altri modi di manipolazione degli array.


Requisiti

Non sono necessarie librerie esterne per utilizzare questo modulo.


Installazione

Non è necessaria nessuna installazione per usare queste funzioni, esse fanno parte del core di PHP.


Configurazione di Runtime

Questa estensione non definisce alcuna direttiva di configurazione in php.ini


Tipi di risorse

Questa estensione non definisce alcun tipo di risorsa.


Costanti predefinite

Le costanti qui elencate sono sempre disponibili in quanto parte del core di PHP.

CASE_LOWER (integer)

CASE_LOWER è usata con array_change_key_case() per convertire le chiavi degli array in minuscolo. Questo è il valore di default per array_change_key_case().

CASE_UPPER (integer)

CASE_UPPER è usata con array_change_key_case() per convertire le chiavi degli array in maiuscolo.

flag per l'ordinamento:

SORT_ASC (integer)

SORT_ASC è usata con array_multisort() per ordinare in senso crescente.

SORT_DESC (integer)

SORT_DESC è usata con array_multisort() per ordinare in senso decrescente.

flag per il tipo di ordinamento: usati da varie funzioni di ordinamento

SORT_REGULAR (integer)

SORT_REGULAR è usata per comparare gli oggetti in modo normale.

SORT_NUMERIC (integer)

SORT_NUMERIC è usata per comparare gli oggetti in modo numerico.

SORT_STRING (integer)

SORT_STRING è usata per comparare gli oggetti come se fossero stringhe.

COUNT_NORMAL (integer)

COUNT_RECURSIVE (integer)

EXTR_OVERWRITE (integer)

EXTR_SKIP (integer)

EXTR_PREFIX_SAME (integer)

EXTR_PREFIX_ALL (integer)

EXTR_PREFIX_INVALID (integer)

EXTR_PREFIX_IF_EXISTS (integer)

EXTR_IF_EXISTS (integer)

EXTR_REFS (integer)

Sommario
array_change_key_case -- Restituisce un array con tutte le chiavi cambiate in maiuscolo o in minuscolo
array_chunk -- Spezza un array in tronconi
array_combine --  Crea un'array utilizzando un'array per le chiavi e un'altro per i suoi valori
array_count_values -- Conta tutti i valori di un array
array_diff_assoc -- Calcola la differenza tra due o più array con un ulteriore controllo sull'indice
array_diff_key -- Computes the difference of arrays using keys for comparison
array_diff_uassoc --  Computes the difference of arrays with additional index check which is performed by a user supplied callback function
array_diff_ukey -- Computes the difference of arrays using a callback function on the keys for comparison
array_diff -- Calcola la differenza di due o più array
array_fill -- Riempie un array con i valori specificati
array_filter --  Filtra gli elementi di un array usando una funzione callback
array_flip -- Scambia tutte le chiavi di un array con i loro valori associati
array_intersect_assoc -- Calcola l'intersezione degli array con un ulteriore controllo sugli indici
array_intersect_key -- Computes the intersection of arrays using keys for comparison
array_intersect_uassoc -- Computes the intersection of arrays with additional index check, compares indexes by a callback function
array_intersect_ukey -- Computes the intersection of arrays using a callback function on the keys for comparison
array_intersect -- Calcola l'intersezione degli arrays
array_key_exists -- Controlla se l'indice (o chiave) specificato esiste nell'array
array_keys -- Restituisce tutte le chiavi di un array
array_map --  Applica la funzione callback a tutti gli elementi dell'array dato
array_merge_recursive -- Fonde due o più array in modo ricorsivo
array_merge -- Fonde uno o più array
array_multisort -- Ordina array multipli o multidimensionali
array_pad --  Riempie con un valore un array fino alla lunghezza specificata
array_pop -- Estrae l'elemento alla fine dell'array
array_push --  Accoda uno o più elementi ad un array
array_rand --  Estrae a caso uno o più elementi da un array
array_reduce --  Riduce iterativamente l'array a un singolo valore utilizzando una funzione callback
array_reverse --  Restituisce un array con gli elementi in ordine invertito
array_search --  Ricerca un dato valore in un array e ne restituisce la chiave corrispondente, se la ricerca ha successo.
array_shift --  Estrae l'elemento alla testa dell'array
array_slice -- Estrae un sottoinsieme da un array
array_splice --  Rimuove una porzione dell'array e la sostituisce con altro
array_sum --  Calcola la somma dei valori di un array.
array_udiff_assoc -- Computes the difference of arrays with additional index check, compares data by a callback function
array_udiff_uassoc -- Computes the difference of arrays with additional index check, compares data and indexes by a callback function
array_udiff -- Computes the difference of arrays by using a callback function for data comparison
array_uintersect_assoc -- Computes the intersection of arrays with additional index check, compares data by a callback function
array_uintersect_uassoc -- Computes the intersection of arrays with additional index check, compares data and indexes by a callback functions
array_uintersect -- Computes the intersection of arrays, compares data by a callback function
array_unique -- Rimuove i valori duplicati di un array
array_unshift --  Inserisce uno o più elementi all'inizio dell'array
array_values -- Restituisce tutti i valori di un array
array_walk_recursive --  Apply a user function recursively to every member of an array
array_walk --  Esegue una funzione su ogni elemento dell'array
array --  Crea un array
arsort --  Ordina un array in ordine decrescente e mantiene le associazioni degli indici
asort -- Ordina un array e mantiene le associazioni degli indici
compact --  Crea un array contenente variabili e il loro valore
count -- Conta gli elementi in una variabile
current -- Restituisce l'elemento corrente di un array
each --  Restituisce la corrente coppia chiave/valore di un array e incrementa il puntatore dell'array
end --  Sposta il puntatore interno dell'array all'ultimo elemento
extract --  Importa le variabili nella tabella dei simboli
in_array -- Controlla se un valore è presente in un array
key -- Estrae la chiave corrente da un array associativo
krsort -- Ordina rispetto alle chiavi di un array in ordine inverso
ksort -- Ordina rispetto alle chiavi di un array
list --  Assegna valori a delle variabili come se fossero un array
natcasesort --  Ordina un array usando un algoritmo di "ordine naturale" non sensibile alle maiuscole/minuscole
natsort --  Ordina un array usando un algoritmo di "ordine naturale"
next --  Incrementa il puntatore interno dell'array
pos -- Restituisce l'elemento corrente di un array
prev -- Decrementa il puntatore interno dell'array
range --  Crea un array contenente una serie di elementi
reset --  Reimposta il puntatore interno di un array sulla posizione iniziale
rsort -- Ordina un array in ordine decrescente
shuffle -- Mescola un array
sizeof -- Alias di count()
sort -- Ordina un array
uasort --  Ordina un array mediante una funzione definita dall'utente e mantiene le associazioni
uksort --  Ordina rispetto alle chiavi di un array mediante una funzione definita dall'utente
usort --  Ordina un array mediante una funzione definita dall'utente

array_change_key_case

(PHP 4 >= 4.2.0, PHP 5)

array_change_key_case -- Restituisce un array con tutte le chiavi cambiate in maiuscolo o in minuscolo

Descrizione

array array_change_key_case ( array input [, int case] )

array_change_key_case() cambia le chiavi nell'array input in modo che siano tutte minuscole o maiuscole. Il tipo di cambiamento dipende dal parametro opzionale case. Si possono usare due costanti, CASE_UPPER per le maiuscole e CASE_LOWER per le minuscole. Il default è CASE_LOWER. La funzione non modifica le chiavi numeriche.

Esempio 1. esempio di array_change_key_case()

<?php
$input_array = array("PriMo" => 1, "SecOndO" => 4);
print_r(array_change_key_case($input_array, CASE_UPPER));
?>

Il risultato di questo programma sarà:

Array
(
    [PRIMO] => 1
    [SECONDO] => 2
)

Se un array ha degli indici che risulteranno identici dopo l'esecuzione di questa funzione (es. "keY" e "kEY") il valore dell'ultimo indice sovrascrivera' gli altri.

array_chunk

(PHP 4 >= 4.2.0, PHP 5)

array_chunk -- Spezza un array in tronconi

Descrizione

array array_chunk ( array input, int dimensione [, bool mantieni_chiavi] )

array_chunk() spezza l'array in più array di dimensione dimensione. L'ultimo array potrebbe ovviamente avere una dimensione inferiore. Gli array sono restituiti in un array multidimensionale indicizzato con chiavi che partono da zero.

Impostando il parametro opzionale preserve_keys a TRUE, si forza PHP a mantenere le chiavi originarie dell'array di input. Se si imposta a FALSE come chiavi verranno usati in ogni array dei numeri crescenti a partire da zero. Il default è FALSE.

Esempio 1. esempio di array_chunk()

<?php
$input_array = array('a', 'b', 'c', 'd', 'e');
print_r(array_chunk($input_array, 2));
print_r(array_chunk($input_array, 2, true));
?>

Il risultato di questo programma sarà:

Array
(
    [0] => Array
        (
            [0] => a
            [1] => b
        )

    [1] => Array
        (
            [0] => c
            [1] => d
        )

    [2] => Array
        (
            [0] => e
        )

)
Array
(
    [0] => Array
        (
            [0] => a
            [1] => b
        )

    [1] => Array
        (
            [2] => c
            [3] => d
        )

    [2] => Array
        (
            [4] => e
        )

)

array_combine

(PHP 5)

array_combine --  Crea un'array utilizzando un'array per le chiavi e un'altro per i suoi valori

Descrizione

array array_combine ( array keys, array values )

Restituisce un'array utilizzando i valori dell'array keys come chiavi e i valori dall' array values come valori corrispondenti.

Restituisce FALSE se il numero degli elementi in ogni array non è uguale o se gli array sono vuoti.

Esempio 1. Esempio di array_combine()

<?php
$a = array('verde', 'rosso', 'giallo');
$b = array('avocado', 'mela', 'banana');
$c = array_combine($a, $b);

print_r($c);
?>

Il risultato è:

Array
(
    [verde]  => avocado
    [rosso]  => mela
    [giallo] => banana
)

Vedere anche array_merge(), array_walk() e array_values().

array_count_values

(PHP 4 , PHP 5)

array_count_values -- Conta tutti i valori di un array

Descrizione

array array_count_values ( array input )

array_count_values() restituisce un array che ha i valori dell'array input per chiavi e la loro frequenza in input come valori.

Esempio 1. Esempio di array_count_values()

<?php
$array = array(1, "ciao", 1, "mondo", "ciao");
print_r(array_count_values($array));
?>

Il risultato di questo programma sarà:

Array
(
    [1] => 2
    [ciao] => 2
    [mondo[ => 1
)

Vedere anche count(), array_unique(), array_values() e count_chars().

array_diff_assoc

(PHP 4 >= 4.3.0, PHP 5)

array_diff_assoc -- Calcola la differenza tra due o più array con un ulteriore controllo sull'indice

Descrizione

array array_diff_assoc ( array array1, array array2 [, array ...] )

array_diff_assoc() restituisce un array contenente tutti i valori di array1 che non sono presenti in alcuno degli altri array. Si noti che le chiavi sono utilizzate nel confronto, diversamente da array_diff().

Esempio 1. esempio di array_diff_assoc()

<?php
$array1 = array("a" => "verde", "b" => "marrone", "c" => "blu", "rosso");
$array2 = array("a" => "verde", "giallo", "rosso");
$result = array_diff_assoc($array1, $array2);
print_r($result);
?>

Il risultato è:

Array
(
    [b] => marrone
    [c] => blu
    [0] => rosso
)

Nell'esempio si vede che la coppia "a" => "verde" è presente in entrambi gli array e quindi non è nel risultato della funzione. Invece, la coppia 0 => "rosso" è nel risultato perché nel secondo argomento "red" cha come chiave 1.

Due valori delle coppie chiave => valore sono considerati uguali solo se (string) $elem1 === (string) $elem2 . In altre parole c'è un controllo stringente che si accerta che le rappresentazioni sotto forma di stringa siano uguali.

Nota: Si noti che questa funzione controlla solo una dimensione di un array n-dimensionale. Ovviamente è possibile controllare le altre dimensioni usando array_diff_assoc($array1[0], $array2[0]);.

Vedere anche array_diff(), array_intersect(), and array_intersect_assoc().

array_diff_key

(no version information, might be only in CVS)

array_diff_key -- Computes the difference of arrays using keys for comparison

Description

array array_diff_key ( array array1, array array2 [, array ...] )

array_diff_key() returns an array containing all the values of array1 that have keys that are not present in any of the other arguments. Note that the associativity is preserved. This function is like array_diff() except the comparison is done on the keys instead of the values.

Esempio 1. array_diff_key() example

<?php
$array1 = array('blue'  => 1, 'red'  => 2, 'green'  => 3, 'purple' => 4);
$array2 = array('green' => 5, 'blue' => 6, 'yellow' => 7, 'cyan'   => 8);

var_dump(array_diff_key($array1, $array2));
?>

The above example will output:

array(2) {
  ["red"]=>
  int(2)
  ["purple"]=>
  int(4)
}

The two keys from the key => value pairs are considered equal only if (string) $key1 === (string) $key2 . In other words a strict type check is executed so the string representation must be the same.

Nota: Please note that this function only checks one dimension of a n-dimensional array. Of course you can check deeper dimensions by using array_diff_key($array1[0], $array2[0]);.

See also array_diff(), array_udiff() array_diff_assoc(), array_diff_uassoc(), array_udiff_assoc(), array_udiff_uassoc(), array_diff_ukey(), array_intersect(), array_intersect_assoc(), array_intersect_uassoc(), array_intersect_key() and array_intersect_ukey().

array_diff_uassoc

(PHP 5)

array_diff_uassoc --  Computes the difference of arrays with additional index check which is performed by a user supplied callback function

Description

array array_diff_uassoc ( array array1, array array2 [, array ..., callback key_compare_func] )

array_diff_uassoc() returns an array containing all the values from array1 that are not present in any of the other arguments. Note that the keys are used in the comparison unlike array_diff().

This comparison is done by a user supplied callback function. It must return an integer less than, equal to, or greater than zero if the first argument is considered to be respectively less than, equal to, or greater than the second. This is unlike array_diff_assoc() where an internal function for comparing the indices is used.

Esempio 1. array_diff_uassoc() example

<?php
function key_compare_func($a, $b) 
{
    if ($a === $b) {
        return 0;
    }
    return ($a > $b)? 1:-1;
}

$array1 = array("a" => "green", "b" => "brown", "c" => "blue", "red");
$array2 = array("a" => "green", "yellow", "red");
$result = array_diff_uassoc($array1, $array2, "key_compare_func");
print_r($result);
?>

The above example will output:

Array
(
    [b] => brown
    [c] => blue
    [0] => red
)

In our example above you see the "a" => "green" pair is present in both arrays and thus it is not in the ouput from the function. Unlike this, the pair 0 => "red" is in the ouput because in the second argument "red" has key which is 1.

The equality of 2 indices is checked by the user supplied callback function.

Nota: Please note that this function only checks one dimension of a n-dimensional array. Of course you can check deeper dimensions by using, for example, array_diff_uassoc($array1[0], $array2[0], "key_compare_func");.

See also array_diff(), array_diff_assoc(), array_udiff(), array_udiff_assoc(), array_udiff_uassoc(), array_intersect(), array_intersect_assoc(), array_uintersect(), array_uintersect_assoc() and array_uintersect_uassoc().

array_diff_ukey

(no version information, might be only in CVS)

array_diff_ukey -- Computes the difference of arrays using a callback function on the keys for comparison

Description

array array_diff_ukey ( array array1, array array2 [, array ..., callback key_compare_func] )

array_diff_ukey() returns an array containing all the values of array1 that have keys that are not present in any of the other arguments. Note that the associativity is preserved. This function is like array_diff() except the comparison is done on the keys instead of the values.

This comparison is done by a user supplied callback function. It must return an integer less than, equal to, or greater than zero if the first key is considered to be respectively less than, equal to, or greater than the second.

Esempio 1. array_diff_ukey() example

<?php
function key_compare_func($key1, $key2)
{
    if ($key1 == $key2)
        return 0;
    else if ($key1 > $key2)
        return 1;
    else
        return -1;
}

$array1 = array('blue'  => 1, 'red'  => 2, 'green'  => 3, 'purple' => 4);
$array2 = array('green' => 5, 'blue' => 6, 'yellow' => 7, 'cyan'   => 8);

var_dump(array_diff_ukey($array1, $array2, 'key_compare_func'));
?>

The above example will output:

array(2) {
  ["red"]=>
  int(2)
  ["purple"]=>
  int(4)
}

Nota: Please note that this function only checks one dimension of a n-dimensional array. Of course you can check deeper dimensions by using array_diff_ukey($array1[0], $array2[0], 'callback_func');.

See also array_diff(), array_udiff() array_diff_assoc(), array_diff_uassoc(), array_udiff_assoc(), array_udiff_uassoc(), array_diff_key(), array_intersect(), array_intersect_assoc(), array_intersect_uassoc(), array_intersect_key() and array_intersect_ukey().

array_diff

(PHP 4 >= 4.0.1, PHP 5)

array_diff -- Calcola la differenza di due o più array

Descrizione

array array_diff ( array array1, array array2 [, array ...] )

array_diff() restituisce un array contenente tutti i valori di array1 che non sono presenti in alcuno degli altri array. Si noti che le associazioni con le chiavi vengono mantenute.

Esempio 1. Esempio di array_diff()

<?php
$array1 = array("a" => "verde", "rosso", "blu", "rosso");
$array2 = array("b" => "verde", "giallo", "rosso");
$risultato = array_diff($array1, $array2);

print_r($result);
?>

Occorrenze multiple in $array1 sono tutte trattate nello stesso modo. Questo codice mostrerà:

Array
(
    [1] => blu
)

Nota: Due elementi sono considerati uguali se e solo se (string) $elem1 === (string) $elem2. Ovvero: quando la rappresentazione sotto forma di stringa è la stessa.

Nota: Si noti che questa funzione controlla solo una dimensione di un array n-dimensionale. Ovviamente è possibile controllare le altre dimensioni usando array_diff($array1[0], $array2[0]);.

Avvertimento

Questa funzione era errata nel PHP 4.0.4!

Vedere anche array_diff_assoc(), array_intersect() e array_intersect_assoc().

array_fill

(PHP 4 >= 4.2.0, PHP 5)

array_fill -- Riempie un array con i valori specificati

Descrizione

array array_fill ( int inizio, int num, mixed valore )

array_fill() riempie un array con num elementi inizializzati con il valore del parametro valore, e con le chiavi che partono dal valore del parametro start_index. Si noti che num deve essere un valore maggiore di zero, altrimenti PHP mostrerà un avvertimento.

Esempio 1. esempio di array_fill()

<?php
$a = array_fill(5, 6, 'banana');
print_r($a);
?>

$a ora è:

Array
(
    [5]  => banana
    [6]  => banana
    [7]  => banana
    [8]  => banana
    [9]  => banana
    [10] => banana
)

Vedere anche str_repeat() e range().

array_filter

(PHP 4 >= 4.0.6, PHP 5)

array_filter --  Filtra gli elementi di un array usando una funzione callback

Descrizione

array array_filter ( array input [, callback callback] )

array_filter() esegue un'iterazione su ogni valore nell' array input passandolo alla funzione. Se funzione restituisce TRUE, il valore corrente di input viene restituito nell'array risultato. Le chiavi sono mantenute.

Esempio 1. Esempio di array_filter()

<?php
function dispari($var) 
{
    return($var % 2 == 1);
}

function pari($var) 
{
    return($var % 2 == 0);
}

$array1 = array("a"=>1, "b"=>2, "c"=>3, "d"=>4, "e"=>5);
$array2 = array(6, 7, 8, 9, 10, 11, 12);

echo "Dispari :\n";
print_r(array_filter($array1, "dispari");
echo "Pari :\n";
print_r(array_filter($array2, "pari");
?>

Il risultato di questo sarà:

Dispari :
Array
(
    [a] => 1
    [c] => 3
    [e] => 5
)
Pari:
Array
(
    [0] => 6
    [2] => 8
    [4] => 10
    [6] => 12
)

Gli utenti non possono modificare l'array attraverso la funzione di callback, ad esempio aggiungere/togliere un elemento, o cancellare l'array su cui array_filter() è applicata. Se l'array viene cambiato, il comportamento di questa funzione non è definito.

Se la funzione callback non viene indicata, array_filter() rimuoverà tutti gli elementi di input che siano uguali a FALSE. Vedere conversione a boolean per ulteriori informazioni.

Esempio 2. array_filter() senza callback

<?php

$entry = array(
             0 => 'pippo',
             1 => false,
             2 => -1,
             3 => null,
             4 => ''
          );

print_r(array_filter($entry));
?>

Questo mostrerà:

Array
(
    [0] => pippo
    [2] => -1
)

Vedere anche array_map() e array_reduce().

array_flip

(PHP 4 , PHP 5)

array_flip -- Scambia tutte le chiavi di un array con i loro valori associati

Descrizione

array array_flip ( array trans )

array_flip() restituisce un array scambiato, ovvero le chiavi di trans diventano valori e i valori di trans diventano chiavi.

Si noti che i valori di trans devono poter diventare chiavi valide, ovvero devo essere di tipo integer o string. Un errore verrà segnalato se un valore ha il tipo errato, e la coppia chiave/valore in questione non verrà scambiata.

Se un valore ha più di una occorrenza, L'ultima chiave verrà usata come valore, e tutte le altre verranno perse.

array_flip() restituisce FALSE se fallisce.

Esempio 1. Esempio di array_flip()

<?php
$trans = array_flip($trans);
$original = strtr($str, $trans);
?>

Esempio 2. Esempio di array_flip(): collisione

<?php
$trans = array("a" => 1, "b" => 1, "c" => 2);
$trans = array_flip($trans);
print_r($trans);
?>

ora $trans è:

Array
(
    [1] => b
    [2] => c
)

Vedere anche array_values(), array_keys() e array_reverse().

array_intersect_assoc

(PHP 4 >= 4.3.0, PHP 5)

array_intersect_assoc -- Calcola l'intersezione degli array con un ulteriore controllo sugli indici

Descrizione

array array_intersect_assoc ( array array1, array array2 [, array ...] )

array_intersect_assoc() restituisce un array contenente tutti i valori di array1 che siano presenti in tutti gli array passati come argomento. Si noti che le chiavi sono utilizzate nel confronto, diversamente da array_intersect().

Esempio 1. esempio di array_intersect_assoc()

<?php
$array1 = array("a" => "verde", "b" => "marrone", "c" => "blu", "rosso");
$array2 = array("a" => "verde", "giallo", "rosso");
$result_array = array_intersect_assoc($array1, $array2);
?>

$result_array sarà:

Array
(
    [a] => verde
)

Nell'esempio si vede che solo la coppia "a" => "verde" è presente in entrambi gli array e quindi viene restituita. Il valore "rosso" non viene restituito perché in $array1 la sua chiave è 0 mentre la chiave di "rosso" in $array2 è 1.

I due valori delle coppie chiave => valore sono considerati uguali solo se (string) $elem1 === (string) $elem2 . In altre parole viene eseguito un controllo stringente che si accerta che le rappresentazioni sotto forma di stringa siano uguali.

Vedere anche array_intersect(), array_uintersect_assoc(), array_intersect_uassoc(), array_uintersect_uassoc(), array_diff() e array_diff_assoc().

array_intersect_key

(no version information, might be only in CVS)

array_intersect_key -- Computes the intersection of arrays using keys for comparison

Description

array array_intersect_key ( array array1, array array2 [, array ...] )

array_intersect_key() returns an array containing all the values of array1 which have matching keys that are present in all the arguments.

Esempio 1. array_intersect_key() example

<?php
$array1 = array('blue'  => 1, 'red'  => 2, 'green'  => 3, 'purple' => 4);
$array2 = array('green' => 5, 'blue' => 6, 'yellow' => 7, 'cyan'   => 8);

var_dump(array_intersect_key($array1, $array2));
?>

The above example will output:

array(2) {
  ["blue"]=>
  int(1)
  ["green"]=>
  int(3)
})

In our example you see that only the keys 'blue' and 'green' are present in both arrays and thus returned. Also notice that the values for the keys 'blue' and 'green' differ between the two arrays. A match still occurs because only the keys are checked. The values returned are those of array1.

The two keys from the key => value pairs are considered equal only if (string) $key1 === (string) $key2 . In other words a strict type check is executed so the string representation must be the same.

See also array_diff(), array_udiff() array_diff_assoc(), array_diff_uassoc(), array_udiff_assoc(), array_udiff_uassoc(), array_diff_key(), array_diff_ukey(), array_intersect(), array_intersect_assoc(), array_intersect_uassoc() and array_intersect_ukey().

array_intersect_uassoc

(PHP 5)

array_intersect_uassoc -- Computes the intersection of arrays with additional index check, compares indexes by a callback function

Description

array array_intersect_uassoc ( array array1, array array2 [, array ..., callback key_compare_func] )

array_intersect_uassoc() returns an array containing all the values of array1 that are present in all the arguments. Note that the keys are used in the comparison unlike in array_intersect().

The index comparison is done by a user supplied callback function. It must return an integer less than, equal to, or greater than zero if the first argument is considered to be respectively less than, equal to, or greater than the second.

Esempio 1. array_intersect_uassoc() example

<?php
$array1 = array("a" => "green", "b" => "brown", "c" => "blue", "red");
$array2 = array("a" => "GREEN", "B" => "brown", "yellow", "red");

print_r(array_intersect_uassoc($array1, $array2, "strcasecmp"));
?>

The above example will output:

Array
(
    [b] => brown
)

See also array_intersect(), array_intersect_assoc(), array_uintersect_assoc(), array_uintersect_uassoc(), array_intersect_key() and array_intersect_ukey().

array_intersect_ukey

(no version information, might be only in CVS)

array_intersect_ukey -- Computes the intersection of arrays using a callback function on the keys for comparison

Description

array array_intersect_ukey ( array array1, array array2 [, array ..., callback key_compare_func] )

array_intersect_ukey() returns an array containing all the values of array1 which have matching keys that are present in all the arguments.

This comparison is done by a user supplied callback function. It must return an integer less than, equal to, or greater than zero if the first key is considered to be respectively less than, equal to, or greater than the second.

Esempio 1. array_intersect_ukey() example

<?php
function key_compare_func($key1, $key2)
{
    if ($key1 == $key2)
        return 0;
    else if ($key1 > $key2)
        return 1;
    else
        return -1;
}

$array1 = array('blue'  => 1, 'red'  => 2, 'green'  => 3, 'purple' => 4);
$array2 = array('green' => 5, 'blue' => 6, 'yellow' => 7, 'cyan'   => 8);

var_dump(array_intersect_ukey($array1, $array2, 'key_compare_func'));
?>

The above example will output:

array(2) {
  ["blue"]=>
  int(1)
  ["green"]=>
  int(3)
})

In our example you see that only the keys 'blue' and 'green' are present in both arrays and thus returned. Also notice that the values for the keys 'blue' and 'green' differ between the two arrays. A match still occurs because only the keys are checked. The values returned are those of array1.

The two keys from the key => value pairs are considered equal only if (string) $key1 === (string) $key2 . In other words a strict type check is executed so the string representation must be the same.

See also array_diff(), array_udiff() array_diff_assoc(), array_diff_uassoc(), array_udiff_assoc(), array_udiff_uassoc(), array_diff_key(), array_diff_ukey(), array_intersect(), array_intersect_assoc(), array_intersect_uassoc() and array_intersect_key().

array_intersect

(PHP 4 >= 4.0.1, PHP 5)

array_intersect -- Calcola l'intersezione degli arrays

Descrizione

array array_intersect ( array array1, array array2 [, array ...] )

array_intersect() restituisce un array contenente tutti i valori di array1 che siano presenti in tutti gli array passati come argomento. Si noti che le associazioni con le chiavi sono mantenute.

Esempio 1. Esempio di array_intersect()

<?php
$array1 = array("a" => "verde", "rosso", "blu");
$array2 = array("b" => "verde", "giallo", "rosso");
$risultato = array_intersect($array1, $array2);
?>

In questo modo $result sarà:

Array
(
    [a] => verde
    [0] => rosso
)

Nota: Due elementi sono considerati uguali solo e solo se (string) $elem1 === (string) $elem2. Ovvero: quando la rappresentazione sotto forma di stringa è la stessa.

Vedere anche array_intersect_assoc(), array_diff() e array_diff_assoc().

array_key_exists

(PHP 4 >= 4.1.0, PHP 5)

array_key_exists -- Controlla se l'indice (o chiave) specificato esiste nell'array

Descrizione

bool array_key_exists ( mixed chiave, array cerca )

array_key_exists() restituisce TRUE se il parametro chiave esiste nell'array. chiave può essere qualsiasi valore accettabile per un indice di array.

Esempio 1. esempio di array_key_exists()

<?php
$un_array = array("primo" => 1, "secondo" => 4);
if (array_key_exists("primo", $un_array)) {
    echo "L'elemento 'primo' è nell'array";
    }
    ?>

Nota: Il nome di questa funzione è key_exists() nel PHP 4.0.6.

Vedere anche isset(), array_keys() e in_array().

array_keys

(PHP 4 , PHP 5)

array_keys -- Restituisce tutte le chiavi di un array

Descrizione

array array_keys ( array input [, mixed valore_ricerca] )

array_keys() rstituisce le chiavi, numeriche e stringa, dell'array input.

Se il parametro opzionale valore_ricerca è specificato, solo le chiavi che corrispondono a quel valore vengono restituite. Altrimenti, vengono restituite tutte le chiavi dell'array input.

Esempio 1. Esempio di array_keys()

?php
$array = array(0 => 100, "colore" => "rosso");
print_r(array_keys($array))

$array = array("blu", "rosso", "verde", "blu", "blu");
print_r(array_keys($array, "blu"));

$array = array("colore" => array("blu", "rosso", "verde"),
               "misura" =&gt; array("piccola", "media", "grande"));
print_r(array_keys($array));
?>

Il risultato di questo programma sarà:

Array
(
    [0] => 0
    [1] => colore
)
Array
(
    [0] => 0
    [1] => 3
    [2] => 4
)
Array
(
    [0] => colore
    [1] => misura
)

Vedere anche array_values() e array_key_exists().

array_map

(PHP 4 >= 4.0.6, PHP 5)

array_map --  Applica la funzione callback a tutti gli elementi dell'array dato

Descrizione

array array_map ( mixed funzione, array arr1 [, array ...] )

array_map() restituisce un array contenente tutti gli elementi di arr1 dopo che è stata loro applicata la funzione callback. Il numero di parametri che la funzione callback accetta deve corrispondere al numero di array passati alla funzione array_map()

Esempio 1. Esempio di array_map()

<?php
function cubo($n) 
{
    return($n * $n * $n);
}

$a = array(1, 2, 3, 4, 5);
$b = array_map("cubo", $a);
print_r($b);
?>

In questo modo $b sarà:

Array
(
    [0] => 1
    [1] => 8
    [2] => 27
    [3] => 64
    [4] => 125
)

Esempio 2. array_map() - usare più array

<?php
function mostra_Spagnolo($n, $m) 
{
    return("Il numero $n si dice $m in Spagnolo");
}

function mappa_Spagnolo($n, $m) 
{
    return(array($n => $m));
}

$a = array(1, 2, 3, 4, 5);
$b = array("uno", "dos", "tres", "cuatro", "cinco");

$c = array_map("mostra_Spagnolo", $a, $b);
print_r($c);

$d = array_map("mappa_Spagnolo", $a, $b);
print_r($d);
?>

Questo restituisce:

//stampa di $c
Array
(
    [0] => Il numero 1 si dice uno in Spagnolo
    [1] => Il numero 2 si dice dos in Spagnolo
    [2] => Il numero 3 si dice tres in Spagnolo
    [3] => Il numero 4 si dice cuatro in Spagnolo
    [4] => Il numero 5 si dice cinco in Spagnolo
)

// stampa di $d
Array
(
    [0] => Array
        (
            [1] => uno
        )

    [1] => Array
        (
            [2] => dos
        )

    [2] => Array
        (
            [3] => tres
        )

    [3] => Array
        (
            [4] => cuatro
        )

    [4] => Array
        (
            [5] => cinco
        )

)

Generalmente, quando si usano due o più array, questi devono avere eguale lunghezza in quanto la funzione callback viene applicata in parallelo agli elementi corrispondenti. Se gli array sono di lunghezza diversa, il più corto verrà esteso con elementi vuoti.

Un uso interessante di questa funzione è quello di costruire un array di array, cosa che può essere facilmente ottenuta usando NULL come nome della funzione callback

Esempio 3. Creare un array di array

<?php
$a = array(1, 2, 3, 4, 5);
$b = array("uno", "due", "tre", "quattro", "cinque");
$c = array("uno", "dos", "tres", "cuatro", "cinco");

$d = array_map(null, $a, $b, $c);
print_r($d);
?>

Il risultato di questo programma sarà;

Array
(
    [0] => Array
        (
            [0] => 1
            [1] => uno
            [2] => uno
        )

    [1] => Array
        (
            [0] => 2
            [1] => due
            [2] => dos
        )

    [2] => Array
        (
            [0] => 3
            [1] => tre
            [2] => tres
        )

    [3] => Array
        (
            [0] => 4
            [1] => quattro
            [2] => cuatro
        )

    [4] => Array
        (
            [0] => 5
            [1] => cinque
            [2] => cinco
        )

)

Vedere anche array_filter(), array_reduce() e array_walk().

array_merge_recursive

(PHP 4 >= 4.0.1, PHP 5)

array_merge_recursive -- Fonde due o più array in modo ricorsivo

Descrizione

array array_merge_recursive ( array array1, array array2 [, array ...] )

Array_merge_recursive() fonde gli elementi di due o più array in modo tale che i valori di un array siano accodati all'array precedente. Restituisce l'array risultante.

Se gli array in input hanno le stesse chiavi stringa, i valori di queste chiavi vengono fusi in un array, e questo è fatto in modo ricorsivo, cio` se uno dei valori è un array, la funzione lo fonder%agrave; con una voce corrispondente in un altro array Comunque, se gli array hanno la stessa chiave numerica, l'ultimo valore non sovrascriver` il valore originale, bensì verrà accodato.

Esempio 1. Esempio di array_merge_recursive()

<?php
$ar1 = array("colore" => array ("preferito" => "rosso"), 5);
$ar2 = array(10, "colore" => array ("preferito" => "verde", "blu"));
$risultato = array_merge_recursive($ar1, $ar2);
?>

La variabile $risultato sarà:

Array
(
    [colore] => Array
        (
             [preferito] => Array
                (
                    [0] => rosso
                    [1] => verde
                )

            [0] => blu
        )

    [0] => 5
    [1] => 10
)

Vedere anche array_merge().

array_merge

(PHP 4 , PHP 5)

array_merge -- Fonde uno o più array

Descrizione

array array_merge ( array array1 [, array array2 [, array ...]] )

array_merge() fonde gli elementi di uno o più array in modo che i valori di un array siano accodati a quelli dell'array precedente. Restituisce l'array risultante.

Se gli array in input hanno le stesse chiavi stringa, l'ultimo valore di quella chiave sovrascriverà i precedenti. Comunque, se gli array hanno le stesse chiavi numeriche, l'ultimo valore non sovrascriverà quello originale, bensì sarà accodato.

Se viene fornito un solo array, e questo è indicizzato numericamente, le chiavi vengono reindicizzate in una sequenza continua. Nel caso di array associativi, delle chiavi duplicate rimane solo l'ultima. Vedere l'esempio tre per ulteriori dettagli.

Esempio 1. Esempio di array_merge()

<?php
$array1 = array("colore" => "rosso", 2, 4);
$array2 = array("a", "b", "colore" => "verde", "forma" => "trapezio", 4);
$risultato = array_merge($array1, $array2);
print_r($risultato);
?>

La variabile $risultato sarà:

Array
(
    [colore] => verde
    [0] => 2
    [1] => 4
    [2] => a
    [3] => b
    [forma] => trapezio
    [4] => 4
)

Esempio 2. Esempio di array_merge()

<?php
$array1 = array();
$array2 = array(1 => "dati");
$result = array_merge($array1, $array2);
?>

Non dimenticarsi che le chiavi numeriche saranno rinumerate!

Array
(
    [0] => data
)

Se si vogliono preservare gli array e li si vuole solo concatenare, usare l'operatore +:

<?php
$array1 = array();
$array2 = array(1 => "dati");
$result = $array1 + $array2;
?>

La chiave numerica sarà preservata e così pure l'associazione.

Array
(
    [1] => data
)

Esempio 3. esempio di array_merge()

<?php
$array_uno = array(0 => "mario", 1 => "roberto", 2 => "andrea", 3 => "dante");
$array_due = array("mario => "roberto", "andrea" => "dante", "mario" => "giacomo");

unset($array_uno[2]);

$risultato_uno = array_merge($array_uno);
$risultato_due = array_merge($array_due);

print_r($risultato_uno);
print_r($risultato_due);
?>

Il risultato sarà:

Array
(
    [0] => mario
    [1] => roberto
    [2] => dante
)
Array
(
    [mario] => giacomo
    [andrea] => dante
)

Nota: Le chiavi condivise verranno sovrascritte dalla prima chiave processata.

Vedere anche array_merge_recursive() e array_combine() e operatori sugli array.

array_multisort

(PHP 4 , PHP 5)

array_multisort -- Ordina array multipli o multidimensionali

Descrizione

bool array_multisort ( array ar1 [, mixed arg [, mixed ... [, array ...]]] )

Array_multisort() Può essere usata per ordinare parecchi array allo stesso tempo, oppure un array multidimensionale, rispetto a una o più dimensioni. Mantiene le associazioni delle chiavi durante l'ordinamento, mentre le chiavi numeriche vengono reindicizzate.

Gli array in input sono trattati come campi di una tabella che vengano ordinati per righe - questo assomiglia alla funzionalità della clausola SQL ORDER BY Il primo array è quello primario, rispetto a cui ordinare. Le righe (valori) in questo array that siano uguali vengono ordinate secondo l'array successivo, e così via.

La struttura degli argomenti di questa funzione è un po' inusuale, ma flessibile. Il primo argomento deve essere un array. In seguito, ogni argomento può essere sia un array che un flag di ordinamento, selezionabile dalla seguente lista.

Flag di ordinamento:

  • SORT_ASC - ordinamento crescente

  • SORT_DESC - ordinamento decrescente

Sorting type flags:

  • SORT_REGULAR - confronta gli elementi in modo normale

  • SORT_NUMERIC - confronta gli elementi numericamente

  • SORT_STRING - confronta gli elementi come stringhe

Dopo ogni array, non si possono specificare due flag dello stesso tipo. I flag specificati dopo un array si applicano solo a quell'array - sono reimpostati ai default SORT_ASC e SORT_REGULAR prima di ogni nuovo array passato come argomento.

Restituisce TRUE in caso di successo, FALSE in caso di fallimento.

Esempio 1. Ordinamre più array

<?php
$ar1 = array("10", 100, 100, "a");
$ar2 = array(1, 3, "2", 1);
array_multisort($ar1, $ar2);
?>

In questo esempio, dopo l'ordinamento, il primo array conterrà "10", "a", 100, 100. Il secondo array conterrà 1, 1, "2", 3. Gli elementi nel secondo array che corrispondono agli elementi identici nel primo array (100 e 100) vengono pure ordinati.

Esempio 2. Ordinare un array multi-dimensionale

<?php
$ar = array(array ("10", 100, 100, "a"), array (1, 3, "2", 1));
array_multisort($ar[0], SORT_ASC, SORT_STRING,
                $ar[1], SORT_NUMERIC, SORT_DESC);
?>

In questo esempio, dopo l'ordinamento, il primo array conterrà 10, 100, 100, "a" (ordinato come stringhe ordine crescente), e il secondo conterrà 1, 3, "2", 1 (ordinati come numeri, in ordine decrescente).

array_pad

(PHP 4 , PHP 5)

array_pad --  Riempie con un valore un array fino alla lunghezza specificata

Descrizione

array array_pad ( array input, int pad_size, mixed pad_value )

array_pad() restituisce una copia di input allungato alla dimensione sepcificata da pad_size con il valore pad_value. Se pad_size è positivo l'array è riempito sulla destra, se è negativo sulla sinistra. Se il valore assoluto di pad_size è minore o uguale alla lunghezza di input non viene effettuata alcuna modifica.

Esempio 1. esempio di array_pad()

<?php
$input = array(12, 10, 9);

$risultato = array_pad($input, 5, 0);
// risultato diventa array(12, 10, 9, 0, 0)

$risultato = array_pad($input, -7, -1);
// risultato diventa array(-1, -1, -1, -1, 12, 10, 9)

$risultato = array_pad($input, 2, "noop");
// ridimensionamento non efettuato
?>

Vedere anche array_fill() e range().

array_pop

(PHP 4 , PHP 5)

array_pop -- Estrae l'elemento alla fine dell'array

Descrizione

mixed array_pop ( array array )

array_pop() estrae e restituisce l'ultimo valore di array, accorciando array di un elemento. Se array è vuoto (o non è un array), viene restituito NULL.

Nota: Questa funzione farà il reset() del puntatore dell'array dopo l'uso.

Esempio 1. esempio di array_pop()

<?php
$pila = array("arancia", "banana", "mela", "lampone");
$frutto = array_pop($pila);
print_r($pila);
?>

Dopo questa istruzione, $pila avrà solo 3 elementi:

Array
(
    [0] => arancia
    [1] => banana
    [2] => mela
)

e lampone verrà assegnato alla variabile $frutto.

Avvertimento

Questa funzione può restituire il Booleano FALSE, ma può anche restituire un valore non-Booleano valutato come FALSE, come ad esempio 0 o "". Per favore fare riferimento alla sezione Booleans per maggiori informazioni. Usare l'operatore === per controllare il valore restituito da questa funzione.

Vedere anche array_push(), array_shift() e array_unshift().

array_push

(PHP 4 , PHP 5)

array_push --  Accoda uno o più elementi ad un array

Descrizione

int array_push ( array array, mixed var [, mixed ...] )

array_push() tratta array come una pila, e accoda le variabili date alla fine di array. La lunghezza di array aumenta del numero di variabili accodate. Ha lo stesso effetto di:
<?php
$array[] = $var;
?>
ripetuto per ogni var.

Restituisce il nuovo numero di elementi nell'array.

Esempio 1. esempio di array_push()

<?php
$pila = array("arancia", "banana");
array_push($pila, "mela", "lampone");
print_r($pila);
?>

In questo esempio $pila avrà i seguenti elementi:

Array
(
    [0] => arancia
    [1] => banana
    [2] => mela
    [3] => lampone
)

Nota: Se si utilizza array_push() per aggiungere un elemento all'array, è preferibile piuttosto utilizzare $array[] = poiché in questo modo non c'è il tempo d'attesa per la chiamata di funzione.

Vedere anche array_pop(), array_shift() e array_unshift().

array_rand

(PHP 4 , PHP 5)

array_rand --  Estrae a caso uno o più elementi da un array

Descrizione

mixed array_rand ( array input [, int num_req] )

array_rand() è piuttosto utile quando si vuole estrarre a caso uno o più elementi da un array. Prende un array (input) e un argomento ozpionale (num_req) che specifica quanti elementi estrarre - se non è specificato, è 1 per default.

Se si sta estraendo solo un elemento, array_rand() restituisce la chiave di un elemento. Altrimenti, restituisce un array di chiavi. Questo viene fatto in modo da permettere di estrarre dall'array sia le chiavi che i valori.

Nota: Come in PHP 4.2.0, non vi è necessità di inizializzare il generatore di numeri casuali con srand() oppure con mt_srand() poichè viene eseguito in modo automatico.

Esempio 1. esempio di array_rand()

<?
srand((float) microtime() * 10000000);
$input = array("Neo", "Morpheus", "Trinity", "Cypher", "Tank");
$chiavi = array_rand($input, 2);
echo $input[$chiavi[0]] . "\n";
echo $input[$chiavi[1]] . "\n";
?>

Vedere anche shuffle().

array_reduce

(PHP 4 >= 4.0.5, PHP 5)

array_reduce --  Riduce iterativamente l'array a un singolo valore utilizzando una funzione callback

Descrizione

mixed array_reduce ( array input, callback funzione [, int initial] )

array_reduce() applica iterativamente la funzione callback agli elementi dell'array input, riducendo l'array a un singolo valore. Seil parametro opzionale intial è specificato, viene usato come valore iniziale all'inizio del processo, o come risultato finale nel caso l'array sia vuoto.

Esempio 1. esempio di array_reduce()

<?php
function rsum($v, $w) 
{
    $v += $w;
    return $v;
}

function rmul($v, $w) 
{
    $v *= $w;
    return $v;
}

$a = array(1, 2, 3, 4, 5);
$x = array();
$b = array_reduce($a, "rsum");
$c = array_reduce($a, "rmul", 10);
$d = array_reduce($x, "rsum", 1);
?>

In questo modo $b conterrà 15, $c conterrà 1200 (= 1*2*3*4*5*10) e $d conterrà 1.

Vedere anche array_filter() e array_map(), array_unique() e array_count_values().

array_reverse

(PHP 4 , PHP 5)

array_reverse --  Restituisce un array con gli elementi in ordine invertito

Descrizione

array array_reverse ( array array [, bool mantieni_chiavi] )

array_reverse() prende array e restituisce un nuovo array con l'ordine degli elementi invertito, mantenendo le chiavi sie mantieni_chiavi è TRUE.

Esempio 1. esempio di array_reverse()

<?php
$input  = array("php", 4.0, array("verde", "rosso"));
$risultato = array_reverse($input);
$resultato_chiavi = array_reverse($input, true);
?>

Questo fa sì che sia $risultato che $risultato_chiavi abbiano gli stessi elementi, ma si noti la differenza tra le chiavi. La stampa di $risultato e $risultato_chiavi sarà:

Array
(
    [0] => Array
        (
            [0] => verde
            [1] => rosso
        )

    [1] => 4
    [2] => php
)
Array
(
    [2] => Array
        (
            [0] => verde
            [1] => rosso
        )

    [1] => 4
    [0] => php
)

Nota: Il secondo parametro è stato aggiunto in PHP 4.0.3.

Vedere anche array_flip().

array_search

(PHP 4 >= 4.0.5, PHP 5)

array_search --  Ricerca un dato valore in un array e ne restituisce la chiave corrispondente, se la ricerca ha successo.

Descrizione

mixed array_search ( mixed ago, array pagliaio [, bool strict] )

Cerca in pagliaio per trovare ago e restituisce la chiave se viene trovato nell'array, FALSE altrimenti.

Nota: Se ago è una stringa, il confronto è fatto tenendo conto delle maiuscole/minuscole.

Nota: Nelle versioni di PHP antecedenti la 4.2.0, array_search() restituisce NULL invece di FALSE in caso di fallimento.

Se il terzo parametro opzionale strict è impostato a TRUE la funzione array_search() controllerà anche il tipo di ago nell'array pagliaio.

Se ago viene ritrovato in pagliaio più di una nolta, viene restituita la prima chiave trovata. Per restituire le chiavi di tutti i valori, utilizzare array_keys() con il parametro opzionale valore_ricerca.

Esempio 1. esempio di array_search()

<?php
$array = array(0 => 'blu', 1 => 'rosso', 2 => 'verde', 3 => 'rosso');

$chiave = array_search('verde', $array); // $chiave = 2;
$chiave = array_search('rosso', $array); // $chiave = 1;
?>

Avvertimento

Questa funzione può restituire il Booleano FALSE, ma può anche restituire un valore non-Booleano valutato come FALSE, come ad esempio 0 o "". Per favore fare riferimento alla sezione Booleans per maggiori informazioni. Usare l'operatore === per controllare il valore restituito da questa funzione.

Vedere anche array_keys(), array_values(), array_key_exists() e in_array().

array_shift

(PHP 4 , PHP 5)

array_shift --  Estrae l'elemento alla testa dell'array

Descrizione

mixed array_shift ( array array )

array_shift() estrae il primo elemento di array e lo restituisce, accorciando array di un elemento e spostando tutti gli altri all'indietro. Tutte le chiavi numeriche verranno modificate al fine di iniziare il conteggio da zero, mentre gli indici alfabetici non verranno modificati. Se array è vuoto (o non è un array), viene restituito NULL.

Nota: Questa funzione farà il reset() del puntatore dell'array dopo l'uso.

Esempio 1. esempio di array_shift()

<?php
$pila = array("arancia", "banana", "mela", lampone");
$frutto = array_shift($pila);
print_r($pila);
?>

In questo modo $pila rimarrà con 3 elementi:

Array
(
    [0] => banana
    [1] => mela
    [2] => lampone
)

e arancia sarà assegnata a $frutto.

Vedere anche array_unshift(), array_push() e array_pop().

array_slice

(PHP 4 , PHP 5)

array_slice -- Estrae un sottoinsieme da un array

Descrizione

array array_slice ( array array, int offset [, int length] )

array_slice() restituisce la sequenza di elementi dell'array array come specificato dai parametri offset e length .

Se offset è positivo, la sequenza comincerà da quell'offset in array. Se offset è negativo, la sequenza comincerà alla distanza offset dalla fine di array.

Se length è specificata ed è positiva, la sequenza conterrà quel numero di elementi. Se length è specificata ed è negativa la sequenza si fermerà a quel numero di elementi dalla fine dell'array. Se viene omessa, la sequenza conterrà tutto da offset fino alla fine di array.

Si noti che array_slice() ignorerà le chiavi dell'array, e calcolerè gli spiazzamenti e le lunghezze basandosi sulle posizioni correnti degli elementi nell'array.

Esempio 1. esempi di array_slice()

<?php
$input = array("a", "b", "c", "d", "e");

$output = array_slice($input, 2);      // restituisce "c", "d" e "e"
$output = array_slice($input, 2, -1);  // restituisce "c", "d"
$output = array_slice($input, -2, 1);  // restituisce "d"
$output = array_slice($input, 0, 3);   // restituisce "a", "b" e "c"
?>

Vedere anche array_splice() e unset().

array_splice

(PHP 4 , PHP 5)

array_splice --  Rimuove una porzione dell'array e la sostituisce con altro

Descrizione

array array_splice ( array input, int offset [, int length [, array replacement]] )

array_splice() rimuove gli elementi specificati da offset e length dall'array input, e li sostituisce con gli elementi dell'array replacement, se fornito. Restituisce un array contenente gli elementi estratti.

Se offset è positivo l'inizio della porzione rimossa è a quella distanza dall'inizio dell'array input. Se offset è negativo inizia a quella distanza dalla fine dell'array input.

Se length è omessa, rimuove tutti gli elementi da offset alla fine dell'array. Se length è specificata a positiva, quel numero di elementi vengono rimossi. Se length è specificata e negativa la porzione da rimuovere terminerà a length elementi dalla fine dell'array. Suggerimento: per rimuovere tutti gli elementi tra offset e la fine dell'array quando è specificato pure replacement, usare count($input) nel parametro length.

Se l'array replacement è specificato, gli elementi rimossi sono sostituiti dagli elementi di questo array. Se offset e length sono tali per cui niente viene rimosso, gli elementi dell'array replacement sono inseriti nella posizione specificata da offset. Suggerimento: se replacement è composto solo da un elemento non è necessario porlo nel costrutto array(), a meno che l'elemento stesso non sia un array.

Valgono le seguenti equivalenze:

Tabella 1. array_splice() equivalents

array_push($input, $x, $y) array_splice($input, count($input), 0, array($x, $y))
array_pop($input) array_splice($input, -1)
array_shift($input) array_splice($input, -1)
array_unshift($input, $x, $y) array_splice($input, 0, 0, array($x, $y))
$a[$x] = $y array_splice($input, $x, 1, $y)

Restituisce un array contenente gli elementi rimossi.

Esempio 1. esempi di array_splice()

<?php
$input = array("rosso", "verde", "blu", "giallo");
array_splice($input, 2);
// $input è ora array("rosso", "verde")

$input = array("rosso", "verde", "blu", "giallo");
array_splice($input, 1, -1);
// $input è ora array("rosso", "giallo")

$input = array("rosso", "verde", "blu", "giallo");
array_splice($input, 1, count($input), "arancio");
// $input è ora array("rosso", "arancio")

$input = array("rosso", "verde", "blu", "giallo");
array_splice($input, -1, 1, array("nero", "marrone"));
// $input è ora array("rosso", "verde",
//          "blu", "nero", "marrone")

$input = array("rosso", "verde", "blu", "giallo");
array_splice($input, 3, 0, "viola");
// $input è ora array("rosso", "verde",
//          "blu", "viola", "giallo");
?>

Vedere anche array_slice()i, unset() e array_merge().

array_sum

(PHP 4 >= 4.0.4, PHP 5)

array_sum --  Calcola la somma dei valori di un array.

Descrizione

mixed array_sum ( array array )

array_sum() restituisce la somma dei valori dell'array sotto forma di integer o float.

Esempio 1. esempi di array_sum()

<?php
$a = array(2, 4, 6, 8);
echo "sum(a) = " . array_sum($a) . "\n";

$b = array("a" => 1.2, "b" => 2.3, "c" => 3.4);
echo "sum(b) = " . array_sum($b) . "\n";
?>

Il risultato di questo programma sarà:

sum(a) = 20
sum(b) = 6.9

Nota: Le versioni di PHP antecedenti alla 4.2.1 modificavano l'array stesso e convertivano le stringhe in numeri (le quali erano convertite in zeri la maggior parte delle volte, a seconda dal valore).

array_udiff_assoc

(PHP 5)

array_udiff_assoc -- Computes the difference of arrays with additional index check, compares data by a callback function

Description

array array_udiff_assoc ( array array1, array array2 [, array ..., callback data_compare_func] )

array_udiff_assoc() returns an array containing all the values from array1 that are not present in any of the other arguments. Note that the keys are used in the comparison unlike array_diff() and array_udiff(). The comparison of arrays' data is performed by using an user-supplied callback. In this aspect the behaviour is opposite to the behaviour of array_diff_assoc() which uses internal function for comparison.

Esempio 1. array_udiff_assoc() example

<?php
class cr {
    private $priv_member;
    function cr($val) 
    {
        $this->priv_member = $val;
    }
    
    function comp_func_cr($a, $b) 
    {
        if ($a->priv_member === $b->priv_member) return 0;
        return ($a->priv_member > $b->priv_member)? 1:-1;
    }
}

$a = array("0.1" => new cr(9), "0.5" => new cr(12), 0 => new cr(23), 1=> new cr(4), 2 => new cr(-15),);
$b = array("0.2" => new cr(9), "0.5" => new cr(22), 0 => new cr(3), 1=> new cr(4), 2 => new cr(-15),);

$result = array_udiff_assoc($a, $b, array("cr", "comp_func_cr"));
print_r($result);
?>

The above example will output:

Array
(
    [0.1] => cr Object
        (
            [priv_member:private] => 9
        )

    [0.5] => cr Object
        (
            [priv_member:private] => 12
        )

    [0] => cr Object
        (
            [priv_member:private] => 23
        )
)

In our example above you see the "1" => new cr(4) pair is present in both arrays and thus it is not in the ouput from the function.

For comparison is used the user supplied callback function. It must return an integer less than, equal to, or greater than zero if the first argument is considered to be respectively less than, equal to, or greater than the second.

Nota: Please note that this function only checks one dimension of a n-dimensional array. Of course you can check deeper dimensions by using, for example, array_udiff_assoc($array1[0], $array2[0], "some_comparison_func");.

See also array_diff(), array_diff_assoc(), array_diff_uassoc(), array_udiff(), array_udiff_uassoc(), array_intersect(), array_intersect_assoc(), array_uintersect(), array_uintersect_assoc() and array_uintersect_uassoc().

array_udiff_uassoc

(PHP 5)

array_udiff_uassoc -- Computes the difference of arrays with additional index check, compares data and indexes by a callback function

Description

array array_udiff_uassoc ( array array1, array array2 [, array ..., callback data_compare_func, callback key_compare_func] )

array_udiff_uassoc() returns an array containing all the values from array1 that are not present in any of the other arguments. Note that the keys are used in the comparison unlike array_diff() and array_udiff(). The comparison of arrays' data is performed by using an user-supplied callback : data_compare_func. In this aspect the behaviour is opposite to the behaviour of array_diff_assoc() which uses internal function for comparison. The comparison of keys (indices) is done also by the callback function key_compare_func. This behaviour is unlike what array_udiff_assoc() does, since the latter compares the indices by using an internal function.

Esempio 1. array_udiff_uassoc() example

<?php
class cr {
    private $priv_member;
    function cr($val) 
    {
        $this->priv_member = $val;
    }

    function comp_func_cr($a, $b) 
    {
        if ($a->priv_member === $b->priv_member) return 0;
        return ($a->priv_member > $b->priv_member)? 1:-1;
    }
    
    function comp_func_key($a, $b) 
    {
        if ($a === $b) return 0;
        return ($a > $b)? 1:-1;
    }
}
$a = array("0.1" => new cr(9), "0.5" => new cr(12), 0 => new cr(23), 1=> new cr(4), 2 => new cr(-15),);
$b = array("0.2" => new cr(9), "0.5" => new cr(22), 0 => new cr(3), 1=> new cr(4), 2 => new cr(-15),);

$result = array_udiff_uassoc($a, $b, array("cr", "comp_func_cr"), array("cr", "comp_func_key"));
print_r($result);
?>

The above example will output:

Array
(
    [0.1] => cr Object
        (
            [priv_member:private] => 9
        )

    [0.5] => cr Object
        (
            [priv_member:private] => 12
        )

    [0] => cr Object
        (
            [priv_member:private] => 23
        )
)

In our example above you see the "1" => new cr(4) pair is present in both arrays and thus it is not in the ouput from the function. Keep in mind that you have to supply 2 callback functions.

For comparison is used the user supplied callback function. It must return an integer less than, equal to, or greater than zero if the first argument is considered to be respectively less than, equal to, or greater than the second.

Nota: Please note that this function only checks one dimension of a n-dimensional array. Of course you can check deeper dimensions by using, for example, array_udiff_uassoc($array1[0], $array2[0], "data_compare_func", "key_compare_func");.

See also array_diff(), array_diff_assoc(), array_diff_uassoc(), array_udiff(), array_udiff_assoc(), array_intersect(), array_intersect_assoc(), array_uintersect(), array_uintersect_assoc() and array_uintersect_uassoc().

array_udiff

(PHP 5)

array_udiff -- Computes the difference of arrays by using a callback function for data comparison

Description

array array_udiff ( array array1, array array2 [, array ..., callback data_compare_func] )

array_udiff() returns an array containing all the values of array1 that are not present in any of the other arguments. Note that keys are preserved. For the comparison of the data data_compare_func is used. It must return an integer less than, equal to, or greater than zero if the first argument is considered to be respectively less than, equal to, or greater than the second. This is unlike array_diff() which uses an internal function for comparing the data.

Esempio 1. array_udiff() example

<?php
class cr {
    private $priv_member;
    function cr($val) 
    {
        $this->priv_member = $val;
    }
    
    function comp_func_cr($a, $b) 
    {
        if ($a->priv_member === $b->priv_member) return 0;
        return ($a->priv_member > $b->priv_member)? 1:-1;
    }
}
$a = array("0.1" => new cr(9), "0.5" => new cr(12), 0 => new cr(23), 1=> new cr(4), 2 => new cr(-15),);
$b = array("0.2" => new cr(9), "0.5" => new cr(22), 0 => new cr(3), 1=> new cr(4), 2 => new cr(-15),);

$result = array_udiff($a, $b, array("cr", "comp_func_cr"));
print_r($result);
?>

The above example will output:

Array
(
    [0.5] => cr Object
        (
            [priv_member:private] => 12
        )

    [0] => cr Object
        (
            [priv_member:private] => 23
        )

)

Nota: Two elements are considered equal if and only if (string) $elem1 === (string) $elem2. In words: when the string representation is the same.

Nota: Please note that this function only checks one dimension of a n-dimensional array. Of course you can check deeper dimensions by using array_udiff($array1[0], $array2[0], "data_compare_func");.

See also array_diff(), array_diff_assoc(), array_diff_uassoc(), array_udiff_assoc(), array_udiff_uassoc(), array_intersect(), array_intersect_assoc(), array_uintersect(), array_uintersect_assoc() and array_uintersect_uassoc().

array_uintersect_assoc

(PHP 5)

array_uintersect_assoc -- Computes the intersection of arrays with additional index check, compares data by a callback function

Description

array array_uintersect_assoc ( array array1, array array2 [, array ..., callback data_compare_func] )

array_uintersect_assoc() returns an array containing all the values of array1 that are present in all the arguments. Note that the keys are used in the comparison unlike in array_uintersect(). The data is compared by using a callback function.

Esempio 1. array_uintersect_assoc() example

<?php
$array1 = array("a" => "green", "b" => "brown", "c" => "blue", "red");
$array2 = array("a" => "GREEN", "B" => "brown", "yellow", "red");

print_r(array_uintersect_assoc($array1, $array2, "strcasecmp"));
?>

The above example will output:

Array
(
    [a] => green
)

For comparison is used the user supplied callback function. It must return an integer less than, equal to, or greater than zero if the first argument is considered to be respectively less than, equal to, or greater than the second.

See also array_uintersect(), array_intersect_assoc(), array_intersect_uassoc() and array_uintersect_uassoc().

array_uintersect_uassoc

(PHP 5)

array_uintersect_uassoc -- Computes the intersection of arrays with additional index check, compares data and indexes by a callback functions

Description

array array_uintersect_uassoc ( array array1, array array2 [, array ..., callback data_compare_func, callback key_compare_func] )

array_uintersect_uassoc() returns an array containing all the values of array1 that are present in all the arguments. Note that the keys are used in the comparison unlike in array_uintersect(). Both the data and the indexes are compared by using a callback functions.

Esempio 1. array_uintersect_uassoc() example

<?php
$array1 = array("a" => "green", "b" => "brown", "c" => "blue", "red");
$array2 = array("a" => "GREEN", "B" => "brown", "yellow", "red");

print_r(array_uintersect_uassoc($array1, $array2, "strcasecmp", "strcasecmp"));
?>

The above example will output:

Array
(
    [a] => green
    [b] => brown
)

For comparison is used the user supplied callback function. It must return an integer less than, equal to, or greater than zero if the first argument is considered to be respectively less than, equal to, or greater than the second.

See also array_uintersect(), array_intersect_assoc(), array_intersect_uassoc() and array_uintersect_assoc().

array_uintersect

(PHP 5)

array_uintersect -- Computes the intersection of arrays, compares data by a callback function

Description

array array_uintersect ( array array1, array array2 [, array ..., callback data_compare_func] )

array_uintersect() returns an array containing all the values of array1 that are present in all the arguments. The data is compared by using a callback function.

Esempio 1. array_uintersect() example

<?php
$array1 = array("a" => "green", "b" => "brown", "c" => "blue", "red");
$array2 = array("a" => "GREEN", "B" => "brown", "yellow", "red");

print_r(array_uintersect($array1, $array2, "strcasecmp"));
?>

The above example will output:

Array
(
    [a] => green
    [b] => brown
    [0] => red
)

For comparison is used the user supplied callback function. It must return an integer less than, equal to, or greater than zero if the first argument is considered to be respectively less than, equal to, or greater than the second.

See also array_intersect(), array_uintersect_assoc(), array_intersect_uassoc() and array_uintersect_uassoc().

array_unique

(PHP 4 >= 4.0.1, PHP 5)

array_unique -- Rimuove i valori duplicati di un array

Descrizione

array array_unique ( array array )

array_unique() prende array e restituisce un nuovo array senza i valori duplicati.

Si noti che le chiavi sono mantenute. array_unique() ordina i valori trattandoli come stringhe, quindi mantiene la prima chiave trovata per ogni valore, e ignorerà tutte le altre chiavi. Questo non significa che la chiave del primo valore dell'array non ancora ordinato verrà mantenuta.

Nota: Due elementi sono considerati uguali se e solo se (string) $elem1 === (string) $elem2. Ovvero: quando la rappresentazione sotto forma di stringa è la stessa.

Verrà usato il primo elemento.

Esempio 1. esempio di array_unique()

<?php
$input = array("a" => "verde", "rosso", "b" => "verde", "blu", "rosso");
$risultato = array_unique($input);
print_r($result);
?>

Questo mostrerà:

Array
(
    [b] => verde
    [1] => blu
    [2] => rosso
)

Esempio 2. array_unique() e i tipi

<?php
$input = array(4, "4", "3", 4, 3, "3");
$risultato = array_unique($input);
var_dump($risultato);
?>

Questo script mostrerà:

array(2) {
  [0] => int(4)
  [2] => string(1) "3"
}

array_unshift

(PHP 4 , PHP 5)

array_unshift --  Inserisce uno o più elementi all'inizio dell'array

Descrizione

int array_unshift ( array array, mixed var [, mixed ...] )

array_unshift() aggiunge gli elementi specificati in testa ad array. Si noti che la lista di elementi è aggiunta in blocco, in modo tale che gli elementi rimangano nello stesso ordine. Tutte le chiavi numeriche vengono modificate per iniziare da zero mentre le chiavi alfabetiche non sono modificate.

Restituisce il nuovo numero di elementi in array.

Esempio 1. esempio di array_unshift()

<?php
$lista = array("arancia", "banana");
array_unshift($lista, "mela", "lampone");
?>

In questo modo $lista conterrà i seguenti elementi:

Array
(
    [0] => mela
    [1] => lampone
    [2] => arancia
    [3] => banana
)

Vedere anche array_shift(), array_push() e array_pop().

array_values

(PHP 4 , PHP 5)

array_values -- Restituisce tutti i valori di un array

Descrizione

array array_values ( array input )

array_values() restituisce tutti i valori dell'array input e indicizza numericamente l'array.

Esempio 1. esempio di array_values()

<?php
$array = array("taglia" => "XL", "colore" => "oro");
print_r(array_values($array));
?>

Questo mostrerà:

Array
(
    [0] => XL
    [1] => oro
)

Vedere anche array_keys().

array_walk_recursive

(PHP 5)

array_walk_recursive --  Apply a user function recursively to every member of an array

Description

bool array_walk_recursive ( array &input, callback funcname [, mixed userdata] )

Applies the user-defined function funcname to each element of the input array. This function will recur into deeper arrays. Typically, funcname takes on two parameters. The input parameter's value being the first, and the key/index second. If the optional userdata parameter is supplied, it will be passed as the third parameter to the callback funcname.

Restituisce TRUE in caso di successo, FALSE in caso di fallimento.

Nota: If funcname needs to be working with the actual values of the array, specify the first parameter of funcname as a reference. Then, any changes made to those elements will be made in the original array itself.

Esempio 1. array_walk_recursive() example

<?php
$sweet = array('a' => 'apple', 'b' => 'banana');
$fruits = array('sweet' => $sweet, 'sour' => 'lemon');

function test_print($item, $key) 
{
    echo "$key holds $item\n";
}

array_walk_recursive($fruits, 'test_print');
?>

The above example will output:

a holds apple
b holds banana
sour holds lemon

You may notice that the key 'sweet' is never displayed. Any key that holds an array will not be passed to the function.

See also array_walk(), and information about the callback type.

array_walk

(PHP 3>= 3.0.3, PHP 4 , PHP 5)

array_walk --  Esegue una funzione su ogni elemento dell'array

Descrizione

bool array_walk ( array &array, callback funzione [, mixed datiutente] )

Restituisce TRUE in caso di successo, FALSE in caso di fallimento.

Esegue la funzione definita dall'utente identificata da funzione su ogni elemento di array. Normalmente funzione accetta due parametri. Il valore del parametro array viene passato per primo, la chiave/indice per secondo. Se il parametro datiutente è specificato, verrà passato come terzo parametro alla funzione callback.

Se funzione richiede più parametri di quanti gliene vengono passati, un errore di livello E_WARNING verrà generato ogni volta che array_walk() la chiama. Questi avvertimenti possono essere soppressi apponendo l'operatore d'errore @ alla chiamata di array_walk(), oppure usando error_reporting().

Nota: Se funzione deve lavorare con i reali valori dell'array, specificare che il primo parametro di funzione deve essere passato come riferimento. A qesto punto ogni modifica a questi elementi verrà effettuata sull'array stesso.

Nota: Il passaggio della chiave e di datiutente a func è stato aggiunto nella versione 4.0.

array_walk() non è influenzato dal puntatore interno dell'array array. array_walk() percorrerà l'intero array indipendentemente dalla posizione del puntatore. Per reinizializzare il puntatore, utilizzare reset(). In PHP 3, array_walk() reinizializza il puntatore.

Gli utenti non possono modificare l'array attraverso la funzione di callback, ad esempio aggiungere/togliere un elemento, o cancellare l'array su cui array_walk() è applicata. Se l'array viene cambiato, il comportamento di questa funzione non è definito ed è imprevedibile.

Esempio 1. esempio di array_walk()

<?php
$frutta = array("d"=>"limone", "a"=>"arancia", "b"=>"banana", "c"=>"mela");

function modifica(&$elemento1, $chiave, $prefisso) 
{
    $elemento1 = "$prefisso: $elemento1";
}

function stampa($elemento2, $chiave) 
{
    echo "$chiave. $elemento2<br />\n";
}

echo "Prima ...:\n";
array_walk($frutta, 'stampa');

array_walk($frutta, 'modifica', 'frutto');
echo "... e dopo:\n";

array_walk($frutta, 'stampa');
?>

Il risultato del programma sarà:

Prima ...:
d. limone
a. arancia
b. banana
c. mela
... e dopo:
d. frutto: limone
a. frutto: arancia
b. frutto: banana
c. frutto: mela

Vedere anche array_walk_recursive(), create_function(), list(), foreach, each(), call_user_func_array() e array_map()

array

(PHP 3, PHP 4, PHP 5 )

array --  Crea un array

Descrizione

array array ( [mixed ...] )

Restituisce un array contenente i parametri. Ai parametri si può dare un indice con l'operatore =>. Leggere la sezione relativa ai tipi per ulteriori informazioni sugli array.

Nota: array() è un costrutto del linguaggio usato per rappresentare array letterali, e non una normale funzione.

La sintassi "indice => valori", separati da virgole, definisce indici e valori. indice può essere di tipo string o numerico. Quando l'indice è omesso, viene generato automaticamente un indice intero, a partire da 0. Se l'indice è un intero, il successivo indice generato sarà l'indice intero più grande + 1. Si noti che quando due indici identici vengono definiti, l'ultimo sovrascrive il primo.

L'esempio seguente dimostra come creare un array bidimensionale, come specificare le chiavi per gli array associativi, e come modificare la serie degli indici numerici negli array normali.

Esempio 1. Esempio di array()

<?php
$frutta = array (
    "frutta"  => array("a" => "arancia", "b" => "banana", "c" => "mela"),
    "numeri"  => array(1, 2, 3, 4, 5, 6),
    "buche"   => array("prima", 5 => "seconda", "terza")
)
?>

Esempio 2. Indice automatico con array()

<?php
$array = array(1, 1, 1, 1,  1, 8 => 1,  4 => 1, 19, 3 => 13);
print_r($array);
?>

che stamperà:

Array
(
    [0] => 1
    [1] => 1
    [2] => 1
    [3] => 13
    [4] => 1
    [8] => 1
    [9] => 19
)

Si noti che l'indice '3' è definito due volte, e che mantiene il valore finale 13. L'indice 4 è definito dopo l'indice 8, e il successivo indice generato (valore 19) è 9, dal momento che l'indice più grande era 8.

Questo esempio crea un array che parte da 1 (1-based).

Esempio 3. Indice 1-based con array()

<?php
$primotrimestre = array(1 => 'Gennaio', 'Febbraio', 'Marzo');
print_r($primotrimestre);
?>

che stamperà:

Array
(
    [1] => Gennaio
    [2] => Febbraio
    [3] => Marzo
)

Vedere anche array_pad(), list(), foreach e range().

arsort

(PHP 3, PHP 4 , PHP 5)

arsort --  Ordina un array in ordine decrescente e mantiene le associazioni degli indici

Descrizione

bool arsort ( array array [, int sort_flags] )

Questa funzione ordina un array in modo tale che i suoi indici mantengano la loro correlazione con gli elementi ai quali sono associati. Viene usata principalmente nell'ordinamento degli array associativi, quando la disposizione originaria degli elementi è importante.

Restituisce TRUE in caso di successo, FALSE in caso di fallimento.

Esempio 1. esempio di arsort()

<?php
$frutta = array("d" => "limone", "a" => "arancia", "b" => "banana", "c" => "mela");
arsort($frutta);
reset($frutta);
while (list($chiave, $valore) = each($frutta)) {
    echo "$chiave = $valore\n";
}
?>

Questo esempio mostrerà:

c = mela
d = limone
b = banana
a = arancia

I frutti sono ordinati in ordine alfabetico decrescente, e l'indice associato a ogni elemento è stato mantenuto.

È possibile modificare il comportamento dell'ordinamento usando il parametro opzionale sort_flags, per maggiori dettagli vedere sort().

vedere anche asort(), rsort(), ksort() e sort().

asort

(PHP 3, PHP 4 , PHP 5)

asort -- Ordina un array e mantiene le associazioni degli indici

Descrizione

bool asort ( array array [, int sort_flags] )

Questa funzione ordina un array in modo tale che i suoi indici mantengano la loro correlazione con gli elementi ai quali sono associati. Viene usata principalmente nell'ordinamento degli array associativi, quando la disposizione originaria degli elementi è importante.

Restituisce TRUE in caso di successo, FALSE in caso di fallimento.

Esempio 1. esempio di asort()

<?php
$frutta = array("d"=>"limone", "a"=>"arancia", "b"=>"banana", "c"=>"mela");
asort($frutta);
reset($frutta);
while (list($chiave, $valore) = each($frutta)) {
    echo "$chiave = $valore\n";
}
?>

Questo esempio mostrerà:

a = arancia
b = banana
d = limone
c = mela

I frutti sono ordinati in ordine alfabetico, e l'indice associato ad ogni elemento è stato mantenuto.

È possibile modificare il comportamento dell'ordinamento usando il parametro opzionale sort_flags, per maggiori dettagli vedere sort().

Vedere anche arsort(), rsort(), ksort() e sort().

compact

(PHP 4 , PHP 5)

compact --  Crea un array contenente variabili e il loro valore

Descrizione

array compact ( mixed varname [, mixed ...] )

compact() accetta un numero variabile di parametri. Ogni parametro può essere una stringa contenente il nome della variabile, o un array di nomi di variabile. L'array può contenere altri array di nomi di variabile; compact() se ne occupa in modo ricorsivo.

Per ognuno di questi, compact() cerca la variabile con quel nome nella tabella dei simboli corrente, e la aggiunge all'array di output in modo tale che il nome della variabile diventi la chiave e i contenuti della variabile diventino il valore associato a quella chiave. In breve, compact() è l'opposto di extract(). Restituisce l'array di output con tutte le variabili aggiunte a quest'ultimo.

Qualsiasi stringa non valorizzata verrà semplicemente ignorata.

Esempio 1. esempio di compact()

<?php
$citta = "Milano";
$provincia = "MI";
$evento = "SMAU";

$var_luoghi = array("citta", "provincia");

$risultato = compact("evento", "niente", $var_luoghi);
?>

In questo modo, $risultato sarà:

Array
(
    [event] => SMAU
    [citta] => Milano
    [provincia] => MI
)

Vedere anche extract().

count

(PHP 3, PHP 4 , PHP 5)

count -- Conta gli elementi in una variabile

Descrizione

int count ( mixed var [, int mode] )

Restituisce il numero di elementi in var, la quale è di norma un array (dal momento che qualsiasi altro oggetto avrà un elemento).

Se var non è un array, verrà restituito 1 (eccezione: count(NULL) restituisce 0).

Nota: Il parametro opzionale mode è disponibile da PHP 4.2.0.

Se il parametro opzionale mode è impostato a COUNT_RECURSIVE (o 1), count() conterà ricorsivamente l'array. Questo è utile in particolare per contare tutti gli elementi di un array multidimensionale. Il valore di default per mode è 0.

Attenzione

count() può restituire 0 per una variabile che non è impostata, ma può anche restituire 0 per una variabile che è stata inizializzata con un array vuoto. Usare isset() per verificare se una variabile è impostata.

Vedere la sezione Arrays nel manuale per una spiegazione dettagliata di come gli array siano implementati ed usati in PHP.

Esempio 1. esempio di count()

<?php
$a[0] = 1;
$a[1] = 3;
$a[2] = 5;
$risultato = count($a);
//$risultato == 3

$b[0]  = 7;
$b[5]  = 9;
$b[10] = 11;
$risultato = count($b);
// $risultato == 3;
?>

Esempio 2. esempio di count() ricorsiva (PHP >= 4.2.0)

<?php
$cibo = array('frutta' => array('arancia', 'banana', 'mela'),
              'verdura' => array('carota', 'zucchina', 'piselli'));

// conteggio ricorsivo
echo count($cibp,COUNT_RECURSIVE); // output 8

// conteggio normale
echo count($cibo);                 // output 2

?>

Nota: La funzione sizeof() è un alias per count().

Vedere anche is_array(), isset() e strlen().

current

(PHP 3, PHP 4 , PHP 5)

current -- Restituisce l'elemento corrente di un array

Descrizione

mixed current ( array array )

Ogni array ha un puntatore interno all'elemento "corrente", che è inizializzato al primo elemento inserito nell'array.

La funzione current() restituisce il valore dell'elemento che è attualmente puntato dal puntatore interno. In ogni caso non muove il puntatore. Se il puntatore interno punta oltre la fine della lista di elementi, current() restituisce FALSE.

Avvertimento

Se l'array contiene elementi vuoti (0 o "", la stringa vuota) la funzione restituirà FALSE pure per questi elementi. Questo rende impossibile stabilire se si è veramente alla fine della lista in un array di questo tipo usando current(). Per attraversare in modo corretto un array che può contenere elementi vuoti, usare la funzione each().

Esempio 1. Esempio di current() e funzioni relative

<?php
$trasporti = array('piedi', 'bicicletta', 'automobile', 'aereo');
$mode = current($trasporti); // $mode = 'piedi';
$mode = next($trasporti);    // $mode = 'bicicletta';
$mode = current($trasporti); // $mode = 'bicicletta';
$mode = prev($trasporti);    // $mode = 'piedi';
$mode = end($trasporti);     // $mode = 'aereo';
$mode = current($trasporti); // $mode = 'aereo';
?>

Vedere anche end(), key(), next(), prev() e reset().

each

(PHP 3, PHP 4 , PHP 5)

each --  Restituisce la corrente coppia chiave/valore di un array e incrementa il puntatore dell'array

Descrizione

array each ( array array )

Restituisce la corrente coppia chiave/valore corrente di array e incrementa il puntatore interno dell'array. Questa coppia è restituita in un array di quattro elementi, con le chiavi 0, 1, key, and value. Gli elementi 0 e key contengono il nome della chiave dell'elemento dell'array, mentre 1 e