PHP

Libreria per gestire database MySQL in PHP 5

In questo tutorial vedremo come creare delle classi in PHP5, che ci forniranno un'interfaccia rapida e meno dispendiosa dei metodi tradizionali, per interrogare i nostri database MySQL.

Per usufruire di questo Tutorial sono richieste buone conoscenze di PHP 5 e MySQL.

30. Classi per interrogare PHP

In questo capitolo costruiremo una classe PhpService per inviare e ricevere dati con PHP in codifica URL, derivando la classe da EventDispatcher.
Questo ci consentirà di gestire gli eventi che ci interessano nel nostro script, aggiungendo eventuali listener direttamente alle istanze di PhpService, come mostrato nel capitolo Gestire gli Eventi.

La nostra classe conterrà quattro attributi :

  • private var vars:Array; (Array che conterrà tutte le variabili che saranno inviate allo script PHP in codifica URL)
  • private var script:String; (Stringa che indica il nome della pagina PHP che conterrà lo script di nostro interesse)
  • public var response:URLVariables; (Conterrà i dati restituiti dallo script PHP in seguito alla richiesta HTTP)
  • public static var scriptPath:String; (Variabile statica utilizzata per impostare l'URL di base dove risiedono gli script PHP)

Il costruttore di classe prenderà in input un solo valore che indicherà il nome del file PHP che conterrà lo script di nostro interessa (attributo script).

Prima di dare un'occhiata al codice vediamo quali metodi costituiscono il corpo di classe :

  • public function reset():void
    Azzera l'array di variabili che contiene i dati da inviare allo script PHP.
  • public function addVar(name:String, content:String):void
    Ogni chiamata al metodo aggiunge una variabile all'array di dati che verrà inviato allo script PHP in codifica URL.
    Il metodo prende due parametri : il primo rappresenta il nome della variabile come verrà letta in PHP attraverso l'array globale $_POST[], mentre il secondo rappresenta il valore contenuto nella variabile.
  • public function request():void
    Effettua la richiesta HTTP contattando lo script, inviando e ricevendo i dati con quest'ultimo.
  • public function completeHandler(event:Event):void
    Memorizza la risposta dello script PHP nell'attributo pubblico response e solleva l'evento Event.COMPLETE.

Di seguito riporto il codice del costruttore e dei primi due metodi, molto semplici :

// Costruttore della classe
public function PhpService(PhpScript:String = "default.php"):void
{
	// Memorizza il nome del file PHP che contiene lo script di interesse
	this.script = PhpScript;
	// Inizialliza un array vuoto di variabili per l'invio dei dati allo script PHP
	this.vars = new Array();
}

public function reset():void
{ this.vars = new Array(); }

public function addVar(name:String, content:String):void
{
	/*
	La sintassi che segue permette di inserire nell'elemento di un array
	direttamente un oggetto dinamico con due proprietà "name" e "content"
	*/
	this.vars.push({name: name, content: content});
}

Il prossimo metodo, request, riutilizza il codice visto nel precedente capitolo, con la differenza di una gestione più completa delle variabili che andrà a leggere dall'array vars, per poi trasformarle in codifica URL pronte da inviare allo script PHP.

public function request():void
{
	var urlencoded:String = new String();

	/* Il ciclo "for" che segue, legge gli elementi dell'array vars e li
	trasforma in una stringa con la codifica URL per l'invio allo script PHP */

	for (var i:uint = 0; i < this.vars.length; i++)
	{
		urlencoded += this.vars[i].name + "=" + this.vars[i].content;
		if ((i + 1) < this.vars.length) urlencoded += "&";
	}

	try
	{
		var variables:URLVariables = new URLVariables(urlencoded);

		var loader:URLLoader = new URLLoader();
		loader.dataFormat = URLLoaderDataFormat.VARIABLES;
		loader.addEventListener(Event.COMPLETE, completeHandler);

		var request:URLRequest = new URLRequest(PhpService.scriptPath + this.script);
		request.method = URLRequestMethod.POST;
		request.data = variables;

		loader.load(request);
	}
	catch (error:Error)
	{ trace("Errore di connessione."); }
}

Per ultimo vediamo il metodo completeHandler, il quale memorizzerà la risposta dello script nell'attributo response e solleverà l'evento Event.COMPLETE in modo da poterlo ricatturare e gestire nella classe documento.

private function completeHandler(event:Event):void
{
	var loader:URLLoader = URLLoader(event.target);
	this.response = new URLVariables(loader.data);

	super.dispatchEvent(new Event(Event.COMPLETE));
}

Potete vedere il codice della classe al completo qui.

Di seguito un esempio di classe documento dove viene utilizzata un'istanza di PhpService.

HelloWorld.as

package
{
	import PhpService;
	import flash.events.Event;
	import flash.display.MovieClip;

	public class HelloWorld extends MovieClip
	{
		private var phpserv:PhpService;

		public function HelloWorld():void
		{
			PhpService.scriptPath = "http://localhost/realizzazionesito/";

			this.phpserv = new PhpService("servizio.php");
			this.phpserv.addVar("utente", "mario");
			// this.phpserv.addVar("utente2", "luca");
			// this.phpserv.addVar("utente3", "giovanni");
			this.phpserv.addEventListener(Event.COMPLETE, completeHandler);
			this.phpserv.request();
		}

		private function completeHandler(evt:Event):void
		{
			trace("Return : " + this.phpserv.response);
		}
	}
}

Per la costruzione di una classe più robusta che possa soddisfare i bisogni di un'applicazione reale, vi consiglio di completare il codice di PhpService, aggiungendo la gestione degli eventi che seguono :

addEventListener(Event.COMPLETE, completeHandler); // Questo è già implementato
addEventListener(Event.OPEN, openHandler);
addEventListener(ProgressEvent.PROGRESS, progressHandler);
addEventListener(SecurityErrorEvent.SECURITY_ERROR, securityErrorHandler);
addEventListener(HTTPStatusEvent.HTTP_STATUS, httpStatusHandler);
addEventListener(IOErrorEvent.IO_ERROR, ioErrorHandler);

29. Comunicare con PHP e MySQL

In questo capitolo vedremo come ActionScript 3 ci consente di interrogare una base di dati (database) in MySQL, attraverso la cooperazione con il linguaggio server-side PHP 5.

Innanzitutto prepariamo una tabella di esempio in MySQL che conterrà due campi, 'id' e 'nome'.
Di seguito il codice in SQL per creare la suddetta tabella :

CREATE TABLE `tabella` (
	`id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
	`nome` VARCHAR( 255 ) CHARACTER SET latin1 COLLATE latin1_general_ci NOT NULL
) ENGINE = MYISAM CHARACTER SET latin1 COLLATE latin1_general_ci;

Prima di costruire una nostra libreria di esempio che ci faciliterà la comunicazione con PHP, diamo un'occhiata alle classi che useremo in ActionScript 3 per inviare e ricevere i dati.

  • URLLoader - ci consente di scaricare dati da un URL attraverso una richiesta HTTP con URLRequest
  • URLRequest - esegue una richiesta HTTP ad un URL specifico, consentendoci di inviare dei dati e di catturare le informazioni di risposta
  • URLVariables - oggetto che rappresenta una collezione di variabili in codifica URL con coppie nome/valore
  • URLRequestMethod - contiene le costanti che ci consentono di specificare il metodo utilizzato per la richiesta HTTP, ossia GET o POST
  • URLLoaderDataFormat - contiene le costanti per impostare il metodo con cui ricevere i dati, ossia in 'binario', 'testo' o in 'codica URL'

Iniziamo con la classe URLVariables, che ci consentirà di inviare dei dati raccolti con Flash ai nostri script PHP, utilizzando la codifica URL con le coppie nome/valore, come mostrato nell'esempio seguente :

/* Segue una stringa che contiene tre variabili
e i rispettivi valori in codifica URL nome=valore */

nome1=valore1&nome2=valore2&nome3=valore3

Di seguito un esempio di inizializzazione di un'istanza URLVariables :

var variables:URLVariables = new URLVariables("nome=mario&cognome=rossi");

Per inviare le nostre variabili allo script PHP è sufficiente creare una istanza della classe URLRequest, che ci consentirà di impostare le informazioni e le modalità per eseguire una richiesta HTTP all'URL specificato.

Attraverso URLLoader potremo sfruttare la suddetta istanza di URLRequest effettuando la richiesta HTTP vera e propria, catturandone la risposta.

// Prepariamo le variabili
var utente:URLVariables = new URLVariables("utente=mario");

// Impostiamo la richiesta HTTP
var request:URLRequest = new URLRequest("http://localhost/servizio.php");
// Usiamo il metodo POST per l'invio dei dati
request.method = URLRequestMethod.POST;
// Specifichiamo quali dati inviare durante la richiesta
request.data = utente; // "utente" è l'istanza di URLVariables creata all'inizio

// Impostiamo l'URLLoader per effettuare la richiesta e catturarne la risposta
var loader:URLLoader = new URLLoader();
// Specifichiamo che vogliamo usare la codifica URL per l'invio dei dati
loader.dataFormat = URLLoaderDataFormat.VARIABLES;
// Aggiungiamo un "Listener" che verrà richiamato a richiesta completata per leggere la risposta dello script PHP
loader.addEventListener(Event.COMPLETE, completeHandler);

// Effettuiamo la richiesta passando "request" (istanza di URLRequest) a "loader"
loader.load(request);

Una volta effettuata la richiesta, verrà richiamata la funzione specificata come listener per gestire la risposta.
Nell'esempio di codice che segue definirò il metodo completeHandler per leggere il risultato dello script in PHP :

private function completeHandler(event:Event):void
{
	var loader:URLLoader = URLLoader(event.target);
	var response:URLVariables = new URLVariables(loader.data);

	trace("Return = " + response);
}

Prima di procedere alla costruzione di una libreria che ci renda il tutto molto più semplice ed immediato, diamo un'occhiata al codice in PHP che ci farà da tramite per manipolare il nostro database MySQL.
Lo script del prossimo esempio prenderà in input una variabile utente tramite il metodo di invio POST, e la inserirà nella tabella MySQL vista all'inizio di questo capitolo :

servizio.php

<?php

	$username = "root";
	$password = "password";
	$database = "test";
	$sqlserver = "localhost";

	$query = "INSERT INTO tabella (nome) VALUES ('" . $_POST["utente"] .  "')";

	$connessione_db = @mysql_pconnect($sqlserver, $username, $password);
	$check = @mysql_select_db($database, $connessione_db);

	$result = intval(@mysql_query($query, $connessione_db));

	if ($result > 0) $result = "Inserimento avvenuto con successo";
	else $result = "Errore durante l'inserimento";

	echo "result=$result";

?>

Nel prossimo capitolo creeremo una classe PhpService da poter utilizzare come libreria ogni volta che ci sarà necessario comunicare con PHP e MySQL.

51. Sicurezza

Un pò di sicurezza non guasta mai, soprattutto quando il traffico generato dal vostro sito diventa consistente.
Purtroppo (parlo per esperienza personale) è pieno di individui inetti senza una vita sociale, che passeranno le ore a cercare bachi e buchi nei vostri script e server con il solo scopo di rompervi i coglioni.

Non riuscirete mai a creare un sistema veramente infallibile, ma cercate almeno di rendere la vita un pò più difficile a questi bastardi, anche se credo che in questo caso ne godranno ancora di più.

Cerchiamo innanzitutto di dare meno informazioni possibili sul nostro server.

Provocando ad esempio un 404 (Pagina non trovata) possiamo subito vedere la risposta standard del nostro web server, nel mio caso :
Apache/2.2.4 (Win32) PHP/5.2.3 Server at localhost Port 80

Diamo fin troppe informazioni ai malintenzionati ... informazioni di nessuna utilità per i navigatori del nostro sito, perciò procediamo aprendo il file di configurazione di Apache (Apache2.2/conf/httpd.conf) e modificando i seguenti parametri :

  • ServerTokens - Di default questo parametro è impostato a Full, cambiatelo con Prod
  • ServerSignature - Di default questo parametro è impostato a On, cambiatelo con Off

In questo modo l'ultima riga viene eliminata restituendo un semplice Not Found.

Altra cosa molto importante è l'estensione dei file di librearia. Molti programmatori hanno l'abitudine di dare un'estensione differente ai file che contengono classi e funzioni (solitamente .inc) dimenticando però di configurare correttamente il web server per proteggere il codice.

A scanso di equivoci io consiglio di utilizzare sempre e solo l'estensione .php anche per i file da includere, in tal modo se viene richiesta una pagina verrà interpretata come codice PHP dal server, e non produrrà quindi alcun output sul browser.

Un altro consiglio che posso darvi è quello di criptare sempre i dati sensibili dei vostri utenti come ad esempio le password.

Personalmente preferisco algoritmi di criptazione a "senso unico", ossia che data una stringa ne viene generata un altra univoca criptata, ma data la stringa criptata non è possibile risalire alla stringa originale (vedi "md5()").

In questo modo se un utente dimentica la password, neppure per noi sarà possibile recuperarla, e il metodo migliore sarà quindi resettare la password con una temporanea generata casualmente consentendo poi all'utente di modificarla a sua volta.


Input & Output

Uno script robusto dovrà processare sempre tutti gli input degli utenti, specie se questi dati in input andranno poi memorizzati in supporti comuni come un database MySQL.

Un attacco comune basato su questi errori è chiamato SQL Injection, di seguito un articolo valido sull'argomento.

Vi consiglio di controllare sempre in modo restrittivo gli input degli utenti attraverso ad esempio le Espressioni regolari, eliminando caratteri speciali quali l'apostrofo, i trattini (-- commento in SQL) e altri.

Se permettete agli utenti di lasciare ad esempio commenti sul sito che saranno automaticamente pubblicati senza approvazione, è buona abitudine eliminare i caratteri speciali HTML dall'output, per rendere vani i tentativi di inserire codice maligno ad esempio in JavaScript.

Questo è possibile attraverso la funzione htmlentities() che sostituisce i caratteri speciali dell'HTML nelle rispettive entità.

Cercate inoltre di evitare di passare dati sensibili e ID di sessione col metodo GET. In questi casi affidatevi a POST.

File

Il valore di default in PHP 5 per la dimensione massima di un file che può essere ricevuto dal server è 8MB.

Molto spesso capita di costruire applicazioni che dovranno gestire solo file di circa 1MB o meno, assicuratevi quindi di non sovraccaricare inutilmente il server con file che non saranno poi gestiti ma eliminati immediatamente.

Questo è possibile modificando la proprietà post_max_size del php.ini attraverso la funzione ini_set() o modificando direttamente il file di configurazione.


Conclusioni

Direi che è tutto, anche se sull'argomento ci si potrebbe scrivere un libro intero.

Vi consiglio quindi di non fermarvi a queste premesse ma di approfondire l'argomento, perchè ci sarà sempre qualcuno più in gamba, e quel qualcuno probabilmente sarà anche più bastardo e disoccupato di voi.

50. I Database

In questo capitolo vedremo le funzioni che PHP 5 ci mette a disposizione per gestire il proprio database MySQL.

Non è scopo di questa lezione spiegarvi cosa è un Database e come funziona, pertanto vi consiglio di apprendere queste informazioni prima di procedere con la lettura di questo capitolo.

Per iniziare vi consiglio due ottimi documenti in italiano su Wikipedia :

Prima di iniziare ad analizzare le funzioni base di PHP vi consiglio di procurarvi phpMyAdmin (chi ha installato AppServ lo ha già incluso nel pacchetto) e di installarlo nel vostro server, poichè vi permetterà di gestire il vostro database in modo molto intuitivo e veloce.

Al riguardo una serie di articoli utili e interessanti :

  • phpMyAdmin - Sito ufficiale con documentazione e download ultima versione
  • Wikipedia - Articolo in italiano su phpMyAdmin con link a risorse utili
  • Guida HTML.it - Guida all'utilizzo di questo tool (in lingua italiana)

Funzioni

  • mysql_connect() - Apre una connessione con il server MySQL specificato.
  • mysql_close() - Chiude la connessione con il server MySQL.
  • mysql_pconnect() - Apre una connessione persistente con il server MySQL specificato, non necessita di un'antagonista "mysql_pclose()" per la chiusura della connessione.
  • mysql_select_db() - Seleziona il database MySQL specificato.
  • mysql_query() - Esegue una query MySQL.
  • mysql_num_rows() - Restituisce il numero di righe prodotto da una query.
  • mysql_fetch_array() - Trasforma una riga del risultato di una query in un array.
  • mysql_fetch_assoc() - Trasforma una riga del risultato di una query in un array associativo.

Per un elenco completo e dettagliato vi rimando alla documentazione ufficiale.

Vediamo ora un esempio di utilizzo con le funzione sopracitate, prendendo in esame una tabella "impiegati" con 4 campi di cui riporto sotto il codice MySQL per la creazione (potete incollarlo direttamente nel campo SQL di phpMyAdmin) :

CREATE TABLE `impiegati` (
	`id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY ,
	`nome` VARCHAR( 200 ) CHARACTER SET latin1 COLLATE latin1_general_ci NOT NULL ,
	`cognome` VARCHAR( 200 ) CHARACTER SET latin1 COLLATE latin1_general_ci NOT NULL ,
	`stipendio` BIGINT UNSIGNED NOT NULL DEFAULT '0'
) ENGINE = MYISAM CHARACTER SET latin1 COLLATE latin1_general_ci;

Inserendo quattro record nella tabella ottengo questo risultato.

Vediamo ora il codice PHP per leggere la tabella dal database MySQL e stamparla nella pagina sotto forma di tabella HTML :

<?php

	$connessione = mysql_connect("localhost", "admin", "password");
	mysql_select_db("nome_database", $connessione);

	// Leggiamo l'intera lista di impiegati in ordine crescente per il campo "id"
	$query = "SELECT * FROM impiegati ORDER BY id ASC";
	$risultato = mysql_query($query);

	$righe = mysql_num_rows($risultato);

	echo "La query ha prodotto $righe righe.\n<br /><br />";
	echo "<table border=\"1\" cellspacing=\"5\">";
	echo "<tr><td>ID</td><td>NOME</td><td>COGNOME</td><td>STIPENDIO</td></tr>";

	while ($riga = mysql_fetch_array($risultato, MYSQL_ASSOC))
	{
		echo "<tr><td>" . $riga["id"] . "</td>";
		echo "<td>" . $riga["nome"] . "</td>";
		echo "<td>" . $riga["cognome"] . "</td>";
		echo "<td>" . $riga["stipendio"] . "</td></tr>";
	}

	echo "</table>";

	mysql_close();

?>

Una volta connessi al server MySQL e selezionato il database corretto, è sufficiente eseguire una query SQL tramite la funzione mysql_query(). Quest'ultima restituirà una risorsa che leggeremo attraverso la funzione mysql_fetch_array().

mysql_fetch_array() estrae una riga dal risultato e lo trasforma in un array associativo (MYSQL_ASSOC) incrementando poi il contatore per puntare alla riga successiva alla prossima chiamata. E' infatti sufficiente richiamare nuovamente la funzione per ottenere l'array associativo della riga successiva.

Per accedere poi ai valori basta usare il nome del campo come chiave di accesso dell'array.

Il risultato ottenuto.


49. Classi per inviare email

In questo capitolo costruiremo una libreria che ci consentirà di inviare email complesse, ad esempio in HTML con uno o più allegati, in modo molto trasparente e veloce.

Questa libreria non è completa anche se funziona correttamente. Non ho infatti implementato alcuna gestione delle eccezioni che vi consiglio pertanto di aggiungere qualora decidiate di usarla nello sviluppo di applicazioni reali.
Inoltre sarebbe stato utile interfacciare la libreria con la classe "File" vista nei capitoli precedenti, ma ho preferito comunque non inserire altre classi esterne essendo lo scopo di questa libreria puramente didattico.

Vediamo ora le Classi che compongono questa nuova libreria e il loro scopo :

  • MIME - Classe usata come contenitore di costanti per definire i tipi MIME supportati dall'applicazione
  • MailBlock - Rappresenta un sottoblocco del messaggio email, quest ultimo sarà quindi composto da una o più istanze di MailBlock
  • Allegato - Derivata da MailBlock, rappresenta un file allegato ossia un sottoblocco più complesso con codifica Base64
  • Email - Classe principale creata per fornire un'interfaccia fra tutte le altre classi, costruendo il messaggio email completo e inviandolo

Classe : "MIME"
Nome file : "MIME.php"

<?php

	class MIME
	{
		const HTML = "text/html";
		const TEXT = "text/plain";
		const MULTI = "multipart/mixed";

		const GIF = "image/gif";
		const JPEG = "image/jpeg";
		const PNG = "image/png";
		const PSD = "image/psd";
		const BMP = "image/bmp";
		const TIFF = "image/tiff";
		const FLASH = "application/x-shockwave-flash";
	}

?>

Classe : "MailBlock"
Nome file : "MailBlock.php"

<?php

	define("EOL", "\r\n");

	class MailBlock
	{
		protected $content_type;
		protected $charset;
		protected $content_transfer_encoding;

		public $content;
		protected $boundary;

		public function MailBlock($content_type, $boundary, $content, $charset = "iso-8859-1", $c_t_encoding = "8bit")
		{
			$this->content_type = $content_type;
			$this->charset = $charset;
			$this->content_transfer_encoding = $c_t_encoding;

			$this->content = $content;
			$this->boundary = $boundary;
		}

		public function __toString()
		{
			$content = "--" . $this->boundary . EOL;
			$content .= "Content-Type: " . $this->content_type . "; charset=" . $this->charset . EOL;
			$content .= "Content-Transfer-Encoding: " . $this->content_transfer_encoding . EOL;
			$content .= $this->content . EOL;
			$content .= "--" . $this->boundary . EOL;

			return $content;
		}
	}

?>

La classe proposta è piuttosto semplice, non fa altro che collezionare i dati necessari a rappresentare un sottoblocco e ad organizzarli attraverso il metodo __toString().
Il codice che segue inizializza correttamente un sottoblocco in formato HTML :

<?php

	require_once("MIME.php");
	require_once("MailBlock.php");

	$boundary = "fa0s7u98hg87ngf0hgk05695j";
	$contenuto = "<ul><li>Linea uno</li><li>Linea due</li></ul>";

	$blocco = new MailBlock(MIME::HTML, $boundary, $contenuto);

	echo $blocco; // Richiama "__toString()" stampando il sottoblocco con la sintassi corretta

?>

Classe : "Allegato"
Nome file : "Allegato.php"

<?php

	require_once("MailBlock.php");

	class Allegato extends MailBlock
	{
		public $url;
		public $name;
		public $description;

		public function Allegato($name, $url, $content_type, $boundary, $description = NULL)
		{
			$this->url = $url;
			$this->name = $name;
			$this->boundary = $boundary;
			$this->description = $description;

			$this->content = $this->leggi();
			parent::MailBlock($content_type, $boundary, $this->content, "utf-8", "base64");
		}

		private function leggi()
		{
			$file = @fopen($this->url, "r");
			$allegato = fread($file, filesize($this->url));
			return base64_encode($allegato);
		}

		public function __toString()
		{
			$content = "--" . $this->boundary . EOL;
			$content .= "Content-Type: " . $this->content_type . "; name=\"" . $this->name . "\"" . EOL;
			$content .= "Content-Transfer-Encoding: " . $this->content_transfer_encoding . EOL;
			$content .= "Content-Description: " . $this->description . EOL;
			$content .= "Content-Disposition: attachment; filename=\"" . $this->name . "\"" . EOL;
			$content .= $this->content . EOL;
			$content .= "--" . $this->boundary . EOL;

			return $content;
		}
	}

?>

La classe soprastante deriva dalla precendente MailBlock, aggiungendo però tre importanti parametri necessari per gestire il file allegato, ossia l'url, il nome del file che sarà visualizzato dal destinatario e infine una descrizione facoltativa.

Il metodo privato leggi() si occupa invece di leggere il file specificato, per poi inserirlo nel sottoblocco in questione usando la codifica Base64.

Il metodo pubblico __toString() si comporta come il suo genitore, organizzando però il sottoblocco con i tre parametri aggiuntivi e inserendo alla fine il contenuto del file specificato.

Nel prossimo capitolo vedremo l'oggetto Email, l'ultima classe della nostra libreria con del codice d'esempio.

In questa lezione vedremo la classe Email, analizzandone brevemente metodi e attributi ed infine un esempio per l'utilizzo della nuova libreria con l'invio di due allegati.

Attributi

  • private $to_mail - Array contenente la lista dei destinatari.
  • private $object - Oggetto dell'email.
  • private $message - Array contenente tutti i sottoblocchi che formeranno il messaggio, ossia istanze di "MailBlock" e "Allegato".
  • public $mime - Versione MIME utilizzata per lo standard dell'email.
  • public $content_type - Content-Type per identificare il contenuto del messaggio (es. "text/html" oppure "multipart/mixed" ...).
  • private $boundary - Delimitatore boundary generato criptando il timestamp Unix corrente.
  • public $cc - Stringa contenente gli indirizzi per l'invio dell'email in copia carbone. Consiglio di rendere private l'attributo e di trasformarlo in un array, costruendo un metodo per un inserimento controllato.
  • public $bcc - Stringa contenente gli indirizzi per l'invio dell'email in copia carbone. Anche qui consiglio di agire come con l'attributo $cc.
  • public $date - Data di invio email (tipo stringa).
  • public $from - Indirizzo email del mittente, consiglio anche qui di effettuare la stessa modifica descritta per l'attributo $cc.
  • public $reply_to - Specifica l'email predefinita a cui il destinatario dell'email potrà rispondere. Anche qui stesso consiglio.
  • public $xmailer - Stringa che identifica il software utilizzato per l'invio dell'email.

Metodi

  • public Email() - Costruttore della classe. Inizializza $object, $content_type e altri attributi.
  • public blocco() - Aggiunge un sottoblocco standard al corpo del messaggio, ossia un'istanza MailBlock.
  • public allegato() - Aggiunge un sottoblocco più complesso al corpo del messaggio che rappresenterà un file allegato, ossia un'istanza di Allegato.
  • public destinatario() - Aggiunge un indirizzo alla lista dei destinatari.
  • private header() - Metodo privato che costruisce l'header dell'email basandosi sui parametri memorizzati negli attributi della classe.
  • public invia() - Metodo per l'invio dell'email. Restituisce true o false per identificare se l'invio è avvenuto con successo.

Classe : "Email"
Nome file : "Email.php"

<?php

	require_once("MIME.php");
	require_once("Allegato.php");

	class Email
	{
		private $to_mail;
		private $object;
		private $message;

		public $mime = "1.0";
		public $content_type;
		private $boundary = NULL;

		public $cc = NULL;
		public $bcc = NULL;
		public $date = NULL;
		public $from = NULL;
		public $replyto = NULL;
		public $xmailer = NULL;

		public function Email($object, $content_type = MIME::TEXT)
		{
			$this->to_mail = array();
			$this->object = $object;
			$this->message = array();

			$this->boundary = md5(time());
			$this->content_type = $content_type;
		}

		public function blocco($content_type, $content, $charset = "iso-8859-1", $c_t_encoding = "8bit")
		{
			$succ = count($this->message);
			$this->message[$succ] = new MailBlock($content_type, $this->boundary, $content, $charset, $c_t_encoding);
		}

		public function allegato($name, $url, $mime_type, $description = NULL)
		{
			$succ = count($this->message);
			$this->message[$succ] = new Allegato($name, $url, $mime_type, $this->boundary, $description);

			/* Se questo metodo viene richiamato significa che è stato inserito almeno un
			allegato quindi per sicurezza modifico il Content-Type a "multipart/mixed" */
			$this->content_type = MIME::MULTI;
		}

		public function destinatario($to_mail)
		{
			array_push($this->to_mail, $to_mail);
		}

		private function header()
		{
			$header = "MIME-Version: " . $this->mime . EOL;
			$header .= "Content-Type: " . $this->content_type . "; boundary=\"" . $this->boundary . "\"" . EOL;
			$header .= "Content-Transfer-Encoding: 8bit" . EOL;

			if ($this->from != NULL) { $header .= "From: " . $this->from . EOL; }
			if ($this->replyto != NULL) { $header .= "Reply-To: " . $this->replyto . EOL; }
			if ($this->cc != NULL) { $header .= "Cc: " . $this->cc . EOL; }
			if ($this->bcc != NULL) { $header .= "Bcc: " . $this->bcc . EOL; }
			if ($this->date != NULL) { $header .= "Date: " . $this->date . EOL; }
			if ($this->xmailer != NULL) { $header .= "X-Mailer: " . $this->xmailer; }

			return $header;
		}

		public function invia()
		{
			$message = "";
			$blocchi = count($this->message);

			for ($i = 0; $i < $blocchi; $i++)
				$message .= $this->message[$i]; // Richiama il metodo __toString() di "Allegato" o "MailBlock"

			$to = implode(", ", $this->to_mail);
			return mail($to, $this->object, $message, $this->header());
		}
	}

?>

Come potete vedere anche la classe Email è piuttosto semplice dovendo principalmente fungere da interfaccia unendo i dati.

Con questa classe la nostra libreria è al completo. Per ultimo vedremo un piccolo foglio PHP come esempio di utilizzo della libreria, inviando un'email con un blocco di testo, un blocco in HTML e 2 file allegati.

test.php

<?php

	require_once("Email.php");

	$mail = new Email("Mail con allegati", MIME::MULTI);

	/* Codice per aggiungere i destinatari */
	$mail->destinatario("RS Staff <posta@realizzazione-sito.info>");
	//$mail->destinatario("Utente1 <utente1@dominio.it>");
	//$mail->destinatario("Utente2 <utente2@dominio.it>");

	$mail->from = "Mittente <email_di_invio@gmail.com>";
	$mail->replyto = "Risposta <email_per_risposta@gmail.com>";

	$mail->blocco(MIME::TEXT, "Iniziamo con un pò di testo nel primo blocco!!");

	/* Memorizzo l'html per il secondo blocco in una
	variabile per favorire la leggibilità del codice */
	$html = "<ul><li>Linea uno</li><li>Linea due</li></ul>";
	$html .= "<table border=\"1\"><tr><td>topolino<td><td>minnie</td></tr></table>";

	$mail->blocco(MIME::HTML, $html);
	$mail->allegato("litfiba.jpg", "allegati/file.jpg", MIME::JPEG);
	$mail->allegato("220 volts.jpg", "allegati/220v.jpg", MIME::JPEG);

	$inviata = $mail->invia();

	if ($inviata) { echo "Mail inviata con successo!!"; }
	else { echo "Mail non inviata!!"; }

?>

Il risultato ottenuto.

Anche in questo caso ho testato il codice solo con GMail, non escludo quindi problemi di compatibilità con altri siti o client di posta (Outlook, Eudora ...), e dovendo riscontrarne vi consiglio di provare a modificare l'EOL o il boundary di chiusura.

Condividi contenuti