PHP

Page last edited 387 giorni 22 ore fa
Da wiki.betaingegneria.it.

PHP: PHypertextPreprocessor[modifica]

Il linguaggio per web che uso di più e con cui mi trovo meglio. Il più figo è Python, ma lo uso poco.

Basics[modifica]

Qui i fondamentali della sintassi. Non tutto, solo quello che mi sono studiato.

Operatori bitwise e operatori logici[modifica]

Operatori logici[modifica]

Gli operatori logici (OR e AND, per il momento) sono gli operatori binari nello spazio delle variabili booleane. Una variabile booleana può assumere i valori esclusivi true (vero) oppure false (falso).

Il problema è che PHP è loosely typed per cui è facilissimo fare casino perché si possono applicare questi operatori anche a variabili non booleane, perché PHP opera un cast (mutazione di tipo) implicito.

Il funzionamento degli operatori logici e, più in generale, delle funzioni logiche (combinazioni di operatori) è completamente definito dalla sua tabella di verità.

Ad esempio:

 | A | B | A OR B | 
 ------------------
 | 0 | 0 |    0   | 
 | 0 | 1 |    1   | 
 | 1 | 0 |    1   | 
 | 1 | 1 |    1   | 

per la funzione OR e

 | A | B | A AND B | 
 -------------------
 | 0 | 0 |    0    | 
 | 0 | 1 |    0    | 
 | 1 | 0 |    0    | 
 | 1 | 1 |    1    | 

per la funzione AND.

Il simbolo che PHP designa per l'operatore di OR è il doppio pipe (||) mentre per l'operatore di AND è la doppia "E" commerciale (&&).

PHP fornisce altri due operatori logici che sono AND e OR che hanno delle diverse regole di precedenza rispetto agli operatori && e ||.

Operatori bitwise[modifica]

Un discorso a parte va fatto per gli operatori bitwise. Questi sono operatori binari che operano sui singoli bit di numeri interi, e sono detti operatori "tipo bit" (bitwise) e sono il singolo pipe (|) e la singola "E" commerciale (&).

Ad esempio,

---------     ---------  -- ---------
risultato     valore     op test
---------     ---------  -- ---------
Bitwise AND (&)
( 0 = 0000) = ( 0 = 0000) & ( 5 = 0101)
( 1 = 0001) = ( 1 = 0001) & ( 5 = 0101)
( 0 = 0000) = ( 2 = 0010) & ( 5 = 0101)
( 4 = 0100) = ( 4 = 0100) & ( 5 = 0101)
( 0 = 0000) = ( 8 = 1000) & ( 5 = 0101)
Bitwise Inclusive OR (|)
( 5 = 0101) = ( 0 = 0000) | ( 5 = 0101)
( 5 = 0101) = ( 1 = 0001) | ( 5 = 0101)
( 7 = 0111) = ( 2 = 0010) | ( 5 = 0101)
( 5 = 0101) = ( 4 = 0100) | ( 5 = 0101)
(13 = 1101) = ( 8 = 1000) | ( 5 = 0101)

Tutti i moduli di php[modifica]

  $ sudo apt-cache search php5-
  php5-cgi - server-side, HTML-embedded scripting language (CGI binary)
  php5-cli - command-line interpreter for the php5 scripting language
  php5-common - Common files for packages built from the php5 source
  php5-curl - CURL module for php5
  ...

cURL: client per trasferire file usando la sintassi URL[modifica]

Generalmente uso la libreria cURL (detto "siURL") quando voglio fare in modo che il mio server web si connetta ad un altro server ma come client (ad esempio un webservice in lettura su un endpoint remoto).

Scaricare e installare cURL[modifica]

  1. scaricare e installare libcurl, di solito si fa con synaptic o apt-get; io lo cerco con il software di installazione applicazioni e ho già la versione curl 7.27.0-1ubuntu1.7.

