Un operatore è un qualcosa che si posiziona tra uno o più valori (od espressioni, in gergo tecnico) e produce un'altro valore (in modo tale che la costruzione stessa diventi a sua volta un'espressione). i
Gli operatori possono essere raggruppati a seconda del numero di valori che trattano. Gli
operatori unari quali richiedono un solo valore, ad esempio !i
(l'operatore logico noti) oppure
++
(l'operatore di autoincremento).
Gli operatori binari accettano due valor, come i familiari
operatori aritmetici
+ (più) e - (meno), e la
maggior parte degli operatori disponibili in PHP ricadono in questa categoria. Infine, esiste un
solo operatore
ternario, ? :, che accetta tre valori; viene
normalmente chiamato "l'operatore ternario" (anche se potrebbe
forse essere chiamato più precisamente operatore condizionale).
Una lista completa degli operatore è fornita nella sezione Precedenza degli operatori. Questa sezione spiega anche la precedenza degli operatori e l'associatività, che stabiliscono esattamente come le espressioni contenenti differenti operatori sono valutate ed eseguite.
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.
Quando gli operatori hanno precedenza identica, la loro associatività decide
come gli operatori sono raggruppati. Per esempio "-" è associativo a sinistra, quindi
1 - 2 - 3 è raggruppato come (1 - 2) - 3
e valutato come -4. D'altra parte "=" è
associativo a destra, quindi $a = $b = $c è raggruppato come
$a = ($b = $c).
Operatori di uguale precedenza che non sono associativi non possono essere usati
vicini l'uno all'altro, per esempio 1 Lt 2 Gt 1 è
illegale in PHP. D'altra parte l'espressione 1 Lt= 1 == 1
è legale, perchè l'operatore == ha una minore
precedenza dell'operatore Lt=.
L'associatività è significativa solo per gli operatori binari (e ternari).
Gli operatori unari sono prefisso o suffisso, quindi questa nozione non è applicabile.
Ad esempio !!$a può essere raggruppato solo come !(!$a).
L'uso delle parentesi, anche quando non strettamente necessario, può spesso aumentare la leggibilità del codice rendendo il raggruppamento esplicito piuttosto che fare affidamento sulla precedenza e sull'associatività implicite degli operatori.
La seguente tabella fornisce una lista della precedenza degli operatori con gli
operatori a più alta precedenza elencati prima. Gli operatori presenti nella medesima linea
hanno uguale precedenza, in questi casi la loro associativià decide il raggruppamento.
Precedenza degli operatori
Associatività
Operatori
Informazioni aggiuntive
(n/a)
clone
new
clone e new
destra
**
operatori aritmetici
(n/a)
+
-
++
--
~
(int)
(float)
(string)
(array)
(object)
(bool)
@
aritmetici (unari + e -),
incremento/decremento,
bitwise,
casting del tipoListendand
controllo dell'errore
sinistra
instanceof
tipo
(n/a)
!
logici
sinistra
*
/
%
aritmetici
sinistra
+
-
.
aritmetici (binari + e -),
arrayListendand
stringhe (. prima di PHP 8.0.0)
sinistra
LtLt
GtGt
bit
sinistra
.
stringhe (a partire da PHP 8.0.0)
non associativi
Lt
Lt=
Gt
Gt=
confronto
non associativi
==
!=
===
!==
LtGt
Lt=Gt
operatori di confronto
sinistra
Amp
operatori sui bitListendand
riferimenti
sinistra
^
operatori sui bit
sinistra
|
operatori sui bit
sinistra
AmpAmp
operatori logici
sinistra
||
operatori logici
destra
??
null coalescing
non associativi
? :
ternari
(associativi a sinistra prima di PHP 8.0.0)
sinistra
=
+=
-=
*=
**=
/=
.=
%=
Amp=
|=
^=
LtLt=
GtGt=
??=
operatori di assegnazione
(n/a)
yield from
yield from
(n/a)
yield
yield
(n/a)
print
print
sinistra
and
operatori logici
sinistra
xor
operatori logici
sinistra
or
operatori logici
Associatività <?php $a = 3 * 3 % 5; // (3 * 3) % 5 = 4 // l'associatività dell'operatore ternario differisce da quella di C/C++ $a = true ? 0 : true ? 1 : 2; // (true ? 0 : true) ? 1 : 2 = 2 (prima di PHP 8.0.0) $a = 1; $b = 2; $a = $b += 3; // $a = ($b += 3) -> $a = 5, $b = 5 ?>
La precedenza e l'associatività dell'operatore determinano solo come le espressioni
sono raggruppate, esse non specificano un ordine di valutazione. PHP non
specifica (nel caso generale) in quale ordine un'espressione è valutata
e un codice che presuppone uno specifico ordine di valutazione dovrebbe essere evitato,
perchè il comportamento può cambiare tra le versioni di PHP o in base al
codice circostante.
Ordine di valutazione indefinito
<?php
$a = 1;
echo $a + $a++; // può stampare 2 o 3
$i = 1;
$array[$i] = $i++; // può impostare l'indice 1 o 2
?>
+, - e . hanno la stessa precedenza (prima di PHP 8.0.0)
<?php
$x = 4;
// questa linea potrebbe causare un risultato inaspettato:
echo "x minus one equals " . $x-1 . ", or so I hope\n";
// perché è valutata come questa linea (prima di PHP 8.0.0):
echo (("x minus one equals " . $x) - 1) . ", or so I hope\n";
// la precedenza desiderata può essere forzata usando le parentesi:
echo "x minus one equals " . ($x-1) . ", or so I hope\n";
?>
Example outputs
-1, or so I hope
-1, or so I hope
x minus one equals 3, or so I hope
= abbia una precedenza minore rispetto
alla maggior parte degli altri operatori, PHP permette comunque espressioni
simili alla seguente: if (!$a = foo()),
in questo caso l'output di foo() viene
inserito in $a.
.+-LtLtGtGt+-LtLtGtGt8.0.0
L'operatore ternario () ora è non-associativo;
precedentemente era associativo a sinistra.
? :7.4.0
Fare affidamento sulla precedenza della concatenazione di stringhe () rispetto all'
addizione/sottrazione aritmetica ( o ) o
lo spostamento bit a bit a sinistra/destra ( o ),
ovvero utilizzarli insieme in un'espressione senza parentesi, è deprecato.
.+-LtLtGtGt7.4.0
Fare affidamento sull'associatività a sinistra dell'operatore ternario (),
ovvero annidare più operatori ternari senza parentesi, è deprecato.
? :Ricordate l'aritmetica di base dalla scuola? Questi operatori funzionano esattamente nello stesso modo.
Operatori aritmeticiEsempioNomeRisultato+$aIdentità Conversione di in o in modo appropriato. $aintfloat-$aNegazioneOpposto di .$a$a + $bAddizioneLa somma di e .$a$b$a - $bSottrazioneLa differenza di e .$a$b$a * $bMoltiplicazioneil prodotto di e .$a$b$a / $bDivisioneQuoziente di e .$a$b$a % $bModuloIl resto di diviso da .$a$b$a ** $bElevamento a potenzaRisultato di elevazione alla esima potenza.$a$bL'operatore di divisione ("/") restituisce un valore float a meno che i due operandi siano interi (oppure stringhe che vengono convertite in interi) e i numeri siano divisibili, nel qual caso viene restituito un valore intero. Per le divisioni di interi, vedere intdiv.
Gli operandi del modulo sono convertiti in int prima dell'operazione. Per il modulo di numeri a virgola mobile, vedere fmod.
Il risultato dell'operatore modulo % ha lo stesso segno
del dividendo - ovvero, il risultato di $a % $b
avrà lo stesso segno di $a. Per esempio:
<?php
echo (5 % 3)."\n"; // prints 2
echo (5 % -3)."\n"; // prints 2
echo (-5 % 3)."\n"; // prints -2
echo (-5 % -3)."\n"; // prints -2
?>
L'operatore di base dell'assegnazione è "=". Il primo impulso può essere quello di pensare che corrisponda a "uguale a". Invece questo operatore significa che l'operando a sinistra assume il valore dell'espressione a destra (cioè, "assegna il valore a").
Il valore di un'espressione di assegnazione è il valore assegnato. Ovvero il valore di "$a = 3" è 3. Questo permette di fare qualche trucchetto: <?php $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 consentono di usare un valore in un'espressione e poi impostare il suo valore al risultato di quell'espressione. Per esempio: <?php $a = 3; $a += 5; // imposta $a a 8, corrispondente a: $a = $a + 5; $b = "Ciao "; $b .= "come va?"; // imposta $b a "Ciao come va?", proprio come $b = $b . "come va?"; ?>
Si noti che l'assegnazione copia la variabile originale nella nuova (assegnazione per valore), così i cambiamenti della prima non si verificheranno nell' altra. Ciò può anche avere rilevanza se si ha bisogno di copiare un grande array in un ciclo molto stretto.
Un'eccezione al comportamento standard dell'assegnazione per valore avviene con gliobject, che sono assegnati per riferimento. Gli oggetti possono essere copiati esplicitamente attraverso la keyword clone.
Assegnazione per referimento
L'assegnazione per riferimento è pure supportato, usando la sintassi "$var = Amp$othervar;. 'Assegnazione per riferimento' significa che entrambe le variabili finiscono con il puntare agli stessi dati, e nulla è copiato.
Assegnare per riferimento <?php $a = 3; $b = &$a; // $b è un riferimento ad $a print "$a\n"; // stampa 3 print "$b\n"; // stampa 3 $a = 4; // modifica $a print "$a\n"; // stampa 4 print "$b\n"; // stampa ugualmente 4, dal momento che $b è un riferimento ad $a, che è // stata modificata ?>
L'operatore new restituisce automaticamente un riferimento, quindi assegnare il risultato di new per riferimento è un errore.
<?php class C {} $o = &new C; ?> Example outputs Parse error: syntax error, unexpected 'new' (T_NEW) in …
Ulteriori informazioni sui riferimenti e sul loro uso possono essere trovati nella sezione del manuale Spiegazioni sui riferimenti.
Operatori di Assegnamento Aritmetici
EsempioEquivalenteOperazione$a += $b$a = $a + $bAddizione$a -= $b$a = $a - $bSottrazione$a *= $b$a = $a * $bMoltiplicazione$a /= $b$a = $a / $bDivisione$a %= $b$a = $a % $bModulo$a **= $b$a = $a ** $bEsponenzialeOperatori di Assegnazione Bit A Bit
EsempioEquivalenteOperazione$a Amp= $b$a = $a Amp $bAnd Bit a Bit$a |= $b$a = $a | $bOr Bit a Bit$a ^= $b$a = $a ^ $bXor Bit a Bit$a LtLt= $b$a = $a LtLt $bShift a Sinistra$a GtGt= $b$a = $a GtGt $bShift a DestraAltri Operatori di Assegnamento
EsempioEquivalenteOperazione$a .= $b$a = $a . $bConcatenazione di stringhe$a ??= $b$a = $a ?? $bNull CoalesceGli operatori sui bit permettono la valutazione e manipolazione di specifici bit in un valore intero.
Operatori sui bitEsempioNomeRisultato$a Amp $bAndVengono accesi i bit che sono accesi sia in che in .$a$b$a | $bOr (inclusive or)Vengono accesi i bit che sono accesi o in oppure in .$a$b$a ^ $bXor (exclusive or) Vengono accesi i bit che sono accesi in o in , ma non quelli accesi in entrambe le variabili. $a$b~ $aNot Vengono accesi i bit che sono spenti in , e viceversa $a$a LtLt $bShift left Sposta verso sinistra i bit di per volte (ogni passo significa "moltiplica per due") $a$b$a GtGt $bShift right Sposta verso destra i bit di per volte (ogni passo significa "dividi per due") $a$bLo spostamento di bit in PHP è aritmetico. I bit spostati al di fuori delle estremità sono scartati. Gli spostamenti a sinistra inseriscono zeri a destra mentre il bit di segno è scartato sulla sinistra, quindi il segno di un operando non è conservato. Gli spostamenti a destra copiano il bit di segno sulla sinistra, quindi il segno di un operando è conservato.
Utilizzare le parentesi per assicurare la
precedenza desiderata.
Per esempio, $a Amp $b == true valuta
l'equivalenza e poi l'operatore and; mentre
($a Amp $b) == true valuta l'operatore and e
poi l'equivalenza.
Se entrambi gli operandi per il operatori Amp, |
e ^ sono stringhe, allora l'operazione verrà
eseguita sui valori ASCII dei caratteri che compongono le stringhe e
il risultato sarà una stringa. In tutti gli altri casi, entrambi gli operandi saranno
convertiti in interi
e il risultato sarà un intero.
Se l'operando per l'operatore ~ è una stringa,
l'operazione verrà eseguita sui valori ASCII dei caratteri che compongono
la stringa e il risultato sarà una stringa, altrimenti l'operando e il
risultato saranno trattati come interi.
Sia gli operandi che il risultato per gli operatori LtLt
e GtGt sono sempre trattati come interi.
L'opzione ini error_reporting di PHP usa valori imappati sui bit,
fornendo quindi una dimostrazione reale dello spegnimento
dei bit. Per mostrare tutti gli errori, eccettuati gli avvisi,
le istruzioni del file php.ini dicono di usare:
E_ALL Amp ~E_NOTICE
Si prende il valore di E_ALL:
00000000000000000111011111111111
Quindi quello di E_NOTICE...
00000000000000000000000000001000
... e lo si inverte con ~:
11111111111111111111111111110111
infine, si usa AND (Amp) pre trovare i bit che sono accesi
in entrambi i valori:
00000000000000000111011111110111
Un altro metodo per ottenere questo risultato è usare XOR (^)
per trovare i bit che sono accesi solo in uno dei due operandi:
E_ALL ^ E_NOTICE
error_reporting può essere usata anche per dimostrare come accendere i bit.
Il modo per mostrare solo gli errori e gli errori recuperabili è:
E_ERROR | E_RECOVERABLE_ERROR
Questo processo combina E_ERROR
00000000000000000000000000000001
e
00000000000000000001000000000000
usando l'operatore OR (|)
per recuperare i bit accesi in entrambi i valori:
00000000000000000001000000000001
Operazioni AND, OR e XOR su interi <?php /* * Ignorare la sezione iniziale, * server solo a formattare per rendere più leggibile il risultato. */ $format = '(%1$2d = %1$04b) = (%2$2d = %2$04b)' . ' %3$s (%4$2d = %4$04b)' . "\n"; echo <<<EOH --------- --------- -- --------- risultato valore op test --------- --------- -- --------- EOH; /* * Ecco gli esempi. */ $values = array(0, 1, 2, 4, 8); $test = 1 + 4; echo "\n Bitwise AND \n"; foreach ($values as $value) { $result = $value & $test; printf($format, $result, $value, '&', $test); } echo "\n Bitwise Inclusive OR \n"; foreach ($values as $value) { $result = $value | $test; printf($format, $result, $value, '|', $test); } echo "\n Bitwise Exclusive OR (XOR) \n"; foreach ($values as $value) { $result = $value ^ $test; printf($format, $result, $value, '^', $test); } ?> Example outputs --------- --------- -- --------- 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) Bitwise Exclusive OR (XOR) ( 5 = 0101) = ( 0 = 0000) ^ ( 5 = 0101) ( 4 = 0100) = ( 1 = 0001) ^ ( 5 = 0101) ( 7 = 0111) = ( 2 = 0010) ^ ( 5 = 0101) ( 1 = 0001) = ( 4 = 0100) ^ ( 5 = 0101) (13 = 1101) = ( 8 = 1000) ^ ( 5 = 0101)
Operazioni XOR su stringhe <?php echo 12 ^ 9; // Ritorna '5' echo "12" ^ "9"; // Ritorna il carattere Backspace (ascii 8) // ('1' (ascii 49)) ^ ('9' (ascii 57)) = #8 echo "hallo" ^ "hello"; // Ritorna i valori ascii #0 #4 #0 #0 #0 // 'a' ^ 'e' = #4 echo 2 ^ "3"; // Ritorna 1 // 2 ^ ((int)"3") == 1 echo "2" ^ 3; // Ritorna 1 // ((int)"2") ^ 3 == 1 ?>
Spostamento di bit su interi <?php /* * Ecco gli esempi. */ echo "\n--- SPOSTAMENTO A DESTRA SU INTERI POSITIVI ---\n"; $val = 4; $places = 1; $res = $val >> $places; p($res, $val, '>>', $places, 'copia del bit di segno inserito a sinistra'); $val = 4; $places = 2; $res = $val >> $places; p($res, $val, '>>', $places); $val = 4; $places = 3; $res = $val >> $places; p($res, $val, '>>', $places, 'i bit escono dal lato destro'); $val = 4; $places = 4; $res = $val >> $places; p($res, $val, '>>', $places, 'come sopra; non c'è spostamento oltre lo 0'); echo "\n--- SPOSTAMENTO A SINISTRA SU INTERI NEGATIVI ---\n"; $val = -4; $places = 1; $res = $val >> $places; p($res, $val, '>>', $places, 'copia del bit di segno inserito a sinistra'); $val = -4; $places = 2; $res = $val >> $places; p($res, $val, '>>', $places, 'i bit escono dal lato destro'); $val = -4; $places = 3; $res = $val >> $places; p($res, $val, '>>', $places, 'come sopra; non c'è spostamento oltre il -1'); echo "\n--- SPOSTAMENTO A SINISTRA SU INTERI POSITIVI ---\n"; $val = 4; $places = 1; $res = $val << $places; p($res, $val, '<<', $places, 'zeri inseriti a destra'); $val = 4; $places = (PHP_INT_SIZE * 8) - 4; $res = $val << $places; p($res, $val, '<<', $places); $val = 4; $places = (PHP_INT_SIZE * 8) - 3; $res = $val << $places; p($res, $val, '<<', $places, 'i bit di segno sono spostati'); $val = 4; $places = (PHP_INT_SIZE * 8) - 2; $res = $val << $places; p($res, $val, '<<', $places, 'i bit escono dal lato sinistro'); echo "\n--- SPOSTAMENTO A SINISTRA SU INTERI NEGATIVI ---\n"; $val = -4; $places = 1; $res = $val << $places; p($res, $val, '<<', $places, 'zeri inseriti a destra'); $val = -4; $places = (PHP_INT_SIZE * 8) - 3; $res = $val << $places; p($res, $val, '<<', $places); $val = -4; $places = (PHP_INT_SIZE * 8) - 2; $res = $val << $places; p($res, $val, '<<', $places, 'i bit escono dal lato sinistro, incluso il bit di segno'); /* * Ignorare questa sezione finale, * server solo a formattare per rendere più leggibile il risultato. */ function p($res, $val, $op, $places, $note = '') { $format = '%0' . (PHP_INT_SIZE * 8) . "b\n"; printf("Espressione: %d = %d %s %d\n", $res, $val, $op, $places); echo " Decimale:\n"; printf(" val=%d\n", $val); printf(" res=%d\n", $res); echo " Binario:\n"; printf(' val=' . $format, $val); printf(' res=' . $format, $res); if ($note) { echo " NOTA: $note\n"; } echo "\n"; } ?> Example outputs 32bit --- SPOSTAMENTO A DESTRA SU INTERI POSITIVI --- Espressione: 2 = 4 >> 1 Decimale: val=4 res=2 Binario: val=00000000000000000000000000000100 res=00000000000000000000000000000010 NOTA: copia del bit di segno inserito a sinistra Espressione: 1 = 4 >> 2 Decimale: val=4 res=1 Binario: val=00000000000000000000000000000100 res=00000000000000000000000000000001 Espressione: 0 = 4 >> 3 Decimale: val=4 res=0 Binario: val=00000000000000000000000000000100 res=00000000000000000000000000000000 NOTA: i bit escono dal lato destro Espressione: 0 = 4 >> 4 Decimale: val=4 res=0 Binario: val=00000000000000000000000000000100 res=00000000000000000000000000000000 NOTA: come sopra; non c'è spostamento oltre lo 0 --- SPOSTAMENTO A DESTRA SU INTERI NEGATIVI --- Espressione: -2 = -4 >> 1 Decimale: val=-4 res=-2 Binario: val=11111111111111111111111111111100 res=11111111111111111111111111111110 NOTA: copia del bit di segno inserito a sinistra Espressione: -1 = -4 >> 2 Decimale: val=-4 res=-1 Binario: val=11111111111111111111111111111100 res=11111111111111111111111111111111 NOTA: i bit escono dal lato destro Espressione: -1 = -4 >> 3 Decimale: val=-4 res=-1 Binario: val=11111111111111111111111111111100 res=11111111111111111111111111111111 NOTA: come sopra; non c'è spostamento oltre il -1 --- SPOSTAMENTO A SINISTRA SU INTERI POSITIVI --- Espressione: 8 = 4 << 1 Decimale: val=4 res=8 Binario: val=00000000000000000000000000000100 res=00000000000000000000000000001000 NOTA: zeri inseriti a destra Espressione: 1073741824 = 4 << 28 Decimale: val=4 res=1073741824 Binario: val=00000000000000000000000000000100 res=01000000000000000000000000000000 Espressione: -2147483648 = 4 << 29 Decimale: val=4 res=-2147483648 Binario: val=00000000000000000000000000000100 res=10000000000000000000000000000000 NOTA:i bit di segno sono spostati Espressione: 0 = 4 << 30 Decimale: val=4 res=0 Binario: val=00000000000000000000000000000100 res=00000000000000000000000000000000 NOTA: i bit escono dal lato sinistro --- SPOSTAMENTO A SINISTRA SU INTERI NEGATIVI --- Espressione: -8 = -4 << 1 Decimale: val=-4 res=-8 Binario: val=11111111111111111111111111111100 res=11111111111111111111111111111000 NOTA: zeri inseriti a destra Espressione: -2147483648 = -4 << 29 Decimale: val=-4 res=-2147483648 Binario: val=11111111111111111111111111111100 res=10000000000000000000000000000000 Espressione: 0 = -4 << 30 Decimale: val=-4 res=0 Binario: val=11111111111111111111111111111100 res=00000000000000000000000000000000 NOTA: i bit escono dal lato sinistro, incluso il bit di segno Example outputs 64bit --- SPOSTAMENTO A DESTRA SU INTERI POSITIVI --- Espressione: 2 = 4 >> 1 Decimale: val=4 res=2 Binario: val=0000000000000000000000000000000000000000000000000000000000000100 res=0000000000000000000000000000000000000000000000000000000000000010 NOTA: copia del bit di segno inserito a sinistra Espressione: 1 = 4 >> 2 Decimale: val=4 res=1 Binario: val=0000000000000000000000000000000000000000000000000000000000000100 res=0000000000000000000000000000000000000000000000000000000000000001 Espressione: 0 = 4 >> 3 Decimale: val=4 res=0 Binario: val=0000000000000000000000000000000000000000000000000000000000000100 res=0000000000000000000000000000000000000000000000000000000000000000 NOTA: i bit escono dal lato destro Espressione: 0 = 4 >> 4 Decimale: val=4 res=0 Binario: val=0000000000000000000000000000000000000000000000000000000000000100 res=0000000000000000000000000000000000000000000000000000000000000000 NOTA: come sopra; non c'è spostamento oltre lo 0 --- SPOSTAMENTO A DESTRA SU INTERI NEGATIVI --- Espressione: -2 = -4 >> 1 Decimale: val=-4 res=-2 Binario: val=1111111111111111111111111111111111111111111111111111111111111100 res=1111111111111111111111111111111111111111111111111111111111111110 NOTA: copia del bit di segno inserito a sinistra Espressione: -1 = -4 >> 2 Decimale: val=-4 res=-1 Binario: val=1111111111111111111111111111111111111111111111111111111111111100 res=1111111111111111111111111111111111111111111111111111111111111111 NOTA: i bit escono dal lato destro Espressione: -1 = -4 >> 3 Decimale: val=-4 res=-1 Binario: val=1111111111111111111111111111111111111111111111111111111111111100 res=1111111111111111111111111111111111111111111111111111111111111111 NOTA: come sopra; non c'è spostamento oltre il -1 --- SPOSTAMENTO A SINISTRA SU INTERI POSITIVI --- Espressione: 8 = 4 << 1 Decimale: val=4 res=8 Binario: val=0000000000000000000000000000000000000000000000000000000000000100 res=0000000000000000000000000000000000000000000000000000000000001000 NOTA: zeri inseriti a destra Espressione: 4611686018427387904 = 4 << 60 Decimale: val=4 res=4611686018427387904 Binario: val=0000000000000000000000000000000000000000000000000000000000000100 res=0100000000000000000000000000000000000000000000000000000000000000 Espressione: -9223372036854775808 = 4 << 61 Decimale: val=4 res=-9223372036854775808 Binario: val=0000000000000000000000000000000000000000000000000000000000000100 res=1000000000000000000000000000000000000000000000000000000000000000 NOTA: i bit di segno sono spostati Espressione: 0 = 4 << 62 Decimale: val=4 res=0 Binario: val=0000000000000000000000000000000000000000000000000000000000000100 res=0000000000000000000000000000000000000000000000000000000000000000 NOTA: i bit escono dal lato sinistro --- SPOSTAMENTO A SINISTRA SU INTERI NEGATIVI --- Espressione: -8 = -4 << 1 Decimale: val=-4 res=-8 Binario: val=1111111111111111111111111111111111111111111111111111111111111100 res=1111111111111111111111111111111111111111111111111111111111111000 NOTA: zeri inseriti a destra Espressione: -9223372036854775808 = -4 << 61 Decimale: val=-4 res=-9223372036854775808 Binario: val=1111111111111111111111111111111111111111111111111111111111111100 res=1000000000000000000000000000000000000000000000000000000000000000 Espressione: 0 = -4 << 62 Decimale: val=-4 res=0 Binario: val=1111111111111111111111111111111111111111111111111111111111111100 res=0000000000000000000000000000000000000000000000000000000000000000 NOTA: i bit escono dal lato sinistro, incluso il bit di segno
PHP_INT_MAX.
pack unpack gmp_and gmp_or gmp_xor gmp_testbit gmp_clrbit
Gli operatori di confronto, come suggerisce il loro nome, permettono di confrontare due valori. Può essere interessante vedere la tabella di raffronto dei tipi, dato che mostra esempi di vari confronti tra i tipi di variabili.
Operatori di confrontoEsempioNomeRisultato$a == $bUguale se è uguale a dopo la manipolazione dei tipi.true$a$b$a === $bIdentico
se è uguale a , ed sono dello stesso
tipo.
true$a$b$a != $bDiversi se è diverso da dopo la manipolazione dei tipi.true$a$b$a LtGt $bDiversi se è diverso da dopo la manipolazione dei tipi.true$a$b$a !== $bNon identici
se è diverso da , o se non sono dello stesso
tipo.
true$a$b$a Lt $bMinore se è strettamente minore di .true$a$b$a Gt $bMaggiore se è strettamente maggiore di .true$a$b$a Lt= $bMinore o uguale se è minore o uguale a .true$a$b$a Gt= $bMaggiore o uguale se è maggiore o uguale a .true$a$b$a Lt=Gt $bSpaceship
Un minore di, uguale a, o maggiore di zero quando
è minore di, uguale a, o maggiore di
.
int$a$b
Se entrambi gli operandi sono
stringhe numeriche
o un operando è un numero e l'altro è una
stringa numerica,
quindi il confronto viene eseguito numericamente.
Queste regole si applicano anche all'
istruzione switch.
La conversione del tipo non ha luogo quando il confronto è
=== o !== poiché implica
il confronto del tipo e del valore.
<?php // Interi echo 1 <=> 1; // 0 echo 1 <=> 2; // -1 echo 2 <=> 1; // 1 // Numeri float echo 1.5 <=> 1.5; // 0 echo 1.5 <=> 2.5; // -1 echo 2.5 <=> 1.5; // 1 // Stringhe echo "a" <=> "a"; // 0 echo "a" <=> "b"; // -1 echo "b" <=> "a"; // 1 echo "a" <=> "aa"; // -1 echo "zz" <=> "aa"; // 1 // Array echo [] <=> []; // 0 echo [1, 2, 3] <=> [1, 2, 3]; // 0 echo [1, 2, 3] <=> []; // 1 echo [1, 2, 3] <=> [1, 2, 1]; // 1 echo [1, 2, 3] <=> [1, 2, 4]; // -1 // Oggetti $a = (object) ["a" => "b"]; $b = (object) ["a" => "b"]; echo $a <=> $b; // 0 $a = (object) ["a" => "b"]; $b = (object) ["a" => "c"]; echo $a <=> $b; // -1 $a = (object) ["a" => "c"]; $b = (object) ["a" => "b"]; echo $a <=> $b; // 1 // non vengono confrontati solo i valori; le chiavi devono corrispondere $a = (object) ["a" => "b"]; $b = (object) ["b" => "b"]; echo $a <=> $b; // 1 ?>
Se i tipi di operandi utilizzati differiscono, il confronto viene svolto nell'ordine indicato della seguente tabella.
Confronti con differenti tipiTipo dell'operando 1Tipo dell'operando 2Risultato oppure nullstringstringSi converte in "", confronto numerico o lessicalenull oppure boolnullqualsiasiConverte entrambi i lati in , Lt boolfalsetrueobjectobjectLe classi predefinite possono avere la propria funzione di confronto, classi differenti
non sono confrontabili, per la stessa classe vedere .
Confronto di Oggetti, , oppure stringresourceintfloat, , oppure stringresourceintfloatStringhe e risorse sono converti in numeri, confronto matematicoarrayarrayLa matrice con meno membri è più piccola, se la chiave dell'operando 1 non si
trova nell'operando 2 allora le matrici non si possono confrontare, in altri casi
il confronto avviene valore per valore (vedere l'esempio seguente)objectqualsiasi è sempre più grandeobjectarrayqualsiasi è sempre più grandearrayConfronto Boolean/null <?php // Bool e null sono confrontati sempre come bool var_dump(1 == TRUE); // TRUE - uguale a (bool)1 == TRUE var_dump(0 == FALSE); // TRUE - uguale a (bool)0 == FALSE var_dump(100 < TRUE); // FALSE - uguale a (bool)100 < TRUE var_dump(-10 < FALSE);// FALSE - uguale a (bool)-10 < FALSE var_dump(min(-100, -10, NULL, 10, 100)); // NULL - (bool)NULL < (bool)-100 è FALSE < TRUE ?>
Trascrizione del confronto standard tra matrici <?php // Gli array vengono confrontati in questo modo con gli operatori di confronto standard e con l'operatore spaceship. function standard_array_compare($op1, $op2) { if (count($op1) < count($op2)) { return -1; // $op1 < $op2 } elseif (count($op1) > count($op2)) { return 1; // $op1 > $op2 } foreach ($op1 as $key => $val) { if (!array_key_exists($key, $op2)) { return 1; } elseif ($val < $op2[$key]) { return -1; } elseif ($val > $op2[$key]) { return 1; } } return 0; // $op1 == $op2 } ?>
=== e !== piuttosto che
== e != nella maggior parte dei casi.
Incomparable Values
Mentre il confronto di identità (=== e !==)
può essere applicato a valori arbitrari, gli altri operatori di confronto dovrebbero essere applicati
solo a valori comparabili. Il risultato del confronto di valori incomparabili non
è definito e non dovrebbe essere considerato attendibile.
strcasecmp strcmp Operatori degli array Tipi
Operatore ternario
Un altro operatore condizionale è l'operatore ternario "?:".
Assegnazione di un valore di default
<?php
// Esempio di utilizzo dell'operatore ternario
$action = (empty($_POST['action'])) ? 'default' : $_POST['action'];
// La riga precedente è simile a
if (empty($_POST['action'])) {
$action = 'default';
} else {
$action = $_POST['action'];
}
?>
L'espressione (espressione1) ? (espressione2) : (espressione3)
vale espressione2 se
espressione1 è true, e
espressione3 se
espressione1 è false.
È possibile tralasciare l'elemento centrale dell'operatore ternario.
L'espressione espressione1 ?: espressione3 viene valutata
al risultato di espressione1 se espressione1
viene valutata true, e espressione3 in caso contrario.
espressione1 viene valutata solo una volta.
return $var == 42 ? $a : $b; in una funzione
che restituisce per riferimento non funzionerà e genererà un
avvertimento.
?:), tuttavia, è stabile e si comporta in modo ragionevole.
Verrà valutato al primo argomento valutato come valore non falso. Si noti che i valori non
definiti genereranno comunque un avviso.
Concatenamento ternario breve
<?php
echo 0 ?: 1 ?: 2 ?: 3, PHP_EOL; //1
echo 0 ?: 0 ?: 2 ?: 3, PHP_EOL; //2
echo 0 ?: 0 ?: 0 ?: 3, PHP_EOL; //3
?>
L'operatore Null Coalescing
Un altro utile operatore abbreviato è il "??" (o null coalescing).
Assegnazione di un valore predefinito
<?php
// Esempio di utilizzo per: Operatore Null Coalesce
$action = $_POST['action'] ?? 'default';
// Quello sopra è identico a questa istruzione if/else
if (isset($_POST['action'])) {
$action = $_POST['action'];
} else {
$action = 'default';
}
?>
L'espressione (expr1) ?? (expr2) viene valutata a
expr2 se expr1 è
null, e expr1 in caso contrario.
In particolare, questo operatore non emette un avviso o un avvertimento se il valore del lato sinistro non esiste, proprio come isset. Questo è particolarmente utile sulle chiavi degli array.
return $foo ?? $bar; in una funzione
che restituisce un riferimento quindi non funzionerà e verrà emesso un
avviso.
PHP supporta un operatore di controllo dell'errore: il carattere at (@).
Quando viene anteposto ad una espressione in PHP, qualunque messaggio di errore che possa
essere generato da quella espressione sarà soppresso.
Se è stata assegnata una funzione personalizzata di gestione degli errori con set_error_handler questa verrà comunque chiamata, anche se la diagnostica è stata soppressa.
0 se l'errore veniva soppresso dall'operatore @.
A partire da PHP 8.0.0, restituisce il valore E_ERROR | E_CORE_ERROR | E_COMPILE_ERROR | E_USER_ERROR | E_RECOVERABLE_ERROR | E_PARSE.
Qualsiasi messaggio di errore generato dall'espressione è disponibile nell'elemento
"message" dell'array restituito da error_get_last.
Il risultato di quella funzione cambierà ad ogni errore, quindi deve essere controllato in anticipo.
<?php /* Errore di file intenzionale */ $my_file = @file ('file_inesistente') or die ("Apertura del file fallita: l'errore è stato '" . error_get_last()['message'] . "'"); // questo funziona per qualsiasi espressione, non solo funzioni: $value = @$cache[$key]; // non verrà generata una notifica se l'indice $key non esiste. ?>
@ funziona solo sulle
espressioni.
Una semplice regola è: se si può ottenere il valore di qualcosa,
allora si può anteporre ad esso l'operatore @.
Per esempio, si può anteporre a variabili, chiamate di funzioni,
determinate chiamate di costrutti di linguaggio (per esempio include),
e così via.
Non si può anteporre a definizioni di funzioni o classi,
o strutture condizionali come if e
foreach, e così via.
@
disabilitare gli errori critici che interrompevano l'esecuzione dello script.
Ad esempio, anteporre @ ad una chiamata di una funzione
che non esiste, non essendo disponibile o digitata in modo errato, causerebbe
il termine dello script senza alcuna indicazione sul perché.
error_reporting Funzioni di Gestione degli Errori e Logging
PHP supporta un operatore di esecuzione: backticks (``). Si noti che non sono apostrofi o apici! PHP cercherà di eseguire il contenuto dei backticks come comando di shell; sarà restituito l'output (ovvero, non sarà semplicemente inviato all'output, ma potrà essere assegnato ad una variabile). L'uso dell'operatore backtick è identico alla funzione shell_exec. <?php $output = `ls -al`; echo "<pre>$output</pre>"; ?>
PHP supporta lo stile C degli operatori di pre- e post-incremento e decremento.
null non ha effetti, ma incrementarlo
darà come risultato 1.
Un semplice script di esempio: <?php echo "<h3>Postincrement</h3>"; $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"; ?>
Il PHP segue le convenzioni di Perl e non del C quando tratta le operazioni matematiche
sui caratteri. Ad esempio, in PHP e Perl
$a = 'Z'; $a++; modifica $a in 'AA', mentre in C
a = 'Z'; a++; modifica a in '['
(il valore ASCII di 'Z' è 90, quello di '[' è 91).
Si noti che le variabili carattere possono essere incrementate ma non decrementate e
anche in questo caso solo i caratteri e i numeri ASCII (a-z, A-Z e 0-9) sono supportati.
Incrementare/decrementare altre variabili di carattere non ha effetto, la
stringa originale non viene modificata.
Operazioni aritmetiche su variabili carattere
<?php
echo '== Alphabets ==' . PHP_EOL;
$s = 'W';
for ($n=0; $n<6; $n++) {
echo ++$s . PHP_EOL;
}
// I caratteri numerici si comportano diversamente
echo '== Digits ==' . PHP_EOL;
$d = 'A8';
for ($n=0; $n<6; $n++) {
echo ++$d . PHP_EOL;
}
$d = 'A08';
for ($n=0; $n<6; $n++) {
echo ++$d . PHP_EOL;
}
?>
Example outputs
== Characters ==
X
Y
Z
AA
AB
AC
== Digits ==
A9
B0
B1
B2
B3
B4
A09
A10
A11
A12
A13
A14
Incrementare o decrementare valori booleani non ha effetto.
Operatori logiciEsempioNomeRisultato$a and $bAnd se e sono entrambe .true$a$btrue$a or $bOr se o è .true$a$btrue$a xor $bXor se o è , ma non entrambe.true$a$btrue! $aNot se non è .true$atrue$a AmpAmp $bAnd se e sono entrambe .true$a$btrue$a || $bOr se o è .true$a$btrueLa ragione per le due differenti variazioni degli operatori "and" e "or" è che operano con differenti precedenze. (Vedere Precedenza degli operatori.)
Dimostrazione degli operatori logici
<?php
// --------------------
// foo() non viene mai chiamata in quanto gli operatori sono in corto-circuito
$a = (false && foo());
$b = (true || foo());
$c = (false and foo());
$d = (true or foo());
// --------------------
// "||" ha una precedenza maggiore rispetto a "or"
// Il risultato dell'espressione (false || true) è assegnato a $e
// Funziona come: ($e = (false || true))
$e = false || true;
// La costante false è assegnata a $f prima che l'operazione "or" avvenga
// Funziona come: (($f = false) or true)
$f = false or true;
var_dump($e, $f);
// --------------------
// "&&" ha una precesenza maggiore rispetto a "and"
// Il risultato dell'espressione (true && false) è assegnato a $g
// Funziona come: ($g = (true && false))
$g = true && false;
// La costante true è assegnata a $h prima che l'operazione "and" avvenga
// Funziona come: (($h = true) and false)
$h = true and false;
var_dump($g, $h);
?>
bool(true)
bool(false)
bool(false)
bool(true)
Ci sono due operatori di stringa. Il primo è l'operatore di concatenazione ('.'), che restituisce la concatenazione dei suoi argomenti di destra e di sinistra. Il secondo è l'operatore di assegnazione concatenato ('.='), che accoda l'argomento sul lato destro all'argomento sul lato sinistro. Vedere Operatori di assegnazione per maggiori informazioni.
<?php $a = "Ciao "; $b = $a . "Mondo!"; // ora $b contiene "Ciao Mondo!" $a = "Ciao "; $a .= "Mondo!"; // ora $a contiene "Ciao Mondo!" ?>
Operatori per matriciEsempioNomeRisultato$a + $bUnioneUnione di e .$a$b$a == $bUguaglianza se e hanno le stesse coppie di chiavi/valori.true$a$b$a === $bIdentità se e hanno le stesse coppie di chiavi/valori nel
medesimo ordine e dl medesimo tipo.true$a$b$a != $bDisuguaglianza se non è uguale a .true$a$b$a LtGt $bDisuguaglianza se non è uguale a .true$a$b$a !== $bNon-identità se non è identico a .true$a$b
L'operatore + restituisce la matrice di destra aggiunta
a quella di sinistra; per le chiavi esistenti in entrambe le matrici, vengono usati gli elementi
della matrice di sinistra, e gli elementi duplicati in quella
di destra sono ignorati.
<?php $a = array("a" => "apple", "b" => "banana"); $b = array("a" => "pear", "b" => "strawberry", "c" => "cherry"); $c = $a + $b; // Unione di $a e $b echo "Union of \$a and \$b: \n"; var_dump($c); $c = $b + $a; // Unione di $b e $a echo "Union of \$b and \$a: \n"; var_dump($c); $a += $b; // Unione di $a += $b è $a e $b echo "Union of \$a += \$b: \n"; var_dump($a); ?> Una volta eseguito, lo script visualizzerà: Union of $a and $b: array(3) { ["a"]=> string(5) "apple" ["b"]=> string(6) "banana" ["c"]=> string(6) "cherry" } Union of $b and $a: array(3) { ["a"]=> string(4) "pear" ["b"]=> string(10) "strawberry" ["c"]=> string(6) "cherry" } Union of $a += $b: array(3) { ["a"]=> string(5) "apple" ["b"]=> string(6) "banana" ["c"]=> string(6) "cherry" }
Gli elementi di una matrice sono uguali nel confronto se hanno le stesse chiavi e gli stessi valori.
Confrontare le matrici <?php $a = array("apple", "banana"); $b = array(1 => "banana", "0" => "apple"); var_dump($a == $b); // bool(true) var_dump($a === $b); // bool(false) ?>
instanceof è utilizzato per determinare se una variabile PHP
è un oggetto istanza di una certa
classe:
Utilizzo di instanceof con le classi
<?php
class MyClass
{
}
class NotMyClass
{
}
$a = new MyClass;
var_dump($a instanceof MyClass);
var_dump($a instanceof NotMyClass);
?>
Example outputs
bool(true)
bool(false)
instanceof può essere usato anche per determinare se una variabile
è un oggetto istanziato da una classe che eredita da una classe parente:
Utilizzo di instanceof con le classi ereditate
<?php
class ParentClass
{
}
class MyClass extends ParentClass
{
}
$a = new MyClass;
var_dump($a instanceof MyClass);
var_dump($a instanceof ParentClass);
?>
Example outputs
bool(true)
bool(true)
Al fine di controllare se un oggetto non è un instanceof di una classe, si
può usare l'operatore logico not
.
Utilizzo di instanceof per controllare se un oggetto non è
un'instanceof di una classe
<?php
class MyClass
{
}
$a = new MyClass;
var_dump(!($a instanceof stdClass));
?>
Example outputs
bool(true)
Infine, instanceof può essere usato anche per deretmnare se
una variable è un oggetto istanziato da una classe che implementa una
interfaccia:
Utilizzo di instanceof con interfacce
<?php
interface MyInterface
{
}
class MyClass implements MyInterface
{
}
$a = new MyClass;
var_dump($a instanceof MyClass);
var_dump($a instanceof MyInterface);
?>
Example outputs
bool(true)
bool(true)
Anche se instanceof è normalmente usata con un nome di classe letterale,
può essere usata con un altro oggetto o con una variabile stringa:
Utilizzo di instanceof con altre variabili
<?php
interface MyInterface
{
}
class MyClass implements MyInterface
{
}
$a = new MyClass;
$b = new MyClass;
$c = 'MyClass';
$d = 'NotMyClass';
var_dump($a instanceof $b); // $b è un oggetto di classe MyClass
var_dump($a instanceof $c); // $c è la stringa 'MyClass'
var_dump($a instanceof $d); // $d è la stringa 'NotMyClass'
?>
Example outputs
bool(true)
bool(true)
bool(false)
instanceof non genera errori se la variabile che viene controllata non è
un oggetto, ma ritorna semplicemente false. Le costanti non erano comunque ammesse
prima di PHP 7.3.0.
Utilizzo di instanceof per controllare altre variabili
<?php
$a = 1;
$b = NULL;
$c = imagecreate(5, 5);
var_dump($a instanceof stdClass); // $a è un integer
var_dump($b instanceof stdClass); // $b è NULL
var_dump($c instanceof stdClass); // $c è una risorsa
var_dump(FALSE instanceof stdClass);
?>
Example outputs
bool(false)
bool(false)
bool(false)
PHP Fatal error: instanceof expects an object instance, constant given
A partire da PHP 7.3.0, le costanti sono permesse sul lato sinistro
dell'operatore instanceof.
Utilizzo di instanceof per testare le costanti
<?php
var_dump(FALSE instanceof stdClass);
?>
Example outputs 73
bool(false)
A partire da PHP 8.0.0, instanceof ora può essere utilizzato con espressioni arbitrarie.
L'espressione deve essere racchiusa tra parentesi e produrre una string.
Utilizzo di instanceof con un'espressione arbitraria
<?php
class ClassA extends \stdClass {}
class ClassB extends \stdClass {}
class ClassC extends ClassB {}
class ClassD extends ClassA {}
function getSomeClass(): string
{
return ClassA::class;
}
var_dump(new ClassA instanceof ('std' . 'Class'));
var_dump(new ClassB instanceof ('Class' . 'B'));
var_dump(new ClassC instanceof ('Class' . 'A'));
var_dump(new ClassD instanceof (getSomeClass()));
?>
Example outputs 8
bool(true)
bool(true)
bool(false)
bool(true)
L'operatore instanceof ha una variante funzionale
con la funzione is_a.
get_class is_a