Il logo del sito

PHP Manual

Language Reference - Functions

Durante la prima stesura di questo documento ho incontrato diversi problemi. Alcuni degli esempi proposti non funzionavano. Finalmente ho avuto il sospetto che la versione di php correntemente installata non fosse quella che mi aspettavo, la 7.0. E così era. Infatti la versione installata era la 5.6.30.

Dopo aver aggiornato la versione di php i problemi sono scomparsi.

Per conoscere la versione di PHP correntemente in esecuzione il codice è questo:

Ho tradotto quasi completamente tutte le parti di questa sezione del manuale e provato tutti gli esempi.

Funzioni definite dall'utente Argomenti delle funzioni Restituzione di valori - statement return Funzioni variabili Funzioni interne (built-in) Funzioni anonime

<?php
   echo phpversion();
?>
7.4.16

§Funzioni definite dall'utente

Pseudo code di definizione di una funzione utente.


<?php
function foo($arg_1, $arg_2, /* ..., */ $arg_n)
{
    echo "Example function.\n";
    return $retval;
}
?>
 

All interno di una funzione può essere inserito un qualsiali frammento di codice PHP valido comprese le definizioni di altre funzioni e le dichiarazioni di classi.

Le funzioni possono essere referenziate anche prima di essere definite, a meno che non si tratti di funzioni condizionali.

NotaI nomi di funzione sono case-insensitive, ma è buona norma chiamare la funzioni allo stesso modo in cui appaiono nella dichiarazione.

Esempi di funzioni condizionali

Quando una funzione è definita in maniera condizionale, la sua definizione deve precedere la chiamata.


<?php
$makefoo = true;

/* Non possiamo ancora chiamare foo() perchè non è stata ancora definita.
   possiamo invece chiamare bar() */

bar();

if ($makefoo) {
  function foo()
  {
    echo nl2br("Io, foo(), non esisto sino a quando il programma non arriva qui\n");
  }
}

/* Ora possiamo chiamre foo()
   dal momento che $makefoo vale true */

if ($makefoo) foo();

function bar() 
{
  echo nl2br("Io, bar(), esisto subito dopo l'avvio del programma.\n");
}
?>
Io, bar(), esisto subito dopo l'avvio del programma.
Io, foo(), non esisto sino a quando il programma non arriva qui

Funzioni dentro funzioni

Tutte le funzioni e le classi PHP hanno scope (visibilità) globale - possono essere chiamate dall'esterno di una funzione anche se esse sono definite all'interno e viceversa.

PHP non supporta l'overload delle funzioni, ne è possibile annullare una definizione o ridefinire una funzione precedentemente definita.


<?php
function foo2() 
{
  function bar2() 
  {
    echo nl2br("Io, bar2(), non esisto sino a quando  foo2() non viene chiamata.\n");
  }
}

/* Non possiamo ancora chiamare bar2() dal momento che ancora non esiste. */

foo2();

/* Ora possiamo chiamare bar2(),
   Il processamento di foo2()ha reso essa accessibile*/

bar2();
?>
Io, bar2(), non esisto sino a quando foo2() non viene chiamata.

Ricorsività

PHP supporta la ricorsività delle funzioni. E' possibile richiamare ricorsivamente una funzione.

Chiamate ricorsive a funzioni o a metodi, con livello di ricorsività superiore a 100-200 può distruggere lo stack e provocare la terminazione del programma. La ricorsione inifinita è considerata un errore di programmazione.

Esempio di funzione ricorsiva.


<?php
function recursion($a)
{
    if ($a < 20) {
        echo nl2br("$a\n");
        recursion($a + 1);
    }
}
recursion(5);
?>
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

§Argomenti di funzione

Esempio sull'uso di parametri di default


<?php
function makecoffee($type = "cappuccino")
// alla variabile $type è stato assegnato il valore di default "cappuccino"
{
    return nl2br("Sto facenco una tazza di $type.\n");
}
echo makecoffee();
echo makecoffee(null);
echo makecoffee("espresso");
?>
Sto facenco una tazza di cappuccino.
Sto facenco una tazza di .
Sto facenco una tazza di espresso.

Esempio sull'uso di variabili non scalari come parametri di default


<?php
function faiCaffe($types = array("cappuccino"), $coffeeMaker = NULL)
{
    $device = is_null($coffeeMaker) ? "le mani" : $coffeeMaker;
    return nl2br("Sto facendo una tazza di ".join(", ", $types)." con $device.\n");
}
echo faiCaffe();
echo faiCaffe(array("cappuccino", "lavazza"), "una teiera");
?>
Sto facendo una tazza di cappuccino con le mani.
Sto facendo una tazza di cappuccino, lavazza con una teiera.

