Importare un file mysql (.sql) da riga di comando

Come importare un file .sql se avete accesso alla riga di comando

Come ben sapete potete importare file .sql tramite phpmyadmin, ma questo ottimo strumento potrebbe non bastare se dovessimo importare file di grosse dimensioni in mysql. Un’altra soluzione può essere importare il nostro file direttamente da riga di comando.

Per importare un backup che avete fatto potete eseguire il comando:
mysql < nome_file.sql -u root -p

Se un errore vi segnala che nel dump non è selezionato il database bisogna specificarlo in questo modo:
mysql < nome_file.sql --database db_name -u root -p

Inoltre se state utilizzando windows dovete entrare tramite riga di comando nella cartella bin all’interno della folder in cui è installato mysql e quindi specificare la root completa del file da importare, per esempio:
mysql < C:nome_file.sql --database db_name -u root -p

Potete trovare altri esempi su come copiare l’intero db o come importare i dati da qui: MySql: Backup e Restore

Se volete invece generare un file di backup .sql di una tabella di grandi dimensioni vi invito a leggere il completissimo articolo "Backup di un database mysql command line, con compressione"

Backup di un database mysql command line, con compressione

Come backuppare un db mysql e comprimerlo in un archivio .tar.gz o .tar.bz2

A tutti sarà capitato di dover fare un backup di un database o di una tabella, il modo più immediato per farlo è attraverso l’esporta di phpMyAdmin che però a volte non è sufficiente per le nostre esigenze.
Se avete bisogno di un backup via riga di comando, o di backuppare grandi moli di dati mysqldump fa al caso vostro.
In realtà esiste un tool più veloce che è mysqlhotcopy ma non è altrettanto versatile, per esempio si possono salvare solo tabelle MyIsam, quindi noi andremo a vedere solo mysqldump.

MySqlDump
Il suo utilizzo è molto semplice, ecco un esempio:
mysqldump dbname > nome_file.sql -u tuo_username -p
Questo esempio fa il dump del database "dbname" sul file "nome_file.sql" con username "tuo_username". Vi verrà richiesto l’username.

Se fate il backup di grandi tabelle vi consiglio di usare queste due opzioni:
mysqldump dbname tablename --skip-extended-insert --quick > file_name.sql -u root -p
–skip-extended-insert serve per far creare un singolo insert per ogni record, questo renderà il dump di dimensioni maggiori ma vi sarà molto comodo per reimportare il db, per esempio attraverso bigdump.
–quick è un’opzione indispensabile per tabelle molto grandi (per esempio 2 Gb), infatti evita di mettere in cache i record prima di salvarli sul file di dump, e li scrive direttamente. Questo aiuta molto per la RAM.
tablename: questa non è un’opzione ma è solo per farvi vedere che è possibile specificare quale tabella del db bisogna salvare. E’ una cosa comoda per tabelle di applicazioni diverse o di grandi dimensioni.

Per importare un backup che avete fatto potete eseguire il comando:
mysql < nome_file.sql -u root -p

Se un errore vi segnala che nel dump non è selezionato il database bisogna specificarlo in questo modo:
mysql < nome_file.sql --database db_name -u root -p

Inoltre se state utilizzando windows dovete entrare tramite riga di comando nella cartella bin all’interno della folder in cui è installato mysql e quindi specificare la root completa del file da importare, per esempio:
mysql < C:nome_file.sql --database db_name -u root -p

Potete trovare altri esempi su come copiare l’intero db o come importare i dati da qui: MySql: Backup e Restore
Qui trovate la documentazione ufficiale di mysqldump.

Compressione .tar
Arriviamo ad una parte interessante, meno per altri che hanno già usato questa utility, la compressione con tar.
Prima di tutto vi segnalo che tar di default crea un "archivio" per i file indicati ma non li comprime se non lo specificate!

