<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Web Magazine. Blog sul mondo del web design. &#187; web design</title>
	<atom:link href="http://www.web-magazine.it/category/web-design-lavoro-e-professioni/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.web-magazine.it</link>
	<description>Guide e rubriche per diventare web designer freelance e per gestire l&#039;attività in proprio senza problemi.</description>
	<lastBuildDate>Thu, 26 Jan 2012 06:00:53 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.4</generator>
		<item>
		<title>Creare siti in PHP – (30) – Le espressioni regolari</title>
		<link>http://www.web-magazine.it/2012/01/creare-siti-in-php-%e2%80%93-30-%e2%80%93-le-espressioni-regolari/</link>
		<comments>http://www.web-magazine.it/2012/01/creare-siti-in-php-%e2%80%93-30-%e2%80%93-le-espressioni-regolari/#comments</comments>
		<pubDate>Thu, 26 Jan 2012 06:00:53 +0000</pubDate>
		<dc:creator>Federico</dc:creator>
				<category><![CDATA[scripting]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[regex]]></category>
		<category><![CDATA[regular expressions]]></category>

		<guid isPermaLink="false">http://www.web-magazine.it/?p=2300</guid>
		<description><![CDATA[Ultima puntata della guida base al linguaggio PHP: parleremo di espressioni regolari. Impareremo a conoscere i metacaratteri, i quantificatori e le classi di caratteri e a usarli per creare pattern utili all'interno dei nostri script tramite le funzioni preg_match e preg_replace.]]></description>
			<content:encoded><![CDATA[<p><img src="http://www.web-magazine.it/wp-content/uploads/2011/11/php30.jpg" alt="Le espressioni regolari" /></p>
<p><strong>Siamo arrivati all&#8217;ultima puntata</strong> di <strong>questa guida base al linguaggio PHP</strong>, e per concludere affrontiamo oggi un argomento di sicuro <strong>non semplice</strong> ma che cercheremo di trattare in modo tale da fornire alcuni strumenti utili per la sua comprensione: stiamo parlando delle <strong>espressioni regolari</strong>. In una sola puntata <strong>non riusciremo</strong> a trattare l&#8217;argomento in modo completo al 100% ma con le nozioni che avremo alla fine potremo<strong> eseguire diverse operazioni</strong>.</p>
<p><span id="more-2300"></span></p>
<h3>Le espressioni regolari</h3>
<p>Per iniziare possiamo dire che cosa sono e a che cosa servono le espressioni regolari. Si tratta di particolari <strong>costrutti</strong> che si usano per verificare se all&#8217;interno di una stringa (e quando in PHP si parla di stringa si intende anche <strong>un testo lungo e complesso</strong>) è presente una certa sottostringa. Potreste pensare che in realtà non ci sono novità perché abbiamo già visto, nella puntata dedicata alle funzioni sulle stringhe, come <strong>cercare e sostituire sottostringhe</strong>. In realtà le espressioni regolari <strong>sono uno strumento molto più potente </strong>perché non definiscono semplici sottostringhe ma, data la loro natura versatile, con <strong>un solo</strong> <em><strong>pattern</strong></em> (una <strong>sequenza di caratteri</strong>) possiamo cercare una <strong>grande varietà di sottostringhe</strong>.</p>
<p>Le espressioni regolari possono essere utili per moltissime situazioni: per esempio, nella puntata in cui parlavamo dei form abbiamo fatto un cenno alle espressioni regolari perché abbiamo detto che servono per controllare se l&#8217;utente inserisce <strong>un indirizzo email corretto</strong>. Questo infatti potrebbe essere un utilizzo, ma potremmo usare le espressioni regolari per altre operazioni, per esempio controllare <strong>se un dominio è stato scritto correttamente</strong>, <strong>evidenziare una certa occorrenza</strong> o un insieme di occorrenze in un testo, <strong>cercare tutte le etichette HTML</strong> presenti in un testo, <strong>sostituire doppi apici con virgolette</strong>, <strong>controllare la complessità di una password</strong> e via dicendo.</p>
<h3>I metacaratteri</h3>
<p>Entriamo subito nell&#8217;argomento e iniziamo a parlare di <strong>“metacaratteri”</strong>, ovvero di caratteri speciali inseriti all&#8217;interno di una espressione regolare e che sono dotati <strong>di un significato ben preciso</strong>. Per esempio la sequenza<strong> [a-z] </strong>indica “qualsiasi lettera minuscola compresa tra la a e la z”. Se volessimo invece trovare tutte le lettere non solo minuscole ma anche maiuscole dovremmo scrivere un&#8217;espressione come questa: <strong>[a-zA-Z]</strong>. Avrete quindi intuito che <strong>le parentesi quadre racchiudono un insieme di caratteri</strong>. Vediamo quali sono i metacaratteri:</p>
<table border="1" cellspacing="1" cellpadding="4" >
<tr valign="TOP">
<td width="27%">[] (parentesi quadre)</td>
<td width="73%">Contengono una sequenza di caratteri</td>
</tr>
<tr valign="TOP">
<td width="27%">() (parentesi tonde)</td>
<td width="73%">Contengono una precisa sottostringa</td>
</tr>
<tr valign="TOP">
<td width="27%">. (punto)</td>
<td width="73%">Qualsiasi carattere</td>
</tr>
<tr valign="TOP">
<td width="27%">^ (accento circonflesso)</td>
<td width="73%">Inizio di stringa o negazione</td>
</tr>
<tr valign="TOP">
<td width="27%">$ (dollaro)</td>
<td width="73%">Fine della stringa</td>
</tr>
<tr valign="TOP">
<td width="27%">| (pipe)</td>
<td width="73%">Operatore disgiuntivo OR</td>
</tr>
<tr valign="TOP">
<td width="27%">\ (backslash)</td>
<td width="73%">Carattere di escape</td>
</tr>
</table>
<h3>I quantificatori</h3>
<p>Esistono poi i <strong>quantificatori</strong>, che indicano <strong>quante volte</strong> bisogna cercare un&#8217;occorrenza all&#8217;interno della nostra stringa principale:</p>
<table border="1" cellspacing="0" cellpadding="4">
<tr valign="TOP">
<td width="27%">* (asterisco)</td>
<td width="73%">Zero o più occorrenze</td>
</tr>
<tr valign="TOP">
<td width="27%">? (punto interrogativo)</td>
<td width="73%">Zero o una occorrenza</td>
</tr>
<tr valign="TOP">
<td width="27%">+ (più)</td>
<td width="73%">Una o più occorrenze</td>
</tr>
<tr valign="TOP">
<td width="27%">{} (parentesi graffe)</td>
<td width="73%">Contengono il numero che rappresenta la 			ripetizione di un&#8217;occorrenza.</td>
</tr>
</table>
<h3>Alcuni esempi&#8230;</h3>
<p>Facciamo alcuni esempi per comprendere meglio:</p>
<table border="0" cellspacing="0" cellpadding="4">
<tr valign="TOP">
<td width="27%">[a-zA-Zàèéìòù0-9]</td>
<td width="73%">Tutti i caratteri minuscoli e maiuscoli, le 			lettere accentate e i numeri</td>
</tr>
<tr valign="TOP">
<td width="27%">[^0-9]</td>
<td width="73%">Un qualsiasi carattere che non sia un numero</td>
</tr>
<tr valign="TOP">
<td width="27%">(ciao)</td>
<td width="73%">La sottostringa “ciao”</td>
</tr>
<tr valign="TOP">
<td width="27%">t?o</td>
<td width="73%">La lettera o preceduta da 0 o 1 occorrenze della 			lettera t (se il testo è “gatto, canto, albero” ci saranno 			tre risultati utili e cioè la sequenza “to” di gatto, la 			sequenza “to” di canto e la “o” di albero)</td>
</tr>
<tr valign="TOP">
<td width="27%">t*o</td>
<td width="73%">La lettera o preceduta da 0 o più occorrenze 			della lettera t (per il testo precedente ci saranno tre risultati 			utili e cioè “tto” di gatto, “to” di canto e “o” di 			albero)</td>
</tr>
<tr valign="TOP">
<td width="27%">t+o</td>
<td width="73%">La lettera o preceduta da 1 o più occorrenze 			della lettera t (due risultati utili, “tto” di gatto e “to” 			di canto)</td>
</tr>
<tr valign="TOP">
<td width="27%">t{2}o</td>
<td width="73%">La lettera o preceduta da 2 occorrenze della 			lettera t (un risultato, “tto” di gatto)</td>
</tr>
<tr valign="TOP">
<td width="27%">t{3,5}o</td>
<td width="73%">La lettera o preceduta da un minimo di 3 fino a 			un massimo di 5 occorrenze della lettera t (nessun risultato)</td>
</tr>
<tr valign="TOP">
<td width="27%">[^t]t{1}o</td>
<td width="73%">Un&#8217;occorrenza della lettera t seguita dalla 			lettera o e preceduta da qualsiasi carattere purché non sia una t 			(un risultato, “to” di canto)</td>
</tr>
<tr valign="TOP">
<td width="27%">[a-s](to)</td>
<td width="73%">Qualsiasi carattere compreso tra a e s seguito 			dalla sottostringa “to” (un solo risultato, “to” di 			canto).</td>
</tr>
<tr valign="TOP">
<td width="27%">(2\+2)</td>
<td width="73%">La stringa “2+2”</td>
</tr>
<tr valign="TOP">
<td width="27%">.$</td>
<td width="73%">Qualsiasi carattere purché sia l&#8217;ultimo della 			stringa</td>
</tr>
<tr valign="TOP">
<td width="27%">(to)|(ro)</td>
<td width="73%">La sottostringa “to” o la sottostringa “ro” 			(tre risultati: “to” di gatto, “to” di canto e “ro” di 			albero</td>
</tr>
</table>
<h3>&#8230; e altri esempi, più pratici</h3>
<p>E così via. A questo punto abbiamo quindi gli strumenti per creare dei pattern utili&#8230; partiamo dall&#8217;esempio più semplice, ovvero <strong>un pattern per validare una partita IVA</strong> che come tutti sappiamo è composta da undici numeri:</p>
<p><code>^[0-9]{11}$</code></p>
<p>Non facciamo altro che creare una sequenza [0-9] <strong>che indica un qualsiasi numero</strong>, e la facciamo seguire subito dalla sequenza {11} che indica che il numero <strong>deve obbligatoriamente occorrere undici volte</strong>. L&#8217;accento circonflesso e il dollaro indicano ovviamente <strong>l&#8217;inizio e la fine della stringa</strong>. Se omettessimo uno dei due, <strong>avremmo vanificato il controllo</strong> in quanto potremmo inserire un qualsiasi numero prima o dopo la nostra partita IVA e il pattern verrebbe comunque validato perché il nostro script non saprebbe <strong>da dove inizia o dove finisce la stringa</strong>.</p>
<p>Possiamo poi creare un <strong>pattern che controlli che un dato file sia un&#8217;immagine</strong>:</p>
<p><code>^.+\.(jpeg|jpg|png|gif)$</code></p>
<p>Abbiamo qui il punto che indica <strong>una qualsiasi sequenza di caratteri</strong>, seguito da un “vero” punto (per essere considerato tale, <strong>deve essere preceduto dal carattere di escape</strong>) e quindi dalle estensioni tipiche delle immagini “da web” (jpeg, jpg, png, gif) <strong>tra parentesi tonde</strong> e separate tra di loro per mezzo dell&#8217;<strong>operatore disgiuntivo</strong>.</p>
<p>Prendiamo poi, per esempio, <strong>un controllo per validare una data</strong>:</p>
<p><code>^[0-9]{1,2}\.[0-9]{1,2}\.[0-9]{4}$</code></p>
<p>In questo caso non facciamo altro che creare tre sequenze [0-9] <strong>rispettivamente per i giorni, i mesi e gli anni</strong>: nei primi due casi il numero può comparire <strong>da un minimo di una a un massimo di due volte </strong>e deve essere seguito da un punto (con cui separiamo i numeri della data&#8230; gusti personali) a sua volta preceduto da un <strong>backslash</strong>. Per quanto riguarda l&#8217;anno invece il numero deve essere <strong>obbligatoriamente presente quattro volte</strong>.</p>
<p>Più complesso invece è il <strong>pattern per validare un indirizzo email</strong>:</p>
<p><code>^[a-zA-Z0-9_\.\-]+@[a-zA-Z0-9_\.\-]+\.[a-z]{2,6}$</code></p>
<p>Nella prima sequenza tra parentesi quadre inseriamo <strong>tutti i caratteri alfanumerici insieme all&#8217;underscore, al punto e al trattino</strong> e indichiamo che possono ricorrere <strong>una o più volte</strong> attraverso l&#8217;uso del segno +, a fui facciamo seguire <strong>la chiocciola</strong>. Questa prima sequenza rappresenta il nome utente dell&#8217;indirizzo. Dopo la chiocciola inseriamo un&#8217;altra sequenza tra parentesi quadre simile alla prima e poi inseriamo <strong>il punto preceduto dal carattere di escape</strong>. Abbiamo quindi <strong>il nome del dominio</strong>, a cui facciamo seguire l&#8217;espressione [a-z] che può ricorrere <strong>da un minimo di 2 fino a un massimo di 6 volte</strong>: è nient&#8217;altro che <strong>l&#8217;estensione del dominio</strong>.</p>
<h3>Le classi di caratteri</h3>
<p>Per alcune delle espressioni che abbiamo utilizzato esistono poi le cosiddette <strong>“classi di caratteri”</strong>, ovvero <strong>caratteri che corrispondono a precise sequenze</strong> e che possono accorciare molto il nostro lavoro. Vediamone alcune:</p>
<table border="1" cellspacing="0" cellpadding="4" width="100%">
<col width="128*"></col>
<col width="128*"></col>
<tbody>
<tr valign="TOP">
<td width="27%">\w</td>
<td width="73%">Corrisponde a [a-zA-Z0-9_]</td>
</tr>
<tr valign="TOP">
<td width="27%">\W</td>
<td width="73%">Corrisponde a [^a-zA-Z0-9_]</td>
</tr>
<tr valign="TOP">
<td width="27%">\d</td>
<td width="73%">Corrisponde a [0-9]</td>
</tr>
<tr valign="TOP">
<td width="27%">\D</td>
<td width="73%">Corrisponde a [^0-9]</td>
</tr>
<tr valign="TOP">
<td width="27%">\s</td>
<td width="73%">Cerca gli spazi</td>
</tr>
<tr valign="TOP">
<td width="27%">\S</td>
<td width="73%">Cerca tutto ciò che non sia uno spazio</td>
</tr>
<tr valign="TOP">
<td width="27%">[:alnum:]</td>
<td width="73%">Corrisponde a [a-zA-Z0-9]</td>
</tr>
<tr valign="TOP">
<td width="27%">[:alpha:]</td>
<td width="73%">Corrisponde a [a-zA-Z]</td>
</tr>
<tr valign="TOP">
<td width="27%">[:lower:]</td>
<td width="73%">Corrisponde a [a-z]</td>
</tr>
<tr valign="TOP">
<td width="27%">[:upper:]</td>
<td width="73%">Corrisponde a [A-Z]</td>
</tr>
<tr valign="TOP">
<td width="27%">[:punct:]</td>
<td width="73%">Cerca i caratteri di punteggiatura</td>
</tr>
</tbody>
</table>
<p>Negli ultimi cinque casi, le parentesi quadre sono parte integrante della sequenza, quindi se vogliamo cercare i i segni di interpunzione nella nostra stringa il pattern dovrà essere strutturato in questo modo:</p>
<p>[[:punct:]]</p>
<p>Con le classi di caratteri, le stringhe per la validazione di partite IVA e indirizzi email, tanto per prendere due degli esempi che abbiamo fatto in precedenza, potrebbero diventare una cosa di questo tipo:</p>
<p><code>^\d{11}$</code></p>
<p><code>^\S+@[\w.-]+\.[a-z]{2,6}$</code></p>
<h3>Espressioni regolari e PHP: preg_match e preg_replace</h3>
<p>Ma come fare per <strong>eseguire il controllo nel nostro script PHP</strong>? Abbiamo bisogno di una funzione, <em>preg_match</em>, che riceve come parametri <strong>il pattern e la stringa da controllare</strong> e nel caso in cui nel testo ci sia almeno una coincidenza con il pattern, la funzione restituirà come risultato 1 (true), e in caso contrario il risultato sarà 0 (false).</p>
<p>Per esempio, poniamo il caso di uno script che controlla se un utente, attraverso un form, <strong>ha caricato un&#8217;immagine con estensione corretta</strong> (il nome dell&#8217;immagine sarà stato precedentemente memorizzato in una variabile $immagine).</p>
<p><code>if (preg_match('/^.+\.(jpeg|jpg|png|gif)$/', $immagine)) {<br />
echo "Grazie per aver caricato l'immagine!";<br />
}<br />
else {<br />
echo "L'immagine ha un'estensione non valida";<br />
}</code></p>
<p>I due slash inseriti dopo gli apici del primo parametro della funzione sono <strong>i delimitatori</strong>: se non inseriti,<strong> lo script restituirà un errore</strong>. Il meccanismo della funzione è molto semplice: il blocco if controlla che il risultato sia true e in caso affermativo stampa la scritta “Grazie per aver caricato l&#8217;immagine!”, mentre in caso contrario la scritta mostrata all&#8217;utente sarà “L&#8217;immagine ha un&#8217;estensione non valida”.</p>
<p>La funzione può essere usata anche, ovviamente, <strong>nel modo inverso</strong>, al negativo, facendo precedere la funzione <strong>dal punto esclamativo che indica negazione</strong>:</p>
<p><code>if (!preg_match('/^[a-zA-Z0-9_\.\-]+@[a-zA-Z0-9_\.\-]+\.[a-z]{2,6}$/', $indirizzoemail)) {<br />
echo "Indirizzo email non valido";<br />
}<br />
else {<br />
echo "Indirizzo email valido!";<br />
}</code></p>
<p>In questo caso <strong>abbiamo controllato un indirizzo email</strong>. La documentazione ufficiale della funzione <em>preg_match</em> si può trovare all&#8217;indirizzo <a href="http://php.net/manual/en/function.preg-match.php">http://php.net/manual/en/function.preg-match.php</a>.</p>
<p>Abbiamo detto poi che attraverso le espressioni regolari possiamo poi anche fare <strong>sostituzioni all&#8217;interno di un testo</strong>. Questa operazione si può eseguire attraverso l&#8217;utilizzo della funzione <em>preg_replace</em> che riceve <strong>tre parametri</strong>: l&#8217;espressione regolare che definisce <strong>le sequenze da sostituire</strong>, <strong>la sottostringa sostituta</strong> e <strong>la stringa all&#8217;interno della quale compiere la sostituzione</strong>. Con un esempio banale:</p>
<p><code>$testo = "Cane, gatto, topo, cavallo, pecora, mucca";<br />
echo preg_replace ("/[aeiou]/", "*", $testo);</code></p>
<p>Attraverso l&#8217;utilizzo della funzione <em>preg_replace</em> (il cui risultato sarà direttamente stampato attraverso <em>echo</em>) cerchiamo nella stringa $testo tutte le volte in cui <strong>occorre una vocale</strong> tramite la sequenza <strong>[aeiou]</strong>, e <strong>sostituiamo ogni vocale con un asterisco</strong>. Questa funzione si presta a diversi utilizzi&#8230; per esempio, stiamo costruendo un blog e vogliamo censurare le parolacce dei nostri commentatori (farò un esempio&#8230; senza parolacce ma che funziona allo stesso modo).</p>
<p><code>$testo = "Il gatto mangia il topo";<br />
echo preg_replace ("/(gatto|topo)/", "***", $testo);</code></p>
<p>In questo caso la parola “gatto” e la parola “topo” vengono sostituite dalla sequenza ***. Possiamo poi adoperare la funzione anche per <strong>sostituire etichette HTML</strong>:</p>
<p><code>$testo = "&lt;strong&gt;Ciao&lt;/strong&gt;!!!!!";<br />
$testo = preg_replace("/(&lt;strong&gt;)/", "&lt;em&gt;", $testo);<br />
echo preg_replace("/(&lt;\/strong&gt;)/", "&lt;/em&gt;", $testo);</code></p>
<p>In questo caso sostituiamo <strong>tutte le parole marcate in grassetto con parole marcate in corsivo</strong>. Questi non sono che alcuni esempi, e <strong>la versatilità delle espressioni regolari</strong> dà modo a ognuno di <strong>sfruttarle al meglio per le proprie esigenze</strong>. Per chiunque fosse interessato all&#8217;argomento, consiglio di approfondire facendo una ricerca sul web: si trovano davvero molti siti che sapranno spiegare meglio di me e in modo più completo l&#8217;utilizzo di questo affascinante strumento.</p>
<h3>Ciao a tutti!!!</h3>
<p>Benissimo, con la puntata di oggi termina anche la nostra guida di base al linguaggio PHP!</p>
<p>Mi auguro che la guida sia stata di vostro gradimento, che possa essere stata utile per imparare qualcosa di nuovo o per ripassare e che possa in generale dare un piccolo aiuto a chiunque voglia cimentarsi con PHP. Ringrazio Laura per avermi fornito questo spazio e ovviamente un grazie a tutti quelli che mi hanno seguito fino a questo punto, a quelli che hanno seguito anche poche puntate, a chi si è collegato una volta sola e a tutti coloro che hanno commentato e hanno tentato di risolvere gli esercizi <img src='http://www.web-magazine.it/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> </p>
<p>Un grande saluto!!!!!!!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.web-magazine.it/2012/01/creare-siti-in-php-%e2%80%93-30-%e2%80%93-le-espressioni-regolari/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Creare siti in PHP – (29) – La sicurezza in PHP: session hijacking</title>
		<link>http://www.web-magazine.it/2012/01/creare-siti-in-php-%e2%80%93-29-%e2%80%93-la-sicurezza-in-php-session-hijacking/</link>
		<comments>http://www.web-magazine.it/2012/01/creare-siti-in-php-%e2%80%93-29-%e2%80%93-la-sicurezza-in-php-session-hijacking/#comments</comments>
		<pubDate>Mon, 23 Jan 2012 06:00:40 +0000</pubDate>
		<dc:creator>Federico</dc:creator>
				<category><![CDATA[scripting]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[sessioni]]></category>
		<category><![CDATA[sicurezza]]></category>

		<guid isPermaLink="false">http://www.web-magazine.it/?p=2296</guid>
		<description><![CDATA[Nella penultima puntata della guida base a PHP parliamo di session hijacking nelle sue due forme più temibili: session fixation e session sidejacking. Impariamo come difenderci utilizzando la funzione session_regenerate_id ed eseguendo controlli sullo user agent]]></description>
			<content:encoded><![CDATA[<p><img src="http://www.web-magazine.it/wp-content/uploads/2011/11/php29.jpg" alt="La sicurezza in PHP: session hijacking " /></p>
<p>Terminiamo oggi la breve panoramica sui più comuni problemi di sicurezza con una puntata sul <strong>session hijacking</strong>, che consiste nel <strong>“furto dell&#8217;identità”</strong> di un utente che si collega a un sito web.</p>
<p><span id="more-2296"></span></p>
<h3>Session hijacking: che cos&#8217;è</h3>
<p>Che cosa fa il malintenzionato che sottopone l&#8217;utente di un sito a session hijacking? Non fa altro che <strong>rubare l&#8217;identificativo di sessione dell&#8217;utente</strong> (ogni sessione <strong>ha un proprio id</strong>) per poi loggarsi al sito <strong>spacciandosi per l&#8217;utente</strong> a cui ha rubato le credenziali. Uno dei metodi più comuni per rubare le credenziali è <strong>sfruttare il cross-site scripting</strong>: abbiamo però già parlato nell&#8217;episodio precedente di come difenderci da questo tipo di attacchi, quindi vedremo oggi come coprirci anche da un furto ottenuto tramite <strong>“session fixation”</strong>: con la <strong>session fixation</strong>, i dati verranno rubati tramite <strong>una sessione creata </strong><em><strong>ad hoc</strong></em> dal malintenzionato.</p>
<p>Certo, affinché si verifichi una session fixation<strong> devono essere soddisfatte due condizioni</strong>: <strong>codice vulnerabile</strong> e <strong>utente sprovveduto</strong>. Nella puntata sulle sessioni non abbiamo parlato del modo in cui l&#8217;id di sessione <strong>viene propagato</strong>: ciò può avvenire <strong>tramite un cookie</strong> che viene appositamente creato per contenere l&#8217;id (cookie che si estinguerà alla chiusura del browser) oppure, nel caso in cui i cookie siano stati disabilitati, <strong>tramite metodi get e post</strong>. Il ladro di sessioni può convincere l&#8217;utente del nostro sito (magari tramite una mail o con un post su un blog) a collegarsi a un indirizzo simile a questo: www.nostrosito.it/login.php?PHPSESSID=12345 dove, <strong>attraverso la query string</strong> e ipotizzando che l&#8217;id di sessione venga <strong>propagato tramite get</strong>, decide il numero di sessione.</p>
<h3>Simuliamo un attacco</h3>
<p>Per comprendere meglio il meccanismo di un attacco session fixation proviamo a simularne uno (ma, come detto nella scorsa puntata, solo affinché vi possiate difendere). Per prima cosa assicuriamoci che nelle impostazioni del nostro PHP sia abilitata la trasmissione dei dati di sessione <strong>attraverso url</strong>: clicchiamo quindi sull&#8217;icona di Wamp, andiamo sotto la voce PHP e quindi apriamo il file php.ini. Cerchiamo adesso la direttiva <em>session.use_trans_sid</em>, che è quella che consente la <strong>tramissione degli id di sessione via url</strong> (a proposito: i commenti sopra di essa vi diranno che <strong>abilitarla sottopone a rischi di sicurezza</strong>). Se è a 1 lasciamola com&#8217;è, altrimenti se è impostata a 0 dobbiamo settarla a 1. Cerchiamo poi la direttiva <em>session.use_only_cookies</em> (permette la trasmissione degli id di sessione <strong>solo tramite cookie</strong>) e impostiamola a 0.</p>
<p>A questo punto creiamo un semplice codice PHP che al nostro collegamento dà inizio a una sessione che memorizza <strong>il numero di volte in cui visualizziamo la pagina</strong> con il nostro browser:</p>
<p><code>&lt;?php<br />
session_start();<br />
if (!isset($_SESSION['conto'])) {<br />
$_SESSION['conto'] = 0;<br />
} else {<br />
$_SESSION['conto']++;<br />
}<br />
echo "Numero:" . $_SESSION['conto']."";<br />
?&gt;</code></p>
<p>Tutto molto semplice. Con la solita funzione <em>isset </em>controlliamo che la variabile $_SESSION['conto'] non sia stata inizializzata: se non esiste, la creiamo e la impostiamo a 0, se invece esiste già la incrementiamo. Terminato il blocco if stampiamo la nostra variabile.</p>
<p>Salvate il file chiamandolo, per esempio, “fixation.php” e inseritelo in una cartella “prova” all&#8217;interno della cartella “www” di Wamp. A questo punto aprite il vostro browser preferito (per esempio Firefox), <strong>eliminate tutti i cookie</strong> di localhost e collegatevi a questo indirizzo: http://localhost/prova/fixation.php?PHPSESSID=12345. Aggiornate la pagina un qualsiasi numero di volte, arriviamo per esempio a 9.</p>
<p>A questo punto chiudete pure il browser. Riaprite un altro browser (esempio, Chrome), magari anche su un altro computer se fate la prova su un server remoto, e provate a collegarvi allo stesso indirizzo: come potrete notare il conto non ripartirà da 0 ma partirà da dove siete rimasti prima (nel nostro caso vedremo “10”). Cosa significa questo? Abbiamo simulato <strong>un ipotetico utente A</strong> che utilizza Firefox, apre la pagina con il link <strong>che gli è stato suggerito dal malintenzionato utente B </strong>e dà inizio a una sessione. L&#8217;utente B aprirà poi il suo Chrome <strong>con l&#8217;id di sessione da lui stesso creato</strong> e <strong>potrà accedere ai dati dell&#8217;utente A</strong>. In questo caso si tratta semplicemente del numero di volte che ha aggiornato la pagina, ma questo tipo di attacco funziona tranquillamente anche su script molto più complessi (per esempio un login a un sito web: il malintenzionato B potrà accedere indisturbato a tutti i dati personali dell&#8217;utente A) che però <strong>hanno seri problemi di sicurezza</strong>.</p>
<h3>Come difendersi: session_regenerate_id</h3>
<p>Come difendersi da questo attacco? Il metodo più semplice è <strong>rigenerare spesso l&#8217;id di sessione</strong>, in modo da rendere inefficaci gli attacchi: questo si può fare agevolmente tramite l&#8217;apposita funzione <em>session_regenerate_id</em>, che si applica in modo molto semplice:</p>
<p><code>session_regenerate_id();</code></p>
<p>E in genere va fatto <strong>dopo aver dato il via alla sessione </strong>con <em>session_start</em>. La documentazione ufficiale di questa funzione si trova all&#8217;indirizzo <a href="http://php.net/manual/en/function.session-regenerate-id.php">http://php.net/manual/en/function.session-regenerate-id.php</a>. Inoltre sarebbe bene che le direttive di cui sopra,  <em>session.use_trans_sid</em> e  <em>session.use_only_cookies</em>, fossero impostate rispettivamente a 0 e 1. Comunque l&#8217;utilizzo di <em>session_regenerate_id </em>è di per sé già sufficiente per difendersi. È quindi bene <strong>rigenerare spesso</strong>, anche <strong>prima che l&#8217;utente abbia fatto login</strong> (inserendo quindi la funzione nella pagina di login, per esempio).</p>
<h3>Come difendersi: controllo sullo user agent</h3>
<p>Infine potremmo eseguire <strong>un controllo aggiuntivo sullo user agent dell&#8217;utente</strong> (perché niente impedisce che <strong>uno stesso id di sessione</strong>, come abbiamo visto, <strong>possa essere utilizzato da due utenti diversi</strong>): questo consente anche di avere una difesa contro attacchi di tipo <strong>“session sidejacking”</strong>. Attraverso questo tipo di attacco, comunque difficile da mettere in atto, il malintenzionato cerca di <strong>intercettare l&#8217;id di sessione attraverso i pacchetti di rete</strong> che vengono scambiati tra il server e il browser dell&#8217;utente. Per ovviare a questa minaccia può essere utile fare in modo che <strong>l&#8217;accesso venga impedito</strong> nel caso in cui lo <em>user agent</em> di chi richiede l&#8217;accesso al nostro sito<strong> non corrisponda </strong>a quello dell&#8217;utente che ha effettuato il login.</p>
<p>Per fare questo abbiamo bisogno della variabile superglobale <strong>$_SESSION</strong>: dovremo associare a essa il valore dell&#8217;elemento <strong>HTTP_USER_AGENT</strong> della variabile superglobale <strong>$_SERVER</strong>, <strong>meglio se codificato tramite funzione md5</strong>. Il tutto nella pagina o nella funzione che consente il login:</p>
<p><code>$_SESSION['HTTP_USER_AGENT'] = md5($_SERVER['HTTP_USER_AGENT']);</code></p>
<p>In questo modo abbiamo creato un elemento della sessione chiamato HTTP_USER_AGENT a cui abbiamo associato nient&#8217;altro che il nostro user agent criptato con md5. A questo punto, per eseguire il controllo, potremmo utilizzare un codice simile a questo:</p>
<p><code>if (isset($_SESSION['HTTP_USER_AGENT'])) {<br />
if ($_SESSION['HTTP_USER_AGENT'] != md5($_SERVER['HTTP_USER_AGENT'])) {<br />
logout();<br />
}<br />
}</code></p>
<p>Con questo script non facciamo altro che controllare, sempre tramite la funzione<em> isset</em>, se esiste la sessione con elemento “HTTP_USER_AGENT”: in caso affermativo, se il suo valore <strong>è diverso dallo user agent</strong>, sempre criptato con md5, <strong>dell&#8217;utente che sta eseguendo lo script</strong> (in altre parole se <strong>chi si è loggato ha uno user agent diverso</strong> rispetto a quello <strong>dell&#8217;utente che sta cercando di forzare l&#8217;accesso al sito</strong>), rimandiamo l&#8217;utente a una ipotetica funzione logout <strong>che distruggerà la sessione</strong>.</p>
<p>Anche per oggi la puntata è arrivata alla fine: vi do appuntamento alla prossima, la trentesima nonché ultima della nostra guida!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.web-magazine.it/2012/01/creare-siti-in-php-%e2%80%93-29-%e2%80%93-la-sicurezza-in-php-session-hijacking/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>Creare siti in PHP – (28) – La sicurezza in PHP: XSS e SQL Injection</title>
		<link>http://www.web-magazine.it/2012/01/creare-siti-in-php-%e2%80%93-28-%e2%80%93-la-sicurezza-in-php-xss-e-sql-injection/</link>
		<comments>http://www.web-magazine.it/2012/01/creare-siti-in-php-%e2%80%93-28-%e2%80%93-la-sicurezza-in-php-xss-e-sql-injection/#comments</comments>
		<pubDate>Thu, 19 Jan 2012 06:00:34 +0000</pubDate>
		<dc:creator>Federico</dc:creator>
				<category><![CDATA[scripting]]></category>
		<category><![CDATA[web design]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[sicurezza]]></category>
		<category><![CDATA[sql injection]]></category>
		<category><![CDATA[strip_tags]]></category>
		<category><![CDATA[xss]]></category>

		<guid isPermaLink="false">http://www.web-magazine.it/?p=2291</guid>
		<description><![CDATA[Prima di due puntate dedicate alla sicurezza in PHP. Parliamo oggi di cross-site scripting (XSS) e di SQL injection e impariamo alcune semplici tecniche su come difendere il nostro sito. E ricordiamoci di filtrare sempre tutti gli input!]]></description>
			<content:encoded><![CDATA[<p><img src="http://www.web-magazine.it/wp-content/uploads/2011/11/php28.jpg" alt="La sicurezza in PHP: XSS e SQL Injection" /><br />
Iniziamo oggi una breve panoramica su due dei <strong>problemi di sicurezza più comuni</strong> degli script PHP.</p>
<p><span id="more-2291"></span></p>
<h3>XSS: Cross-site scripting</h3>
<p>Partiamo dal cosiddetto <strong>“Cross-site scripting”</strong>, noto anche come <strong>XSS</strong>: si tratta di un problema, molto diffuso, che riguarda <strong>la sicurezza dei form</strong> e in particolare i form che <strong>non applicano controlli sui campi</strong>. Il malintenzionato può, tramite il form, far eseguire un codice JavaScript che magari <strong>rimanda a un suo sito</strong> dove è contenuto <strong>uno script dannoso</strong>. A proposito: ricordo a tutti quelli che leggono (visti i numerosi accessi al sito) che alcune delle cose che sto per illustrare, se messe in pratica, <strong>costituiscono un reato penalmente perseguibile</strong>. <strong>Ve ne parlo solo affinché vi possiate difendere</strong>.</p>
<p>Tornando al nostro XSS, prendiamo un semplicissimo form per inserire un messaggio:</p>
<p><code>&lt;form action="xss.php" method="get"&gt;<br />
Nome:&lt;br /&gt;<br />
&lt;input type="text" name="nome" /&gt;&lt;br /&gt;<br />
Messaggio: &lt;br /&gt;<br />
&lt;textarea rows="10" cols="20" name="messaggio"&gt;&lt;/textarea&gt;&lt;br /&gt;<br />
&lt;input type="submit" name="invia" value="Invia!" /&gt;&lt;br /&gt;<br />
&lt;/form&gt;</code></p>
<p>E supponiamo che il codice della pagina xss.php sia strutturato in questo modo:</p>
<p><code>&lt;?php<br />
echo "Nome: {$_GET['nome']}";<br />
echo "&lt;br /&gt;&lt;br /&gt;Messaggio: &lt;br /&gt;&lt;br /&gt;";<br />
echo stripslashes($_GET['messaggio']);<br />
?&gt;</code></p>
<p>Bene, questo è <strong>un codice del tutto insicuro </strong>perché <strong>non ci sono controlli di sicurezza</strong>. Nel campo “messaggio” l&#8217;hacker può <strong>facilmente inserire un codice JavaScript </strong>di questo tipo:</p>
<p><code>&lt;script language="text/javascript"&gt;document.location.href="http://www.web-magazine.it";&lt;/script&gt;</code></p>
<p>Dove ovviamente al posto di web-magazine.it c&#8217;è <strong>un sito malvagio</strong>. Attraverso la stampa con <em>echo</em>, il codice <strong>viene inserito nella pagina xss.php e quindi eseguito</strong>. E ovviamente, date le tante cose che si possono fare con JavaScript, il reindirizzamento non è che <strong>una possibilità</strong>: il malintenzionato può infatti anche <strong>installare script dannosi direttamente all&#8217;interno del sito</strong>. E questo tipo di attacco funziona sia che il nostro form abbia metodo <strong>get</strong>, sia che abbia metodo <strong>post</strong>. Tipicamente, gli script XSS vengono utilizzati per <strong>rubare cookie</strong> ai malcapitati.</p>
<h3>Come difendersi dal cross-site scripting</h3>
<p>Difendersi da questo tipo di attacchi <strong>è veramente molto semplice</strong>: bisogna <strong>solo tenerlo a mente</strong>! Basterà fare in modo che i<strong> caratteri riservati del linguaggio HTML </strong> <strong>vengano sostituiti con le relative entità</strong> (per esempio la parentesi uncinata aperta con &amp;lt;) o che le etichette HTML vengano del tutto cancellate.</p>
<p>Per fare questo abbiamo tre funzioni: <em>htmlspecialchars</em>, <em>htmlentities</em> e <em>strip_tags</em>. <strong>Funzionano tutte allo stesso modo</strong>: ricevono come parametro <strong>la stringa per la quale dobbiamo sostituire i caratteri</strong>. Ecco quindi qual è il codice corretto e sicuro da utilizzare nella pagina xss.php:</p>
<p><code>&lt;?php<br />
echo "&lt;br /&gt;&lt;br /&gt;Messaggio: &lt;br /&gt;&lt;br /&gt;";<br />
echo htmlspecialchars(stripslashes($_GET['messaggio']));<br />
?&gt;</code></p>
<p>Oppure</p>
<p><code>echo htmlentities(stripslashes($_GET['messaggio']));</code></p>
<p>O ancora</p>
<p><code>echo strip_tags(stripslashes($_GET['messaggio']));</code></p>
<h3>htmlspecialchars, htmlentities e strip_tags</h3>
<p>Ci sono ovviamente <strong>alcune differenze tra le tre funzioni</strong>. La differenza tra <em>htmlspecialchars</em> e <em>htmlentities</em> consiste nel fatto che la prima converte in entità <strong>solo i caratteri riservati di HTML</strong>, mentre la seconda converte <strong>anche i caratteri speciali</strong> (per esempio, se dovessimo scrivere in tedesco, la o con la dieresi – ö – sarebbe convertita in &amp;ouml;). La funzione <em>strip_tags</em> invece <strong>elimina del tutto le etichette HTML</strong>. In ogni caso, il codice immesso dal malintenzionato verrebbe <strong>stampato sullo schermo e non eseguit</strong>o (anzi, nel caso di <em>strip_tags</em> <strong>le tag verrebbero del tutto eliminate</strong>). E<strong> ricordate sempre</strong>: uno dei migliori metodi per difendersi dagli attacchi è <strong>filtrare tutto ciò che arriva in input sul nostro sito</strong>. In questo caso abbiamo visto come filtrare attraverso le tre funzioni di cui abbiamo parlato: potete trovare le documentazioni ufficiali delle funzioni a queste pagine: <a href="http://www.php.net/manual/en/function.htmlspecialchars.php">http://www.php.net/manual/en/function.htmlspecialchars.php</a> (<em>htmlspecialchars</em>), <a href="http://php.net/manual/en/function.htmlentities.php">http://php.net/manual/en/function.htmlentities.php</a> (<em>htmlentities</em>), <a href="http://it.php.net/manual/en/function.strip-tags.php">http://it.php.net/manual/en/function.strip-tags.php</a> (<em>strip_tags</em>).</p>
<h3>SQL Injection</h3>
<p>Il secondo problema di vulnerabilità che vediamo oggi è la cosiddetta <strong>SQL Injection</strong> (iniezione di SQL). Anche in questo caso l&#8217;attacco prende di mira <strong>form scritti male </strong>per eseguire<strong> un codice SQL malevolo</strong>, e adesso vedremo nel dettaglio in cosa consiste questa pratica e <strong>perché è tanto pericolosa</strong>. Prendiamo per esempio questo semplice form per connettersi a un sito:</p>
<p><code>&lt;form action="login.php?step=2" method="post"&gt;<br />
Nickname:&lt;br /&gt;<br />
&lt;input type="text" name="nickname" /&gt;&lt;br /&gt;<br />
Password: &lt;br /&gt;<br />
&lt;input type="password" name="psw" /&gt;&lt;br /&gt;<br />
&lt;input type="submit" name="invia" value="Invia!" /&gt;&lt;br /&gt;<br />
&lt;/form&gt;</code></p>
<p>In questo caso il nostro form, invece di rimandare a una nuova pagina, rimanda alla stessa ma con l&#8217;aggiunta della query string <strong>?step=2</strong>, in modo da scrivere <strong>tutto nella stessa pagina</strong>. L&#8217;azione del form andrà quindi scritta in un blocco if di questo tipo:</p>
<p><code>if (isset($_GET['step']) &amp;&amp; $_GET['step'] == 2) {<br />
// azione<br />
}<br />
else {<br />
}</code></p>
<p>Ipotizziamo anche che il gestore del sito o del blog sia stato così sprovveduto da aver fatto in modo che le password <strong>vengano inserite in chiaro nel database</strong> (quindi senza criptarle attraverso il form di registrazione). Ora prendiamo il pessimo script che esegue il controllo sui dati immessi dall&#8217;utente:</p>
<p><code>$query = "SELECT * FROM autori WHERE Nickname = '{$_POST['nickname']}' AND Password = '{$_POST['psw']}'";<br />
$risultato = mysql_query($query);<br />
if (mysql_num_rows($risultato) == '1') {<br />
echo "Benvenuto, utente autenticato";<br />
// codice che mostra l'eventuale pagina personale dell'utente<br />
}<br />
else {<br />
echo "Spiacente, password errata";<br />
}</code></p>
<p>Chiariamo subito la funzione nuova, <em>mysql_num_rows</em>: restituisce <strong>il numero dei record trovati dalla query </strong>(nel nostro caso uno, anche perché si suppone che<strong> gli username siano univoci</strong>) e riceve come parametro il risultato della query. Qua si trova la documentazione ufficiale della funzione: <a href="http://php.net/manual/en/function.mysql-num-rows.php">http://php.net/manual/en/function.mysql-num-rows.php</a>. Pertanto se la funzione dà come risultato 1 (e quindi trova il record), <strong>l&#8217;utente sarà loggato</strong>, in caso contrario ci sarà un messaggio che informerà l&#8217;utente di <strong>aver inserito una password errata</strong>.</p>
<p>Questo codice <strong>è estremamente vulnerabile</strong>, soprattutto nel caso in cui l&#8217;impostazione <em>magic quotes gpc</em> di PHP sia disattivata: in locale potete controllarlo su WAMP cliccando sull&#8217;icona nella barra delle applicazioni, quindi andare alla voce PHP e ancora andare su Impostazioni PHP. Se la voce “magic quotes gpc” è spuntata significa che è attiva e avete <strong>maggiori protezioni contro le SQL Injection</strong>. Ci sono però tanti provider che non attivano le <em>magic quotes</em> sui loro server. <strong>Ma cosa sono le magic quotes</strong>? Si tratta di un processo che <strong>aggiunge in automatico i caratteri di escape alle stringhe</strong>, ma dobbiamo sapere che a partire dalla versione 5.3.0 di PHP, <strong>magic quotes è deprecato</strong> e nella versione 6<strong> addirittura non c&#8217;è più</strong>.</p>
<p>Vediamo quindi cosa può fare il malintenzionato. Nella casella nickname può inserire il nome “Federico”, e fin qui niente di strano. Ma nella casella password può tranquillamente inserire questa stringa:</p>
<p><code>' OR Nickname='Federico </code></p>
<p>Così facendo, il nostro codice eseguirebbe questa query:</p>
<p><code>$query = "SELECT * FROM autori WHERE Nickname = 'Federico' AND Password =<br />
'' OR Nickname='Federico'";</code></p>
<p>La clausola OR inserita dal malintenzionato <strong>vanificherà il controllo sulla password</strong>: questo perché la query strutturata in tal modo dice di selezionare tutti i record della tabella autori il cui nickname sia Federico e la cui password sia vuota <strong>oppure</strong>, <strong>in alternativa a quest&#8217;ultima clausola</strong>, il cui nickname sia Federico. Dal momento che la seconda clausola è soddisfatta il malintenzionato <strong>riuscirà a entrare agevolmente </strong>al posto di Federico all&#8217;interno del sito, spacciandosi per lui e magari rubando i suoi dati&#8230; o insomma facendo tutto ciò che di cattivo si può fare entrando nel profilo di un&#8217;altra persona.</p>
<h3>Criptiamo la password con md5</h3>
<p>La prima operazione da fare è <strong>criptare la password </strong>attraverso la funzione <em>md5</em>: nel database <strong>non dovrà essere inserita in chiaro </strong>ma andrà fatta passare attraverso questa funzione (in un&#8217;ipotetica query con comando INSERT INTO metteremo tra i VALUES &#8216;md5($_POST['password']&#8216;). <strong>MD5</strong> è un <strong>algoritmo crittografico di hashing</strong> che fu realizzato nel 1991 da <strong>Ronald Linn Rivest</strong>, un crittografo statunitense: l&#8217;algoritmo <strong>trasforma una stringa in un&#8217;altra stringa a 128 bit</strong>, e <strong>non è possibile risalire alla stringa originale</strong> (se non andando&#8230; a tentativi). La funzione md5 di PHP riceve come parametro semplicemente la stringa da criptare e la documentazione ufficiale si trova qui: <a href="http://it.php.net/manual/en/function.md5.php">http://it.php.net/manual/en/function.md5.php</a>.</p>
<p>Questo è solo uno dei tanti modi per criptare una password: parliamo di questo perché <strong>è il più semplice da utilizzare</strong>, ma c&#8217;è chi usa anche <strong>sistemi più sofisticati</strong>. Il nostro codice pertanto dovrà presentarsi in questa forma:</p>
<p><code>$query = "SELECT * FROM autori WHERE Nickname = '{$_POST['nickname']}' AND Password = '". md5($_POST['psw']). "'";</code></p>
<p>Dove i punti che separano md5($_POST['psw']) dal resto del codice sono un modo per concatenare valori all&#8217;interno di una variabile (le virgole non funzionano).</p>
<p>In questo caso ci salviamo dal malintenzionato che immette i dati di cui sopra, <strong>ma siamo ancora vulnerabili</strong>. Questo perché l&#8217;hacker potrebbe scrivere nella casella del nickname <strong>questa stringa cattivissima</strong>:</p>
<p><code>Federico' --</code></p>
<p>E magari può anche lasciare in bianco il campo della password. In tal modo la query diventerebbe questa:</p>
<p><code>$query = "SELECT * FROM autori WHERE Nickname = 'Federico' -- AND Password =<br />
''";</code></p>
<p>I <strong>due trattini </strong>nel <strong>linguaggio SQL</strong> indicano<strong> i commenti</strong>: pertanto tutto ciò che viene dopo i due trattini <strong>sarà ignorato</strong>. Capite quindi <strong>la pericolosità della cosa</strong> malgrado il controllo tramite algoritmo md5. Sarà un giochetto per il malintenzionato riuscire a entrare nel sito e magari carpire tutta la lista degli utenti registrati o a far di peggio: pensate se potesse <strong>entrare con l&#8217;account dell&#8217;amministratore</strong>.</p>
<h3>Come difendersi dalla SQL injection</h3>
<p>Qual è pertanto <strong>il modo più sicuro per difendersi da questo tipo di attacco</strong>? Non dovremo far altro che <strong>aggiungere una funzione per controllare i dati immessi dall&#8217;utente </strong>(ricordate&#8230; <strong>filtrare sempre tutto</strong>), e si tratta della funzione <em>mysql_real_escape_string</em>, che inserisce i giusti<strong> caratteri di escape</strong> prima dei caratteri “pericolosi”. Riceve come parametro semplicemente <strong>la stringa a cui aggiungere i parametri di escape</strong>. Quindi la nostra query dovrà assumere questa forma per evitare attacchi:</p>
<p><code>$query = "SELECT * FROM autori WHERE Nickname = '". mysql_real_escape_string($_POST['nickname']) ."' AND Password = '". mysql_real_escape_string($_POST['psw']). "'";</code></p>
<p>Riusciremo così a <strong>rendere inoffensivo</strong> l&#8217;attacco del malintenzionato, perché l&#8217;ultima stringa che abbiamo visto risulterà invece in questo modo:</p>
<p><code>$query = "SELECT * FROM autori WHERE Nickname = 'Federico\' -- AND Password = ''";</code></p>
<p>Questa funzione va utilizzata solo nel caso in cui <em>magic quotes gpc</em> sia disattivo. Per essere però del tutto sicuri utilizziamo la funzione <em>get_magic_quotes_gpc</em>, che controlla la configurazione delle <em>magic quotes</em> (non riceve alcunché come parametro), e inseriamola in un blocco if:</p>
<p><code>if(get_magic_quotes_gpc()) {<br />
$query = "SELECT * FROM autori WHERE Nickname = '". $_POST['nickname'] ."' AND Password = '".<br />
$_POST['psw']. "'";<br />
}<br />
else {<br />
$query = "SELECT * FROM autori WHERE Nickname = '". mysql_real_escape_string($_POST['nickname']) ."'<br />
AND Password = '". mysql_real_escape_string($_POST['psw']). "'";<br />
}</code></p>
<p>Controlliamo con il ciclo che il processo <em>magic quotes gpc</em> sia attivo, e in caso affermativo creiamo la nostra query senza la funzione <em>mysql_real_escape_string</em>, e in caso contrario ovviamente la aggiungiamo. Trovate la documentazione ufficiale di queste due funzioni qui <a href="http://it.php.net/manual/en/function.mysql-real-escape-string.php">http://it.php.net/manual/en/function.mysql-real-escape-string.php</a> (<em>mysql_real_escape_string</em>) e qui <a href="http://php.net/manual/en/function.get-magic-quotes-gpc.php">http://php.net/manual/en/function.get-magic-quotes-gpc.php</a> (<em>get_magic_quotes_gpc</em>).</p>
<p>Vi aspetto come sempre alla prossima puntata!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.web-magazine.it/2012/01/creare-siti-in-php-%e2%80%93-28-%e2%80%93-la-sicurezza-in-php-xss-e-sql-injection/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Un logo non è un pareo di Donna Moderna. (to be continued&#8230;)</title>
		<link>http://www.web-magazine.it/2012/01/un-logo-non-e-un-pareo-di-donna-moderna-to-be-continued/</link>
		<comments>http://www.web-magazine.it/2012/01/un-logo-non-e-un-pareo-di-donna-moderna-to-be-continued/#comments</comments>
		<pubDate>Tue, 17 Jan 2012 19:24:42 +0000</pubDate>
		<dc:creator>Laura</dc:creator>
				<category><![CDATA[pianeta freelance]]></category>
		<category><![CDATA[freelance]]></category>
		<category><![CDATA[logo]]></category>
		<category><![CDATA[storie]]></category>

		<guid isPermaLink="false">http://www.web-magazine.it/?p=2335</guid>
		<description><![CDATA[...io che non voglio che i loghi vengano considerati come accessori gratuiti di un sito, come il bicchiere che il supermercato ti regala se acquisti il latte, come il cioccolatino che ti offre il bar mentre ti serve il caffè, come il pareo che esce da Donna Moderna ad Agosto. Ecco, il logo non è il pareo di Donna Moderna.]]></description>
			<content:encoded><![CDATA[<p><img class="alignnone" title="pareo" src="http://www.web-magazine.it/wp-content/uploads/2012/01/pareo.jpg" alt="Un logo non è un pareo di Donna Moderna" width="500" height="160" /></p>
<p>Ce ne ho messo di tempo ma alla fine ho pensato che sarebbe stato giusto dare delle spiegazioni.<br />
Il mio problema è che non ho capacità di sintesi per cui mi sa che queste spiegazioni dureranno parecchi post.</p>
<p><span id="more-2335"></span></p>
<p>Spiegazioni riguardo due cose principalmente.</p>
<p><strong>La prima è il blog, e la carenza di aggiornamenti.</strong></p>
<p>Web Magazine non si è fermato ma quasi, tempo di scrivere non ne ho più e non credo che ne avrò mai, e se non fosse per i miei preziosi <strong><a href="http://www.web-magazine.it/author/Federico/">Federico</a></strong> e <strong><a href="http://www.web-magazine.it/author/Dario/">Dario</a></strong>, rispettivamente Mr. Php e Mr. Seo, il blog sarebbe quasi defunto.</p>
<p>Lunga vita ai miei collaboratori!</p>
<p>Leggete i loro post Leggete i loro post Leggete i loro postLeggete i loro post Leggete i loro post Leggete i loro postLeggete i loro post..</p>
<p>i ragazzi si impegnano! <img src='http://www.web-magazine.it/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> </p>
<p><strong>La seconda spiegazione è il perchè dopo anni in cui ho professato la cosiddetta missione freelance io sia tornata a timbrare cartellini.</strong></p>
<p>Facciamo però un passo indietro, anticipando prima di tutto che questo non è un post tecnico, nè un tutorial nè una guida, è un post assolutamente personale dedicato ai miei storici seguaci e a chi proprio non sa farsi gli affari propri.</p>
<p>Leggendo questo post non imparerete nulla, qualcuno si farà due risate e straccerà il mio ebook&#8230; dopo averlo stampato.</p>
<p>Ma se pensate che le esperienze vissute possano in qualche modo arricchire allora vi racconto la mia vita negli ultimi sei mesi e cercheremo anche di dare un senso a quel titolo assurdo.</p>
<p><strong>Giugno 2011 </strong>-  Dopo un breve scambio di email decido di accettare un prestigioso nonchè <em>molto-ma-mooolto-ben-pagato </em>incarico, rigorosamente freelance, come <em>interface designer</em> per un progetto della Commissione Europea, progetto che mi avrebbe portato a 900km da casa per sei mesi fino ad un massimo di tutta la vita, se lo avessi voluto.<br />
Progetto che puoi andare a sbandierare in giro perchè oggettivamente lavorare in una ex centrale nucleare in un contesto europeo dove si parla esclusivamente in inglese è una cosa maledettamente fica, non facciamo i falsi modesti.</p>
<p>A quel punto se fossimo stati in una di quelle storie di Topolino con il &#8220;bivio&#8221; (si ok, leggevo topolino ma mi stava sulle palle) avrei imboccato la strada cosiddetta: Ricca e alquanto infelice. Ma qui ci arriveremo.</p>
<p>Aspettavo quindi  la partenza di Settembre, potevo godermi le vacanze certa del fatto che sarei poi partita per <em>soldolandia </em>e nel frattempo avrei fatto giusto qualche lavoretto da casa, il bello di lavorare e abitare praticamente su una spiaggia è che in estate fare pausa pranzo in costume ti ripaga da tutte le rotture di palle che ti portano i clienti.. ma invece no, niente relax pre partenza, accetto una consulenza.</p>
<p>In realtà era una sorta di sostituzione di un web designer, quindi sarei dovuta restare  per 6 settimane in una web agency di Napoli non potendo lavorare da casa per questo tipo di incarico, ma l&#8217;agenzia già in fase di colloquio mi aveva impressionata positivamente. Persone umili ma assolutamente competenti, idee chiare in termini di business e un ambiente allegro e giovanile che, diciamocela tutta, non potevo di certo trovare nelle 4 mura del mio studiolo casalingo.</p>
<p>E si, accetto, nonostante la spiaggia, il costume, e il perenne e dolcissimo suono del mare.</p>
<p>Prendo l&#8217;auto e torno ai rumori della città, al caos delle agenzie, e alla bellezza di poter scambiare opinioni dal vivo con un collega.</p>
<p>E il primo giorno in agenzia, mentre mi sentivo come una scolaretta di trent&#8217;anni che aveva tanta voglia di fare bella figura,  vengo assalita dal panico.</p>
<p>Mi viene assegnato il primo incarico: <strong>Disegnare un logo</strong><strong>.</strong></p>
<p>Io, che non ho problemi a dire ad un cliente che se vuole il logo lo pagherà il doppio semplicemente perchè odio fare i loghi;</p>
<p>io, che ho fatto le migliori litigate nella speranza di chiarire il  concetto che un web designer e un grafico pubblicitario sono due figure  assolutamente diverse..</p>
<p>io che non voglio che i loghi vengano considerati come accessori gratuiti di un sito, come il  bicchiere che il supermercato ti regala se acquisti il latte, come il cioccolatino che ti offre il bar mentre ti serve il caffè, come il  pareo che esce da Donna Moderna ad Agosto.</p>
<p>Ecco, il logo non è il pareo di Donna Moderna.</p>
<p>Io dovevo disegnare un logo???</p>
<p>Pensavo mi considerassero una discreta web designer, e mi hanno chiesto di disegnare un logo.</p>
<p>Il primo giorno di lavoro.</p>
<p>Ma ora ho tanta fame quindi il resto lo scriverò poi.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.web-magazine.it/2012/01/un-logo-non-e-un-pareo-di-donna-moderna-to-be-continued/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Creare siti in PHP – (27) – Le sessioni e i cookie</title>
		<link>http://www.web-magazine.it/2012/01/creare-siti-in-php-%e2%80%93-27-%e2%80%93-le-sessioni-e-i-cookie/</link>
		<comments>http://www.web-magazine.it/2012/01/creare-siti-in-php-%e2%80%93-27-%e2%80%93-le-sessioni-e-i-cookie/#comments</comments>
		<pubDate>Mon, 16 Jan 2012 06:10:33 +0000</pubDate>
		<dc:creator>Federico</dc:creator>
				<category><![CDATA[scripting]]></category>
		<category><![CDATA[web design]]></category>
		<category><![CDATA[cookie]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[sessioni]]></category>
		<category><![CDATA[setcookie]]></category>

		<guid isPermaLink="false">http://www.web-magazine.it/?p=2287</guid>
		<description><![CDATA[Panoramica sull'utilizzo delle sessioni e dei cookie in PHP per memorizzare dati sulla navigazione: come creare sessioni e cookie, come recuperarne i valori, come eliminarli. ]]></description>
			<content:encoded><![CDATA[<p><img src="http://www.web-magazine.it/wp-content/uploads/2011/11/php27.jpg" alt="Le sessioni e i cookie" /></p>
<p>Con la puntata di oggi vedremo in che modo, con PHP, è possibile <strong>conservare informazioni durante la navigazione</strong>: si tratta di un aspetto <strong>molto utile </strong>soprattutto se è necessario costruire un sito web che debba consentire ai propri utenti di <strong>fare il login</strong> e di navigare le pagine in qualità di <strong>utenti registrati</strong>. Per fare questo abbiamo <strong>due strumenti a nostra disposizione</strong>: il primo è costituito dalle <strong>sessioni</strong>, il secondo dai <strong>cookie</strong>.</p>
<p><span id="more-2287"></span></p>
<h3>Le sessioni</h3>
<p>Iniziamo dalle <strong>sessioni</strong>: dobbiamo immaginare le sessioni come “contenitori” in cui possiamo inserire <strong>diverse informazioni</strong>. Queste informazioni verranno <strong>memorizzate sul server</strong> e dureranno il tempo di una&#8230; “sessione”, appunto, perché quando il browser verrà chiuso tutte queste informazioni <strong>saranno cancellate</strong>.</p>
<h3>La funzione session_start</h3>
<p><strong>PHP </strong>mette a disposizione di chiunque voglia creare una sessione <strong>la variabile superglobale $_SESSION</strong>, che funziona proprio come tutte le altre variabili superglobali di cui abbiamo già parlato nelle puntate scorse. Prima di tutto però c&#8217;è <strong>un&#8217;operazione preliminare da compiere</strong>, ovvero <strong>avviare la sessione</strong>. Lo si fa con una sezione apposita, <em>session_start</em>, che deve obbligatoriamente essere inserita <strong>prima di qualsiasi tipo di output </strong>all&#8217;interno del nostro file PHP:</p>
<p><code>&lt;?php<br />
session_start();<br />
// codice...<br />
?&gt;</code></p>
<h3>Creare sessioni</h3>
<p>La funzione <em>session_start</em> (la cui documentazione ufficiale si può trovare all&#8217;indirizzo <a href="http://php.net/manual/en/function.session-start.php">http://php.net/manual/en/function.session-start.php</a>) non solo permette di <strong>creare una sessione</strong>, ma permette anche di <strong>recuperare dati </strong>da una sessione <strong>creata in un&#8217;altra pagina</strong>. Ma come si fa a <strong>creare una sessione</strong>? Basta semplicemente <strong>utilizzare la variabile superglobale $_SESSION</strong> e <strong>associare a essa le informazioni</strong>:</p>
<p><code>$_SESSION['nome'] = "Federico";<br />
$_SESSION['id'] = "1";<br />
$_SESSION['livello'] = "3";</code></p>
<p>Ovviamente queste informazioni, nel caso di un utente che si collega al nostro sito, si possono agevolmente <strong>recuperare da un database </strong>(nell&#8217;esempio ometterò, per semplicità, la query, perché parleremo <strong>nella prossima puntata</strong> di come recuperare <strong>in modo corretto</strong> e allo stesso tempo semplice i dati immessi da un utente per fare un login):</p>
<p><code>$query = // ipotetica select per verificare i dati inseriti dall'utente<br />
$result = mysql_query($query);<br />
$numero_record = mysql_num_rows($result);<br />
if($numero_record == 1) {<br />
while($row = mysql_fetch_array($result, MYSQL_ASSOC)) {<br />
$_SESSION['id'] = $row['id'];<br />
$_SESSION['nome'] = $row['nome'];<br />
$_SESSION['livello'] = $row['livello'];<br />
}<br />
echo "Login effettuato con successo!";<br />
}</code></p>
<p>In tutte le pagine che vorremo riservare agli utenti registrati, dovremo inserire <strong>prima di qualsiasi altra cosa</strong> la funzione <em>session_start</em>: se omettessimo la funzione, la pagina non potrebbe ricevere le informazioni delle sessioni. Se per esempio con un blocco if controlliamo che l&#8217;utente sia loggato (per esempio verificando, tramite <em>isset</em>, che sia impostato il <strong>livello dell&#8217;utente </strong>a sua volta memorizzato nella variabile superglobale $_SESSION) ma allo stesso tempo <strong>dimentichiamo</strong> di inserire la funzione <em>session_start</em>, la conseguenza sarà che la pagina non conoscerà le informazioni memorizzate nella sessione e la nostra applicazione si comporterà come se l&#8217;utente <strong>non si fosse mai loggato al sito</strong>. Attenzione anche a <strong>non dichiarare due volte la funzione</strong> (spesso, includendo file nella pagina, può capitare di farlo), perché <em>session_start </em>può essere dichiarata <strong>una volta soltanto</strong>.</p>
<h3>Come azzerare o eliminare le sessioni</h3>
<p>Le sessioni possono essere poi <strong>azzerate o eliminate</strong>: per fare questo è possibile utilizzare le funzioni <em>session_unset</em> e <em>session_destroy</em>. La differenza consiste nel fatto che la prima funzione <strong>elimina soltanto i dati</strong> (senza cancellare <strong>gli elementi dell&#8217;array</strong> che abbiamo dichiarato in precedenza), la seconda invece <strong>elimina dati e array</strong>. Pertanto in seguito a<em> session_destroy </em><strong>sarà necessario dichiarare nuovamente</strong> <em>session_start</em>. Sono utili in funzioni di <strong>logout</strong> e si invocano in modo molto semplice:</p>
<p><code>session_unset();<br />
session_destroy();</code></p>
<h3>I cookie</h3>
<p>Parliamo adesso dei <strong>cookie</strong>: molti di voi li avranno già sentiti nominare. I cookie (letteralmente “biscotti”) sono <strong>informazioni </strong>che vengono inviate <strong>dal server al client</strong>: e proprio qui sta la prima differenza rispetto alle sessioni, perché queste ultime <strong>rimangono sul server</strong>. Un&#8217;altra differenza consiste nel fatto che la sessione viene <strong>cancellata</strong> nel momento in cui il browser <strong>viene chiuso</strong>: il cookie invece <strong>persiste fino alla sua scadenza</strong>, impostata quando il cookie viene creato. Data la natura dei cookie, questi ci torneranno utili se vogliamo creare un modulo di login che si <strong>“ricordi”</strong> dell&#8217;utente <strong>una volta chiuso il browser</strong>, per evitargli magari di immettere nuovamente nome e password al collegamento successivo. Un altro esempio può essere dato da <strong>un sito multilingua</strong>: se il nostro sito accoglie l&#8217;utente in italiano, ma quest&#8217;ultimo preferisce l&#8217;inglese, potrebbe rendersi necessario un cookie che <strong>si ricordi dell&#8217;impostazione settata dall&#8217;utente</strong> (ovvero “sito in lingua inglese”) <strong>ogni volta che si collega</strong>.</p>
<h3>La funzione setcookie e i suoi parametri</h3>
<p>Per creare un cookie esiste un&#8217;apposita funzione, <em>setcookie</em>, che riceve tre parametri principali: <strong>il nome del cookie</strong>, le <strong>informazioni</strong> e la <strong>durata</strong>:</p>
<p><code>setcookie("nome", "Federico", time()+3600);</code></p>
<p>La durata si imposta utilizzando la funzione <em>time</em>: quest&#8217;ultima restituisce<strong> il numero di secondi trascorsi dal 1 gennaio 1970 alle ore 00:00:00</strong>. Si tratta della data di inizio del tempo calcolato sui <strong>sistemi Unix</strong> ed è, come già detto, <strong>espresso in secondi</strong>: si intuisce quindi che al valore restituito da time bisognerà aggiungere<strong> un numero di secondi equivalente al periodo di durata </strong>del nostro cookie. Nel caso dell&#8217;esempio, 3600 secondi: significa che il cookie <strong>avrà la durata di un&#8217;ora</strong> (formata da 3600 secondi). Si intuisce quindi che è possibile settare una durata qualsiasi per il nostro cookie, <strong>anche di anni</strong>!</p>
<p><code>setcookie("nome", "Federico", time()+3600*24); //un giorno</code></p>
<p><code>setcookie("nome", "Federico", time()+3600*24*30); // un mese</code></p>
<p><code>setcookie("nome", "Federico", time()+3600*24*365); // un anno</code></p>
<p>Se invece la scadenza non viene impostata, il cookie scadrà semplicemente <strong>alla fine della sessione</strong>. La documentazione ufficiale della funzione time è disponibile all&#8217;indirizzo <a href="http://php.net/manual/en/function.time.php">http://php.net/manual/en/function.time.php</a>.</p>
<p>Quello che abbiamo visto sopra è <strong>l&#8217;esempio più tipico</strong>, ma in realtà si possono estendere a <strong>sette </strong>i parametri che la funzione setcookie può ricevere, perché oltre a nome, valore e scadenza possiamo specificare anche <strong>percorso</strong> (ovvero la directory per cui è valido il cookie), il <strong>dominio</strong> (come per il percorso, ma si estende a tutto il dominio), la <strong>sicurezza</strong> (che se settata a <em>true</em> fa in modo che il cookie venga trasmesso solo attraverso protocollo sicuro https) e <strong>httponly</strong> (funziona come la sicurezza: se settato a<em> true</em>, fa in modo che il cookie venga trasmesso solo tramite protocollo http, e di conseguenza non sarà accessibile a linguaggi di scripting come JavaScript). Per esempio:</p>
<p><code>setcookie("nome", "Federico", time()+3600, "/prova/", "web-magazine.it", true, true);</code></p>
<p>In questo caso il cookie è valido solo per la cartella “prova” del sito “web-magazine.it” (che non va scritto con “www” anteposto), si trasmette solo in presenza di una connessione sicura ed è accessibile solo al protocollo http.</p>
<p><code>setcookie("nome", "Federico", time()+3600, "/");</code></p>
<p>In questo caso invece abbiamo creato, attraverso la formula &#8220;/&#8221;, un cookie che è valido per tutte le cartelle del sito.</p>
<h3>Recuperare il valore dei cookie</h3>
<p>Per recuperare il valore di un cookie che abbiamo impostato in precedenza, sarà necessario utilizzare <strong>la variabile superglobale $_COOKIE</strong>, e il nome dell&#8217;elemento dell&#8217;array non sarà altro che<strong> il primo valore</strong> che abbiamo passato <strong>come parametro</strong> alla funzione <em>setcookie</em>:</p>
<p><code>echo $_COOKIE['nome']; // stampa “Federico”</code></p>
<p>È ovvio che possiamo anche inizializzare variabili a cui abbinare i valori delle nostre sessioni o dei nostri cookie:</p>
<p><code>$nome = $_SESSION['nome'];<br />
$cognome = $_COOKIE['cognome'];</code></p>
<p>Per poi<strong> utilizzarle comodamente</strong> all&#8217;interno del nostro codice, magari su blocchi condizionali. Tipicamente, ci si assicura che prima le variabili di sessione e i cookie siano settati tramite funzione <em>isset</em>, onde evitare di veder comparire <em>warning </em>sul sito nel caso in cui sessioni e cookie <strong>non siano ancora stati scritti </strong>(per esempio quando l&#8217;utente si è appena collegato al sito <strong>e non ha ancora fatto login</strong>).</p>
<h3>Eliminare i cookie</h3>
<p>Abbiamo visto prima come <strong>eliminare una sessione</strong>. I cookie <strong>non hanno una specifica funzione</strong> per eliminarli, ma per farlo basta semplicemente utilizzare, di nuovo, la funzione <em>setcookie</em> (a proposito, la pagina di documentazione ufficiale è <a href="http://php.net/manual/en/function.setcookie.php">http://php.net/manual/en/function.setcookie.php</a>) impostando però, come scadenza, <strong>un tempo negativo</strong>:</p>
<p><code>setcookie("nome", "Federico", time()-3600);</code></p>
<p>E così facendo <strong>avremo eliminato il nostro cookie</strong>. Sempre la solita funzione si utilizza se vogliamo <strong>modificare</strong> i valori di un cookie: basterà semplicemente invocare setcookie con i nuovi parametri.</p>
<p>E anche per oggi la puntata arriva al termine&#8230; arrivederci al prossimo episodio!!!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.web-magazine.it/2012/01/creare-siti-in-php-%e2%80%93-27-%e2%80%93-le-sessioni-e-i-cookie/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Creare siti in PHP – (26) – Costruiamo un form di ricerca con PHP/MySQL</title>
		<link>http://www.web-magazine.it/2011/11/creare-siti-in-php-%e2%80%93-26-%e2%80%93-costruiamo-un-form-di-ricerca-con-phpmysql/</link>
		<comments>http://www.web-magazine.it/2011/11/creare-siti-in-php-%e2%80%93-26-%e2%80%93-costruiamo-un-form-di-ricerca-con-phpmysql/#comments</comments>
		<pubDate>Mon, 28 Nov 2011 06:00:46 +0000</pubDate>
		<dc:creator>Federico</dc:creator>
				<category><![CDATA[scripting]]></category>
		<category><![CDATA[database]]></category>
		<category><![CDATA[MySQL]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[query]]></category>
		<category><![CDATA[sql]]></category>

		<guid isPermaLink="false">http://www.web-magazine.it/?p=2253</guid>
		<description><![CDATA[In questo episodio impariamo a costruire un semplicissimo form di ricerca per eseguire ricerche all'interno del nostro database. Impariamo l'utilizzo dell'operatore LIKE e della specifica ESCAPE.]]></description>
			<content:encoded><![CDATA[<p><img src="http://www.web-magazine.it/wp-content/uploads/2011/11/php26.jpg" alt="Costruiamo un form di ricerca con PHP/MySQL" /></p>
<p>Con la puntata di oggi metteremo in pratica i concetti appresi negli ultimi episodi della guida e vedremo come costruire un semplice<strong> form di ricerca PHP/MySQL</strong> per fare ricerche all&#8217;interno del nostro blog. Come sempre, in occasione di puntate “pratiche”, faremo un ripasso generale degli ultimi concetti ma introdurremo anche qualcosa di nuovo.</p>
<p><span id="more-2253"></span></p>
<h3>Costruiamo il form</h3>
<p>Allora, iniziamo a costruire il nostro form, in maniera molto semplice, come siamo abituati:</p>
<p><code>&lt;form name="ricerca" action="ricerca.php" method="post"&gt;<br />
&lt;input type="text" name="cerca" /&gt;<br />
&lt;input type="submit" name="vai" value="Cerca!" /&gt;<br />
&lt;/form&gt;</code></p>
<p>Si tratta, come vedete, di un semplicissimo<strong> form con metodo post </strong>che rimanda a una pagina “ricerca.php”. Il nostro form ha un campo, che servirà all&#8217;utente per <strong>immettere il testo da ricercare</strong>, e un <strong>bottone per inviare i dati</strong>.</p>
<p>Nel costruire la pagina “ricerca.php”, come prima cosa assicuriamoci di <strong>fare un controllo sul pulsante</strong>: se è stato premuto, quindi se l&#8217;utente <strong>proviene dalla pagina del form</strong>, <strong>sarà eseguito il codice</strong>, e in caso contrario (se per esempio l&#8217;utente arriva alla pagina ricerca.php semplicemente digitandola nella barra degli indirizzi) <strong>non dovrà succedere alcunché</strong>. Vediamo:</p>
<p><code>if(isset($_POST['vai'])) {<br />
// codice<br />
// codice<br />
// codice<br />
}<br />
else {<br />
}</code></p>
<h3>Iniziamo a riempire la pagina dei risultati&#8230;</h3>
<p>Vediamo ora come <strong>riempire il blocco if</strong>. Per prima cosa dobbiamo decidere se la ricerca riguarderà <strong>soltanto i post o i commenti</strong>. Noi vedremo tre esempi: il primo <strong>per i post</strong>, il secondo <strong>per i commenti</strong> e il terzo <strong>per entrambi</strong>.</p>
<p>Iniziamo dalla ricerca nei soli post. Per prima cosa stampiamo una scritta per indicare all&#8217;utente che <strong>la ricerca è stata compiuta </strong>e quindi inizializziamo una variabile, a cui <strong>assoceremo la parola cercata</strong>:</p>
<p><code>echo "Ecco i risultati della tua ricerca:&lt;br /&gt;&lt;br /&gt; ";<br />
$parolacercata = $_POST['cerca'];</code></p>
<p>Fatto questo è arrivato il momento di creare la nostra query per la ricerca all&#8217;interno della base di dati:</p>
<p><code>$query = "SELECT * FROM Post WHERE Titolo LIKE '%$parolacercata%' OR TestoHTML LIKE '%$parolacercata%'";</code></p>
<h3>L&#8217;operatore LIKE e i suoi utilizzi</h3>
<p>Bene, vedete che abbiamo <strong>due “novità”</strong>: la prima è <strong>l&#8217;operatore LIKE</strong>, e la seconda sono <strong>i due simboli di percentuale </strong>prima e dopo la variabile. Procediamo con ordine.</p>
<p>LIKE è <strong>un operatore di confronto</strong>, come l&#8217;uguale, il maggiore, il minore e tutti gli altri. Funziona <strong>più o meno come l&#8217;operatore di uguaglianza</strong>, ma con <strong>una differenza molto significativa</strong>: con l&#8217;uguale avremmo cercato la parola precisa, invece con LIKE eseguiamo una ricerca <strong>“non precisa”</strong>. I due caratteri di percentuale prima e dopo la variabile della parola cercata servono infatti per dare una <strong>“connotazione”</strong> all&#8217;operatore LIKE, nel senso che immettendolo <strong>prima della variabile</strong>, dichiariamo che <strong>potrebbero esserci altri caratteri prima della parola che abbiamo cercato</strong>, e invece immettendolo dopo non facciamo altro che dichiarare che potrebbero esserci altri caratteri <strong>subito dopo</strong>.</p>
<p>Ma vediamo un esempio concreto. Supponiamo di avere tre post, il primo che si intitola “Ciao”, il secondo che si intitola “Ciao a tutti!” e il terzo “Un ciao ai miei amici!”. E supponiamo anche di avere alcune <strong>query di ricerca</strong> (per semplicità operiamo soltanto sul titolo):</p>
<p><code>$query = "SELECT * FROM Post WHERE Titolo = '$parolacercata'";</code></p>
<p><code>$query = "SELECT * FROM Post WHERE Titolo LIKE '$parolacercata'";</code></p>
<p><code>$query = "SELECT * FROM Post WHERE Titolo LIKE '%$parolacercata'";</code></p>
<p><code>$query = "SELECT * FROM Post WHERE Titolo LIKE '$parolacercata%'";</code></p>
<p><code>$query = "SELECT * FROM Post WHERE Titolo LIKE '%$parolacercata%'";</code></p>
<p>Supponiamo adesso di cercare la parola “ciao”. Vediamo i risultati per i cinque casi che abbiamo elencato sopra:</p>
<ul>
<li><em>Caso 1</em>: viene 	trovato <strong>soltanto il post intitolato “Ciao”</strong>, perché 	abbiamo chiesto informazioni precise, ovvero i post il cui titolo è 	<strong>esattamente uguale alla parola cercata</strong> (maiuscole e minuscole 	non contano perché <strong>SQL non è case sensitive </strong>come abbiamo 	avuto già modo di rimarcare);</li>
<li><em>Caso 2</em>: <strong>è 	del tutto equivalente</strong> al caso 1 (quindi <strong>è praticamente 	inutile usare LIKE da solo</strong>);</li>
<li><em>Caso 3</em>: 	vengono trovati i post che contengono la parola cercata <strong>anche se 	ci sono caratteri che la precedono</strong>. Nel nostro caso troviamo 	soltanto “Ciao”, perché è vero che il post “Un ciao ai miei 	amici!” ha la parola “ciao” preceduta da altri caratteri, ma è 	anche seguita da un&#8217;altra sequenza (“ ai miei amici”), quindi 	<strong>non soddisfa i requisiti di ricerca</strong>. Se avessimo avuto un 	post intitolato “Un ciao”, sarebbe stato restituito come 	risultato;</li>
<li><em>Caso 4</em>: <strong>il 	contrario del precedente</strong>, vengono trovati “Ciao” e “Ciao a 	tutti!”. Abbiamo infatti cercato i record dove il campo titolo 	contiene la parola cercata ma <strong>può anche contenere una stringa di 	caratteri dopo</strong>. “Ciao” e “Ciao a tutti!” soddisfano 	questa condizione;</li>
<li><em>Caso 5</em>: 	vengono trovati tutti e tre i post, dal momento che abbiamo detto di 	estrarre i record il cui campo titolo contiene la parola cercata, 	che può essere <strong>o preceduta o seguita da altre sequenze di 	caratteri</strong>.</li>
</ul>
<p>Possiamo poi anche fare <strong>ricerche “negative”</strong>:</p>
<p><code>$query = "SELECT * FROM Post WHERE Titolo NOT LIKE '%$parolacercata%'";</code></p>
<p>In questo caso, anteponendo quindi <strong>la parola NOT all&#8217;operatore LIKE</strong>, la nostra interrogazione fa in modo che vengano estratti i post il cui titolo<strong> non contiene la parola cercata</strong>, preceduta o seguita da altre stringhe di caratteri. E poi abbiamo anche un altro carattere speciale, l&#8217;<strong>underscore</strong>:</p>
<p><code>$query = "SELECT * FROM Post WHERE Titolo LIKE '_$parolacercata_'";</code></p>
<p>In questo caso la nostra interrogazione estrae tutti i post che contengono la parola cercata, <strong>preceduta o seguita da un solo carattere</strong>: pertanto, se il carattere di percentuale equivale a <strong>“qualsiasi numero di caratteri”</strong>, l&#8217;underscore equivale a<strong> “un solo carattere”</strong>.</p>
<h3>La specifica ESCAPE</h3>
<p>Potremmo però voler cercare una parola che sia <strong>effettivamente preceduta da un underscore</strong>, e quindi non volerlo considerare come carattere speciale. In questo caso dovremo scrivere questo:</p>
<p><code>$query = "SELECT * FROM post WHERE Titolo NOT LIKE '_$parolacercata' ESCAPE";</code></p>
<p>Aggiungendo <strong>la specifica ESCAPE</strong> facciamo capire che quello che precede la variabile cercata è un vero underscore e non un carattere speciale.</p>
<p>Bene, una volta inviata la nostra interrogazione possiamo procedere con la stampa:</p>
<p><code>while ($record = mysql_fetch_array($risultato, MYSQL_ASSOC)) {<br />
echo $record['Titolo']; echo "&lt;br /&gt;";<br />
}</code></p>
<h3>Riepiloghiamo&#8230;</h3>
<p>In questo caso stampiamo soltanto il titolo, ma possiamo decidere a piacere come far apparire all&#8217;utente il risultato della nostra ricerca. Quindi riepiloghiamo tutto il codice della pagina “ricerca.php”:</p>
<p><code>if(isset($_POST['vai'])) {<br />
echo "Ecco i risultati della tua ricerca:&lt;br /&gt;&lt;br /&gt; ";<br />
$parolacercata = $_POST['cerca'];<br />
$query = "SELECT * FROM post WHERE Titolo NOT LIKE '%$parolacercata%'";<br />
$risultato = mysql_query($query);<br />
while ($record = mysql_fetch_array($risultato, MYSQL_ASSOC)) {<br />
echo $record['Titolo']; echo "&lt;br /&gt;";<br />
}<br />
}<br />
else {<br />
}</code></p>
<p>E anche per oggi è tutto&#8230; vi aspetto alla prossima!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.web-magazine.it/2011/11/creare-siti-in-php-%e2%80%93-26-%e2%80%93-costruiamo-un-form-di-ricerca-con-phpmysql/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Creare siti in PHP – (25) – Operazioni sul database: funzioni aggregate e query annidate</title>
		<link>http://www.web-magazine.it/2011/11/creare-siti-in-php-%e2%80%93-25-%e2%80%93-operazioni-sul-database-funzioni-aggregate-e-query-annidate/</link>
		<comments>http://www.web-magazine.it/2011/11/creare-siti-in-php-%e2%80%93-25-%e2%80%93-operazioni-sul-database-funzioni-aggregate-e-query-annidate/#comments</comments>
		<pubDate>Thu, 24 Nov 2011 06:00:23 +0000</pubDate>
		<dc:creator>Federico</dc:creator>
				<category><![CDATA[scripting]]></category>
		<category><![CDATA[database]]></category>
		<category><![CDATA[MySQL]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[sql]]></category>

		<guid isPermaLink="false">http://www.web-magazine.it/?p=2249</guid>
		<description><![CDATA[Ultima puntata sulle operazioni sul database. Impariamo alcune funzioni aggregate (COUNT, SUM, AVG, MAX e MIN) e impariamo a eseguire query annidate.]]></description>
			<content:encoded><![CDATA[<p><img src="http://www.web-magazine.it/wp-content/uploads/2011/11/php25.jpg" alt="Funzioni aggregate e query annidate" /></p>
<p>Terminiamo il nostro panorama sulle <strong>operazioni </strong>che si possono fare sul <strong>database </strong>parlando oggi di <strong>funzioni aggregate </strong>e di <strong>query annidate</strong>. Iniziamo dalle prime, dette anche <strong>“funzioni di aggregazione”</strong>: si tratta di una serie di <strong>funzioni </strong>che il linguaggio <strong>SQL</strong> ci mette a disposizione per estrarre <strong>diversi tipi di informazione</strong> dal nostro database, perlopiù di tipo <strong>statistico</strong>.</p>
<p><span id="more-2249"></span></p>
<h3>La funzione COUNT</h3>
<p>Supponiamo, per esempio, di voler creare una pagina all&#8217;interno della quale inserire una serie di statistiche relative al nostro blog. Potremmo iniziare dal <strong>numero complessivo</strong> dei post presenti nel blog (e quindi nel database). Come fare per sapere quanti sono? Utilizziamo la funzione aggregata <strong>COUNT</strong>, che invocheremo sulla tabella dando un <strong>nome al risultato</strong> che verrà estratto tramite la clausola <strong>AS</strong>. Vediamo la sintassi:</p>
<p><code>$query = "SELECT COUNT(*) AS TotalePost FROM Post";<br />
$risultato = mysql_query($query);</code></p>
<p>Tutte le funzioni devono essere invocate dopo il comando <strong>SELECT</strong>. Nel nostro caso, invochiamo la funzione COUNT <strong>su tutti i campi </strong>(*) e quindi chiamiamo il risultato TotalePost. Possiamo poi stampare il tutto come abbiamo visto finora:</p>
<p><code>while ($record = mysql_fetch_array($risultato, MYSQL_ASSOC)) {<br />
echo "Totale post presenti nel blog: "; echo $record['TotalePost'];<br />
}</code></p>
<h3>La funzione SUM</h3>
<p>Supponiamo invece di voler conoscere il <strong>numero totale dei commenti</strong> ma <strong>senza operare </strong>sulla tabella <em>Commenti</em>: vogliamo utilizzare un campo <em>NumCommenti </em>della tabella <em>Post </em>in cui avremo inserito il numero di commenti per ogni singolo post. In questo caso ci sarà di aiuto la funzione <strong>SUM</strong>, che, come si può intuire dal nome, esegue la <strong>somma dei valori dei record</strong>. Supponiamo di avere quattro post: il primo ha dodici commenti, il secondo cinque, il terzo nove e il quarto quindici per un totale di quarantuno commenti.</p>
<p>La sintassi è del tutto simile a quella di COUNT. Invochiamo SUM subito dopo il comando SELECT, tra parentesi indichiamo <strong>il campo che ci interessa</strong> (ovvero il campo i cui valori saranno sommati tra di loro), diamo un nome al risultato e selezioniamo la tabella:</p>
<p><code>$query2 = "SELECT SUM(NumCommenti) AS TotaleCommenti FROM Post";<br />
$risultato2 = mysql_query($query2);<br />
while ($record2 = mysql_fetch_array($risultato2, MYSQL_ASSOC)) {<br />
echo "Totale commenti presenti nel blog: "; echo $record2['TotaleCommenti'];<br />
}</code></p>
<h3>La funzione AVG</h3>
<p>A questo punto potrebbe essere interessante sapere qual è <strong>il numero medio di commenti</strong> ai post del nostro blog (nel nostro caso è 10,25). Abbiamo anche una funzione per conoscere la media: si tratta di <strong>AVG</strong> (dall&#8217;inglese “average” che significa “media”) e il meccanismo è identico a quello di SUM. Vediamo:</p>
<p><code>$query3 = "SELECT AVG(NumCommenti) AS MediaCommenti FROM Post";<br />
$risultato3 = mysql_query($query3);<br />
while ($record3 = mysql_fetch_array($risultato3, MYSQL_ASSOC)) {<br />
echo "Media commenti ai post: "; echo $record3['MediaCommenti'];<br />
}</code></p>
<h3>Le funzioni MAX e MIN</h3>
<p>Non è cambiato niente, se non la funzione invocata subito dopo il comando SELECT. Potremmo poi voler conoscere qual è il numero dei commenti del <strong>post con il maggior numero di commenti</strong> e al contrario qual è il numero di commenti del <strong>post con il minor numero di commenti</strong>. Per compiere queste due operazioni abbiamo le funzioni <strong>MAX </strong>e <strong>MIN</strong>, e anche in questi due casi il meccanismo è simile a quello delle funzioni che abbiamo appena visto. Diamo un&#8217;occhiata a MAX:</p>
<p><code>$query4 = "SELECT MAX(NumCommenti) AS Massimo FROM Post";<br />
$risultato4 = mysql_query($query4);<br />
while ($record4 = mysql_fetch_array($risultato4, MYSQL_ASSOC)) {<br />
echo "Numero commenti massimo: "; echo $record4['Massimo'];<br />
}</code></p>
<p>E adesso MIN:</p>
<p><code>$query5 = "SELECT MIN(NumCommenti) AS Minimo FROM Post";<br />
$risultato5 = mysql_query($query5);<br />
while ($record5 = mysql_fetch_array($risultato5, MYSQL_ASSOC)) {<br />
echo "Numero commenti minimo: "; echo $record5['Minimo'];<br />
}</code></p>
<h3>Le query annidate</h3>
<p>Ma cosa dovremmo fare se volessimo sapere <strong>qual è il post con il maggior numero di commenti</strong> (e quindi non solo qual è il numero di commenti del post con il maggior numero di commenti)? Dobbiamo ricorrere a una <strong>query annidata</strong>, detta anche <strong>“subquery”</strong>: le query annidate sono <strong>interrogazioni che si trovano all&#8217;interno di altre interrogazioni</strong>. Il caso che prendiamo in esame noi è <strong>il più semplice</strong>: una interrogazione viene posta come <strong>condizione della clausola WHERE</strong>. Vediamo come funziona:</p>
<p><code>$query6 = "SELECT Titolo FROM Post WHERE NumCommenti = (SELECT MAX(NumCommenti) FROM Post)";<br />
$risultato6 = mysql_query($query6);</code></p>
<p>Fino al WHERE quindi <strong>niente di strano</strong>: dopo l&#8217;uguale però inseriamo <strong>un nuovo comando SELECT</strong>, che dovrà estrarre <strong>il numero massimo di commenti presenti in un post</strong>. La query “più grande” estrarrà quindi il titolo il cui numero di commenti sarà uguale al massimo numero di commenti per un post presenti nel nostro database. Stampiamo poi molto semplicemente così:</p>
<p><code>while ($record6 = mysql_fetch_array($risultato6, MYSQL_ASSOC)) {<br />
echo "Post con il maggior numero di commenti: "; echo $record6['Titolo'];<br />
}</code></p>
<p>Ripetiamo la stessa cosa anche per conoscere il post con il minor numero di commenti. Possiamo poi creare dei comandi SELECT che <strong>estraggono informazioni dai risultati di altri comandi SELECT</strong>, come in questo caso:</p>
<p><code>$query = "SELECT * FROM (SELECT * FROM Post WHERE Id &gt; 5) AS PrimaSelect WHERE NumCommenti &gt; 6";<br />
$risultato = mysql_query($query);</code></p>
<p>Che è una complicazione inutile in quanto avremmo ottenuto lo stesso risultato con un solo comando SELECT, ma è utile per capire il meccanismo delle query annidate. In questo caso selezioniamo tutti i risultati tratti a loro volta dai risultati di una prima selezione, che dovrà obbligatoriamente essere nominata (AS PrimaSelect), altrimenti la query non funzionerà e ci sarà un errore. La prima selezione, quella interna, estrae tutti i record dalla tabella <em>Post </em>che hanno un id maggiore di 5, e da questa selezione, il comando SELECT principale estrae i post che hanno più di sei commenti.</p>
<h3>L&#8217;esercizio di oggi</h3>
<p>Vi lascio come sempre con un esercizio: create una query che esegua la somma di tutti i commenti presenti nel database escludendo però il post con il maggior numero di commenti. Alla prossima!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.web-magazine.it/2011/11/creare-siti-in-php-%e2%80%93-25-%e2%80%93-operazioni-sul-database-funzioni-aggregate-e-query-annidate/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Creare siti in PHP – (24) – Operazioni sul database: SELECT e JOIN</title>
		<link>http://www.web-magazine.it/2011/11/creare-siti-in-php-%e2%80%93-24-%e2%80%93-operazioni-sul-database-select-e-join/</link>
		<comments>http://www.web-magazine.it/2011/11/creare-siti-in-php-%e2%80%93-24-%e2%80%93-operazioni-sul-database-select-e-join/#comments</comments>
		<pubDate>Mon, 21 Nov 2011 06:00:22 +0000</pubDate>
		<dc:creator>Federico</dc:creator>
				<category><![CDATA[scripting]]></category>
		<category><![CDATA[MySQL]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[select]]></category>
		<category><![CDATA[sql]]></category>

		<guid isPermaLink="false">http://www.web-magazine.it/?p=2178</guid>
		<description><![CDATA[Seconda puntate del ciclo dedicato alle operazioni sul database. Impariamo oggi a estrarre informazioni dalla base di dati con il comando SELECT e a unire tabelle con il comando JOIN. Introduciamo le clausole ORDER BY e AS. Impariamo a utilizzare le informazioni estratte dal database: la funzione mysql_fetch_array]]></description>
			<content:encoded><![CDATA[<p><img src="http://www.web-magazine.it/wp-content/uploads/2012/11/php24.jpg" alt="Creare siti in PHP" /></p>
<p>Continuiamo la panoramica sulle <strong>operazioni</strong> che si possono fare sul <strong>database</strong> vedendo oggi <strong>due delle operazioni più importanti</strong>: la prima serve per <strong>estrarre record </strong>(e quindi <strong>informazioni</strong>) dalle tabelle, la seconda invece serve per <strong>unire due o più tabelle insieme</strong>.</p>
<p><span id="more-2178"></span></p>
<h3>Estraiamo informazioni dal database con SELECT</h3>
<p>La prima di queste due operazioni si compie utilizzando il comando <strong>SELECT</strong>. Proviamo per esempio a selezionare il campo Titolo e il campo Link dalla tabella post:</p>
<p><code>$query = "SELECT Titolo, Link FROM Post";</code></p>
<p>La sintassi è quindi semplice: basta scrivere <strong>SELECT </strong>seguito dal <strong>nome dei campi</strong> da cui vogliamo <strong>estrarre informazioni</strong>, ognuno <strong>separato dall&#8217;altro</strong> attraverso <strong>una virgola</strong>, e quindi, dopo la parola <strong>FROM</strong> scrivere il <strong>nome della tabella</strong>. E se volessimo invece selezionare <strong>tutti i campi</strong>? Invece di scrivere i nomi di tutti quanti i campi, basta semplicemente inserire <strong>un asterisco tra SELECT e FROM</strong>:</p>
<p><code>$query = "SELECT * FROM Post";</code></p>
<p>E ovviamente, anche con SELECT, possiamo utilizzare <strong>le clausole WHERE, AND e OR</strong>:</p>
<p><code>$query = "SELECT * FROM Post WHERE Titolo = 'Ciao'";<br />
$query2 = "SELECT * FROM Post WHERE Titolo = 'Ciao' AND IdAutore = 1";<br />
$query3 = "SELECT * FROM Post WHERE Titolo = 'Ciao a tutti' OR Titolo = 'Ciao'";<br />
</code></p>
<p>Nel primo caso abbiamo selezionato tutti i campi della tabella Post dai record il cui titolo è “Ciao”, nella seconda query stessa cosa ma i post devono essere stati scritti dall&#8217;autore contrassegnato dall&#8217;id numero 1, e nella terza interrogazione abbiamo invece selezionato tutti i campi dei record che hanno come titolo “Ciao a tutti” oppure “Ciao”.</p>
<h3>La clausola ORDER BY</h3>
<p>Possiamo poi anche <strong>dare un ordine ai record </strong>che estraiamo con il comando SELECT, utilizzando la clausola <strong>ORDER BY </strong>seguita dal campo in base al quale vogliamo ordinare le informazioni. Se per esempio vogliamo ordinarli in base alla data:</p>
<p><code>$query = "SELECT * FROM Post WHERE Titolo = 'Ciao' AND IdAutore = 1 ORDER BY Data DESC";<br />
</code><br />
E possiamo scegliere se <strong>ordinare in modo decrescente</strong>, come nel caso dell&#8217;esempio (<strong>DESC</strong>) oppure per <strong>ordinare in modo crescente</strong> (<strong>ASC</strong>).</p>
<h3>Utilizziamo le informazioni estratte: mysql_fetch_array</h3>
<p>In genere il SELECT si usa, come abbiamo detto all&#8217;inizio, per <strong>estrarre informazioni</strong>: e tali informazioni andranno poi <strong>mostrate all&#8217;utente</strong>. Bene, come si fa per mostrare queste informazioni all&#8217;utente? Abbiamo bisogno di una nuova funzione, <strong>mysql_fetch_array</strong>. Riceve come <strong>primo parametro</strong> il <strong>risultato della funzione mysql_query</strong>, e come <strong>secondo parametro il tipo di array</strong> che vogliamo utilizzare, perché il risultato della nostra <em>query</em> <strong>sarà trasformato in un array</strong>. Possiamo quindi scegliere un <strong>array numerico (MYSQL_NUM)</strong>, un <strong>array associativo (MYSQL_ASSOC)</strong> o <strong>entrambi (MYSQL_BOTH)</strong>. Il mio consiglio è quello di utilizzare un <strong>array associativo</strong>: gli<strong> indici</strong> saranno nient&#8217;altro che i <strong>nomi dei campi</strong>. Se <strong>non volete specificare</strong> il tipo di array, sarà assegnato quello di default, ovvero <strong>MYSQL_BOTH</strong>.</p>
<p>E dal momento che avremo bisogno di creare<strong> un array per ogni record del database</strong>, dovremo utilizzare <strong>una iterazione di tipo while</strong>, e per stampare ciò che ci interessa dovremo <strong>tener conto</strong> del fatto che staremo <strong>operando su di un array</strong>:</p>
<p><code>$query = "SELECT * FROM Post WHERE IdAutore = 1";<br />
$risultato = mysql_query($query);<br />
while ($record = mysql_fetch_array($risultato, MYSQL_ASSOC)) {<br />
echo "{$record['Titolo']}&lt;br /&gt;";<br />
}</code></p>
<p>Attraverso <strong>il nostro while</strong>, nel caso dell&#8217;esempio, con una stampa scriviamo nella pagina il titolo dei post che soddisfano le condizioni poste dal comando SELECT.</p>
<h3>Uniamo le tabelle con JOIN</h3>
<p>Bene, facciamo ora un altro esempio. Supponiamo di voler scrivere, da qualche parte nella home page del nostro blog, <strong>i titoli dei post accompagnati dal nickname dell&#8217;autore</strong>. Nella tabella post il nickname dell&#8217;autore degli articoli non è presente: abbiamo soltanto l&#8217;id. Come facciamo quindi a compiere questa operazione? Dovremo necessariamente <strong>unire la tabella Post con la tabella Autori</strong>, per fare in modo che ai campi della tabella Post vengano anche aggiunti i campi della tabella Autori.</p>
<p>Per fare questo utilizziamo il comando <strong>JOIN</strong>, ma ci deve essere <strong>una condizione</strong>, ovvero<strong> la base su cui uniremo le tabelle</strong>. Cosa significa? Significa che dovrà esserci <strong>un campo che avrà gli stessi valori per entrambe le tabelle</strong>. Nel nostro caso è il campo dell&#8217;id dell&#8217;autore, ovvero IdAutore nella tabella Post e Id nella tabella Autori: affinché le due tabelle possano essere unite, ci deve essere <strong>una corrispondenza tra IdAutore di Post e Id di Autori</strong>. Questo significa che a tutti i record che hanno un certo IdAutore <strong>verranno abbinati i valori</strong> di quei record della tabella Autori il cui Id è lo stesso di IdAutore.</p>
<p>Nel nostro database l&#8217;autore 1 è Laura. Con il comando JOIN, a tutti i post scritti da Laura memorizzati nella tabella Post e contrassegnati, ovviamente, con l&#8217;IdAutore uguale a 1, saranno affiancati i record della tabella Autori il cui Id è uguale a 1.</p>
<p>Vediamo quindi la sintassi:</p>
<p><code>$query = "SELECT * FROM Post JOIN Autori ON Post.IdAutore = Autori.Id";<br />
$risultato = mysql_query($query);</code></p>
<p>Quindi subito dopo il nome della tabella inseriamo<strong> il comando JOIN</strong> seguito <strong>dal nome della tabella da unire</strong>. Inseriamo poi <strong>la clausola ON</strong> seguita dai <strong>due campi delle tabelle che devono corrispondere tra di loro</strong>: nel nostro caso IdAutore per quanto riguarda Post e Id per quanto riguarda Autori. Deve essere scritto prima il nome della tabella, quindi, <strong>dopo un punto</strong>, il nome del campo (<em>tabella.campo</em>).</p>
<p>Per stampare i risultati il metodo è ancora quello di prima:</p>
<p><code>while ($record = mysql_fetch_array($risultato, MYSQL_ASSOC)) {<br />
echo "{$record['Titolo']}, scritto da {$record['Nickname']}&lt;br /&gt;";<br />
}</code></p>
<h3>Rinominiamo (provvisoriamente) campi e tabelle con la clausola AS</h3>
<p>Supponiamo ora di voler stampare sia davanti al post che davanti all&#8217;autore il rispettivo id. Per esempio in questa forma: “Post numero 2: Ciao a tutti!!!, scritto da LauraD (autore numero 1)”. Se scrivessimo una cosa del genere:</p>
<p><code>echo "Post numero {$record['Id']}: {$record['Titolo']}, scritto da {$record['Nickname']} (autore<br />
numero {$record['Id']})&lt;br /&gt;";</code></p>
<p>Ovviamente non otterremmo il risultato sperato, perché <strong>ci sono due campi che hanno lo stesso nome</strong> (Id), e quando succede questo viene preso il campo Id <strong>dell&#8217;ultima tabella presa in considerazione </strong>(nel nostro caso Autori) e scartato il campo <strong>con lo stesso nome nelle tabelle precedenti</strong>. Per ovviare a questo problema <strong>possiamo rinominare</strong>, all&#8217;interno della query, <strong>il campo che crea il conflitto</strong>. Lo facciamo tramite la<strong> clausola AS</strong>, che deve essere seguita <strong>dal nuovo nome</strong> del campo che ci interessa:</p>
<p><code>$query = "SELECT Post.Titolo, Post.Id, Autori.Id AS NumeroAutore, Autori.Nickname FROM Post JOIN Autori ON Post.IdAutore = Autori.Id";<br />
$risultato = mysql_query($query);</code></p>
<p>Abbiamo quindi<strong> rinominato il nome del campo</strong> Id della tabella Autori in NumeroAutore (<strong>ovviamente solo momentaneamente</strong>, per la query: <strong>non abbiamo alterato</strong> in alcun modo la <strong>struttura della tabella</strong> all&#8217;interno del nostro<strong> database</strong>). Stampiamo poi in questo modo:</p>
<p><code>while ($record = mysql_fetch_array($risultato, MYSQL_ASSOC)) {<br />
echo "Post numero {$record['Id']}: {$record['Titolo']}, scritto da {$record['Nickname']} (autore<br />
numero {$record['NumeroAutore']})&lt;br /&gt;";<br />
}</code></p>
<p>Si possono poi <strong>rinominare anche le tabelle</strong>, magari per questioni di praticità e rapidità, e il sistema è lo stesso che abbiamo appena visto:</p>
<p><code>$query = "SELECT * FROM Post AS p JOIN Autori AS a ON p.IdAutore = a.Id";<br />
$risultato = mysql_query($query);</code></p>
<h3>Tipi di unioni</h3>
<p>Le unioni che abbiamo visto fino a questo momento sono unioni di tipo <strong>INNER JOIN</strong>: significa che vengono <strong>combinati tutti i record che hanno una corrispondenza</strong> e vengono invece <strong>scartati i record che non hanno corrispondenza</strong>. Avremmo potuto specificare meglio le query viste finora (prendiamo per esempio l&#8217;ultima) scrivendo così:</p>
<p><code>$query = "SELECT * FROM Post AS p INNER JOIN Autori AS a ON p.IdAutore = a.Id";<br />
$risultato = mysql_query($query);</code></p>
<p>Ma dal momento che si tratta del tipo di unione predefinito possiamo anche non specificarlo. Questo perché esiste anche un altro tipo di unione, <strong>OUTER JOIN</strong>, che al contrario delle unioni di tipo INNER JOIN tiene conto <strong>anche dei risultati che non trovano corrispondenza tra di loro</strong>. Le unioni OUTER JOIN si suddividono a loro volta in <strong>LEFT JOIN</strong>, ovvero unioni che contengono sempre <strong>tutti i record della prima tabella</strong> (la tabella di sinistra, <em>left</em>) mentre per quanto riguarda i record della seconda tabella (quella di destra, right) vengono estratti <strong>solo i record che trovano una corrispondenza </strong>con quelli della tabella di sinistra, e in <strong>RIGHT JOIN</strong>, che funzionano<strong> all&#8217;inverso</strong> rispetto alle unioni LEFT JOIN.</p>
<p>Per esempio, supponiamo di avere tre autori e quattro post: tre scritti dall&#8217;autore 1, uno scritto dall&#8217;autore 2 e nessuno scritto dall&#8217;autore 3. Prendiamo questa query:</p>
<p><code>$query = "SELECT * FROM Autori LEFT JOIN Post ON Autori.Id = Post.IdAutore";<br />
$risultato = mysql_query($query);</code></p>
<p>In questo caso vengono selezionati tutti i record della tabella Autori uniti ai soli record della tabella Post che trovano una corrispondenza. Con un INNER JOIN l&#8217;autore numero 3 non sarebbe stato preso in considerazione dalla query, invece con questo OUTER JOIN di tipo LEFT (avremmo potuto scrivere, nel comando, anche <strong>LEFT OUTER JOIN</strong>) l&#8217;autore numero 3 viene <strong>comunque estratto</strong>. Se poi stampassimo:</p>
<p><code>while ($record = mysql_fetch_array($risultato, MYSQL_ASSOC)) {<br />
echo "{$record['Titolo']}, scritto da {$record['Nickname']}&lt;br /&gt;";<br />
}<br />
</code><br />
Nel ciclo corrispondente all&#8217;autore numero 3 verrebbe stampato <strong>uno spazio bianco</strong>, perché <strong>non esisterebbe</strong> un elemento dell&#8217;array con indice Titolo abbinato all&#8217;elemento “Nickname” relativo all&#8217;autore 3.</p>
<p>Il RIGHT JOIN funziona allo stesso modo del LEFT JOIN ma <strong>in maniera inversa</strong>:</p>
<p><code>$query = "SELECT * FROM Post RIGHT JOIN Autori ON Autori.Id = Post.IdAutore";<br />
$risultato = mysql_query($query);</code></p>
<p>In questo caso vengono estratti tutti i record della tabella di destra (Autori) mentre per quanto riguarda la tabella di sinistra (Post) vengono estratti solo i record che hanno una corrispondenza con Autori.</p>
<p>Vediamo <strong>un&#8217;altra informazione importante</strong>. <strong>Specifichiamo sempre la clausola ON </strong>altrimenti, se scrivessimo una cosa del genere:</p>
<p><code>$query = "SELECT * FROM Post JOIN Autori";<br />
$risultato = mysql_query($query);</code></p>
<p>Otterremmo un <strong>CROSS JOIN</strong>, ovvero il <strong>prodotto cartesiano delle due tabelle</strong>, cosa che sicuramente, almeno ai fini del nostro blog, non ci interessa.</p>
<h3>Unioni tra tre o più tabelle</h3>
<p>Possiamo poi unire anche<strong> tre o più tabelle tra loro</strong>. Per esempio, se avessimo un&#8217;ipotetica tabella DatiAutori in cui inserire indirizzi, numeri di telefono, immagini e quant&#8217;altro, potremmo scrivere una cosa del genere:</p>
<p><code>$query = "SELECT Post.Titolo, Autori.Nickname, DatiAutori.Email FROM Post JOIN Autori ON Post.IdAutore = Autori.Id JOIN DatiAutori ON Autori.Id = DatiAutori.IdAutore";<br />
$risultato = mysql_query($query);</code></p>
<p>E poi stampare in questo modo:</p>
<p><code>while ($record = mysql_fetch_array($risultato, MYSQL_ASSOC)) {<br />
echo "{$record['Titolo']}, scritto da {$record['Nickname']} (email: {$record['Email']})&lt;br /&gt;&lt;br /&gt;";<br />
}</code></p>
<p>Abbiamo quindi ottenuto <strong>un&#8217;unione di tre tabelle</strong>, ma <strong>non c&#8217;è limite</strong> al numero di tabelle che possiamo unire.</p>
<h3>L&#8217;esercizio di oggi</h3>
<p>Bene, per oggi siamo arrivati alla fine e vi lascio con un esercizio. Create uno script per stampare, nella home page, il titolo dei post, il nome dell&#8217;autore e i titoli dei commenti relativi al post, in questa forma:</p>
<p>Post: Ciao a tutti!<br />
Scritto da: Federico</p>
<p>Commenti&#8230;<br />
Ciao!<br />
Benvenuto!<br />
Bellissimo sito!</p>
<p>Postate come sempre le soluzioni come commenti, io vi aspetto alla prossima puntata!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.web-magazine.it/2011/11/creare-siti-in-php-%e2%80%93-24-%e2%80%93-operazioni-sul-database-select-e-join/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Creare siti in PHP – (23) – Operazioni sul database: INSERT, UPDATE e DELETE</title>
		<link>http://www.web-magazine.it/2011/11/creare-siti-in-php-%e2%80%93-23-%e2%80%93-operazioni-sul-database-insert-update-e-delete/</link>
		<comments>http://www.web-magazine.it/2011/11/creare-siti-in-php-%e2%80%93-23-%e2%80%93-operazioni-sul-database-insert-update-e-delete/#comments</comments>
		<pubDate>Mon, 14 Nov 2011 06:00:57 +0000</pubDate>
		<dc:creator>Federico</dc:creator>
				<category><![CDATA[scripting]]></category>
		<category><![CDATA[database]]></category>
		<category><![CDATA[MySQL]]></category>
		<category><![CDATA[php]]></category>

		<guid isPermaLink="false">http://www.web-magazine.it/?p=2175</guid>
		<description><![CDATA[Prima di tre puntate dedicate a operazioni con database. Impariamo oggi a inserire dati con il comando INSERT, ad aggiornarli con il comando UPDATE e a eliminarli con il comando DELETE. Impariamo anche l'utilizzo delle clausole WHERE, OR, AND e LIMIT.]]></description>
			<content:encoded><![CDATA[<p><img src="http://www.web-magazine.it/wp-content/uploads/2011/09/php23.jpg" alt="operazioni sul database" /></p>
<p>Iniziamo oggi una <strong>“gita”</strong> di tre puntate all&#8217;interno delle <strong>operazioni che si possono fare sul database</strong>, cercando di fornire una panoramica abbastanza completa per poter gestire un sito <strong>PHP/MySQL </strong>di una certa complessità. Oggi vedremo <strong>tre operazioni sul database</strong>, e in particolare vedremo come <strong>inserire</strong>, <strong>aggiornare</strong> e <strong>cancellare</strong> record.</p>
<p><span id="more-2175"></span></p>
<h3>Inseriamo dati con INSERT</h3>
<p>Partiamo dalla prima: l&#8217;operazione <strong>INSERT</strong>. No, non è una parola urlata: i comandi <strong>SQL</strong> si scrivono <strong>tutti maiuscoli</strong> (in <strong>PHP</strong> si possono comunque scrivere <strong>tutti minuscoli</strong> e non succede niente di strano: è sempre però bene scriverli tutti maiuscoli in primo luogo perché così prevede la <strong>documentazione ufficiale</strong>, in secondo luogo per <strong>non rischiare di fare confusione</strong> e in terzo luogo perché è sempre bello <strong>mantenere una forma elegante</strong>!</p>
<p>Prima però dobbiamo fare una <strong>piccola introduzione</strong>. L&#8217;ultima volta abbiamo detto che le <strong>interrogazioni al database </strong>si chiamano <strong>“query”</strong> (anche le operazioni di <strong>inserimento</strong>, <strong>aggiornamento</strong> e <strong>cancellazione</strong> si chiamano “query”). Per gestire le <em>query</em> inviate al database esiste una specifica funzione PHP, che si chiama <strong>mysql_query</strong> e che riceve come parametro proprio la<em> query</em>. Ma cos&#8217;è in sostanza una<em> query </em>parlando solo di PHP? Non è altro che <strong>una stringa di testo</strong>, ma una stringa <strong>un po&#8217; particolare</strong>, perché contiene nient&#8217;altro che le <strong>istruzioni SQL</strong>.</p>
<p>Vediamo quindi come funziona il tutto. L&#8217;operazione di inserimento prevede che venga scritto prima il comando <strong>INSERT INTO</strong>, quindi il nome della tabella all&#8217;interno della quale inserire i dati, poi la <strong>clausola VALUES</strong> seguita, tra parentesi tonde, dai <strong>dati da inserire </strong>scritti <strong>nell&#8217;ordine di come appaiono i campi nella tabella</strong>. Prendiamo come punto di riferimento la tabella <em>Post</em> che abbiamo creato la volta scorsa: dovremo seguire, in fase di inserimento, l&#8217;ordine Id – IdAutore – Titolo – TestoHTML – Data – Link. Questo è ciò che dovremo quindi scrivere:</p>
<p><code>$query = "INSERT INTO Post VALUES ('NULL', '1', 'Ciao a tutti', 'Ciao a tutti! Questo è il mio primo post', '2011-04-03 12:00:00', '/post/primopost')";</code></p>
<p>Se invertissimo l&#8217;ordine (per esempio scambiando “1” con “Ciao a tutti”) il risultato sarebbe l&#8217;inserimento di “Ciao a tutti” nel campo IdAutore e “1” nel campo Titolo: <strong>ci sarebbe quindi un errore</strong>, perché abbiamo assegnato a IdAutore il tipo INT, e “Ciao a tutti” non è davvero <strong>un numero intero</strong>. Quindi bisogna fare <strong>grande attenzione</strong> a <strong>rispettare l&#8217;ordine dei campi</strong> in questa operazione (<strong>sbagliarsi non è difficile</strong>). Un&#8217;altra accortezza: le stringhe di testo vanno sempre messe <strong>tra apici o doppi apici</strong>. Per quanto riguarda i campi di tipo <strong>INT</strong>, si possono anche lasciare senza apici. Mi raccomando, perché se non inserite le stringhe tra apici, <strong>la query non verrà eseguita</strong>. Infine, l&#8217;ultima cosa di cui tener conto. Abbiamo inserito il valore <strong>NULL </strong>nel campo Id perché si tratta di un campo a cui abbiamo assegnato <strong>l&#8217;auto-incremento</strong>: non sarà quindi necessario specificare il numero, perché verrà a<strong>utomaticamente inserito</strong> il <strong>primo numero libero disponibile</strong>. Per esempio, se questo è il primissimo post del nostro blog, nel campo Id sarà inserito il numero zero.</p>
<p>Bene, detto questo e una volta dichiarata la variabile $query, che non è altro che una stringa di testo, come abbiamo detto, dobbiamo invocare la funzione <em>mysql_query</em>:</p>
<p><code>mysql_query($query);</code></p>
<p>Fatte queste operazioni, i dati <strong>verranno inseriti nel database</strong>. Mi preme specificare che la funzione <em>mysql_query</em> è da utilizzarsi <strong>per qualsiasi operazione eseguita sul database</strong>, quindi sarà una funzione che ci accompagnerà per un bel po&#8217; di tempo. Potete trovare la documentazione ufficiale a questa pagina: <a href="http://php.net/manual/en/function.mysql-query.php">http://php.net/manual/en/function.mysql-query.php</a>.</p>
<p>Abbiamo visto come inserire dati che <strong>riempiano tutti i campi della tabella</strong>. Ma cosa dovremmo fare se volessimo riempire soltanto alcuni campi? Per esempio se volessimo lasciare in bianco il campo Link? Dovremmo specificare <strong>i singoli campi subito dopo il nome della tabella</strong>, inserendoli tra parentesi tonde, come nell&#8217;esempio seguente:</p>
<p><code>$query = "INSERT INTO Post (Id, IdAutore, Titolo, TestoHTML, Data) VALUES ('NULL', '1', 'Ciao a tutti', 'Ciao a tutti! Questo è il mio primo post', '2011-04-03 12:00:00')";<br />
mysql_query($query);<br />
</code></p>
<p>In questo modo verranno inseriti tutti i dati che abbiamo specificato ma sarà <strong>lasciato in bianco</strong> il campo Link. Questa sintassi è più o meno simile per <strong>tutte le operazioni SQL</strong>: abbiamo un <strong>comando</strong> e abbiamo poi una o più <strong>clausole </strong>che specificano meglio ciò che viene indicato dal comando.</p>
<h3>Aggiorniamo i dati con UPDATE</h3>
<p>Passiamo ora al comando <strong>UPDATE</strong>, che serve per<strong> aggiornare i record</strong> e che è un pochino più complesso rispetto a INSERT. Partiamo dal <strong>caso base</strong>, quello per aggiornare un solo campo, ma in tutti i record:</p>
<p><code>$query = "UPDATE Post SET IdAutore = 1";<br />
mysql_query($query);</code></p>
<h3>La clausola WHERE</h3>
<p>Questo è il caso più banale (e, se vogliamo, anche il più inutile): con il comando UPDATE abbiamo <strong>aggiornato</strong> la tabella Post impostando <strong>tutti i valori</strong> del campo IdAutore (quindi su tutti i record) a 1. Per aggiornare<strong> soltanto un campo nella tabella</strong> (o due o tre o comunque<strong> non tutti</strong>), dovremo essere <strong>più specifici</strong>: ci servirà la clausola <strong>WHERE</strong>, tramite la quale specificheremo <strong>un altro campo</strong> che dovrà identificare bene <strong>il record (o i record) da aggiornare</strong>. Ma vedendo il codice è più facile da intuire:</p>
<p><code>$query = "UPDATE Post SET Titolo = 'Secondo post' WHERE Id = '1'";<br />
mysql_query($query);</code></p>
<p>In questo modo <strong>abbiamo modificato un solo record</strong>, quello che ha come Id il numero uno (ricordiamo che Id è la <strong>chiave primaria</strong> della nostra tabella quindi si tratta di un campo che<strong> non può essere doppio</strong>, non ci saranno cioè due record <strong>con lo stesso valore nel campo Id</strong>). Una piccola parentesi: noi stiamo facendo le operazioni <strong>con due passaggi</strong> ma nessuno vi vieta di fare le interrogazioni in questo modo:</p>
<p><code>mysql_query("UPDATE Post SET Titolo = 'Secondo post' WHERE Id = '1'");</code></p>
<p>È un modo più rapido per fare <strong>la stessa cosa</strong>: in questa guida facciamo però uso delle variabili per <strong>una più chiara lettura e comprensione della sintassi SQL</strong>.</p>
<p>Ma andiamo avanti con le nostre operazioni. Se nel nostro database avessimo due post che hanno come titolo “Ciao” e volessimo cambiarlo in “Ciao a tutti!” dovremmo comportarci come sopra:</p>
<p><code>$query = "UPDATE Post SET Titolo = 'Ciao a tutti!' WHERE Titolo = 'Ciao'";<br />
mysql_query($query);</code></p>
<h3>Le clausole OR e AND</h3>
<p><strong>WHERE</strong> è una delle <strong>clausole più importanti </strong>della sintassi SQL perché si abbina <strong>a moltissimi comandi</strong>. Cosa dobbiamo fare invece se vogliamo dare <strong>lo stesso titolo</strong> a <strong>due post che hanno titoli diversi</strong>, per esempio uno “Ciao” e uno “Ciao a tutti!”? Introduciamo un&#8217;altra clausola, <strong>OR</strong>:</p>
<p><code>$query = "UPDATE Post SET Titolo = 'Ciao a tutti quanti!!!' WHERE Titolo = 'Ciao' OR Titolo = 'Ciao a tutti!'";<br />
mysql_query($query);</code></p>
<p>La clausola OR serve per <strong>“legare”</strong> tra di loro due espressioni introdotte dalla clausola WHERE, e possiamo usarla, all&#8217;interno della stessa query, <strong>tutte le volte che vogliamo</strong> (anche tre o quattro o più volte:</p>
<p><code>$query = "UPDATE Post SET Titolo = 'Ciao a tutti quanti!!!' WHERE Titolo = 'Ciao' OR Titolo = 'Ciao a tutti!' OR Titolo = 'Altro post' ";<br />
mysql_query($query);</code></p>
<p>Cosa fare invece quando abbiamo tre post con titolo “Ciao a tutti!”, scritti <strong>da due autori diversi</strong>, e noi vogliamo cambiare il titolo <strong>solo a quelli scritti da un certo autore</strong>? Dobbiamo utilizzare la clausola <strong>AND</strong>:</p>
<p><code>$query = "UPDATE Post SET Titolo = 'Ciao a tutti quanti!!!' WHERE Titolo = 'Ciao a tutti!' AND IdAutore = 1";<br />
mysql_query($query);</code></p>
<p>In questo modo abbiamo impostato il titolo a tutti quei post che hanno come titolo “Ciao a tutti!”<strong> e che sono stati scritti </strong>dall&#8217;autore contrassegnato dall&#8217;id 1. Quindi se ci sono altri post che hanno per titolo “Ciao a tutti!” (scritti ovviamente da autori diversi) o se ci sono altri post scritti dallo stesso autore (con titolo diverso), bene, tutti questi post <strong>non saranno aggiornati</strong>: l&#8217;operazione sarà valida solo per i post che <strong>soddisfano le clausole WHERE e AND</strong>.</p>
<p>Ovviamente poi, nelle espressioni delle clausole, è possibile usare, oltre all&#8217;uguale, anche <strong>altri operatori </strong>(maggiore, minore, maggiore-uguale, minore-uguale). Per esempio, volendo cambiare il titolo a tutti i post che hanno un Id maggiore di 5:</p>
<p><code>$query = "UPDATE Post SET Titolo = 'Ciao' WHERE Id &gt; 5";<br />
mysql_query($query);</code></p>
<h3>La clausola LIMIT</h3>
<p>Introduciamo poi un&#8217;<strong>ulteriore clausola</strong>, che ci serve se vogliamo prendere un certo numero di <strong>record contigui</strong>. Per esempio, prendiamo il caso che abbiamo visto adesso: vogliamo cambiare il titolo a <strong>tutti i post </strong>che hanno un id <strong>maggiore di 5</strong>, ma arrivando solo <strong>fino a quello che ha come id 8</strong> (quindi valido solo per i primi tre record). Vogliamo quindi <strong>non aggiornare</strong> i post che hanno id 9, 10, 11 eccetera. Ci serve la clausola <strong>LIMIT</strong> che deve essere seguita <strong>da un numero</strong> che <strong>indica il numero di post da tenere in considerazione</strong>:</p>
<p><code>$query = "UPDATE Post SET Titolo = 'Ciao a tutti!!!' WHERE Id &gt; 5 LIMIT 3";<br />
mysql_query($query);</code></p>
<p>In questo modo aggiorniamo sì i post che hanno un id maggiore di 5, ma solo i tre immediatamente successivi grazie alla clausola LIMIT. Verranno aggiornati quindi solo i post 6, 7 e 8.</p>
<h3>Cancelliamo i dati con DELETE</h3>
<p>Vediamo infine l&#8217;ultima istruzione, <strong>DELETE</strong>, che serve per <strong>cancellare record dal nostro database</strong>. Per cancellare un singolo record dal database la sintassi è molto semplice:</p>
<p><code>$query = "DELETE FROM Post WHERE Id = '1'";<br />
mysql_query($query);</code></p>
<p>Abbiamo semplicemente cancellato il post che ha come id il numero 1. Possiamo<strong> applicare anche a DELETE</strong> tutte le <strong>clausole</strong> che abbiamo visto per <strong>UPDATE</strong>. Vediamo per esempio con le clausole OR e AND:</p>
<p><code>$query = "DELETE FROM post WHERE Id = 5 OR Id = 6";<br />
mysql_query($query);</code></p>
<p><code>$query2 = "DELETE FROM post WHERE Titolo = 'Ciao a tutti' AND IdAutore = 3";<br />
mysql_query($query2);</code></p>
<p>Nel primo caso abbiamo cancellato i post contrassegnati dagli id 5 e 6, nel secondo caso abbiamo invece cancellato tutti i post che hanno per titolo “Ciao a tutti” e che sono stati scritti dall&#8217;autore contrassegnato dall&#8217;id numero 3.</p>
<p>È possibile anche <strong>cancellare tutta la tabella</strong>:</p>
<p><code>$query = "DELETE FROM post";<br />
mysql_query($query);</code></p>
<p><strong>Attenzione</strong> però! Una volta eseguito lo script <strong>non è più possibile arrestarlo o tornare indietro</strong>, quindi mi raccomando di usarlo con parsimonia, <strong>solo se si è sicuri del risultato</strong> e dove <strong>non fa danni</strong>.</p>
<h3>L&#8217;esercizio di oggi</h3>
<p>Bene, siamo arrivati alla fine e vi lascio con un esercizio: riprendiamo quindi la tradizione iniziata qualche puntata fa! Costruite una vera pagina per scrivere post in un blog, nel senso che abbiamo un form con una serie di opzioni, e una volta compilato il tutto, i dati immessi dal nostro utente vengono inviati al nostro database. Per la stampa della data potete utilizzare la funzione <em>date</em> che abbiamo visto nella puntata in cui abbiamo costruito il guestbook. Alla prossima!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.web-magazine.it/2011/11/creare-siti-in-php-%e2%80%93-23-%e2%80%93-operazioni-sul-database-insert-update-e-delete/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Creare siti in PHP – (22) – Costruiamo il database</title>
		<link>http://www.web-magazine.it/2011/11/creare-siti-in-php-%e2%80%93-22-%e2%80%93-costruiamo-il-database/</link>
		<comments>http://www.web-magazine.it/2011/11/creare-siti-in-php-%e2%80%93-22-%e2%80%93-costruiamo-il-database/#comments</comments>
		<pubDate>Mon, 07 Nov 2011 06:00:59 +0000</pubDate>
		<dc:creator>Federico</dc:creator>
				<category><![CDATA[scripting]]></category>
		<category><![CDATA[web design]]></category>
		<category><![CDATA[database]]></category>
		<category><![CDATA[MySQL]]></category>
		<category><![CDATA[php]]></category>

		<guid isPermaLink="false">http://www.web-magazine.it/?p=2171</guid>
		<description><![CDATA[Impariamo a utilizzare il programma PhpMyAdmin per creare e gestire basi di dati. Creiamo le nostre prime tabelle e inseriamo qualche record. Infine, connettiamoci al nostro database con le apposite funzioni PHP.]]></description>
			<content:encoded><![CDATA[<p><img src="http://www.web-magazine.it/wp-content/uploads/2011/09/php22.jpg" alt="Costruiamo il database" /></p>
<p>Dopo una <strong>panoramica teorica</strong> su <strong>MySQL</strong>, è finalmente arrivato il momento di <strong>costruire il nostro database</strong>. Lo faremo direttamente tramite il programma <strong>PhpMyAdmin</strong>, senza utilizzare comandi. Per prima cosa avviamo il nostro <strong>Wamp</strong>, facciamo clic con il tasto sinistro sull&#8217;icona nella barra delle applicazioni e quindi, dal menù, selezioniamo la seconda voce: <strong>PhpMyAdmin</strong>.</p>
<p><span id="more-2171"></span></p>
<h3>Creiamo un nuovo database con PhpMyAdmin</h3>
<p>Ci si aprirà la pagina del browser che avevamo scelto durante le fasi di installazione di Wamp. Se avete il programma in italiano, noterete che più o meno al centro della pagina c&#8217;è una sezione con scritto “<strong>MySQL localhost</strong>” e, subito sotto, la scritta <strong>“Crea un nuovo database”</strong> sotto la quale compaiono due campi. In quello vuoto, inseriamo il <strong>nome del nostro database</strong> (per esempio, “mioblog”). Il secondo è un <strong>select</strong>, che serve per selezionare la <strong>“collation”</strong>, ovvero <strong>il set di caratteri</strong> del nostro <strong>database</strong>: andrà bene un <em>utf8_general_ci</em>.</p>
<p>Possiamo quindi fare clic sul tasto <em>crea</em>: adesso abbiamo un <strong>database</strong>, chiamato “mioblog”, ovviamente vuoto perché dobbiamo ancora <strong>creare le tabelle</strong>. Portiamoci quindi dentro la pagina del database: vediamo un menù con una serie di voci “struttura”, “sql”, “cerca”, “query da esempio”, “esporta”, “importa”, “operazioni”, “privilegi”, “elimina”. Vedremo dopo a cosa servono queste voci: adesso è il momento di creare <strong>una tabella</strong>.</p>
<p>Lo facciamo tramite <strong>il form</strong> che vediamo <strong>al centro della pagina</strong>. Supponiamo quindi di voler creare la tabella “post” come abbiamo visto <strong>nell&#8217;ultima puntata</strong>. Inseriamo<strong> nel primo campo il nome della tabella</strong>, e <strong>nel secondo il numero di campi</strong> (cioè degli <strong>attributi</strong> a cui andremo ad associare i <strong>valori</strong>): nel nostro caso, i campi sono sei (uno per l&#8217;id, uno per l&#8217;id dell&#8217;autore, uno per il titolo, uno per il testo formattato in linguaggio HTML, uno per la data e uno per il link al post).</p>
<p>A questo punto ci comparirà un form con un numero di righe uguale al numero che abbiamo immesso poc&#8217;anzi, e per ogni riga notiamo una serie di colonne, di cui adesso comprendiamo il significato:</p>
<ul>
<li><strong>Campo</strong>: è il 	nome del campo. Nel caso della nostra tabella, il primo sarà “Id”, 	il secondo “IdAutore”, il terzo “Titolo” e così via. Il 	<strong>consiglio che vi do</strong> è quello di utilizzare, per i campi, 	sempre <strong>caratteri alfanumerici</strong> o al più <strong>underscore</strong> se 	vogliamo inserire spazi. Sono <strong>da evitare</strong> caratteri accentati 	e caratteri speciali. In più, <strong>non è possibile</strong> assegnare ai 	nomi dei campi <strong>le parole chiave che definiscono i comandi SQL</strong> (sono un gruppo di parole come SELECT, DELETE, LIKE, LIMIT, JOIN e 	altre che conosceremo nelle prossime puntate);</li>
<li><strong>Tipo</strong>: è il 	tipo del campo. I principali sono: <strong>INT</strong> (numero intero), 	<strong>VARCHAR</strong> (stringa di caratteri a lunghezza variabile), <strong>DATE</strong> e <strong>DATETIME</strong> (per le date: il secondo tipo può contenere anche 	l&#8217;ora), <strong>TEXT</strong>, <strong>MEDIUMTEXT</strong> e <strong>LONGTEXT</strong> (testi per 	un massimo di, rispettivamente, 2^16, 2^24 e 2^32 caratteri), 	<strong>DECIMAL</strong> (per i numeri decimali). Nel nostro caso inseriremo i 	tipi <strong>INT</strong> per Id, IdAutore e NumCommenti, <strong>VARCHAR</strong> per 	Titolo e Link,  <strong>DATETIME</strong> per data e <strong>TEXT</strong> per TestoHTML 	;</li>
<li><strong>Lunghezza/Set</strong>: 	la lunghezza massima dei campi. Per i campi numerici tipicamente si 	inserisce 11 come lunghezza (ovvero il numero massimo che un campo 	di tipo INT può avere come lunghezza: se lasciamo in bianco verrà 	apposto automaticamente proprio 11), mentre per i nostri campi 	VARCHAR possiamo scegliere una lunghezza massima di 100 caratteri. 	Lasciamo in bianco DATETIME e TEXT;</li>
<li><strong>Predefinito, 	Collation, Attributi e Null</strong>: possiamo tralasciare queste colonne 	per cui le lasciamo in bianco (per la cronaca, servono 	rispettivamente: se vogliamo dare un <strong>valore predefinito al campo</strong>, 	se vogliamo dare al campo un <strong>set di caratteri diverso </strong>rispetto 	a quello dell&#8217;<strong>intero database</strong>, se vogliamo specificare<strong> attribuiti particolari</strong> -per esempio se vogliamo assegnare al 	campo una <strong>collation binaria</strong>- e se vogliamo associare, tra gli 	altri, anche il valore <strong>NULL </strong>al nostro campo).</li>
<li><strong>Indice</strong>: serve 	per impostare l&#8217;indice al campo. A noi interessa l&#8217;indice <strong>“PRIMARY”</strong>, 	che serve per identificare il campo <strong>“più importante” </strong>della 	tabella, il cui valore deve essere univoco (non devono cioè esserci 	altri record con lo stesso valore per quel campo). Solitamente è il 	campo Id;</li>
<li><strong>AUTO_INCREMENT</strong>: 	questo è molto importante. Serve per <strong>far aumentare 	automaticamente di una unità </strong>il campo ogni volta che verrà 	inserito <strong>un nuovo record</strong>. Lo spuntiamo solo per il campo Id;</li>
<li><strong>Commenti</strong>: se 	vogliamo aggiungere commenti per un campo.</li>
</ul>
<h3>Gestiamo le tabelle</h3>
<p>Una volta creata la nostra prima tabella <strong>possiamo creare tutte le altre</strong> e cominciare a svolgere su di esse <strong>alcune operazioni</strong>. Prima però vediamo cosa significano quelle voci di MySQL di cui abbiamo parlato prima:</p>
<ul>
<li><strong>Struttura</strong>: ci 	mostra la <strong>struttura del database</strong>, ovvero l&#8217;elenco delle 	tabelle;</li>
<li><strong>SQL</strong>: contiene 	un campo che ci permette di eseguire <strong>sintassi SQL</strong> (che 	inizieremo a vedere dalla prossima puntata);</li>
<li><strong>Cerca</strong>: per 	cercare una parola, un valore nel database;</li>
<li><strong>Query da esempio</strong>: 	se non conosciamo la sintassi SQL, questa voce ci aiuta a fare 	interrogazioni al database;</li>
<li><strong>Esporta</strong>: per 	esportare il database (possiamo scegliere tra tanti formati);</li>
<li><strong>Importa</strong>: se 	abbiamo un database (solitamente un file con estensione .sql) 	possiamo importarlo;</li>
<li><strong>Operazioni</strong>: 	se vogliamo inserire una nuova tabella, rinominare il database, 	copiarlo o cambiare la collation;</li>
<li><strong>Privilegi</strong>: se 	ci sono più utenti che utilizzano PhpMyAdmin, possiamo impostare da 	qui i loro privilegi in termini di operazioni che possono eseguire 	sui database.</li>
</ul>
<p>Vediamo ora quali sono<strong> le operazioni</strong> che si possono fare <strong>sulle diverse tabelle</strong>. Clicchiamo quindi su una delle nostre tabelle (ricordo che l&#8217;elenco si può trovare nella pagina <strong>“Struttura”</strong>): vedremo un&#8217;altra serie di voci che costituiscono un menù. Vediamo a cosa servono:</p>
<ul>
<li><strong>Mostra</strong>: 	cliccando su questa voce potremo vedere <strong>tutti i record del 	database</strong>, e possiamo <strong>modificarli velocemente</strong> (facendo 	clic sull&#8217;<strong>icona a forma di penna</strong>, attraverso la quale ci si 	aprirà un form simile a quello della voce <strong>“Inserisci”</strong> che vedremo tra poco) o eliminarli (facendo clic <strong>sull&#8217;icona a 	forma di croce</strong>: prima ci verrà chiesta la conferma 	dell&#8217;operazione);</li>
<li><strong>Struttura</strong>: ci 	mostra la <strong>struttura della tabella</strong>. I campi possono essere 	<strong>modificati o eliminati</strong>;</li>
<li><strong>SQL</strong>: per 	eseguire<strong> sintassi SQL</strong> sulla tabella;</li>
<li><strong>Cerca</strong>: per 	cercare un <strong>valore</strong> nella tabella;</li>
<li><strong>Inserisci</strong>: 	per inserire <strong>record</strong> nella tabella. Ci apparirà un form in 	cui dovremo inserire un <strong>valore per ogni attributo </strong>e quindi 	fare clic su “esegui”;</li>
<li><strong>Esporta e 	Importa</strong>: per esportare e importare la tabella;</li>
<li><strong>Operazioni</strong>: 	da qui possiamo riordinare, spostare, copiare, rinominare, 	commentare, analizzare la tabella;</li>
<li><strong>Svuota</strong>: per 	cancellare <strong>tutti i record della tabella</strong>;</li>
<li><strong>Elimina</strong>: per 	cancellare <strong>tutta la tabella</strong>.</li>
</ul>
<p>Gestire i database con <strong>PhpMyAdmin</strong>, una volta appresi questi concetti, diventa, ovviamente con l&#8217;esercizio e con la pratica, <strong>molto semplice e intuitivo</strong>.</p>
<h3>La connessione al database da PHP</h3>
<p>Come ultimo argomento di oggi vediamo come <strong>connetterci al database</strong> attraverso il nostro sito in <strong>PHP</strong>. Dobbiamo innanzitutto creare <strong>quattro variabili</strong>, che ci servono per <strong>memorizzare l&#8217;indirizzo del server</strong>, il<strong> nome del database</strong>, il <strong>nome dell&#8217;utente</strong> e la <strong>password dell&#8217;utente del database</strong>. Tipicamente, quando si lavora in locale, il server è <strong>“localhost”</strong> e il nome dell&#8217;utente è<strong> “root”</strong>:</p>
<p><code>$host = 'localhost';<br />
$utente = 'root';<br />
$password = 'password';<br />
$db = 'primoprogetto';</code></p>
<p>A questo punto dobbiamo quindi invocare la funzione <strong>mysql_connect</strong>, che serve, come avrete intuito dal nome, a far sì che il nostro sito <strong>possa connettersi al server MySQL</strong>. La funzione riceve come parametri <strong>l&#8217;indirizzo del server, il nome dell&#8217;utente e la sua password</strong>:</p>
<p><code>$connessione = mysql_connect($host,$utente,$password);</code></p>
<p>Tipicamente si usa “estendere” la funzione <strong>mysql_connect</strong> con la funzione <strong>die</strong>, che serve per <strong>fermare lo script in caso di errori </strong>e per stampare di conseguenza <strong>un messaggio all&#8217;utente</strong>. Si invoca subito dopo <em>mysql_connect</em>, a cui viene unita tramite la parola <strong>“or”</strong>:</p>
<p><code>$connessione = mysql_connect($host,$utente,$password) or die("Connessione non riuscita");</code></p>
<p>Se non avverrà una connessione al server MySQL per un qualsiasi errore (per esempio, se abbiamo inserito la password sbagliata), ci sarà un <strong>warning</strong> e verrà stampata la scritta “Connessione non riuscita”. Abbiamo associato il risultato di questa funzione a una variabile perché è possibile chiudere la connessione tramite la funzione <strong>mysql_close</strong>, che riceve come parametro proprio il risultato di <em>mysql_connect</em>:</p>
<p><code>mysql_close($connessione);</code></p>
<p>È bene specificare che la connessione <strong>si chiude comunque quando si arresta lo script</strong> che la esegue: tuttavia <em>mysql_close</em> può servirci se vogliamo chiudere noi la connessione <strong>in un qualche punto preciso</strong> del nostro sito.</p>
<p>A questo punto, dopo esserci <strong>connessi al server</strong>, dobbiamo selezionare il database che ci interessa, e lo facciamo tramite la funzione <strong>mysql_select_db</strong>, che riceve come parametro<strong> il nome del nostro database</strong> (che avevamo memorizzato nella variabile $db):</p>
<p><code>mysql_select_db($db);</code></p>
<p>Bene! Adesso siamo collegati al nostro database. Le documentazioni ufficiali delle funzioni che abbiamo visto nella puntata si trovano qui: <a href="http://php.net/manual/en/function.mysql-connect.php">http://php.net/manual/en/function.mysql-connect.php</a> (mysql_connect), <a href="http://it.php.net/manual/en/function.die.php">http://it.php.net/manual/en/function.die.php</a> (die), <a href="http://it.php.net/manual/en/function.mysql-close.php">http://it.php.net/manual/en/function.mysql-close.php</a> (mysql_close), <a href="http://it.php.net/manual/en/function.mysql-select-db.php">http://it.php.net/manual/en/function.mysql-select-db.php</a> (mysql_select_db).</p>
<p>Quindi, ricapitolando, il codice per connetterci al database è questo:</p>
<p><code>&lt;?php<br />
$host = 'localhost';<br />
$utente = 'root';<br />
$password = 'password';<br />
$db = 'primoprogetto';<br />
$conn = mysql_connect($host,$utente,$password) or die("Connessione non riuscita");<br />
mysql_select_db($db);<br />
?&gt;</code></p>
<p>E dovremo utilizzarlo <strong>in ogni singola pagina del sito</strong> per la quale è prevista una interazione con il database, quindi <strong>il consiglio</strong> che vi do è quello di <strong>creare un file esterno</strong> in cui inserirete questi dati, e poi lo richiamerete in ogni pagina semplicemente con un <em>include</em>. Ci vediamo alla prossima puntata!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.web-magazine.it/2011/11/creare-siti-in-php-%e2%80%93-22-%e2%80%93-costruiamo-il-database/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>