posso rendermi conto che la libreria è installata e funzionante con questo comando:

  marcob@js:~$ curl -I www.betaingegneria.it
  HTTP/1.1 200 OK
  Date: Mon, 23 Dec 2013 14:34:34 GMT
  Server: Apache
  X-Pingback: http://www.betaingegneria.it/xmlrpc.php
  Content-Type: text/html; charset=UTF-8

Da help di curl, il parametro -I significa che cURL scaricherà solo l'header http.

Configurazione di PHP[modifica]

La configurazione di PHP è duplice; si fa nella directory /etc/php5/ che è così composta:

 root@js:/etc/php5# ll
 totale 32
 drwxr-xr-x   6 root root  4096 giu 15  2013 ./
 drwxr-xr-x 166 root root 12288 feb 26 10:20 ../
 drwxr-xr-x   2 root root  4096 feb 19 12:15 apache2/
 drwxr-xr-x   2 root root  4096 giu 15  2013 cli/
 drwxr-xr-x   2 root root  4096 feb 26 12:06 conf.d/
 drwxr-xr-x   2 root root  4096 lug 17  2013 mods-available/

ci sono due configurazioni, una per Apache e una per la modalità client :

  • apache
  • cli

ciascuna di queste directory contiene un file php.ini di inizializzazione che poi fa riferimento alle directory comuni mods-available e conf.d. Quest'ultima non è altro che un contenitore di link simbolici a file contenuti nella prima:

  root@js:/etc/php5/conf.d# ll
  totale 8
  drwxr-xr-x 2 root root 4096 feb 26 12:06 ./
  drwxr-xr-x 6 root root 4096 giu 15  2013 ../
  lrwxrwxrwx 1 root root   25 giu 15  2013 10-pdo.ini -> ../mods-available/pdo.ini
  lrwxrwxrwx 1 root root   28 giu 15  2013 20-mysqli.ini -> ../mods-available/mysqli.ini
  lrwxrwxrwx 1 root root   27 giu 15  2013 20-mysql.ini -> ../mods-available/mysql.ini
  lrwxrwxrwx 1 root root   26 lug 17  2013 20-oci8.ini -> ../mods-available/oci8.ini
  lrwxrwxrwx 1 root root   31 giu 15  2013 20-pdo_mysql.ini -> ../mods-available/pdo_mysql.ini

Compilazione PHP[modifica]

Per usare il supporto cURL di PHP dobbiamo anche compilare PHP con la direttiva --with-curl[=DIR] dove DIR è la posizione della directory contenete le directory lib e include. Nella directory include dovrebbe esserci una carteòòa chiamata curl che dobrebbe contenere i fili easy.h e curl.h. Dovrebbe esserci un file chiamato libcurl.a situato nella directory lib. A partire dal PHP 4.3.0 possiamo configurare PHP per l'uso di cURL per flussi URL --with-curlwrappers.

Installazione di libssh2[modifica]

Non so perché ad un certo punto mi è uscito l'errore

Protocol "sftp" not supported or disabled in libcurl

Cercando in rete trovo questo sito. Effettivamente il phpinfo mi da come installato curl ma senza il supporto per sftp. Non me lo spiego a rifaccio l'installazione.

  $ wget https://www.libssh2.org/download/libssh2-1.8.0.tar.gz
  $ tar xzf libssh2-1.8.0.tar.gz
  $ cd libssh2-1.8.0
  $ sudo ./configure
  $ sudo make
  $ sudo make install

Reinstallare curl[modifica]

Qui c'è da fare una scelta su quale versione di Ubuntu ce ne sono parecchie:

La mia:

  $ lsb_release -a
  No LSB modules are available.
  Distributor ID:	Ubuntu
  Description:	Ubuntu 15.10
  Release:	15.10
  Codename:	wily

La wili non c'è tra quelle disponibili nel sito.

Va be', me lo faccio a mano:

  $ cd 
  $ cd Scaricati
  $ wget https://curl.haxx.se/download/curl-7.54.0.tar.gz
  $ tar xzf curl-7.54.0.tar.gz
  $ cd curl-7.54.0/
  $ sudo ./configure --with-libssh2=/usr/local
  $ sudo make
  $ sudo make install