Esempio d'uso scorretto degli argomenti di default


<?php
function makeyogurt($type = "acidophilus", $flavour)
{
    return "Making a bowl of $type $flavour.\n";
}
 
echo makeyogurt("raspberry");   // non funziona, manca un argomento.
?>

<?php
?>

Dichiarazioni di tipo

La dichiarazione del tipo consente ad una funzione di accettare solo parametri di tipo prestabilito.Se viene passato ad una funzione un valore di tipo non previsto viene generato un errore. In PHP 7 viene lanciata una eccezione di TypeError

Tipi accettati:

Warning Gli aliases per i tipi scalari non sono supportati.

Esempio di uso scorretto di un alias non supportato


<?php
 function test(boolean $param){}
 echo nl2br("cavolo che perdita di tempo\n");
  try{
      test(true);
   }
   catch (TypeError $e){
      echo nl2br("TypeError Exception \n");
      echo ($e);
   }
   catch (Exception $e){
      echo nl2br("Exception di tipo generale\n");
      echo($e);
   }
?>
cavolo che perdita di tempo
TypeError Exception Catturata
TypeError: Argument 1 passed to test() must be an instance of boolean, bool given, called in /var/www/virtual/clamin.it/htdocs/TestPages/php_Functions.php on line 345 and defined in /var/www/virtual/clamin.it/htdocs/TestPages/php_Functions.php:342 Stack trace: #0 /var/www/virtual/clamin.it/htdocs/TestPages/php_Functions.php(345): test(true) #1 {main}

Questo esempio mi ha fatto perdere un sacco di tempo. Significa forse che non posso inserire la dichiarazione di tipo per i parametri di tipo scalare? Ma allora perchè sono stati inseriti nell'elenco dei tipi validi?

In più non riuscivo nemmeno a catturare l'errore. Ma questo dipendeva dalla versione vecchia di PHP la 5.6.30. Ora ho la 7.0.19

Esempio base di dichiarazione argomento di tipo class


<?php
class C {}
class D extends C {}

// La classe E non estende C.
class E {}

function f(C $c) {
    echo nl2br(get_class($c)."\n");
}
try{
f(new C);
f(new D);
f(new E);
}
catch(TypeError $e){
   echo nl2br("TypeError Exception Catturata\n");
   var_dump($e);
}
?>
C
D
TypeError Exception Catturata
object(TypeError)#3 (7) { ["message":protected]=> string(155) "Argument 1 passed to f() must be an instance of C, instance of E given, called in /var/www/virtual/clamin.it/htdocs/TestPages/php_Functions.php on line 400" ["string":"Error":private]=> string(0) "" ["code":protected]=> int(0) ["file":protected]=> string(61) "/var/www/virtual/clamin.it/htdocs/TestPages/php_Functions.php" ["line":protected]=> int(394) ["trace":"Error":private]=> array(1) { [0]=> array(4) { ["file"]=> string(61) "/var/www/virtual/clamin.it/htdocs/TestPages/php_Functions.php" ["line"]=> int(400) ["function"]=> string(1) "f" ["args"]=> array(1) { [0]=> object(E)#2 (0) { } } } } ["previous":"Error":private]=> NULL }

La funzione f richiede un argomento di classe C. La chiamata f(new E) provoca un errore fatale perchè E non estende C.

Esempio base di dichiarazione argomento di tipo interfaccia


<?php
interface I { public function f2(); }
class C2 implements I { public function f2() {} }

// La classe E2 non implementa l'interfaccia I.
class E2 {}

function f2(I $i) {
    echo nl2br(get_class($i)."\n");
}
try{
   f2(new C2);
   f2(new E2);
}catch(TypeError $e){
   echo nl2br("TypeError Exception Catturata\n");
   var_dump($e);
}
?>
C2
TypeError Exception Catturata
object(TypeError)#4 (7) { ["message":protected]=> string(159) "Argument 1 passed to f2() must implement interface I, instance of E2 given, called in /var/www/virtual/clamin.it/htdocs/TestPages/php_Functions.php on line 445" ["string":"Error":private]=> string(0) "" ["code":protected]=> int(0) ["file":protected]=> string(61) "/var/www/virtual/clamin.it/htdocs/TestPages/php_Functions.php" ["line":protected]=> int(440) ["trace":"Error":private]=> array(1) { [0]=> array(4) { ["file"]=> string(61) "/var/www/virtual/clamin.it/htdocs/TestPages/php_Functions.php" ["line"]=> int(445) ["function"]=> string(2) "f2" ["args"]=> array(1) { [0]=> object(E2)#1 (0) { } } } } ["previous":"Error":private]=> NULL }