Compressione .tar.gz (gzip)
tar -czvf nome_archivio_compresso.tar.gz file_da_comprimere.sql
tar è l’utility che stiamo utilizzando per l’archiviazione
-c indica che bisogna creare un nuovo archivio
z indica che vogliamo una compressione gzip
v ci aggiorna sull’andamento della compressione (utile se archiviamo più di un file)
f indica che andreamo a specificare il nome del file
Se non ci fosse stata la z il file sarebbe stato archiviato senza compressione, nel nostro caso sarebbe stato totalmente inutile.

Compressione .tar.bz2 (bzip2)
tar -cjvf nome_archivio_compresso.tar.bz2 file_da_comprimere.sql
j indica che questo file dovrà essere compresso in bzip2

Decompressione
tar -xvfz nome_archivio.tar.gz
x indica che stiamo estraendo un archivio
z indica che stiamo decomprimendo da gzip, togli z e metti j se invece l’archivio era bz2

Meglio gzip o bzip2?
Grazie ai preziosi benchmarks di Lasse Collin possiamo trovare una risposta a questa domanda.
Come al solito… dipende! Direi che in generale gzip è la migliore forma di compressione visto la sua velocità mentre bzip2, che risulta notevolmente più lento come metodo, riesce ad ottenere risultati di compressione migliori, seppur in più tempo.
Se avete bisogno di prestazioni direi gzip, se non vi preoccupate della CPU optate per bzip2 ma avrete una compressione migliore del solo 5%.

Bene, ora sarete in grado di fare un backup tramite mysqldump, comprimerlo e metterlo dove volete.
Buon lavoro!

Can’t use function return value in write context in…

if (empty(trim($var))) …

Può capitare in PHP che spunti fuori questo errore:
Fatal error: Can't use function return value in write context in.
cosa fare?

Nel caso in cui usiate il metodo empty nella riga che genera errore
if (empty(trim($var)))
   // Some code

la comprensione del problema è immediata: sulla documentazione ufficiale (empty()) è specificato che il metodo empty() accetta come argomento solo una VARIABILE (attenzione, variabile != valore) e qualsiasi altra cosa genera errore.
In sostanza all’interno di empty potete mettere qualsiasi cosa inizi con il $ (dollaro) ma nessun altro metodo.

Quindi per risolvere il problema
Fatal error: Can't use function return value in write context in...
a riga
if (empty(trim($var)))
   // Some code

il codice diverrà:
$trimmedVar = trim($var);
if (empty($trimmedVar))
   // Some code

o più concisamente:
if (!trim($var))
   // Some code

Lo stesso messaggio di errore può avvenire anche con altri metodi che necessitano di variabili in input, in questi casi la soluzione più valida è la prima.


Mambo: Unknown column ‘c.access’ in ‘on clause’

Risolvere una incopatibilità di Mambo con nuove versioni di MySql

Se state trasferendo una vecchia versione di Mambo 4.5.1, 4.5.2 o 4.5.3 verso un server con MySql 5 incontrerete questo errore sotto il menù "Content -> Content Managers -> All content items":
Unknown column ‘c.access’ in ‘on clause’ SQL=SELECT c.*, g.name AS groupname, cc.name FROM mos_content AS c, mos_categories AS cc, mos_sections AS s LEFT JOIN mos_groups AS g ON g.id = c.access WHERE c.state = -1 AND c.catid=cc.id AND cc.section=s.id AND s.scope=’content’ ORDER BY c.catid, c.ordering LIMIT 0,1

Le soluzioni possono essere due:

  1. Fare l’upgrade di Mambo (installare una versione più recente)
  2. Risolvere in modo mirato questo problema