Tra i messaggi di output del terzo comando c'è questo importante:

  Libraries have been installed in:
   /usr/local/lib
  
  If you ever happen to want to link against installed libraries
  in a given directory, LIBDIR, you must either use libtool, and
  specify the full pathname of the library, or use the '-LLIBDIR'
  flag during linking and do at least one of the following:
   - add LIBDIR to the 'LD_LIBRARY_PATH' environment variable
   during execution
   - add LIBDIR to the 'LD_RUN_PATH' environment variable
   during linking
   - use the '-Wl,-rpath -Wl,LIBDIR' linker flag
   - have your system administrator add LIBDIR to '/etc/ld.so.conf'
  
  See any operating system documentation about shared libraries for
  more information, such as the ld(1) and ld.so(8) manual pages.

Verifico:

  $ curl -V
  curl 7.54.0 (x86_64-pc-linux-gnu) libcurl/7.43.0 OpenSSL/1.0.2d zlib/1.2.8 libidn/1.28 librtmp/2.3
  Protocols: dict file ftp ftps gopher http https imap imaps ldap ldaps pop3 pop3s rtmp rtsp smb smbs smtp smtps telnet tftp 
  Features: AsynchDNS IDN IPv6 Largefile GSS-API Kerberos SPNEGO NTLM NTLM_WB SSL libz TLS-SRP UnixSockets

Non c'è SFTP!!

sudo ./configure --with-libssh2=/usr/local/lib

 curl version:     7.54.0
 Host setup:       x86_64-pc-linux-gnu
 Install prefix:   /usr/local
 Compiler:         gcc
 SSL support:      enabled (OpenSSL)
 SSH support:      enabled (libSSH2)
 zlib support:     enabled
 GSS-API support:  no      (--with-gssapi)
 TLS-SRP support:  enabled
 resolver:         default (--enable-ares / --enable-threaded-resolver)
 IPv6 support:     enabled
 Unix sockets support: enabled
 IDN support:      no      (--with-{libidn2,winidn})
 Build libcurl:    Shared=yes, Static=yes
 Built-in manual:  enabled
 --libcurl option: enabled (--disable-libcurl-option)
 Verbose errors:   enabled (--disable-verbose)
 SSPI support:     no      (--enable-sspi)
 ca cert bundle:   /etc/ssl/certs/ca-certificates.crt
 ca cert path:     no
 ca fallback:      no
 LDAP support:     enabled (OpenLDAP)
 LDAPS support:    enabled
 RTSP support:     enabled
 RTMP support:     enabled (librtmp)
 metalink support: no      (--with-libmetalink)
 PSL support:      no      (libpsl not found)
 HTTP2 support:    disabled (--with-nghttp2)
 Protocols:        DICT FILE FTP FTPS GOPHER HTTP HTTPS IMAP IMAPS LDAP LDAPS POP3 POP3S RTMP RTSP SCP SFTP SMB SMBS SMTP SMTPS TELNET TFTP

hint

Installare l'estensione Mysql[modifica]

Cosa strana, avevo installapho php5_mysql ma non c'era traccia nel phpinfo();

Call to undefined function mysql_connect()

Alla fine:

 root@js:/usr/lib/php5/20100525# ll
 totale 1236
 drwxr-xr-x 2 root root   4096 ott 12 18:34 ./
 drwxr-xr-x 6 root root   4096 ott 12 18:04 ../
 -rw-r--r-- 1 root root 699862 feb 26  2014 oci8.so
 -rw-r--r-- 1  500  500  60869 feb 11  2014 package.xml

Manca nella directory /usr/lib/php5/20100525!!! Però c'era nella directory

 root@js:/usr/lib/php5/20121212# ll
 totale 768
 drwxr-xr-x 2 root root   4096 ott 12 18:06 ./
 drwxr-xr-x 6 root root   4096 ott 12 18:04 ../
 -rw-r--r-- 1 root root 142400 lug  7 19:09 mysqli.so
 -rw-r--r-- 1 root root 264368 lug  7 19:09 mysqlnd.so
 -rw-r--r-- 1 root root  51920 lug  7 19:09 mysql.so
 -rw-r--r-- 1 root root 135056 lug  7 19:09 opcache.so
 -rw-r--r-- 1 root root  31624 lug  7 19:09 pdo_mysql.so
 -rw-r--r-- 1 root root 113984 lug  7 19:09 pdo.so
 -rw-r--r-- 1 root root  31472 lug  7 19:09 readline.so