La funzione f2 richiede come argomento una classe che implementi l'interfaccia I. La chiamata f2(new E2) provoca un errore fatale perchè la classe E2 non implementa l'interfaccia I.

Esempio di dichiarazione di tipo annullabile


<?php
class C3 {}

function f3(C3 $c = null) {
    var_dump($c);
    echo nl2br("\n");
}
f3(new C3);
f3(null);
?>
object(C3)#3 (0) { }
NULL

Strict typing.

Esempio di strict typing


<?php
function sum(int $a, int $b) {
    return $a + $b;
}
try{
   var_dump(sum(1, 2));
   echo nl2br("\n");
   var_dump(sum(1.5, 2.5));
   echo nl2br("\n");
}catch(TypeError $e){
   echo nl2br("TypeError Exception Catturata\n");
   var_dump($e);
}
?>
int(3)
TypeError Exception Catturata
object(TypeError)#3 (7) { ["message":protected]=> string(148) "Argument 1 passed to sum() must be of the type int, float given, called in /var/www/virtual/clamin.it/htdocs/TestPages/php_Functions.php on line 505" ["string":"Error":private]=> string(0) "" ["code":protected]=> int(0) ["file":protected]=> string(61) "/var/www/virtual/clamin.it/htdocs/TestPages/php_Functions.php" ["line":protected]=> int(499) ["trace":"Error":private]=> array(1) { [0]=> array(4) { ["file"]=> string(61) "/var/www/virtual/clamin.it/htdocs/TestPages/php_Functions.php" ["line"]=> int(505) ["function"]=> string(3) "sum" ["args"]=> array(2) { [0]=> float(1.5) [1]=> float(2.5) } } } ["previous":"Error":private]=> NULL }

Devrò ritornare sull'esempio con dichiarazione di tipo boolean.

Esempio di weak typing


<?php
function sum2(int $a, int $b) {
    return $a + $b;
}

//var_dump(sum2(1, 2));

// These will be coerced to integers: note the output below!
// var_dump(sum2(1.5, 2.5));
?>
int(3)
TypeError Exception Catturata
object(TypeError)#4 (7) { ["message":protected]=> string(149) "Argument 1 passed to sum2() must be of the type int, float given, called in /var/www/virtual/clamin.it/htdocs/TestPages/php_Functions.php on line 536" ["string":"Error":private]=> string(0) "" ["code":protected]=> int(0) ["file":protected]=> string(61) "/var/www/virtual/clamin.it/htdocs/TestPages/php_Functions.php" ["line":protected]=> int(529) ["trace":"Error":private]=> array(1) { [0]=> array(4) { ["file"]=> string(61) "/var/www/virtual/clamin.it/htdocs/TestPages/php_Functions.php" ["line"]=> int(536) ["function"]=> string(4) "sum2" ["args"]=> array(2) { [0]=> float(1.5) [1]=> float(2.5) } } } ["previous":"Error":private]=> NULL }

Per permettere un weak typing dovrei dichiarare strict_types=0. Ma per gli esempi precedenti ho dichiarato strict_type=1

Esempio di cattura degli errori

In realtà questo l'ho fatto già nei precedenti esempi. Ma nella prima versione del documento ho avuto un problema con la versione che non mi faceva funzionare questo ed altri esempi.


<?php
declare(strict_types=1);

function sum3(int $a, int $b) {
    return $a + $b;
}

try {
     var_dump(sum3(1, 2));
     var_dump(sum3(1.5, 2.5));
} catch (TypeError $e) {
    echo "Error: ".$e->getMessage();
}
?>
int(3) Error: Argument 1 passed to sum3() must be of the type int, float given, called in /var/www/virtual/clamin.it/htdocs/TestPages/php_Functions.php on line 575

Lista di argomenti di lunghezza variabile

Esempio per accedere ad un numero variabile di argomenti


<?php
function sum4(...$numbers) {
    $acc = 0;
    foreach ($numbers as $n) {
        $acc += $n;
    }
    return $acc;
}

echo sum4(1, 2, 3, 4);
?>
10

Esempio per fornire argomenti


<?php
function add($a, $b) {
    return $a + $b;
}