Ovviamente la prima soluzione è la consigliata ma nel caso in cui non poteste farlo eccovi come risolvere questo probelama:

  1. Cerca il file /administrator/components/com_content/admin.content.php
  2. Fanne un backup per sicurezza
  3. Aprilo con un editor di testo (per esempio Blocco Note di Windows)
  4. Sostituisci la riga . "n FROM , #__content AS c, #__categories AS cc, #__sections AS s"  con la riga . "n FROM #__categories AS cc, #__sections AS s, #__content AS c " (più o meno la riga è la 201 ma può variare tra le diverse versioni)
  5. e sostituisci la riga . "n FROM , #__content AS c, #__categories AS cc, #__sections AS s" con la riga . "n FROM #__categories AS cc, #__sections AS s, #__content AS c "(la riga è più o meno la 312).
  6. Salvate il file e caricatelo sul server (via FTP per esempio)

Perfetto, la soluzione è attualta! Personalmente ho già usato questa soluzione su due installazioni di Mambo che ho dovuto migrare. Ringrazio per la soluzione MajorGlory.

I 10 font più compatibili per un sito web

Ecco l’elenco dei font compatibili con Windows, Linux e Mac

Ogni volta che si inizia a scrivere il foglio di stile di un sito ci chiediamo quale font usare e ci limitiamo spesso ad usare i soliti Verdana e Times New Roman ma finalmente ecco che trovo una risorsa fantastica:
Un post di Megan McDermott intitolato "Complete Guide to Pre-Installed Fonts in Linux, Mac, and Windows"
Qui trovate infatti un’ottima tabella comparativa che vi mostra i font installati di default su Windows, Mac e Linux.

Font da usare per il web
Dalla tabella evinciamo che i font più compatibili con le tre principali piattaforme sono:

  • Georgia
  • Palatino Linotype
  • Times New Roman
  • Arial
  • Trebuchet MS
  • Verdana
  • Comic Sans MS
  • Courier New

Nota: visto che il carattere "Palatino Linotype" ha nomi diversi su diverse piattaforme il codice corretto per utilizzarlo è il seguente:
font-family: 'Palatino Linotype', 'Palatino', 'URW Palladio L';

Nel caso in cui vi interessasse solo la compatibilità fra font Windows e Mac (ignorando Linux) potete considerare anche il font:

  • Tahoma


mentre se il vostro interesse è mantenere la compatibilità tra font Windows e Linux ignorando Mac potete aggiungere il carattere:

  • Impact


Ora potrete finalmente aver il cuor più leggero quando sceglierete il font per il vostro prossimo foglio di stile!


Array in JSON: come abilitarne l’uso

Come poter utilizzare liberamente array ed array associativi con JSON

Oggi mi sono imbattuto in un inaspettato problema utilizzando le liberie JSON (www.json.org): "JSON does not support cyclic data structures".

Infatti utilizzando un Array multidimensionale potreste provare il mio stesso stupore:
questo codice infatti vi mostrerà un array VUOTO.
<script type="text/javascript" src="json2.js"></script>
<script>

var Auto = new Array();
Auto[0] = new Array();
Auto[0]['marca'] = "BMW";
Auto[0]['nazionalita'] = "Tedesca";
Auto[1] = new Array();
Auto[1]['marca'] = "Fiat";
Auto[1]['nazionalita'] = "Italiana";

var JSONText = JSON.stringify(Auto);
alert(JSONText);

</script>

Come risolvere il problema? E’ presto detto:
   trasformare il nostro Array (e i suoi figli) in un oggetto (di tipo Object) e per fare ciò ecco un’utilissima funzione:

array2obj.js
/**
 * Returns an Object with same structure and content of a given array
 * Useful for Array to Object convertion required for JSON stringify()
 *
 * @author Alessandro Coscia
 * @see www.programmatorephp.it
 * @param Array array
 * @return Object
 */
function array2obj(array) {
  var obj = new Object();
 
  for (var label in array) {
    obj[label] = new Object();
   
    // Recursion if needed
    if (typeof array[label] == "object") {
      obj[label] = array2obj(array[label]);
    }
    // Simple vars
    else
      obj[label] = array[label];
  }
 
  return obj;
}