ho copiato i file nell'altra directory

 root@js:/usr/lib/php5/20100525# ll
 totale 1236
 drwxr-xr-x 2 root root   4096 ott 12 18:34 ./
 drwxr-xr-x 6 root root   4096 ott 12 18:04 ../
 -rw-r--r-- 1 root root 142400 ott 12 18:33 mysqli.so
 -rw-r--r-- 1 root root 264368 ott 12 18:33 mysqlnd.so
 -rw-r--r-- 1 root root  51920 ott 12 18:33 mysql.so
 -rw-r--r-- 1 root root 699862 feb 26  2014 oci8.so
 -rw-r--r-- 1  500  500  60869 feb 11  2014 package.xml
 -rw-r--r-- 1 root root  31624 ott 12 18:34 pdo_mysql.so

e ha funzionato tutto.

Installare l'estensione Oracle OCI[modifica]

Parto dalla situazione in cui ho giò Apache2 e PHP5 a bordo.

risorse di riferimento[modifica]

howto[modifica]

http://www.oracle.com/technetwork/articles/technote-php-instant-084410.html

download[modifica]

http://www.oracle.com/technetwork/topics/linuxx86-64soft-092277.html

download instant client[modifica]

  wget http://download.oracle.com/otn/linux/instantclient/11203/instantclient-basic-linux.x64-11.2.0.3.0.zip
  wget http://download.oracle.com/otn/linux/instantclient/11203/instantclient-sdk-linux.x64-11.2.0.3.0.zip
  root@myhost:/usr/lib/oracle/11.2# cp /home/myuser/software/oracle/instantclient-basic-linux.x64-11.2.0.3.0.zip .
  root@myhost:/usr/lib/oracle/11.2# cp /home/myuser/software/oracle/instantclient-sdk-linux.x64-11.2.0.3.0.zip .
  root@myhost:/usr/lib/oracle/11.2# unzip instantclient-basic-linux.x64-11.2.0.3.0.zip
  root@myhost:/usr/lib/oracle/11.2# unzip instantclient-sdk-linux.x64-11.2.0.3.0.zip

If you are using the ZIP files, the SDK should unzipped to the same directory as the basic package, and a symbolic link manually created:

  ln -s libclntsh.so.11.1 libclntsh.so

install the oci8 php library[modifica]

  root@myhost:/usr/lib/oracle/11.2# apt-get install php-pear
  root@myhost:/usr/lib/oracle/11.2# apt-get install php5-dev
  root@myhost:/usr/lib/oracle/11.2# pecl install oci8

Attenzione: da PHP7 in poi questa linea da' queto messaggio:

  # pecl install oci8
  pecl/oci8 requires PHP (version >= 7.0.0), installed version is 5.6.11-1ubuntu3.1
  No valid packages found
  install failed

Ora la versione che ho a bordo è la 5.6.11. In questo caso (vedi qui):

  PHP OCI8 2.1 builds with PHP 7.
  Use 'pecl install oci8' to install OCI8 for PHP 7.
  Use 'pecl install oci8-2.0.10' to install OCI8 for PHP 5.2 - PHP 5.6.
  Use 'pecl install oci8-1.4.10' to install OCI8 for PHP 4.3.9 - PHP 5.1.

Quindi

  root@jsbach:/usr/lib/oracle/11.2# pecl install oci8-2.0.10