echo nl2br(add(...[1, 2])."\n");

$a = [1, 2, 3, 4, 5];
echo add(...$a);
?>
3
3

Di questo esempio non ho proprio capito l'utilità!

Dichiarazione di un numero variabile di argomenti


<?php
function total_intervals($unit, DateInterval ...$intervals) {
    $time = 0;
    foreach ($intervals as $interval) {
        $time += $interval->$unit;
    }
    return $time;
}

$a = new DateInterval('P1D');
$b = new DateInterval('P2D');
try{
echo nl2br(total_intervals('d', $a, $b).' days'."\n");

// This will fail, since null isn't a DateInterval object.
echo total_intervals('d', null);
}catch (Error $e){
   echo nl2br("TypeError Exception Catturata\n");
   var_dump($e);
}
?>
3 days
TypeError Exception Catturata
object(TypeError)#2 (7) { ["message":protected]=> string(171) "Argument 2 passed to total_intervals() must be an instance of DateInterval, null given, called in /var/www/virtual/clamin.it/htdocs/TestPages/php_Functions.php on line 674" ["string":"Error":private]=> string(0) "" ["code":protected]=> int(0) ["file":protected]=> string(61) "/var/www/virtual/clamin.it/htdocs/TestPages/php_Functions.php" ["line":protected]=> int(661) ["trace":"Error":private]=> array(1) { [0]=> array(4) { ["file"]=> string(61) "/var/www/virtual/clamin.it/htdocs/TestPages/php_Functions.php" ["line"]=> int(674) ["function"]=> string(15) "total_intervals" ["args"]=> array(2) { [0]=> string(1) "d" [1]=> NULL } } } ["previous":"Error":private]=> NULL }

§ Restituzione di valori - statement return.

Esempio d'uso dello statement return


<?php
function square($num)
{
    return $num * $num;
}
echo square(4);   // outputs '16'.
?>
16

Restituzione di una array


<?php
function small_numbers()
{
    return array (0, 1, 2);
}
list ($zero, $one, $two) = small_numbers();
echo nl2br($zero."\n");
echo nl2br($one."\n");
echo nl2br($two."\n");
?>
0
1
2

Restituzione di reference da una funzione


<?php
function &returns_reference()
{
    return $someref;
}

$newref =& returns_reference();
?>

Questo esempio non è che l'ho capito molto.

Per maggiori info sui references, si può consultare References Explained.

Dichiarazione del tipo di ritorno

PHP 7 supporta la dichiarazione del tipo di ritorno. In modo analogo alla dichiarazione del tipo di argomento, la dichiarazione del tipo di ritorno specifica il tipo di valore restituito da una funzione. I tipi di ritorno ammissibili sono gli stessi dei tipi di argomento ammissibili.

La dichiarazione strict_types si comporta alla stesso modo sia sui tipi di argomento che sul tipo di return.

Esempio base di dichiarazione del tipo di ritorno.

Ricordo che strict_types è settata a 1 (true)


<?php
function sum5($a, $b): float {
    return $a + $b;
}
try {
   var_dump(sum5(1., 2.));
   echo nl2br("\n");
   var_dump(sum5(1, 2));
   echo nl2br("\n");
} catch (TypeError $e) {
    echo 'Error: '.$e->getMessage();
   echo nl2br("\n");
}
?>
float(3)
float(3)

Non da errore perchè come unica eccezione alla violazione della dichiarazione strict_types un int può essere assegnato ad un float senza dare errore.

Strict Mode in azione

Ricordo che strict_types è settata a 1 (true)


<?php
function sum6($a, $b): int {
    return $a + $b;
}
try {
   var_dump(sum6(1, 2));
   echo nl2br("\n");
   var_dump(sum6(1, 2.5));
   echo nl2br("\n");
} catch (TypeError $e) {
    echo 'Error: '.$e->getMessage();
   echo nl2br("\n");
}
?>
int(3)
Error: Return value of sum6() must be of the type int, float returned

La seconda chiamata a sum6 da errore perchè ho restituito un float mentre era previsto che restituissi un int.

Restituzione di un oggetto

Ricordo che strict_types è settata a 1 (true)


<?php
class C {}

function getC(): C {
    return new C;
}
try {
   var_dump(getC());
   echo nl2br("\n");
} catch (TypeError $e) {
    echo 'Error: '.$e->getMessage();
   echo nl2br("\n");
}
?>
object(C4)#2 (0) { }