Come usarla? Ecco qui l’esempio completo:
<script type="text/javascript" src="json2.js"></script>
<script type="text/javascript" src="array2obj.js"></script>
<script>

var Auto = new Array();
Auto[0] = new Array();
Auto[0]['marca'] = "BMW";
Auto[0]['nazionalita'] = "Tedesca";
Auto[1] = new Array();
Auto[1]['marca'] = "Fiat";
Auto[1]['nazionalita'] = "Italiana";

// Questo non funzionera'
var JSONText = JSON.stringify(Auto);
alert(JSONText);

// Questo funzionera'
Auto = array2obj(Auto);
var JSONText = JSON.stringify(Auto);
alert(JSONText);

</script>

Con questo semplice tip potrete essere liberi di utilizzare array ed array associativi nelle vostre applicazioni AJAX che fanno uso di JSON.
Buon coding!

ps: dove trovare il file json2.js? Sul sito ufficiale: http://www.json.org/json2.js


Il pattern Singleton in PHP: persistenza durante una sessione

Rendere una classe persistente durante la sessione di un utente

Vi avevamo già spiegato cos’è e come si implementa un Singleton nell’articolo precedente, ora renderemo quella stessa classe persistente durante tutta la sessione dell’utente (ovvero sinchè l’utente chiuderà il browser.

Ovviamente nessun programmatore con un minimo di senno si diverte a reinventare l’acqua calda dunque utilizzeremo le sessioni già messe a disposizione da PHP.

Ricordiamo il codice d’esempio di un Singleton presentato nell’articolo precedente:

<?php

class Single {

  private static $singleton = null;
  private $var;

  static function getInstance(){
    if (Single::$singleton == null){
      Single::$singleton = new Single();
    }
    return Single::$singleton;
  }

  function __construct(){
    $this->var = rand();
  }

  function getVar(){
    return $this->var;
  }
}

$single = Single::getInstance();
echo "Primo get: ".$single->getVar()."<br />";

$single = Single::getInstance();
echo "Secondo get: ".$single->getVar()."<br />";

?>

Prima di tutto aggiungeremo in cima a questo sorgente (o prima quando necessario) il richiamo al metodo per avviare le sessioni in PHP
session_start()

In seguito andiamo ad operare su getInstance() facendo in modo che non controlli solo la propria variabile static ma che controlli anche in $_SESSION se c’è una sua istanza archiviata:
  static function getInstance(){
    if (Single::$singleton == null){
        if (isset($_SESSION['single'])) {
            Single::$singleton = $_SESSION['single'];
        }
        else {
              Single::$singleton = new Single();
              $_SESSION['single'] = Single::$singleton;
        }
    }
    return Single::$singleton;
  }

In questo modo se non c’è un’istanza di Single si cerca nelle sessioni prima di crearne una.
Ciò vuol dire che il Singleton di cui parliamo sarà persistente durante tutta una sessione relativamente ad un solo utente. Inoltre alla chiusura del browser il singleton verrà perso.

Le applicazioni di un sistema del genere potrebbero essere molteplici, un Singleton come questo potrebbe dare un punto di vista privilegiato (e favorevole) al programmatore per capire gli spostamenti dell’utente (per esempio sistemi di tracciamento e rilevazione dei ROI).

Ripubblico di seguito l’intero codice, buon divertimento!
<?php
session_start();

class Single {

    private static $singleton = null;
    private $var;

    static function getInstance(){
        if (Single::$singleton == null){
            if (isset($_SESSION['single'])) {
                Single::$singleton = $_SESSION['single'];
            }
            else {
                Single::$singleton = new Single();
                $_SESSION['single'] = Single::$singleton;
            }
        }
        return Single::$singleton;
    }

    function __construct(){
        $this->var = rand();
    }

    function getVar(){
        return $this->var;
    }
}

$single = Single::getInstance();
echo "Primo get: ".$single->getVar()."<br />";

$single = Single::getInstance();
echo "Secondo get: ".$single->getVar()."<br />";

?>


Launch4j: creare eseguibili Windows per applicazioni Java

Utilizzare Launch4j per incorporare e eseguire archivi JAR in classici file .exe

Una delle prime domande che sorgono ai newbie di Java è: “come creo un file eseguibile .exe per le mie applicazioni Java?”. Java è un linguaggio multipiattaforma interpretato, e quindi non è così logico creare dei file .exe compatibili solo con i sistemi Windows. Per distribuire un’applicazione Java si devono distribuire tutti i file .class in bytecode, oppure un unico archivio JAR. In entrambi i casi l’esecuzione dell’applicazione deve avvenire invocando direttamente la Java Virtual Machine, solitamente creando un apposito script command (.cmd), batch (.bat), o shell (.sh nei sistemi UNIX/Linux).

Launch4j è un progetto open source che permette di eliminare questo problema creando un file eseguibile .exe per i sistemi Windows a partire dall’archivio JAR dell’applicazione.
Attenzione: Launch4j non converte l’applicazione in un eseguibile, perchè questo provoca spesso molti problemi. Semplicemente si pone come wrapper verso l’applicazione Java, ed è quindi comunque necessario che il sistema abbia installata una qualche versione del Java Runtime Environment. Potete scaricare Launch4j dal sito ufficiale del progetto.

Launch4j dispone di una GUI che semplifica il processo di creazione dell’eseguibile. Nello screenshot sottostante è possibile vedere le configurazioni principali di Launch4j. In Output file bisogna specificare il path dell’eseguibile che verrà creato, mentre in Jar il path dell’archivio JAR dell’applicazione. E’ poi possibile specificare un’icona e un eventuale file manifest per specificare la necessità di particolari privilegi per l’esecuzione.

L’eseguibile può agire in due modi differenti. Solitamente l’archivio JAR viene totalmente incorporato nell’eseguibile, consentendo così di evitare di distribuirlo assieme all’applicazione. In alternativa, selezionando Don’t wrap the jar, launch only, è possibile far si che l’eseguibile mantenga separato il file JAR, occupandosi solamente di eseguirlo invocando la JVM. In quest’ultimo caso è necessario distrubuire il file JAR assieme all’applicazione. E’ importante sottolineare che i due approcci sono del tutto equivalenti, in quanto Launch4j non effettua conversioni del codice, ma funge semplicemente da wrapper.

Il parametro Change dir permette di specificare in quale directory spostarsi prima di eseguire l’applicazione: ciò è importante se l’applicazione fa riferimento a file utilizzando path relativi alla propria directory di esecuzione. Inserendo un punto (.) come valore Launch4j si sposterà nella directory dell’eseguibile prima di eseguire l’applicazione. In Command line args si possono invece inserire tutti i parametri che l’applicazione deve ricevere da riga di comando.

Una delle funzionalità più importanti e utili di Launch4j è la capacità di controllare automaticamente la presenza del JRE e la relativa versione, e di avvisare l’utente nel caso sia necessario scaricare un’altra versione del JRE, proponendo il link verso la pagina di download. Per sfruttare questa funzionalità è necessario specificare, nel tab JRE della GUI, la versione minima del JRE affinchè l’applicazione funzioni (es. 1.6.0.11), ed eventualmente anche la versione massima e il criterio di selezione del JRE nel caso sia installato anche il Java Development Kit (JDK). Nella stessa scheda è possibile anche impostare i parametri per l’esecuzione della JVM, quali le dimensioni dello heap e le opzioni della JVM.

Nell’eseguibile vengono incorporate anche le informazioni sulla versione, il titolo dell’applicazione, il copyright, ecc… Tutto ciò è impostabile nel tab Version Info. E’ anche possibile forzare Windows a consentire una sola esecuzione contemporanea dell’applicazione, impostando il mutex di controllo nel tab Single Instance. Infine una funzionalità simpatica è la possibilità di inserire uno splash screen.

Configurato il tutto è possibile salvare la configurazione e avviare la creazione dell’eseguibile. Il gioco è fatto, d’ora in poi non saranno più necessari quei fastidiosi file .cmd per l’avvio delle applicazioni Java.

Far cercare parole corte a MySql Full-Text

Modificare il minimo numero di lettere per parole trovabili con MySql Full-Text

Le ricerche MySql Full-Text servono per cercare delle parole chiave fra le colonne di una tabella. Si usa Full-Text perchè è molto più veloce di LIKE ma non entreremo nel merito.

Perchè non trovo parole corte con Full-Text?
Per questioni di ottimizzazione delle prestazioni vengono cercate solo parole di almeno 4 lettere.

Posso risolvere il problema?
La soluzione per cercare parole più corte di 4 caratteri è modificare le configurazioni di MySql ma per fare ciò devi avere i permessi per modificarle. Per farla breve generalmente solo chi dispone di un server dedicato o virtuale può fare questa operazione.

Si, ho un server dedicato o virtuale, come procedo per la soluzione?
E’ molto semplice ma ti consiglio di leggere bene tutto prima di iniziare.
Prima di tutto trova il tuo file di configurazioni con il comando (se sei su linux)
locate my.cnf
Di solito è in /etc/my.cnf o più probabilmente in /etc/mysql/my.cnf
Trovato il file è come sempre meglio farne una copia di backup
cd /etc/mysql
cp my.cnf my.cnf_BackUp
Ora puoi modificare il file di configurazioni con il tuo editor preferito, per esempio vi
vi my.cnf
Cerca sotto la voce [mysqld] se è già presente la variabile ft_min_word_len.
Se esiste modifica il suo valore altrimenti aggiungila appena sotto [mysqld]
[mysqld]
ft_min_word_len = 3

per esempio imposta Full-Text per cercare parole anche di 3 lettere. Ricorda che più diminuisci questo valore e più basse saranno le prestazioni.
Ora devi riavviare il server MySql
/etc/init.d/mysql restart
Infine devi ricostruire gli indici Full-Text, per esempio con un comando REPAIR
REPAIR TABLE tbl_name QUICK;
(Questa ultima operazione puoi farla anche da phpmyadmin).

Ora sarà possibile fare query anche con parole di 3 caratteri.

Nota importante:
Come specifica MySql il comando myisamchk utilizza le configurazioni di default e potrebbe provocare problemi ed anche query fallite dopo questa modifica.
Per risolvere questo problema ci sono due opzioni:

  1. Utilizzare sempre l’opzione ft_min_word_len via shell, per esempio:
    • shell> myisamchk --recover --ft_min_word_len=3 tbl_name.MYI
  2. Modificare il file di configurazione aggiungendo il parametro ft_min_word_len anche sotto la dicitura [myisamchk] con lo stesso lavore che in [mysqld]

Ovviamente la seconda opzione è fortemente consigliata. Lo stesso problema si propone con il motore isam nel caso in cui utilizzassi una vecchia versione di MySql.

Breve sitografia:

Spero che questa guida vi sia servita e vi sia stata chiara, non esitate a contattarci per problemi.
A presto!

Implementare il pattern Singleton in script PHP

Perchè un oggetto singleton non è poi così unico

Il design pattern Singleton è uno dei pattern fondamentali dell’ingegneria del software. Se ne era già accennato negli articoli riguardanti la programmazione ad oggetti in PHP, precisamente qui, e qui, rimandando però sempre la questione.

Do per scontato che chi sta leggendo conosca il pattern. In ogni caso Wikipedia nè dà, come sempre, una spiegazione perfetta. Ho scelto di scrivere un articolo apposta, piuttosto che parlarne negli articoli sulla programmazione ad oggetti, non tanto perchè il singleton sia un pattern complicato da implementare (anzi, è il più banale), ma perchè in PHP il singleton ha un comportamento "anomalo".

In pratica un singleton in PHP è singolo solo all’interno della stessa esecuzione dello script. Ovvero è valido solo per la singola richiesta. Per chiarire meglio basta eseguire questo codice: è una classe singleton più alcune istruzioni che creano un oggetto singolo e ne richiamano il metodo getVar() due volte di seguito.

<?php

class Single {

  private static $singleton = null;
  private $var;

  static function getInstance(){
    if (Single::$singleton == null){
      Single::$singleton = new Single();
    }
    return Single::$singleton;
  }

  function __construct(){
    $this->var = rand();
  }

  function getVar(){
    return $this->var;
  }
}

$single = Single::getInstance();
echo "Primo get: ".$single->getVar()."<br />";

$single = Single::getInstance();
echo "Secondo get: ".$single->getVar()."<br />";

?>

Nel costruttore dell’oggetto viene generato un numero random, memorizzato nella variabile $var. Il metodo getVar() ritorna semplicemente questa variabile. Se provate ad eseguire lo script, vi verrà stampato:

Primo get: xxxxx
Secondo get: xxxxx

dove xxxxx è il numero casuale generato. In pratica le due chiamate del metodo getVar() restituiscono, ovviamente, lo stesso valore. Fin qui tutto ok.
Provate però ora a fare un refresh della pagina. Lo script viene eseguito nuovamente, e, a sorpresa, è stato generato un altro numero. Notare che la richiesta viene sempre dallo stesso utente (stesso client, stesso browser, stessa finestra del browser) e ancora in un momento in cui la sessione precedente è ancora valida. Questa è l’anomalia.

In una normale applicazione il singleton rimane unico dall’inizio al termine del processo. Il problema in PHP è che non esiste il concetto di applicazione. Ovvero, ogni script è come se un’applicazione a sè stante. Per questo ad ogni nuova esecuzione il singleton precedente è sparito. Esso è stato creato, e poi eliminato al termine dello script. Per questo all’esecuzione successiva è sparito.
Se provaste ad implementare un singleton ad esempio tramite dei servlet Java, notereste che questo inconveniente non esiste. Perchè il deploy di un servlet Java avviene in un application server, che provvede a crearle un "ambiente" che gli permette di comportarsi come una applicazione vera e propria. Ecco che quindi il singleton continuerebbe a vivere anche dopo l’esecuzione del servlet, indipendentemente che le richieste arrivino da browser diversi, client diversi, o in momenti diversi.

Per questo motivo il singleton in PHP non è utile come in molti altri linguaggi di programmazione. Ad esempio non è possibile utilizzarlo per implementare una cache, perchè essa verrebbe persa alla fine dello script. Ovviamente esistono dei rimedi. Eccone alcuni, con pro e contro, ma ognuno può pensare alla soluzione che più gli piace:

  • Memorizzare il singleton, ad esempio in un database al momento della creazione, e poi recuperarlo ad ogni richiesta. Valutata la capacità di caching dei DBMS, potrebbe essere una soluzione da non scartare, soprattutto se è possibile utilizzare MySQL con engine Memory, che non richiede accessi al disco.
  • Se il singleton deve essere relativo ad un utente, può essere in qualche modo serializzato e memorizzato in cookies sul client. Ma ovviamente non è un metodo da usare per dati sensibili, come login, e soprattutto password.
  • Se il singleton deve esistere per una sessione, può essere memorizzato tra i dati della sessione dell’utente.
  • qualsiasi altra cosa vi viene in mente…

Ora che abbiamo fatto chiarezza sul problema del singleton in PHP, è possibile capire che questo problema si presenta anche nel caso di attributi statici delle classi, per il medesimo motivo. Quindi, pensare di usare una classe con variabili statiche al posto di un singleton, non cambierebbe il risultato. Anche queste classi sono allocate e deallocate ad ogni richiesta.