ad un certo punto si interrompe e il prompt chiede di scrivere la directory in cui si trova l'instant client.

  checking ORACLE_HOME library validity... configure: error: Expected an ORACLE_HOME top level directory but /usr/lib/oracle/11.2 appears to be an Instant Client directory. 
  Try --with-oci8=instantclient,/usr/lib/oracle/11.2
  instantclient,/usr/lib/oracle/11.2/ <------ AGGIUNGERE QUESTA STRINGA
  Use an explicit, absolute path since PECL does not expand environment variables.
  ...
  Build complete.
  Don't forget to run 'make test'.
  
  running: make INSTALL_ROOT="/tmp/pear/temp/pear-build-rootXRUlXI/install-oci8-2.0.8" install
  Installing shared extensions:     /tmp/pear/temp/pear-build-rootXRUlXI/install-oci8-2.0.8/usr/lib/php5/20121212/
  running: find "/tmp/pear/temp/pear-build-rootXRUlXI/install-oci8-2.0.8" | xargs ls -dils
  8389194   4 drwxr-xr-x 3 root root   4096 gen  7 17:41 /tmp/pear/temp/pear-build-rootXRUlXI/install-oci8-2.0.8
  ...
  Build process completed successfully
  Installing '/usr/lib/php5/20121212/oci8.so'
  install ok: channel://pecl.php.net/oci8-2.0.8
  configuration option "php_ini" is not set to php.ini location
  You should add "extension=oci8.so" to php.ini
  root@myhost:/usr/lib/oracle/11.2#

add "extension=oci8.so" to php.ini[modifica]

  root@myhost:/etc/php5/mods-available# nano oci8.ini
  ; configuration for php Oracle module
  ; priority=20
  extension=oci8.so
  root@myhost:/etc/php5/apache2/conf.d# ln -s ../../mods-available/oci8.ini 20-oci8.ini
  root@myhost:/usr/lib/oracle/11.2# export LD_LIBRARY_PATH=/usr/lib/oracle/11.2/

CRUCIALE: impostare le variabili di ambiente![modifica]

editare /etc/apache2/envvars e aggiungere alla fine

  export LD_LIBRARY_PATH=/usr/lib/oracle/11.2/
  export ORACLE_HOME=/usr/lib/oracle/11.2/
  export TNS_ADMIN=/home/marcob

Importante!!! Add the Instant Client directory to /etc/ld.so.conf, or manually set LD_LIBRARY_PATH to /usr/lib/oracle/11.2/client64/lib. You might also want to set Oracle globalization language environment variables such as TNS_ADMIN and NLS_LANG. If NLS_LANG is not set, a default local environment will be assumed. See the Globalization chapter in The Underground PHP and Oracle Manual for more details.

It is important to set all Oracle environment variables before starting Apache so that the OCI8 process environment is correctly initialized. Setting environment variables in PHP scripts can lead to obvious or non-obvious problems. On Oracle Linux, export environment variables in /etc/sysconfig/httpd. On Debian-based machines set them in /etc/apache2/envvars.

Nota, in effetti ORACLE_HOME non l'ho vsta nel phpinfo() finché non ho impostato anche il TNS_ADMIN

Restart Apache, for example[modifica]

  service httpd restart

per noi

  root@myhost:/usr/lib/oracle/11.2# apache2ctl restart

TROUBLESHOOTING[modifica]

  ORA-12162: TNS:net service name is incorrectly specified
   Cause: The connect descriptor corresponding to the net service name in TNSNAMES.ORA or in the directory server (Oracle Internet Directory) is incorrectly specified.
   Action: If using local naming make sure there are no syntax errors in the corresponding connect descriptor in the TNSNAMES.ORA file. If using directory naming check the information provided through the administration used for directory naming.

soluzione: manca la variabile di ambiente TNS_ADMIN

  ORA-12169: TNS:Net service name given as connect identifier is too long
   Cause: The net service name you are attempting to resolve is too long.
   Action: The maximum length of a net service name is 255 bytes; this limit has been exceeded. Use a smaller net service name. If this is not possible, contact Worldwide Customer Support.

