Se i frammenti di tipo PHP abbondano su Internet, allora perché scriverne un altro? Beh, i frammenti PHP trovati al giro sono generalmente zoppi. Frammenti che generano una stringa casuale o un ritorno di $_SERVER["REMOTE_ADDR"]
per un indirizzo IP da un client in realtà non sono così interessanti e sono di utilità modesta. Invece, ecco alcuni frammenti che senza dubbio troverete interessanti e utili e che mi hanno tolto dai guai in più occasioni.
<?php $csv = ""; foreach ($data as $row) { $csv .= join(",", $row) . "\n"; } echo $csv; ?>
fputcsv()
, che esegue il tutto molto più velocemente anche perché la sua implementazione è in codice C e gestisce il necessario quotando/escapando i caratteri per noi.Il codice seguente avvolge la logica per costruire l’output in CSV da un array di dati. Ha dei parametri opzionali per consentire di aggiungere le colonne di intestazione e per svuotare il CSV direttamente al browser o per restituire l’output sotto forma di stringa. L’eleganza del codice è l’uso dei flussi con
fputcsv()
che, come funzione, richiede un file aperto per gestire l’operazione.<?php function creaCSV($dati, $intestazioni = array(), $comeStringa = false) { $ritorno = ''; $flusso = $comeStringa ? fopen("php://temp/maxmemory", "w+") : fopen("php://output", "w"); if (!empty($intestazioni)) { fputcsv($flusso, $intestazioni); } foreach ($dati as $elemento) { fputcsv($flusso, $elemento); } if ($comeStringa) { rewind($flusso); $ritorno = stream_get_contents($flusso); fclose($flusso); return $ritorno; } else { fclose($flusso); } } ?>
creaCSV()
nel nostro arsenale, generare i files di tipo CSV diventa semplice e facile.Lo standard non descrive quali sono le funzionalità supportate, che dovrebbero essere forniti da un autoloader PSR-0 compatibile (metodi di registrazione, opzioni di configurazione, ecc.). Se è in grado di trovare automaticamente una definizione di classe nella cartella con il modello
\\(\
), allora è PSR-0 compliant. Inoltre, non specifica la directory principale per
. L’extra, o il contorno, della maggior parte delle implementazioni autoloader è conveniente se è necessario specificare la posizione tramite il codice, ma è inutile se si usa semplicemente una directory già dentro il percorso di inclusione di PHP.<?php spl_autoload_register(function ($nomeClasse) { $nomeClasse = ltrim($nomeClasse, "\\"); preg_match('/^(.+)?([^\\\\]+)$/U', $nomeClasse, $match); $nomeClasse = str_replace("\\", "/", $match[1]) . str_replace(["\\", "_"], "/", $match[2]) . ".php"; include_once $nomeClasse; }); ?>
$match[2]
, e $match[1]
avrà il nome del namespace, che può essere una stringa vuota. Questo è necessario per identificare le parti perché la sottolineatura non ha alcun significato particolare nella porzione di spazio dei nomi facendo una sostituzione alla cieca con la sottolineatura e il backslash correttoI dati a lunghezza fissa sono relativamente facili da elaborare in linguaggi come C, perché i dati, una volta caricati in memoria, si allineano perfettamente con la struttura dell’accesso ai dati. Ma per alcuni, lavorando con i dati a lunghezza fissa in un linguaggio dinamico come PHP può essere una lotta: la mancanza di tipizzazione del linguaggio rende l’accesso alla memoria impossibile. E come risultato, spesso vediamo del codice che assomiglia a quanto segue:
<?php // analisi di una intestazione NACHA $row = fread($fp, 94); $header = array(); $header["type"] = substr($row, 0, 1); $header["priority"] = substr($row, 1, 2); $header["immDest"] = substr($row, 3, 10); $header["immOrigin"] = substr($row, 13, 10); $header["date"] = substr($row, 23, 6); $header["time"] = substr($row, 29, 4); $header["sequence"] = substr($row, 33, 1); $header["size"] = substr($row, 34, 3); $header["blockFactor"] = substr($row, 37, 2); $header["format"] = substr($row, 39, 1); $header["destName"] = substr($row, 40, 23); $header["originName"] = substr($row, 63, 23); $header["reference"] = substr($row, 86, 8); print_r($header); ?>
unpack()
.La documentazione per
unpack()
nel manuale PHP dice: “spacchetta una stringa binaria in una matrice in base al formato dato” e mostra l’utilizzo con degli esempi con i caratteri di escape usando dati binari. Ciò che non può essere immediatamente evidente è che la funzione può essere utilizzata per analizzare stringhe a lunghezza fissa grazie allo specificatore del formato di A, che rappresenta un carattere (dopo tutto, non è una stringa seguita da una serie di bits e bytes?).Utilizzando
unpack()
, l’esempio precedente può essere riscritto in modo più elegante come segue:<?php // analisi di una intestazione NACHA $row = fread($fp, 94); $header = unpack("A1type/A2priority/A10immDest/" . "A10immOrigin/A6date/A4time/" . "A1sequence/A3size/A2blockFactor/" . "A1format/A23destName/" . "A23originName/A8reference", $row); print_r($header); ?>
A6date
per esempio analizza i 6 caratteri e li rende disponibili in $header["date"]
.<?php class Template { protected $dir; protected $vars; public function __construct($dir = "") { $this->dir = (substr($dir, -1) == "/") ? $dir : $dir . "/"; $this->vars = array(); } public function __set($var, $value) { $this->vars[$var] = $value; } public function __get($var) { return $this->vars[$var]; } public function __isset($var) { return isset($this->vars[$var]); } public function set() { $args = func_get_args(); if (func_num_args() == 2) { $this->__set($args[0], $args[1]); } else { foreach ($args[0] as $var => $value) { $this->__set($var, $value); } } } public function out($template, $comeStringa = false) { ob_start(); require $this->dir . $template . ".php"; $content = ob_get_clean(); if ($comeStringa) { return $content; } else { echo $content; } } } ?>
Template
, eventualmente si passa un nome di directory utilizzato per cercare il file del template. Poi, si passano i valori che dovrebbero popolare il modello con metodo il metodo set()
o come nuda proprietà. Una volta che tutti i valori sono stati specificati, si chiama il metodo out()
per il rendering del template.<?php $t = new Template(); // imposta un valore come se fosse una proprietà $t->saluti = "Ciao Mondo!"; // imposta un valore con set() $t->set("numero", 42); // imposta valori multipli con set() $t->set(array( "foo" => "Pippo", "bar" => "Pluto" )); // esegue il rendering del template $t->out("miotemplate"); ?>
<!DOCTYPE html> <html lang="it"> <head> <meta charset="utf-8"> ... </head> <body> <div role="main"> <h1><?=$this->saluti;?></h1> ... </div> </body> </html>
Con il secondo parametro opzionale per
out()
è possibile specificare se restituire il contenuto del modello come una stringa, invece di scaricarlo direttamente al browser, che è possibile sfruttare per sostituire il segnaposto in un modello con il risultato di un modello già compilato.Il problema che basarsi su cURL per le richieste HTTP è duplice:
- ci sono spesso molte opzioni che devono essere impostate, anche per la più semplice delle operazioni;
- si tratta di un’estensione che potrebbe non essere disponibile a seconda dello hosting che ospita il nostro sito web; è una estensione comune, ma non è abilitato per default.
file_get_contents()
e stream_context_create()
sono due funzioni native di PHP e sono disponibili a partire dalla versione 4.3. Insieme, possono essere utilizzati per eseguire molte delle stesse richieste comunemente effettuate tramite cURL.
Per le richieste del tipo GET, file_get_contents()
può essere usato da solo:
<?php $html = file_get_contents("http://sitoweb.com/prodotto/33"); ?>
stream_context_create()
e quindi passare il contesto file_get_contents()
.<?php $context = stream_context_create(array( "http" => array( "method" => "POST", "header" => "Content-Type: multipart/form-data; boundary=--foo\r\n", "content" => "--foo\r\n" . "Content-Disposition: form-data; name=\"mioFile\"; filename=\"immagine.jpg\"\r\n" . "Content-Type: image/jpeg\r\n\r\n" . file_get_contents("image.jpg") . "\r\n" . "--foo--" ) )); $html = file_get_contents("http://example.com/upload.php", false, $context); ?>
POST
, con l’array come contesto, con le informazioni necessarie per l’operazione con le chiavi: “method
“, “header
” e “content
“.Quando si utilizza
file_get_contents()
per le richieste complesse come il caricamento di un file, può essere utile fare prima un finto web form ed eseguirlo tramite Firefox
con firebug abilitato o qualcosa di simile per poi esaminare ciò che è stato incluso nella richiesta. Da lì si può dedurre gli elementi di intestazione importanti da includere.
Ancora nessun commento