Il mistero dell'operatore : è chiarito. Sì leggere attentamente questa parte del manuale è utile.

§ Funzioni Variabili.

PHP supporta il concetto di funzioni variabili. Ciò significa che se aggiungiamo una coppia di parentesi al nome di variabile, PHP cercherà una funzione con lo stesso nome della variabile e e cercherà di eseguirla. Questa comportamento è utilizzato per implementare il meccanismo di richiamata, per realizzare tabelle di funzioni e così via.

Le funzioni variabili non funzioneranno con i costrutti del linguaggio quali echo, print, unset (), isset (), empty (), include, require e simili. Per utilizzare questi costrutti come funzioni variabili occorre inserirli in funzioni wrapper.

Esempio di funzione variabile


<?php
function foo3() {
    echo nl2br("Esecuzione di foo3()\n");
}

function bar3($arg = '')
{
    echo nl2br("Esecuzione di bar3(); l'argomento passato è ". $arg ."\n");
}

// This è una funzione wrapper per echo
function echoit($string)
{
    echo $string;
}

$func = 'foo3';
$func();        // chiama foo3()

$func = 'bar3';
$func('test');  // chaiama bar3()

$func = 'echoit';
$func('test');  // chiama echoit()
?>
Esecuzione di foo3()
Esecuzione di bar3(); l'argomento passato è test
test

Esempio di metodo variabile


<?php
class Foo
{
    function Variable()
    {
        $name = 'Bar4';
        $this->$name(); // chiamata del metodo Bar4() dell'oggetto della classe Foo
    }
    
    function Bar4()
    {
        echo nl2br("Questo è il metodo Bar4\n");
    }
}

$foo = new Foo();
$funcname = "Variable";
$foo->$funcname();  // Chiamata del metodo $foo->Variable() dell'oggetto $foo
?>
Questo è il metodo Bar4

Esempio di metodo variabile con properties statiche

Quando si chiama un metodo statico, la chiamata di funzione è più forte dell'operatore di proprietà statica.


<?php
class Foo2
{
    static $variable =  "static property\n" ;
    static function Variable()
    {
        echo nl2br("Esecuzione del metodo Variable della classe Foo2\n");
    }
}

echo nl2br(Foo2::$variable); // Questo stampa 'static property'. Non c'e bisogno che $varible sia nel suo scope.
$variable = "Variable";
Foo2::$variable();  // Questo chiama il metodo $Foo->Variable() leggendo $variable nel suo scope.
?>
static property
Esecuzione del metodo Variable della classe Foo2

Richiamate complesse


<?php
class Foo3{
    static function bar(){
        echo nl2br("eseguito il metodo bar\n");
    }
    function baz(){
        echo nl2br("eseguito il metodo baz\n");
    }
}

$func = array("Foo3", "bar");
$func(); // stampa, eseguito il metodo bar
$func = array(new Foo3, "baz");
$func(); // stampa, eseguito il metodo baz
$func = "Foo3::bar";
$func(); // stampa, eseguito il metodo bar con PHP 7.0.0; 
         //le versioni precedenti avrebbero generato un errore fatale
?>
eseguito il metodo bar
eseguito il metodo baz
eseguito il metodo bar

§ Funzioni interne (built-in).

PHP è distribuito con molte funzioni e costrutti standard. Ci sono anche funzioni che richiedono la compilazione di specifiche estensioni di PHP, altrimenti sarebbero generati errori fatali di "undefined function". Ad esempio, per utilizzare funzioni di trattamento dell'immagine come imagecreatetruecolor (), PHP deve essere compilato con il supporto GD. Oppure, per utilizzare mysql_connect (), PHP deve essere compilato con il supporto MySQL. Ci sono molte funzioni fondamentali che sono incluse in ogni versione di PHP, come le funzioni string e variable. Una chiamata a phpinfo () o get_loaded_extensions () mostra quali estensioni sono correntemente caricate in PHP. Notare inoltre che molte estensioni sono abilitate per impostazione predefinita e che il manuale di PHP è suddiviso per estensioni. Vedere la configurazione, l'installazione e i singoli capitoli di estensione, per informazioni su come impostare PHP.

Come leggere e comprendere la dichiarazione di una funzione è spiegato nella sezione del manuale intitolata How to read a function definition. È importante capire cosa una funzione restituisce o se agisce direttamente su un valore che gli viene passato. Ad esempio, str_replace() restituirà la stringa modificata mentre usort() agisce sulla variabile passata stessa. Ogni pagina del manuale dispone di informazioni specifiche per ciascuna funzione, come informazioni sui parametri, i cambiamenti di comportamento, i valori di ritorno per successo e fallimento e le informazioni sulla disponibilità. Conoscere queste importanti (ma spesso sottili) differenze è fondamentale per la scrittura di codice PHP corretto.