Bisogna risparmiare spazio per i descrittori; ad esempio ho ridotto oracle.name.it a questa stringa

 oracle.name.it=(description=(enable=broken)(failover=on)(load_balance=off)(address=(protocol=tcp)(host=physical.oracle.name.it)(port=1521))(connect_data=
 (service_name=oracle.name.it)(failover_mode=(type=select)(method=basic))))
  ORA-01017: invalid username/password; logon denied

va be' questo non dovrebbe essere un problema

 DEBUG CONTENT:
 
 SQL = select sysdate from dual
 PRM = NULL
 
 Oracle correctly connected!
 array(1) { [0]=> array(1) { ["SYSDATE"]=> string(9) "08-JAN-15" } } 

Funziona.

Però instantclient non funziona con charset diversi da utf8![modifica]

Questo è quello che trovo in questo sito dove è citato un misterioso file /etc/zrc.d che io non trovo nel mio fs. In quest'altro sito c'è un workaround per questo.

Installare estensione GD[modifica]

  $ sudo apt-get install php5-gd

Fare ripartire Apache.

  $ sudo apachectl restart

Per verificare che è stato installato: o così:

  $ php5 -m | grep -i gd
  gd

oppure da una pagina info.php contentente

  <?php phpinfo(); ?>

Problemi di sintassi[modifica]

include[modifica]

Per UNIX

  $ cat foo

e

  $ cat ./foo

è la stessa cosa.

Ad esempio:

  marcob@jsbach:~$ stat tnsnames.ora 
    File: "tnsnames.ora"
    Dim.: 4952      	Blocchi: 16         Blocco di IO: 4096   file regolare
  Device: 801h/2049d	Inode: 2097790     Coll.: 1
  Accesso: (0664/-rw-rw-r--)  Uid: ( 1000/  marcob)   Gid: ( 1000/  marcob)
  Accesso  : 2015-07-14 11:10:02.125345923 +0200
  Modifica : 2015-02-24 10:54:07.532536428 +0100
  Cambio   : 2015-02-24 10:54:07.676536423 +0100
  Creazione: -
  marcob@jsbach:~$ stat ./tnsnames.ora 
    File: "./tnsnames.ora"
    Dim.: 4952      	Blocchi: 16         Blocco di IO: 4096   file regolare
  Device: 801h/2049d	Inode: 2097790     Coll.: 1
  Accesso: (0664/-rw-rw-r--)  Uid: ( 1000/  marcob)   Gid: ( 1000/  marcob)
  Accesso  : 2015-07-14 11:10:02.125345923 +0200
  Modifica : 2015-02-24 10:54:07.532536428 +0100
  Cambio   : 2015-02-24 10:54:07.676536423 +0100
  Creazione: -
  

Per l'istruzione include di PHP invece no.

Normalmente il file da includere sono prima cercati in ogni voce include_path relativa alla directory di lavoro corrente, e quindi nella directory di script corrente.

Ad es., se il vostro include_path è

  libraries, 

la directory di lavoro corrente è

  /www/, 

e avente al suo interno un file alla posizione

  (/www/)include/a.php 

all'interno del quale vi è un direttiva

  include("b.php");

il file b.php viene prima cercato in

  /www/libraries/ 

e poi in

  /www/include/. 

Se il nome del file inizia con ./ o ../, viene cercato solo nella directory di lavoro corrente.

  ./foo 

significa "nella directory corrente".

  foo 

significa "nella directory corrente e nell'include_path".

Esempio completo[modifica]

In questo semplice programma, residente in /var/www/html/ (la DOC_ROOT di Apache), si include una classe (Smarty.class.php) che si trova in

  /usr/local/lib/php/Smarty/libs

Questa versione (senza ./)

  <?php
  include('Smarty.class.php');
  $smarty = new Smarty();
  echo 'ok';
  ?>

produce come output

  ok

Se tento invece questa inclusione

  include('./Smarty.class.php');

si verifica questo errore

  PHP Fatal error:  Class 'Smarty' not found in /var/www/html/include.php on line 5

L'istruzione use[modifica]

[1] Lo scopo della parola chiave use:

Si consideri un caso in cui si dispone di due classi con lo stesso nome; troverete strana questa circostanza, ma quando si lavora con grandi strutture MVC, questo accade. Quindi, se avete due classi con lo stesso nome, mettetele subito in spazi di nomi diversi. Consideriamo ora quando il caricatore automatico sta caricando entrambe le classi (lo fa con l'istruzione require), e si sta per usare un oggetto della classe. In questo caso, il compilatore si confonde su quale oggetto di classe caricare tra i due. Per aiutare il compilatore a prendere una decisione, è possibile utilizzare l'istruzione use in modo che esso possa decidere su quale oggetto utilizzare.

Oggi giorno i moderni framework eseguono questo compito utilizzando le istruzioni include o require attraverso composer e psr autoloader.

Utilizzare questi strumenti può esserti di ulteriore aiuto. È inoltre possibile utilizzare alias per individuare la classe esatta. Immaginadi avere due classi con lo stesso nome, ad esempio Mailer, con due spazi dei nomi diversi:

  namespace SMTP;
  class Mailer {}

e

  namespace Mailgun;
  class Mailer {}

E se si desidera utilizzare entrambe le classi Mailer allo stesso tempo, quindi è possibile utilizzare gli alias.

  use SMTP\Mailer as SMTPMailer;
  use Mailgun\Mailer as MailgunMailer;

e più avanti nel codice, se si vuole accedere a tali oggetti di classe, allora si può fare come segue:

  $smtp_mailer = new SMTPMailer;
  $mailgun_mailer = new MailgunMailer;

e farà riferimento alla loro classe originaria.

Problemi con l'istruzione use[modifica]

PHP Parse error: syntax error, Unexpected use ('T_USE')[modifica]

Spostare le direttive di inclusione all'inizio del file

PHP Fatal error: Class 'Html2Pdf\\Html2Pdf' not found[modifica]

Zend Developer Tools[modifica]

Ho scaricato l'Eclipse PDT 3.0.x All In Ones dal sito della Zend

Download All-In-One package including Eclipse 3.7.2 and PDT 3.0.2 from Zend

Ho installato il pacchetto sotto

  marcob@js:~$ cd Documenti/Marco/software/php/zend-eclipse-php/

(basta fare il tar -x). Quindi, per avviarlo:

  marcob@js:~/Documenti/Marco/software/php/zend-eclipse-php$ ./zend-eclipse-php 

Ho messo il workspace sotto

  marcob@js:~/workspace/php$ 

OOP[modifica]

Qual è la differenza tra metodi/variabili pubblici/protetti/privati?[modifica]

Partiamo con questo esempio: scriviamo una classe Madre con un metodo diCiao() e una proprietà $a, entrambi protetti:

  <?php
  class Madre {
      // proprietà
      protected $a = 10;
  
      // metodi
      protected function diCiao() {
          echo "Hello!";
      }
  }

Estendiamo questa classe ad un'altra classe derivata Figlia con un metodo e una proprietà entrambi public:

   <?php
   include('Madre.php');
   
   class Figlia extends Madre {
   
       public $b;
   
       public function __construct() {
           $this->b = $this->a;
       }
    
       public function diNuovoCiao() {
           $this->diCiao();
       }
    
   }

Come si vede, la variabile pubblica rispecchia il valore della variabile protetta e il metodo pubblico invoca, dall'interno, il metodo protetto; questa tecnica si chiama wrapping ed è una specie di busta con la quale noi possiamo portare all'esterno della classe delle proprietà o metodi che normalmente sarebbero a disposizione della sola classe. È una via di mezzo tra le variabili pubbliche e quelle private.

Ed ora facciamo alcuni test: nei commenti è riportato ciò che succede.

   <?php
   include('Figlia.php');
   
   $Madre = new Madre();
   $Figlia = new Figlia();
   
   // invocazione del metodo diCiao con o senza wrapper
   
   $Figlia->diNuovoCiao(); // tutto ok
   
   $Figlia->diCiao(); // PHP Fatal error:  Call to protected method Madre::diCiao() from context  in est.php on line 12
   
   $Madre->diCiao();  // PHP Fatal error:  Call to protected method Madre::diCiao() from context  in test.php on line 14
   
   //exit();
   
   // stampa la variabile protetta $a
   echo $Madre->a;  // PHP Fatal error:  Cannot access protected property Madre::$a in test.php on line 19
   
   // stampa la variabile protetta $a
   echo $Figlia->a; // PHP Fatal error:  Cannot access protected property Figlia::$a in test.php on line 22
   
   // stampa la variabile pubblica $b
   echo $Figlia->b; // tutto ok;

Quindi le variabili e i metodi protected non possono essere invocati direttamente dalla classe madre né dalla classe figlia, però posso accedere loro attraverso dei wrapper, cioè delle funzioni pubbliche (il metodo diNuovoCiao()) che invocano la funzione protected oppure delle variabili pubbliche (la variabile $b) che assumono il valore delle variabili protected.

Se dichiarassimo private le variabili e i metodi protected, questa tecnica del wrapping non funzionerebbe più. Infatti se dichiariamo private il metodo Madre::sayHello() anziché protected, l'esecuzione del codice sopra test.php si arresta alla linea:

   $Figlia->diNuovoCiao(); // PHP Fatal error:  Call to private method MyClass::sayHello() from context 'AnotherClass' in AnotherClass.php on line 14

Editor PHP[modifica]

Tra gli editor per PHP citiamo, in ordine crescente di completezza, Geany, Adobe Brackets, PHPStorm.

Brackets[modifica]

Appena installato ho subito notato che il font della UI era ridicolmente piccolo. Per poterlo aumentare occorre installare una estensione (ui-too-small). Istruzioni qui (nella parte seconda). In sostanza:

  • aprire il gestore delle estensioni: File > Manager delle estensioni
  • cercare ui-too-small
  • installarlo

Poi Aprire il file di configurazione del plugin:

  .config/Brackets/extensions/user/ui-too-small/main.js

Modificare

  "#quick-view-container *, #function-hint-container *  { font-size: 16px !important;"+

con il valore che si vuole.

Riavviare Brackets.


PHP: interpretato o compilato?[modifica]

Un po' di chiarezza. In pratica oggigiorno PHP funziona un po' come Java.

In Java ho un compilatore che (a comando) produce un bytecode che viene eseguito da una JVM (ad esempio Oracle JVM).

In PHP ho un compilatore che (runtime) produce un bytecode che viene interpretato da uno Zend Engine.

Questo è quento riporato in questo forum:


PHP un linguaggio compilato fin dal PHP 4.0


L'idea su cosa sia un compilatore sembra essere una argomento che genera grande confusione. Alcuni pensano che sia un programma che converte codice sorgente, scritto in un certo linguaggio, in un programma eseguibile. La definizione su cosa sia un compilatore è effettivamente più ampia di questa.

Un compilatore è un programma che trasforma un codice sorgente in un'altra rappresentazione del codice. La rappresentazione finale è spesso codice macchina, ma può anche essere codice in un altro linguaggio o addirittura nello stesso linguaggio.

PHP è divenuto un linguaggio compilato nell'anno 2000, quando PHP 4 fu rilasciato per la prima volta. Fino alla versione 3, il codice sorgente PHP veniva analizzato ed immediatamente eseguito dall'interprete PHP [come il BASIC].

PHP 4 introdusse il motore Zend. Questo motore suddivide il processo del codice PHP in più fasi.

  1. La prima fase analizza il codice sorgente PHP e genera una rappresentazione binaria del codice PHP noto come Zend opcodes [blocco Run-time compiler in figura]. Gli opcodes sono insiemi di istruzioni simili ai bytecodes del Java. Questi opcodes vengono immagazzinati in memoria.
  2. La seconda fase del processo del motore Zend consiste nell'eseguire gli opcodes generati [Blocco Executor in figura]

La struttura di un sistema che è in grado di eseguire codice PHP agganciato ad un web server è illustrata nella figura seguente:

Errore nella creazione della miniatura: Impossibile salvare la miniatura nella destinazione

(Fonte: Developer Knowhow)