phpinfo()

Per ottenere informazioni sulla configurazione corrente può essere usata la seguente funzione:


<?php
echo phpinfo();
?>
Mostra la configurazione corrente di PHP

get_loaded_extensions()

Per ottenere informazioni sulle estensioni caricate può essere usata la seguente funzione:


<?php
$estensioniCaricate = get_loaded_extensions();
foreach($estensioniCaricate as $estensione){
   echo nl2br($estensione."\n");
}
?>
Mostra le estensioni di PHP correntemente caricate

§ Funzioni anonime.

Le funzioni anonime, note anche come closures, consentono la creazione di funzioni senza uno specifico nonme. Sono principalmente utilizzate come parametri di richiamata, ma hanno molti altri usi.

Le funzioni anonime vengono implementate utilizzando la classe Closure

Esempio di funzione anonima.


<?php
echo preg_replace_callback('~-([a-z])~', function ($match) {
    return strtoupper($match[1]);
}, 'hello-world-friend');
// outputs helloWorldFriend
?>
helloWorldFriend

Esempio di assegnazione a funzione anonima variabile.


<?php
$greet = function($name){
            printf(nl2br("Hello %s\r\n"), $name);
         };

$greet('World');
$greet('PHP');
?>
Hello World
Hello PHP

Esempio di eredità di variabili dallo scope del padre.

Le closures possono anche ereditare variabili dallo scope del padre. Queste variabili devono essere passate al costrutto use. Da PHP 7.1, queste variabili non devono includere superglobals, $this, o variabili con lo stesso nome di un parametro.


<?php
$message = 'hello';

// No "use"
$example = function () {
    var_dump($message);
};
$example();

// Inherit $message
$example = function () use ($message) {
    var_dump($message);
};
$example();

// Inherited variable's value is from when the function
// is defined, not when called
$message = 'world';
$example();

// Reset message
$message = 'hello';

// Inherit by-reference
$example = function () use (&$message) {
    var_dump($message);
};
$example();

// The changed value in the parent scope
// is reflected inside the function call
$message = 'world';
$example();

// Closures can also accept regular arguments
$example = function ($arg) use ($message) {
    var_dump($arg . ' ' . $message);
};
$example("hello");
?>
NULL string(5) "hello" string(5) "hello" string(5) "hello" string(5) "world" string(11) "hello world"

Closures e visibilità.

Ereditare variabili dal padre, non è la stessa cosa che utilizzare variabili globali. Le variabili globali esistono nell'ambiente globale, che è lo stesso a prescindere dalla funzione in esecuzione. L'ambiente padre di una closure è la funzione in cui la closure è dichiarata (non necessariamente la funzione da cui è chiamata). Vedi i seguenti esempi.


<?php
// Una semplice lista della spesa contenente un elenco di prodotti con le rispettive quantità.
// Include un metodo che calcola il prezzo totale degli items usando una closure come callback.
class Cart {
    const PRICE_BUTTER  = 1.00;
    const PRICE_MILK    = 3.00;
    const PRICE_EGGS    = 6.95;

    protected $products = array();
    
    public function add($product, $quantity){
        $this->products[$product] = $quantity;
    }
    
    public function getQuantity($product){
        return isset($this->products[$product]) ? $this->products[$product] :
               FALSE;
    }
    
    public function getTotal($tax){
        $total = 0.00;
        
        $callback =
            function ($quantity, $product) use ($tax, &$total){
                $pricePerItem = constant(__CLASS__ . "::PRICE_" .
                    strtoupper($product));
                $total += ($pricePerItem * $quantity) * ($tax + 1.0);
            };
        
        array_walk($this->products, $callback);
        return round($total, 2);
    }
}

$my_cart = new Cart;

// Add some items to the cart
$my_cart->add('butter', 1);
$my_cart->add('milk', 3);
$my_cart->add('eggs', 6);

// Print the total with a 5% sales tax.
print $my_cart->getTotal(0.05) . "\n";
// The result is 54.29
?>
54.29

Binding automatico di $this.


<?php
class Test
{
    public function testing()
    {
        return function() {
            var_dump($this);
        };
    }
}

$object = new Test;
$function = $object->testing();
$function();
?>
object(Test)#8 (0) { }