<?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 developer Archivi - Cesare Bordi | Innovation Manager &amp; Back-end Developer</title>
	<atom:link href="https://www.cesarebordi.it/tag/web-developer/feed/" rel="self" type="application/rss+xml" />
	<link>https://www.cesarebordi.it/tag/web-developer/</link>
	<description>Innovare con soluzioni software efficaci e gioco di squadra</description>
	<lastBuildDate>Mon, 23 Oct 2023 08:27:54 +0000</lastBuildDate>
	<language>it-IT</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.4.2</generator>

<image>
	<url>https://www.cesarebordi.it/wp-content/uploads/2016/02/CB-logo-88x88.png</url>
	<title>web developer Archivi - Cesare Bordi | Innovation Manager &amp; Back-end Developer</title>
	<link>https://www.cesarebordi.it/tag/web-developer/</link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>PSR-7 Http Message: standard php per Request e Response.</title>
		<link>https://www.cesarebordi.it/psr-7-http-message-standard-php-request-response/</link>
					<comments>https://www.cesarebordi.it/psr-7-http-message-standard-php-request-response/#respond</comments>
		
		<dc:creator><![CDATA[cesarebordi]]></dc:creator>
		<pubDate>Wed, 23 Sep 2020 07:27:42 +0000</pubDate>
				<category><![CDATA[Lezioni]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[best practice]]></category>
		<category><![CDATA[developer]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[php-fig]]></category>
		<category><![CDATA[phpfig]]></category>
		<category><![CDATA[psr]]></category>
		<category><![CDATA[psr-7]]></category>
		<category><![CDATA[psr7]]></category>
		<category><![CDATA[standard]]></category>
		<category><![CDATA[web developer]]></category>
		<category><![CDATA[webservice]]></category>
		<guid isPermaLink="false">https://www.cesarebordi.it/?p=1273</guid>

					<description><![CDATA[<p>PSR-7 Http Message del PHP-FIG propone interfacce php standard per rappresentare i messaggi Http di Request e Response.</p>
<p>L'articolo <a href="https://www.cesarebordi.it/psr-7-http-message-standard-php-request-response/">PSR-7 Http Message: standard php per Request e Response.</a> sembra essere il primo su <a href="https://www.cesarebordi.it">Cesare Bordi | Innovation Manager &amp; Back-end Developer</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p><strong>PSR-7 Http Message</strong> del PHP-FIG propone interfacce <strong>php</strong> standard per rappresentare i <strong>messaggi Http</strong> di <strong>Request</strong> e <strong>Response</strong> oltre ad analizzarne il contenuto.</p>



<blockquote class="wp-block-quote"><p>HTTP messages are the foundation of web development.</p></blockquote>



<p>Standardizzare questo aspetto è importantissimo poiché i messaggi Http sono le fondamenta dello sviluppo web. I browser ed i client come cURL inviano <strong>richieste Http</strong> al server che fornisce un&#8217;adeguata <strong>risposta Http</strong>.</p>



<p>Di seguito analizzeremo le interfacce proposte dal <a href="https://www.php-fig.org/psr/psr-7/" target="_blank" rel="noreferrer noopener">PSR-7</a> che rappresentano astrazioni dei messaggi Http e degli elementi che li compongono. Per il significato delle parole chiave presenti nell&#8217;articolo si rimanda alle <a href="https://www.cesarebordi.it/psr-1-regole-scrittura-codice-php/#note" target="_blank" rel="noreferrer noopener">note dell’articolo sul PSR-1</a>.</p>



<h2 class="wp-block-heading">Http Request</h2>



<p>Iniziamo esaminando il contenuto di una <strong>Http Request</strong>.</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: plain; gutter: false; title: ; notranslate">
POST /path HTTP/1.1
Host: example.com

foo=bar&amp;baz=bat
</pre></div>


<p>La prima riga,  detta &#8220;request line&#8221;, contiene il <strong>metodo della richiesta Http</strong>, il <strong>target della richiesta Http</strong>, solitamente una URI assoluta o un percorso sul server web, la <strong>versione del protocollo Http</strong> utilizzato. A questo seguono una o più <strong>intestazioni Http</strong>, una riga vuota ed il <strong>corpo del messaggio</strong>.</p>



<h2 class="wp-block-heading">Http Response</h2>



<p>Esaminiamo ora il contenuto di una <strong>Http Response</strong>.</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: plain; gutter: false; title: ; notranslate">
HTTP/1.1 200 OK
Content-Type: text/plain

This is the response body
</pre></div>


<p>La prima riga di una <strong>Http Response</strong>, detta &#8220;status line&#8221;, contiene la <strong>versione del protocollo Http</strong>, il <strong>codice di stato Http</strong> ed una <strong>descrizione comprensibile</strong> del codice di stato. Come per il messaggio di richiesta, questa riga è seguita da una o più <strong>intestazioni Http</strong>, una riga vuota ed il <strong>corpo del messaggio</strong>.</p>



<h2 class="wp-block-heading">PSR-7: specifiche</h2>



<h3 class="wp-block-heading">Messaggi Http</h3>



<p>Un <strong>messaggio Http</strong> è una richiesta da un client ad un server o una risposta da un server ad un client. PSR-7 definisce le rispettive interfacce per i messaggi Http: <strong><em><code>Psr\Http\Message\RequestInterface</code></em></strong> e <strong><em><code>Psr\Http\Message\ResponseInterface</code></em></strong>.</p>



<p>Entrambe estendono <strong><em><code>Psr\Http\Message\MessageInterface</code></em></strong>.<br />Mentre <strong><em><code>&lt;a href=&quot;#MessageInterface&quot;&gt;Psr\Http\Message\MessageInterface&lt;/a&gt;</code></em></strong> <strong>PUÒ essere implementato</strong> direttamente, gli implementatori <strong>DOVREBBERO implementare</strong> <strong><em><code>Psr\Http\Message\RequestInterface</code></em></strong> e <strong><em><code>Psr\Http\Message\ResponseInterface</code></em></strong>.<br />Per migliorare la lettura dell&#8217;articolo, da qui in avanti verrà omesso il namespace <em><code>Psr\Http\Message</code></em> per riferirsi a queste interfacce.</p>



<h3 class="wp-block-heading">HTTP Headers</h3>



<h4 class="wp-block-heading">Nomi case-insensitive nei campi di intestazione.</h4>



<p>I <strong>messaggi Http</strong> possono includere vari campi nell&#8217;intestazione (header) <strong>senza distinzione tra maiuscole e minuscole</strong>. Allo stesso modo dovranno essere recuperate dalle classi che implementano <code>&lt;strong&gt;&lt;em&gt;&lt;a href=&quot;#MessageInterface&quot;&gt;MessageInterface&lt;/a&gt;&lt;/em&gt;&lt;/strong&gt;</code>. <br />Ad esempio, il recupero dell&#8217;intestazione <code>foo</code> restituirà lo stesso risultato del recupero dell&#8217;intestazione <code>FoO</code>. Allo stesso modo, l&#8217;impostazione dell&#8217;intestazione <code>Foo</code> sovrascriverà qualsiasi valore di intestazione <code>foo</code> precedentemente impostato.</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: php; title: ; notranslate">
$message = $message-&gt;withHeader('foo', 'bar');

echo $message-&gt;getHeaderLine('foo');
// Outputs: bar

echo $message-&gt;getHeaderLine('FOO');
// Outputs: bar

$message = $message-&gt;withHeader('fOO', 'baz');

echo $message-&gt;getHeaderLine('foo');
// Outputs: baz
</pre></div>


<p>Nonostante le intestazioni possano essere recuperate senza distinzione tra maiuscole e minuscole, <strong>il case originale DEVE essere rispettato</strong> nell&#8217;implementazione, in particolar modo quando viene recuperato con <code>getHeaders()</code>. Questo perché applicazioni Http non conformi possono dipendere da un determinato caso.</p>



<h4 class="wp-block-heading">Campi di intestazione con valori multipli</h4>



<p>Per gestire campi di intestazione con più valori e fornire una migliore flessibilità nella gestione, le intestazioni possono essere recuperate da un&#8217;istanza di <code>&lt;strong&gt;&lt;em&gt;MessageInterface&lt;/em&gt;&lt;/strong&gt;</code> come array o stringa. Nel primo caso useremo <code>&lt;strong&gt;getHeader()&lt;/strong&gt;</code>, nel secondo <code>&lt;strong&gt;getHeaderLine()&lt;/strong&gt;</code>. </p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: php; title: ; notranslate">
$message = $message
    -&gt;withHeader('foo', 'bar')
    -&gt;withAddedHeader('foo', 'baz');

$header = $message-&gt;getHeaderLine('foo');
// $header contiene: 'bar,baz'

$header = $message-&gt;getHeader('foo');
// &#x5B;'bar', 'baz']
</pre></div>


<p>Da notare che non tutti i valori di intestazione possono essere concatenati con la virgola (es: Set-Cookie). In questo caso gli utilizzatori <strong>DOVREBBERO usare metodo <code>getHeader()</code></strong> per recuperare tali intestazioni multivalore.</p>



<h4 class="wp-block-heading">Intestazione &#8220;Host&#8221;</h4>



<p>Nelle richieste, l&#8217;intestazione <code>Host</code> riporta l&#8217;host dell&#8217;URI, nonché l&#8217;host utilizzato per stabilire la connessione Tcp. Le specifiche del protocollo Http consentono però all&#8217;intestazione <code>Host</code> di differire da entrambi. Le implementazioni, se non viene fornita alcuna intestazione <code>Host</code>, <strong>DEVONO tentare di impostarla da un URI predefinito</strong> .</p>



<p><code>&lt;strong&gt;RequestInterface :: withUri (UriInterface $uri, $preserveHost = false)&lt;/strong&gt;</code>, per impostazione predefinita, sostituirà l&#8217;intestazione Host della richiesta restituita con quella dell&#8217;oggetto di tipo <code>&lt;strong&gt;UriInterface&lt;/strong&gt;</code> passatogli. Per mantenere il valore originale basterà passare <code>true</code> al secondo argomento (<code>$preservHost</code>). Ciò manterrà invariata l&#8217;intestazione Host a patto che il messaggio ne contenga una.</p>



<p>Questa tabella mostra cosa restituirà <code>getHeaderLin(&#039;Host&#039;)</code> per una richiesta restituita da <code>withUri()</code> con l&#8217;argomento <code>$preservHost</code> impostato su <code>true</code> in varie richieste iniziali e URI.</p>



<table>
  <thead>
    <tr>
      <th>Request Host header<sup>1</sup></th>
      <th>Request host component<sup>2</sup></th>
      <th>URI host component<sup>3</sup></th>
      <th>Result</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>’’</td>
      <td>’’</td>
      <td>’’</td>
      <td>’’</td>
    </tr>
    <tr>
      <td>’’</td>
      <td>foo.com</td>
      <td>’’</td>
      <td>foo.com</td>
    </tr>
    <tr>
      <td>’’</td>
      <td>foo.com</td>
      <td>bar.com</td>
      <td>foo.com</td>
    </tr>
    <tr>
      <td>foo.com</td>
      <td>’’</td>
      <td>bar.com</td>
      <td>foo.com</td>
    </tr>
    <tr>
      <td>foo.com</td>
      <td>bar.com</td>
      <td>baz.com</td>
      <td>foo.com</td>
    </tr>
  </tbody>
</table>



<ol><li>Valore dell&#8217;intestazione host prima dell&#8217;operazione.</li><li>Componente host dell&#8217;URI composto nella richiesta prima dell&#8217;operazione.</li><li>Componente host dell&#8217;URI settato tramite <code>withUri()</code>.</li></ol>



<h3 class="wp-block-heading">Streams</h3>



<p>I messaggi Http sono costituiti da una riga iniziale, alcune intestazioni ed un corpo che può essere anche molto grande. Rappresentare il body di un messaggio come una stringa potrebbe consumare molta memoria fino a precludere la possibiltà di lavorare con body di grandi dimensioni. <code>&lt;strong&gt;StreamInterface&lt;/strong&gt;</code> viene utilizzato proprio per nascondere i dettagli di implementazione quando un flusso di dati viene letto o scritto. Per le situazioni in cui una stringa sarebbe un&#8217;implementazione del messaggio appropriata, è possibile utilizzare flussi incorporati come <code>php://memory</code> e <code>php://temp</code>.<br /><br /><strong><code>StreamInterface</code></strong> espone diversi metodi che consentono di leggere, scrivere e scorrere gli stream in modo efficace.<br /><br />Gli stram espongono le loro capacità utilizzando tre metodi: <strong><code>isReadable()</code></strong>, <code>&lt;strong&gt;isWritable()&lt;/strong&gt;</code> e <code>&lt;strong&gt;isSeekable()&lt;/strong&gt;</code>. Gli oggetti che vogliono utilizzare uno stream possono utilizzare questi metodi per determinare se è in grado di soddisfare determinati requisiti.<br /><br />Ogni istanza di uno stream avrà diverse funzionalità: può essere di sola lettura, di sola scrittura o di lettura/scrittura. Può consentire un accesso casuale arbitrario (ricerca in avanti o indietro in qualsiasi posizione) o solo accesso sequenziale come nel caso di socket, pipe, o callback-based stream.<br /><br />Infine, <strong><code>StreamInterface</code></strong> definisce un metodo <strong><code>__toString()</code></strong> per recuperare o inviare l&#8217;intero contenuto del corpo in una sola volta.<br /><br />A differenza delle interfacce di Request e Response, <strong><code>StreamInterface</code></strong> interagisce con gli stream che, per loro natura, possono mutare durante il loro utilizzo. La raccomandazione di Php-Fig è di utilizzare flussi di sola lettura per le richieste lato server e le risposte lato client.</p>



<h3 class="wp-block-heading">Target della richiesta ed URI</h3>



<p>Secondo lo standard <a rel="noreferrer noopener" href="https://tools.ietf.org/html/rfc7230" target="_blank">RFC 7230</a> i messaggi di richiesta contengono uno dei seguenti tipi di &#8220;target&#8221;:</p>



<ul><li><strong>origin-form</strong>: costituito da <strong>percorso</strong> e, se presente, <strong>stringa della query</strong>. È solitamente definito come un URL relativo. I messaggi trasmessi via Tcp sono tipicamente di tipo <em>origin-form</em>; i dati di <em>scheme</em> e <em>authority</em> sono presenti tramite variabili CGI.</li><li><strong>absolute-form</strong>: costituito da <strong>scheme</strong>, <strong>authority</strong> (“[user-info@]host[:port]”, dove gli elementi tra parentesi sono facoltativi), <strong>percorso</strong> (se presente), <strong>stringa della query</strong> (se presente) e<strong> fragment</strong> ( se presente). È solitamente definito come un URI assoluto ed è l&#8217;unico che consente di specificare una URI come descritto nel <a rel="noreferrer noopener" href="https://tools.ietf.org/html/rfc3986" target="_blank">RFC 3986</a>. Questo modulo è comunemente usato quando si effettuano richieste ai proxy Http</li><li><strong>authority-form</strong>: costituito dalla sola <strong>authority.</strong> È solitamente utilizzato nelle CONNECT Request per stabilire una connessione tra un client Http e un server proxy.</li><li><strong>asterisk-form</strong>: costituito unicamente dalla <strong>stringa asterisco</strong> ( &#8221; * &#8221; ). È solitamente utilizzato con il <strong>metodo OPTIONS</strong> per determinare le capacità generali di un server web.</li></ul>



<p>Oltre a questi target di richiesta, c&#8217;è spesso un &#8220;URL effettivo&#8221; che è separato dal target di richiesta. L&#8217;URL effettivo non viene trasmesso all&#8217;interno di un messaggio Http, ma viene utilizzato per determinare il protocollo (http / https), la porta e l&#8217;host-name per effettuare la richiesta.</p>



<p>L&#8217;URL effettivo è rappresentato da <code>&lt;strong&gt;UriInterface&lt;/strong&gt;</code>. <code>UriInterface</code> rappresenta gli URI Http e Https fornendo i metodi per interagire con le varie parti dell&#8217;URI evitendo un&#8217;analisi ripetuta dell&#8217;URI. Specifica inoltre un metodo <code>__toString()</code> per rappresentare la URI come stringa.</p>



<p>Quando si recupera la destinazione della richiesta con <code>&lt;strong&gt;getRequestTarget()&lt;/strong&gt;</code>, per impostazione predefinita questo metodo utilizzerà l&#8217;oggetto URI ed estrarrà tutti i componenti necessari per costruire l&#8217;origin-form che è il request-target più comune.</p>



<p>Se si desidera utilizzare uno degli altri tre tipi di target o se l&#8217;utente desidera sovrascrivere esplicitamente il target della richiesta si utilizzerà il metodo <code>&lt;strong&gt;withRequestTarget()&lt;/strong&gt;</code>. La chiamata a questo metodo non influisce sull&#8217;URI, poiché viene restituito da <code>&lt;strong&gt;getUri()&lt;/strong&gt;</code>.</p>



<p>Ad esempio, un utente potrebbe voler effettuare una richiesta in formato asterisco a un server:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: php; gutter: false; title: ; notranslate">
$request = $request
    -&gt;withMethod('OPTIONS')
    -&gt;withRequestTarget('*')
    -&gt;withUri(new Uri('https://example.org/'));
</pre></div>


<p>L&#8217;esempio creerebbe questo tipo di richiesta Http:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: plain; title: ; notranslate">
OPZIONI * HTTP / 1.1
</pre></div>


<p>Il client Http sarà poi in grado di utilizzare l&#8217;URL effettivo (<code>getUri()</code>) per determinare il protocollo, l&#8217;host-name e la porta Tcp.</p>



<p>Un client Http <strong>DEVE</strong> ignorare i valori di <code>&lt;strong&gt;Uri::getPath()&lt;/strong&gt;</code> e <code>&lt;strong&gt;Uri::getQuery()&lt;/strong&gt;</code> ed utilizzare il valore restituito da <code>&lt;strong&gt;getRequestTarget()&lt;/strong&gt;</code> che concatena questi due valori.</p>



<p>I client che scelgono di non implementare 1 o più dei 4 request-target form, <strong>DEVONO</strong> comunque utilizzare <code>&lt;strong&gt;getRequestTarget()&lt;/strong&gt;</code>. Questi client <strong>DEVONO</strong> rifiutare <strong>request-target</strong> che non supportano e <strong>NON DEVONO</strong> utilizzare i valori di <code>&lt;strong&gt;getUri()&lt;/strong&gt;</code>.</p>



<p><code>&lt;strong&gt;RequestInterface&lt;/strong&gt;</code> fornisce metodi per recuperare il target della richiesta o creare una nuova istanza specificando il target. Per impostazione predefinita, se non viene specificato il request-target, <code>&lt;strong&gt;getRequestTarget()&lt;/strong&gt;</code> restituirà l&#8217;origin-form della URI composta o &#8221; / &#8221; se non è stata composta una URI. <strong><code>withRequestTarget($requestTarget</code>)</strong> crea una nuova istanza con il request-target specificato ed è utile per creare connessioni verso un server.</p>



<h3 class="wp-block-heading">Richieste Server-side</h3>



<ul><li><code>&lt;strong&gt;RequestInterface&lt;/strong&gt;</code> permette di rappresentare un messaggio di richiesta Http, ma le richieste lato server side richiedono un&#8217;attenzione particolare. I processi server-side devono tener conto della Common Gateway Interface (CGI) e dell&#8217;interazione di PHP con essa attraverso le sue via Server API (SAPI) . PHP ci fornisce una semplificazione per la gestione degli input attraverso variabili superglobali:</li><li><code>&lt;strong&gt;$_COOKIE&lt;/strong&gt;</code>: deserializza e fornisce un accesso ai cookie Http.</li><li><code>&lt;strong&gt;$_GET&lt;/strong&gt;</code>: deserializza e fornisce un accesso agli argomenti della query string.</li><li><strong><code>$_POST</code></strong>: deserializza e fornisce un accesso per i parametri inviati tramite. Post Http. Può essere considerato il risultato dell&#8217;analisi del message body.</li><li><strong><code>$_FILES</code></strong>: fornisce metadati relativi ai caricamenti dei file.</li><li><strong><code>$_SERVER</code></strong>: fornisce l&#8217;accesso alle variabili d&#8217;ambiente CGI / SAPI che includono il metodo di richiesta, lo schema di richiesta, l&#8217;URI della richiesta e le intestazioni.</li></ul>



<p><strong><code>ServerRequestInterface</code></strong> estende <strong><code>RequestInterface</code></strong> per fornire un&#8217;astrazione su questi variabili superglobali riducendo l&#8217;accoppiamento.<br /><br />La richiesta server-side fornisce una proprietà aggiuntiva,  gli &#8220;attributi&#8221;, che consentono di esaminare, scompore e cercare match in modo da interpretare la richiesta in base alle specifiche necessità nell&#8217;applicativo.</p>



<h3 class="wp-block-heading">Upload dei file</h3>



<p><code>&lt;strong&gt;ServerRequestInterface&lt;/strong&gt;</code> specifica un metodo per recuperare una rappresentazione dei file caricati attraverso una struttura normalizzata in cui ogni elemento è un&#8217;istanza di <code>&lt;strong&gt;UploadedFileInterface&lt;/strong&gt;</code>.</p>



<p><strong><code>$_FILES</code></strong> ha alcuni problemi noti, ad esempio se si tenta di inviare da un form molteplici file attraverso campi di input aventi name &#8220;files&#8221;, l&#8217;array risultante verrà così rappresentato da PHP:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: php; gutter: false; title: ; notranslate">
array(
    'files' =&gt; array(
        'name' =&gt; array(
            0 =&gt; 'file0.txt',
            1 =&gt; 'file1.html',
        ),
        'type' =&gt; array(
            0 =&gt; 'text/plain',
            1 =&gt; 'text/html',
        ),
        /* etc. */
    ),
)
</pre></div>


<p>Mentre ci si aspetterebbe una rappresentazione di questo tipo:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: php; gutter: false; title: ; notranslate">
array(
    'files' =&gt; array(
        0 =&gt; array(
            'name' =&gt; 'file0.txt',
            'type' =&gt; 'text/plain',
            /* etc. */
        ),
        1 =&gt; array(
            'name' =&gt; 'file1.html',
            'type' =&gt; 'text/html',
            /* etc. */
        ),
    ),
)
</pre></div>


<p>Gli utilizzatori devono conoscere quindi i dettagli dell&#8217;implementazione nel linguaggio PHP e scrivere il codice per interpretare correttamente i dati di un determinato caricamento. </p>



<p>In alcuni casi poi <code>$_FILES</code> non viene popolato con i dati relativi ai file caricati:</p>



<ul><li>Quando il metodo Http non è POST.</li><li>Quando si esegue una unit test.</li><li>Quando si opera in un ambiente non SAPI come ad esempio ReactPHP.</li></ul>



<p>In questi casi si dovranno utilizzare approcci diversi, ad esempio:</p>



<ul><li>Un processo potrebbe analizzare il message body per scoprire i file caricati. </li><li>Negli scenari di unit test, gli sviluppatori devono essere in grado di bloccare e/o simulare i metadati di caricamento del file per convalidare e verificare i diversi scenari.</li></ul>



<p><code>&lt;strong&gt;getUploadedFiles()&lt;/strong&gt;</code> fornisce una struttura normalizzata e l&#8217;implementazione dovrebbe:</p>



<ul><li>Aggregare tutte le informazioni per un determinato caricamento di file e usarle per popolare un&#8217;istanza<code> &lt;strong&gt;Psr\Http\Message\UploadedFileInterface&lt;/strong&gt;</code>.</li><li>Ricreare la struttura ad albero inviata in cui ogni foglia rappresenti un&#8217;istanza di <code>&lt;strong&gt;Psr\Http\Message\UploadedFileInterface&lt;/strong&gt;</code> appropriata.</li><li>La struttura ad albero dovrebbe seguire la struttura dei nomi in cui sono stati inviati i file.</li></ul>



<p>Vediamo un esempio con un singolo campo di input con un &#8220;name semplice&#8221;:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: xml; gutter: false; title: ; notranslate">
&lt;input type=&quot;file&quot; name=&quot;avatar&quot; /&gt;
</pre></div>


<p>In questo caso, la struttura di $ _FILES sarebbe:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: php; gutter: false; title: ; notranslate">
array(
    'avatar' =&gt; array(
        'tmp_name' =&gt; 'phpUxcOty',
        'name' =&gt; 'my-avatar.png',
        'size' =&gt; 90996,
        'type' =&gt; 'image/png',
        'error' =&gt; 0,
    ),
)
</pre></div>


<p>Mentre la forma normalizzata restituita da <code>getUploadedFiles()</code> potrebbe essere:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: php; gutter: false; title: ; notranslate">
array(
    'avatar' =&gt; /* UploadedFileInterface instance */
)
</pre></div>


<p>Vediamo invece un caso di campo di input che utilizza crea un array nell&#8217;attributo nome:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: xml; gutter: false; title: ; notranslate">
&lt;input type=&quot;file&quot; name=&quot;my-form&#x5B;details]&#x5B;avatar]&quot; /&gt;
</pre></div>


<p>In questo caso il contenuto di $_FILES sarà</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: php; gutter: false; title: ; notranslate">
array (
    'my-form' =&gt; array (
        'name' =&gt; array (
            'details' =&gt; array (
                'avatar' =&gt; 'my-avatar.png',
            ),
        ),
        'type' =&gt; array (
            'details' =&gt; array (
                'avatar' =&gt; 'image/png',
            ),
        ),
        'tmp_name' =&gt; array (
            'details' =&gt; array (
                'avatar' =&gt; 'phpmFLrzD',
            ),
        ),
        'error' =&gt; array (
            'details' =&gt; array (
                'avatar' =&gt; 0,
            ),
        ),
        'size' =&gt; array (
            'details' =&gt; array (
                'avatar' =&gt; 90996,
            ),
        ),
    ),
)
</pre></div>


<p>E l&#8217;albero corrispondente restituito da <code>getUploadedFiles()</code> dovrebbe essere:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: php; gutter: false; title: ; notranslate">
array(
    'my-form' =&gt; array(
        'details' =&gt; array(
            'avatar' =&gt; /* UploadedFileInterface instance */
        ),
    ),
)
</pre></div>


<p>Vediamo ora il caso di un array di file:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: xml; gutter: false; title: ; notranslate">
Upload an avatar: &lt;input type=&quot;file&quot; name=&quot;my-form&#x5B;details]&#x5B;avatars]&#x5B;]&quot; /&gt;
Upload an avatar: &lt;input type=&quot;file&quot; name=&quot;my-form&#x5B;details]&#x5B;avatars]&#x5B;]&quot; /&gt;
</pre></div>


<p>Ecco cosa conterrà <code>$_FILES</code>:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: php; gutter: false; title: ; notranslate">
array (
    'my-form' =&gt; array (
        'name' =&gt; array (
            'details' =&gt; array (
                'avatar' =&gt; array (
                    0 =&gt; 'my-avatar.png',
                    1 =&gt; 'my-avatar2.png',
                    2 =&gt; 'my-avatar3.png',
                ),
            ),
        ),
        'type' =&gt; array (
            'details' =&gt; array (
                'avatar' =&gt; array (
                    0 =&gt; 'image/png',
                    1 =&gt; 'image/png',
                    2 =&gt; 'image/png',
                ),
            ),
        ),
        'tmp_name' =&gt; array (
            'details' =&gt; array (
                'avatar' =&gt; array (
                    0 =&gt; 'phpmFLrzD',
                    1 =&gt; 'phpV2pBil',
                    2 =&gt; 'php8RUG8v',
                ),
            ),
        ),
        'error' =&gt; array (
            'details' =&gt; array (
                'avatar' =&gt; array (
                    0 =&gt; 0,
                    1 =&gt; 0,
                    2 =&gt; 0,
                ),
            ),
        ),
        'size' =&gt; array (
            'details' =&gt; array (
                'avatar' =&gt; array (
                    0 =&gt; 90996,
                    1 =&gt; 90996,
                    3 =&gt; 90996,
                ),
            ),
        ),
    ),
)
</pre></div>


<p>L&#8217;array sopra riportato corrisponderebbe alla seguente struttura restituita da <code>&lt;strong&gt;getUploadedFiles()&lt;/strong&gt;</code>:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: php; gutter: false; title: ; notranslate">
array(
    'my-form' =&gt; array(
        'details' =&gt; array(
            'avatars' =&gt; array(
                0 =&gt; /* UploadedFileInterface instance */,
                1 =&gt; /* UploadedFileInterface instance */,
                2 =&gt; /* UploadedFileInterface instance */,
            ),
        ),
    ),
)
</pre></div>


<p>Per accedere all&#8217;elemento [1]:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: php; gutter: false; title: ; notranslate">
$request-&gt;getUploadedFiles()&#x5B;'my-form']&#x5B;'details']&#x5B;'avatars']&#x5B;1];
</pre></div>


<p>Seguendo il nostro esempio avremo:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: php; gutter: false; title: ; notranslate">
$file0 = $request-&gt;getUploadedFiles()&#x5B;'files']&#x5B;0];
$file1 = $request-&gt;getUploadedFiles()&#x5B;'files']&#x5B;1];

printf(
    &quot;Received the files %s and %s&quot;,
    $file0-&gt;getClientFilename(),
    $file1-&gt;getClientFilename()
);
</pre></div>


<p>Poiché le inforazioni sui file caricati, oltre che da <code>$_FILES</code>, possono derivare da altri elementi della richiesta,  è presente il metodo <code>&lt;strong&gt;withUploadedFiles()&lt;/strong&gt;</code> che consente di delegare la normalizzazione ad un altro processo.</p>



<p>Lo standard PSR-7 considera anche le implementazioni in ambienti non SAPI. Pertanto, <code>UploadedFileInterface</code> fornisce metodi per garantire che le operazioni funzionino indipendentemente dall&#8217;ambiente. In particolare:</p>



<ul><li><strong><code>moveTo($targetPath)</code></strong> viene fornito come alternativa sicura e consigliata per richiamare <code>move_uploaded_file()</code> sul file di caricamento temporaneo. Le implementazioni rileveranno il corretto funzionamento da utilizzare in base all&#8217;ambiente.</li><li><code>&lt;strong&gt;getStream()&lt;/strong&gt;</code> restituirà un&#8217;istanza <code>StreamInterface</code>. In ambienti non SAPI, una possibilità proposta è quella di eseguire il parsing dei file caricati nello stream <code>php://temp</code>.</li></ul>



<p>Ad esempio:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: php; gutter: false; title: ; notranslate">
// Move a file to an upload directory
$filename = sprintf(
    '%s.%s',
    create_uuid(),
    pathinfo($file0-&gt;getClientFilename(), PATHINFO_EXTENSION)
);
$file0-&gt;moveTo(DATA_DIR . '/' . $filename);

// Stream a file to Amazon S3.
// Assume $s3wrapper is a PHP stream that will write to S3, and that
// Psr7StreamWrapper is a class that will decorate a StreamInterface as a PHP
// StreamWrapper.
$stream = new Psr7StreamWrapper($file1-&gt;getStream());
stream_copy_to_stream($stream, $s3wrapper);
</pre></div>


<h2 class="wp-block-heading">PSR-7: Interfacce</h2>



<h3><a name="MessageInterface"></a>Psr\Http\Message\MessageInterface</h3>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: php; title: ; notranslate">
interface MessageInterface {
    /**
     * Recupera la versione del protocollo HTTP (Es: &quot;1.1&quot;, &quot;1.0&quot;)
     *
     * @return string HTTP protocol version.
     */
    public function getProtocolVersion();

    /**
     * Restituisce un'istanza con una specifica versione del protocollo HTTP
     *
     * @param string $version HTTP protocol version
     * @return static
     */
    public function withProtocolVersion($version);

    /**
     * Recupera tutti i valori di intestazione del messaggio
     *
     * @return string&#x5B;]&#x5B;] Returns an associative array of the message's headers.
     */
    public function getHeaders();

    /**
     * Verifica se esiste un'intestazione in base al nome senza distinzione tra maiuscole e minuscole.
     *
     * @param string $name Case-insensitive header field name.
     * @return bool
     */
    public function hasHeader($name);

    /**
     * Recupera un valore di intestazione del messaggio in base al nome senza distinzione tra maiuscole e minuscole.
     *
     * @param string $name Case-insensitive header field name.
     * @return string&#x5B;] An array of string values as provided for the given header.
     */
    public function getHeader($name);

    /**
     * Recupera una stringa separata da virgole dei valori per una singola intestazione.
     *
     * @param string $name Case-insensitive header field name.
     * @return string A string of values as provided for the given header concatenated together using a comma.
     */
    public function getHeaderLine($name);

    /**
     * Restituisce un'istanza sostituendo il valore dell'intestazione specificata.
     *
     * @param string $name Case-insensitive header field name.
     * @param string|string&#x5B;] $value Header value(s).
     * @return static
     * @throws \InvalidArgumentException for invalid header names or values.
     */
    public function withHeader($name, $value);

    /**
     * Restituisce un'istanza appendendo un valore al campo di intestazione specificato.
     *
     * @param string $name Case-insensitive header field name to add.
     * @param string|string&#x5B;] $value Header value(s).
     * @return static
     * @throws \InvalidArgumentException for invalid header names or values.
     */
    public function withAddedHeader($name, $value);

    /**
     * Restituisce un'istanza eliminando l'intestazione specificata.
     *
     * @param string $name Case-insensitive header field name to remove.
     * @return static
     */
    public function withoutHeader($name);

    /**
     * Ottiene il corpo del messaggio.
     *
     * @return StreamInterface Returns the body as a stream.
     */
    public function getBody();

    /**
     * Restituisce un'istanza con il corpo del messaggio specificato.
     *   
     * @param StreamInterface $body Body.
     * @return static
     * @throws \InvalidArgumentException When the body is not valid.
     */
    public function withBody(StreamInterface $body);
}
</pre></div>


<p></p>
<p>L'articolo <a href="https://www.cesarebordi.it/psr-7-http-message-standard-php-request-response/">PSR-7 Http Message: standard php per Request e Response.</a> sembra essere il primo su <a href="https://www.cesarebordi.it">Cesare Bordi | Innovation Manager &amp; Back-end Developer</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.cesarebordi.it/psr-7-http-message-standard-php-request-response/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Guida ai comandi Linux più utilizzati da Terminale</title>
		<link>https://www.cesarebordi.it/linux-shell-comandi-piu-utilizzati/</link>
					<comments>https://www.cesarebordi.it/linux-shell-comandi-piu-utilizzati/#respond</comments>
		
		<dc:creator><![CDATA[cesarebordi]]></dc:creator>
		<pubDate>Fri, 05 Jun 2020 09:46:00 +0000</pubDate>
				<category><![CDATA[Server]]></category>
		<category><![CDATA[attività sistemistica]]></category>
		<category><![CDATA[console]]></category>
		<category><![CDATA[find]]></category>
		<category><![CDATA[linux]]></category>
		<category><![CDATA[mkdir]]></category>
		<category><![CDATA[script]]></category>
		<category><![CDATA[server]]></category>
		<category><![CDATA[shell]]></category>
		<category><![CDATA[shutdown]]></category>
		<category><![CDATA[terminale]]></category>
		<category><![CDATA[touch]]></category>
		<category><![CDATA[web developer]]></category>
		<category><![CDATA[webserver]]></category>
		<category><![CDATA[wget]]></category>
		<category><![CDATA[zip]]></category>
		<guid isPermaLink="false">http://www.cesarebordi.it/?p=287</guid>

					<description><![CDATA[<p>Una utile guida ai comandi linux da terminale più utilizzati dai web developer che devono svolgere attività sistemistiche o di controllo su server linux utilizzando la console. Guida...</p>
<p>L'articolo <a href="https://www.cesarebordi.it/linux-shell-comandi-piu-utilizzati/">Guida ai comandi Linux più utilizzati da Terminale</a> sembra essere il primo su <a href="https://www.cesarebordi.it">Cesare Bordi | Innovation Manager &amp; Back-end Developer</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p>Una utile<strong> guida ai comandi linux da terminale </strong>più utilizzati dai <strong>web developer</strong> che devono svolgere <strong>attività sistemistiche</strong> o di controllo su <strong>server linux</strong> utilizzando la <strong>console</strong>.</p>



<span id="more-287"></span>



<h2 class="wp-block-heading">Guida comandi linux</h2>



<figure class="wp-block-table is-style-regular"><table><thead><tr><th class="has-text-align-left" data-align="left">COMANDO</th><th>UTILIZZO</th></tr></thead><tbody><tr><td class="has-text-align-left" data-align="left" colspan="2"><strong><mark style="background-color:#afcb08" class="has-inline-color">INFO SUL SISTEMA</mark></strong></td></tr><tr><td class="has-text-align-left" data-align="left">uname -m</td><td>mostra l&#8217;architettura del sistema</td></tr><tr><td class="has-text-align-left" data-align="left">uname -r</td><td>mostra la versione del kernel</td></tr><tr><td class="has-text-align-left" data-align="left">cat /proc/cpuinfo</td><td>mostra info sulla CPU</td></tr><tr><td class="has-text-align-left" data-align="left">cat /proc/meminfo</td><td>mostra info sulla memoria ram</td></tr><tr><td class="has-text-align-left" data-align="left">cat /proc/cpuinfo</td><td>mostra info sulla CPU</td></tr><tr><td class="has-text-align-left" data-align="left" colspan="2"><strong><mark style="background-color:#afcb08" class="has-inline-color">ARRESTO / RIAVVIO</mark></strong></td></tr><tr><td class="has-text-align-left" data-align="left">shutdown <strong>-h</strong> now</td><td>arresto istantaneo del sistema</td></tr><tr><td class="has-text-align-left" data-align="left">shutdown <strong>-r</strong> now</td><td>riavvio istantaneo del sistema</td></tr><tr><td class="has-text-align-left" data-align="left" colspan="2"><strong><mark style="background-color:#afcb08" class="has-inline-color">OPERAZIONI DI BASE SU FILE / CARTELLE</mark></strong></td></tr><tr><td class="has-text-align-left" data-align="left">cd /percorso</td><td>si sposta nella cartella indicata</td></tr><tr><td class="has-text-align-left" data-align="left">cd ..</td><td>risalire di un livello</td></tr><tr><td class="has-text-align-left" data-align="left">cd ../..</td><td>risalire di due livelli</td></tr><tr><td class="has-text-align-left" data-align="left">cp file1 file2</td><td>copiare un file</td></tr><tr><td class="has-text-align-left" data-align="left">cp -a dir1 dir2</td><td>copiare una directory</td></tr><tr><td class="has-text-align-left" data-align="left">rsync -av /path/sorgente/ /path/destinazione/</td><td>copia una directory e tutto il suo contenuto mantenendo i permessi e la proprietà dei file</td></tr><tr><td class="has-text-align-left" data-align="left">ln -s file1 lnk1</td><td>creare un link simbolico al file(o directory) &#8216;file1&#8217; chiamato lnk1</td></tr><tr><td class="has-text-align-left" data-align="left">ln file1 lnk1</td><td>creare un link fisico al file(o directory) &#8216;file1&#8217; chiamato lnk1</td></tr><tr><td class="has-text-align-left" data-align="left">ls -lh</td><td>visualizzare contenuto della directory</td></tr><tr><td class="has-text-align-left" data-align="left">ls -Flh (reverse: -Flhr)</td><td>distingue file e directory</td></tr><tr><td class="has-text-align-left" data-align="left">ls -Slh (reverse: -Slhr)</td><td>ordina per dimensione</td></tr><tr><td class="has-text-align-left" data-align="left">ls -a</td><td>visualizza file nascosti</td></tr><tr><td class="has-text-align-left" data-align="left">tree /percorso</td><td>visualizza file e directory in una rappresentazione ad albero</td></tr><tr><td class="has-text-align-left" data-align="left">mkdir dir1</td><td>creare la directory &#8216;dir1&#8217;</td></tr><tr><td class="has-text-align-left" data-align="left">mkdir dir1 dir2</td><td>creare due directory contemporaneamente</td></tr><tr><td class="has-text-align-left" data-align="left">mkdir -p /dir1/dir2</td><td>creare un albero di directory</td></tr><tr><td class="has-text-align-left" data-align="left">mv dir1 new_dir</td><td>rinominare/muovere una directory o file</td></tr><tr><td class="has-text-align-left" data-align="left">pwd</td><td>visualizzare il path della directory di lavoro</td></tr><tr><td class="has-text-align-left" data-align="left">rm -f file1</td><td>eliminare il file &#8216;file1&#8217;</td></tr><tr><td class="has-text-align-left" data-align="left">rm -rf dir1</td><td>eliminare ricorsivamente la directory &#8216;dir1&#8217; e sul contenuto</td></tr><tr><td class="has-text-align-left" data-align="left">rm -rf dir1 dir2</td><td>eliminare ricorsivamente due directory ed il loro contenuto con un solo comando</td></tr><tr><td class="has-text-align-left" data-align="left">rmdir dir1</td><td>eliminare la directory &#8216;dir1&#8217;</td></tr><tr><td class="has-text-align-left" data-align="left">find /dir1 -type f -name &#8220;*.ext&#8221; -delete</td><td>elimina tutti i file con una certa estensione cercando all&#8217;interno di una cartella e relative sottocartele.</td></tr><tr><td class="has-text-align-left" data-align="left">touch -t 1612011030 file1</td><td>modificare il timestamp di un file o directory &#8211; (YYMMDDhhmm)</td></tr><tr><td class="has-text-align-left" data-align="left">touch file1</td><td>utile pre creare un file vuoto</td></tr><tr><td class="has-text-align-left" data-align="left">touch -c file1</td><td>-c evita di creare nuovi file.</td></tr><tr><td class="has-text-align-left" data-align="left">find /percorso/ -name &#8220;file.ext&#8221; -delete</td><td>Cerca ed elimina tutti i file &#8220;file.ext&#8221; dal percorso (anche nelle sottocartelle)</td></tr><tr><td class="has-text-align-left" data-align="left" colspan="2"><strong><mark style="background-color:#afcb08" class="has-inline-color">DIMENSIONI FILE / CARTELLE</mark></strong></td></tr><tr><td class="has-text-align-left" data-align="left">df -h</td><td>visualizzare l&#8217;elenco delle partizioni montate</td></tr><tr><td class="has-text-align-left" data-align="left">du -sh dir1</td><td>conoscere lo spazio su disco occupato dalla directory &#8216;dir1&#8217;</td></tr><tr><td class="has-text-align-left" data-align="left">du -skh /percorso/* &#8211;time | sort -h</td><td>visualizzare la dimensione dei file e delle directory ordinanti per dimensione</td></tr><tr><td class="has-text-align-left" data-align="left">ls -l | wc -l</td><td>conta gli elementi presenti nella cartella in cui ci si trova</td></tr><tr><td class="has-text-align-left" data-align="left" colspan="2"><strong><mark style="background-color:#afcb08" class="has-inline-color">RINOMINARE FILE</mark></strong></td></tr><tr><td class="has-text-align-left" data-align="left">rename -n -v &#8216;s/^/PREFISSO/&#8217; *</td><td>Aggiunge un prefisso davanti al nome di i file contenuti in una cartella (NOTA:le opzioni -n -v eseguono una simulazione, rimuoverle per rendere il comando effettivo)</td></tr><tr><td class="has-text-align-left" data-align="left">rename -n -v &#8216;s/^(.{2})//&#8217; *</td><td>Rimuove i primi due caratteri dal nome di tutti i file contenuti in una cartella (NOTA:le opzioni -n -v eseguono una simulazione, rimuoverle per rendere il comando effettivo)</td></tr><tr><td class="has-text-align-left" data-align="left" colspan="2"><strong><mark style="background-color:#afcb08" class="has-inline-color">COMPRIMERE FILE</mark></strong></td></tr><tr><td class="has-text-align-left" data-align="left">zip archivio.zip file1 file2 file3</td><td>comprime file specifici nell&#8217;archivio &#8216;archivio.zip&#8217;</td></tr><tr><td class="has-text-align-left" data-align="left">zip -r archivio.zip dir1</td><td>comprime la directory &#8216;dir1&#8217; nell&#8217;archivio &#8216;archivio.zip&#8217;</td></tr><tr><td class="has-text-align-left" data-align="left">zip -r9 archivio.zip dir1</td><td>comprime la directory &#8216;dir1&#8217; nell&#8217;archivio &#8216;archivio.zip&#8217; utilizzando la compressione massima.</td></tr><tr><td class="has-text-align-left" data-align="left">unzip archivio.zip</td><td>decomprime l&#8217;archivio &#8216;archivio.zip&#8217; nella posizione corrente</td></tr><tr><td class="has-text-align-left" data-align="left" colspan="2"><strong><mark style="background-color:#afcb08" class="has-inline-color">TRASFERIMENTO FILE / DOWNLOAD / WGET</mark></strong></td></tr><tr><td class="has-text-align-left" data-align="left">wget http://www.dominio.ext/file.ext</td><td>scarica &#8216;file.ext&#8217; nella posizione corrente</td></tr><tr><td class="has-text-align-left" data-align="left">wget http://www.dominio.ext/file.ext -O nuovoNome.ext</td><td>scarica &#8216;file.ext&#8217; rinominandolo in &#8216;nuovoNome.ext&#8217;</td></tr><tr><td class="has-text-align-left" data-align="left">wget http://www.dominio.ext/file.ext</td><td>scarica in background &#8216;file.ext&#8217; nella posizione corrente</td></tr><tr><td class="has-text-align-left" data-align="left">wget -i listaFile.txt</td><td>Scarica i file contenuti nel file &#8216;listaFile.txt&#8217;</td></tr><tr><td class="has-text-align-left" data-align="left">wget &#8211;limit-rate=500k http://www.dominio.ext/file.ext</td><td>Scarica &#8216;file.ext&#8217; limitando la velocità a 500 Kb</td></tr><tr><td class="has-text-align-left" data-align="left">wget -r &#8211;ftp-user=Username &#8211;ftp-password=Password ftp://ftp.dominio.ext/&#8230;</td><td>Scarica ricorsivamente tutto il contenuto a partire dalla posizione FTP indicata.</td></tr><tr><td class="has-text-align-left" data-align="left">scp -r -P 22 user@host:/percorso/sorgente/remota/ /percorso/destinazione/locale/</td><td><strong>Secure Copy</strong> (scp) copia ricorsivamente il contenuto da un server remoto nella cartella locale (o altro server emoto).</td></tr></tbody></table></figure>
<p>L'articolo <a href="https://www.cesarebordi.it/linux-shell-comandi-piu-utilizzati/">Guida ai comandi Linux più utilizzati da Terminale</a> sembra essere il primo su <a href="https://www.cesarebordi.it">Cesare Bordi | Innovation Manager &amp; Back-end Developer</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.cesarebordi.it/linux-shell-comandi-piu-utilizzati/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Php Namespaces</title>
		<link>https://www.cesarebordi.it/php-namespaces/</link>
					<comments>https://www.cesarebordi.it/php-namespaces/#comments</comments>
		
		<dc:creator><![CDATA[cesarebordi]]></dc:creator>
		<pubDate>Thu, 16 Apr 2020 13:35:24 +0000</pubDate>
				<category><![CDATA[Articoli]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Programmazione]]></category>
		<category><![CDATA[class]]></category>
		<category><![CDATA[classi]]></category>
		<category><![CDATA[codice]]></category>
		<category><![CDATA[coding]]></category>
		<category><![CDATA[constant]]></category>
		<category><![CDATA[costanti]]></category>
		<category><![CDATA[developer]]></category>
		<category><![CDATA[esempi]]></category>
		<category><![CDATA[function]]></category>
		<category><![CDATA[funzioni]]></category>
		<category><![CDATA[guida]]></category>
		<category><![CDATA[interfacce]]></category>
		<category><![CDATA[interface]]></category>
		<category><![CDATA[namespaces]]></category>
		<category><![CDATA[oop]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[programmatore]]></category>
		<category><![CDATA[programmazione]]></category>
		<category><![CDATA[programmazione ad oggetti]]></category>
		<category><![CDATA[web developer]]></category>
		<guid isPermaLink="false">https://www.cesarebordi.it/?p=572</guid>

					<description><![CDATA[<p>I namespaces in PHP rappresentano un'innovazione ed hanno legami stretti con lo standard PSR-4 e l'autoloading delle classi.</p>
<p>L'articolo <a href="https://www.cesarebordi.it/php-namespaces/">Php Namespaces</a> sembra essere il primo su <a href="https://www.cesarebordi.it">Cesare Bordi | Innovation Manager &amp; Back-end Developer</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<div class="wp-block-group"><div class="wp-block-group__inner-container is-layout-flow wp-block-group-is-layout-flow">
<p class="has-text-align-left has-text-align-justify">L&#8217;introduzione dei <strong>namespaces </strong>in <strong>PHP</strong> rappresenta un&#8217;innovazione nel <strong>linguaggio </strong>ed ha legami stretti con lo <strong><a rel="noreferrer noopener" aria-label=" (apre in una nuova scheda)" href="https://www.php-fig.org/psr/psr-4/" target="_blank">standard PSR-4</a></strong> e l&#8217;<strong>autoloading delle classi</strong>.  A livello teorico l&#8217;argomento può sembrare semplice, ma nell&#8217;<strong>implementazione del codice</strong> non è così immediato.</p>
</div></div>



<h2 class="wp-block-heading">Cosa sono i namespaces in php?</h2>



<blockquote class="wp-block-quote"><p>What are namespaces? In the broadest definition namespaces are a way of encapsulating items.</p></blockquote>



<p>I <strong><a href="https://www.php.net/manual/en/language.namespaces.rationale.php">namespaces</a></strong>, introdotti in <strong>PHP 5.3</strong> e migliorati in<strong> PHP 7</strong>, permettono di <strong>raggruppare </strong><span style="text-decoration: underline;"><strong>classi</strong></span>, <span style="text-decoration: underline;"><strong>interfacce</strong></span>, <span style="text-decoration: underline;"><strong>funzioni</strong></span> e<strong> </strong><span style="text-decoration: underline;"><strong>costanti</strong></span> per evitare ambiguità di denominazione. In questo modo potremo far coesistere classi <span style="text-decoration: underline;">con lo stesso nome</span> &#8220;incapsulate&#8221; in namespace differenti esattamente come avviene per file con lo stesso nome posti in cartelle diverse del filesystem.  La possibilità di creare una gerarchizzazione (<strong>sub-namespace</strong>) fornisce una chiara indicazione sull&#8217;organizzazione delle risorse del nostro applicativo.  Ad esempio, assegnando i namespaces <em><strong><code>Framework\Core\Main</code></strong></em> ad un file contenente una classe e <em><strong><code>Framework\Core\Main\Libs</code></strong></em> ad un altro contenente un&#8217;altra classe con il medesimo nome, è facilmente intuibile come la prima si riferisca alle funzionalità di base del nostro ipotetico framework e l&#8217;altra sia presente in una libreria secondaria.</p>



<p>Pur essendo forte l&#8217;analaogia con il filesystem <strong>non sussite alcuna relazione diretta fra un namespace ed il percorso dei file .php</strong>. E&#8217; però intuitivo utilizzare questa analogia per creare vincoli convenzionali e sfruttarli nella pratica dell&#8217;autoloading la cui implementazione più diffusa è sintetizzata nello standard <a rel="noreferrer noopener" aria-label=" (apre in una nuova scheda)" href="https://www.php-fig.org/psr/psr-4/" target="_blank">PSR-4</a> che approfondirò in un altro articolo.</p>



<h2 class="wp-block-heading">Namespaces: vantaggi di utilizzo</h2>



<ul><li><strong>Risolvono il problema di omonimia</strong> di <span style="text-decoration: underline;">classi, interfacce, funzioni e costanti</span> tra il codice scritto dallo sviluppatore, quello integrato in librerire di terze parti e quello nativo di Php.</li><li><strong>Facilitano lo sviluppo di codice ordinato</strong>, organizzato ed &#8220;eloquente&#8221;.</li><li><strong>Migliorano la leggibilità e la scrittura del codice</strong> permettendo di utilizzare degli <strong>alias </strong>nel momento in cui la precisa ed inevitabile lunghezza del namespace non fosse necessaria.</li></ul>



<h2 class="wp-block-heading">Namespaces: dichiarazione</h2>



<p>Compresi i vantaggi  del loro utilizzo vediamo come utilizzare i namespaces iniziando dalla loro dichiarazione attraverso l&#8217;apposita <span style="text-decoration: underline;">keyword <code>&lt;strong&gt;namespace&lt;/strong&gt;</code></span>.<br />Uno script che faccia uso di namespaces deve dichiararlo all&#8217;inizio del listato fatta eccezione per i commenti ed eventuali istruzioni <em>declare</em>.</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: php; title: ; notranslate">
&lt;?php
declare(encoding='UTF-8');

// Dichiaro il namespace...
namespace Framework\Core\Main;
</pre></div>


<h3 class="wp-block-heading">Attenzione!</h3>



<ul><li>I namespaces<strong> non possono contenere keywords</strong> del linguaggio php.<br /><strong><em><code>Framework\Core\&lt;s&gt;Class&lt;/s&gt;</code></em></strong></li><li>I namespaces <strong>non possono iniziare con un numero</strong>.<br /><em><strong><code>Framework\Core\&lt;s&gt;1Class&lt;/s&gt;</code></strong></em></li><li>E&#8217; possibile, ma altamente<strong> sconsigliato, dichiarare più namespaces nello stesso file</strong> utilizzando le parentesi graffe.<br /><code>&lt;?php&lt;br /&gt;&lt;em&gt;&lt;strong&gt;Framework\Core\Main&lt;/strong&gt;&lt;/em&gt; { // codice }&lt;br /&gt;&lt;em&gt;&lt;strong&gt;Framework\Core\Libs&lt;/strong&gt;&lt;/em&gt; { // codice }</code></li></ul>



<h2 class="wp-block-heading">Php Namespaces: dalla teoria alla pratica</h2>



<p>Immaginiamo di creare ed includere due file php contenenti la dichiarazione di una classe denominata nello stesso modo (Es: <code>MyClass</code>). Una volta in esecuzione otterremmo questo errore:<br /><code>&lt;strong&gt;Fatal error&lt;/strong&gt;:  Cannot declare class MyClass, because the name is already in use</code></p>



<p>Aggiungiamo ora ai due file una dichiarazione namespace&#8230;</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: php; title: ; notranslate">
&lt;?php // File 1: /Framework/Core/Main/MyClass.php

namespace Framework\Core\Main;

Class MyClass {
    public function __construct() {
        echo '&lt;p&gt;MAIN: MyClass ready!&lt;/p&gt;';
    }
}
</pre></div>

<div class="wp-block-syntaxhighlighter-code "><pre class="brush: php; title: ; notranslate">
&lt;?php // File 2: /Framework/Core/Main/Libs/MyClass.php

namespace Framework\Core\Main\Libs;

Class MyClass {
    public function __construct() {
        echo '&lt;p&gt;LIBS: MyClass ready!&lt;/p&gt;';
    }
}
</pre></div>


<p>Creiamo ora il file principale ex01.php che li includerà e tenterà di creare un oggetto.</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: php; title: ; notranslate">
&lt;?php // File: /ex01.php

// Includo i file
require_once('Framework/Core/Main/MyClass.php');
require_once('Framework/Core/Main/Libs/MyClass.php');

// Creo l'oggetto
$objOne = New MyClass();
</pre></div>


<p>Mandandolo in esecuzione ci troveremo davanti ancora un errore&#8230;<br /><code>&lt;strong&gt;Fatal error&lt;/strong&gt;:  Uncaught Error: Class &#039;MyClass&#039; not found in...</code></p>



<p>Questo si verifica poichè le nostre due classi &#8220;MyClass&#8221; sono assegnate ai rispettivi namespaces, mentre il nostro file principale non ha alcun namespace specificato e si riferisce quindi a quello globale in cui la classe MyClass() non è definita.</p>



<h2 class="wp-block-heading">Namespaces: tipi di riferimento</h2>



<p>Sappiamo definire i namespaces, ma per richiamarli correttamente dobbiamo conoscere quali sono i <strong>tipi di riferimento</strong> che possiamo utilizzare e che nuovamente hanno una forte analogia con i percorsi dei filesystem:</p>



<ul><li><strong>Unqualified name</strong> (nomi non qualificati): si riferiscono solo al namespace corrente.  È come cercare un fille nella cartella in cui ci si trova.<br /><code>MyClass()</code></li><li><strong>Qualified name</strong> (nomi qualificati): paragonabile al percorso relativo di un file.<br /><code>Main\Libs\MyClass()</code></li><li><strong>Fully-qualified name</strong> (nomi completamente  qualificati): inizia sempre con un backslash iniziale ed è paragonabile ad un percorso assoluto.  È il modo  più sicuro anche se più verboso. <br /><code>\Framework\Core\Main\Libs\MyClass()</code></li></ul>



<p><strong>Unqualified name</strong> &#8211; Nel file principale (ex02.php) dichiariamo lo stesso namespace di uno dei due file contenenti la dichiarazione di MyClass() che vorremmo richiare, ad esempio Libs: <code>Framework\Core\Main\Libs</code>. Ecco finalmente il primo risultato positivo!</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: php; title: ; notranslate">
&lt;?php // File: /ex02.php

// Dichiaro il namespace
namespace Framework\Core\Main\Libs;

// Includo i file
require_once('Framework/Core/Main/MyClass.php');
require_once('Framework/Core/Main/Libs/MyClass.php');

// UNQUALIFIED NAME...
$objOne = New MyClass();
</pre></div>


<p><strong>Qualified name</strong> &#8211; Nel file principale (ex03.php) dichiariamo un namespace più generico <code>Framework\Core</code> ed utilizzamo nomi qualificati per riferirci ad entrambe le nostre classi ed ottenere i relativi oggetti.</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: php; title: ; notranslate">
&lt;?php
// File: /ex03.php

// Dichiaro il namespace
namespace Framework\Core;

require_once('Framework/Core/Main/MyClass.php');
require_once('Framework/Core/Main/Libs/MyClass.php');

// QUALIFIED NAME...
$objOneMain = New Main\MyClass();
$objOneLib = New Main\Libs\MyClass();
</pre></div>


<p><strong>Nota</strong>: una volta dichiarato un namespace, per riferirsi al contesto globale è necessario anteporre il backslash.</p>



<p><strong>Fully-qualified name</strong> &#8211;  Nel file principale (ex04.php) omettiamo il namespace, ma utilizziamo un nome completamente qualificato per riferirci alle due classi.</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: php; title: ; notranslate">
&lt;?php // File: /ex04.php

// Includo i file
require_once('Framework/Core/Main/MyClass.php');
require_once('Framework/Core/Main/Libs/MyClass.php');

// FULLY-QUALIFIED NAME...
$objOneMain = New \Framework\Core\Main\MyClass();
$objOneLib = New \Framework\Core\Main\Libs\MyClass();
</pre></div>


<h2 class="wp-block-heading">Php Namespaces: importazione e aliasing tramite l&#8217;operatore &#8220;use&#8221;</h2>



<p>Una caratteristica importante dei namespaces è la possibilità di essere importati e di creare degli alias per renderne più pratico l&#8217;utilizzo vista la loro &#8220;eloquenza&#8221;. Queste funzioni trovano un parallelismo nella capictà dei filesystem di creare link simbolici a file o cartelle.<br />A tale scopo Php mette a disposizione la <span style="text-decoration: underline;">keyword <code>&lt;strong&gt;use&lt;/strong&gt;</code></span> con la quale è possibile eseguire i seguenti tipi di seguenti tipi di importazione/aliasing:</p>



<ul><li>nomi di classi o interfacce (<code>use Name\Space\ClassName</code>),  </li><li>nomi di classi o interfacce globali (<code>use DateTime</code>)</li><li>namespaces (use <code>Name\Space\For\...</code>)</li><li>nomi di funzioni (<code>use&nbsp;function Name\Space\FunctionName</code>)</li><li>nomi di costanti (<code>use&nbsp;const&nbsp;Name\Space\CONSTANT</code>).</li></ul>



<p>E&#8217; possibile importare anche più elementi nello stesso file purché non si generino delle ambiguità, in tal caso si potrà ricorrere agli alias. </p>



<p>Applichiamo <code>use</code> al nostro scenario di esempio (ex05.php) per importare i namespaces comuni alla due classi e sintetizzarli in &#8220;Main&#8221;.</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: php; title: ; notranslate">
&lt;?php // File: /ex05.php

use Framework\Core\Main as Main;

// Includo i file
require_once('Framework/Core/Main/MyClass.php');
require_once('Framework/Core/Main/Libs/MyClass.php');

// QUALIFIED NAME...
$objOneMain = New Main\MyClass();
$objOneLib = New Main\Libs\MyClass();
</pre></div>


<p>Nell&#8217;esempio seguente (ex06.php) utilizziamo <code>use</code> per superare l&#8217;ambiguita dei nomi delle classi e creare un alias dei namespaces.</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: php; title: ; notranslate">
&lt;?php // File: /ex06.php

use Framework\Core\Main\MyClass as MainMy;
use Framework\Core\Main\Libs\MyClass as LibsMy;

// Includo i file
require_once('Framework/Core/Main/MyClass.php');
require_once('Framework/Core/Main/Libs/MyClass.php');

// UNQUALIFIED NAME...
$objOneMain = New MainMy();
$objOneLib = New LibsMy();
</pre></div>


<p>Direi sia tutto! Qui trovate i file di esempio visti nella lezione e se l&#8217;articolo è stato utile&#8230; condividilo!</p>



<div class="wp-block-buttons is-layout-flex wp-block-buttons-is-layout-flex">
<div class="wp-block-button"><a class="wp-block-button__link has-text-color has-white-color has-background has-black-background-color" href="https://www.cesarebordi.it/lessons/downloads/namespaces.zip" target="_blank" rel="noreferrer noopener">SCARICA I FILE DI ESEMPIO: namespaces.zip</a></div>
</div>
<p>L'articolo <a href="https://www.cesarebordi.it/php-namespaces/">Php Namespaces</a> sembra essere il primo su <a href="https://www.cesarebordi.it">Cesare Bordi | Innovation Manager &amp; Back-end Developer</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.cesarebordi.it/php-namespaces/feed/</wfw:commentRss>
			<slash:comments>1</slash:comments>
		
		
			</item>
		<item>
		<title>Conversione immagine: Imagemagick RGB to CMYK in PHP</title>
		<link>https://www.cesarebordi.it/imagemagick-rgb-to-cmyk-php/</link>
					<comments>https://www.cesarebordi.it/imagemagick-rgb-to-cmyk-php/#respond</comments>
		
		<dc:creator><![CDATA[cesarebordi]]></dc:creator>
		<pubDate>Mon, 04 Dec 2017 19:32:24 +0000</pubDate>
				<category><![CDATA[Articoli]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Programmazione]]></category>
		<category><![CDATA[image]]></category>
		<category><![CDATA[imagemagick]]></category>
		<category><![CDATA[imagick]]></category>
		<category><![CDATA[immagini]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[programmazione]]></category>
		<category><![CDATA[web developer]]></category>
		<category><![CDATA[web project]]></category>
		<category><![CDATA[webserver]]></category>
		<guid isPermaLink="false">http://www.cesarebordi.it/?p=473</guid>

					<description><![CDATA[<p>Spero di poter aiutare i colleghi developer alle prese con la conversione attraverso Imagemagick RGB to CMYK. Scenario: dobbiamo convertire lato server un&#8217;immagine RGB in CMYK Problema: letta...</p>
<p>L'articolo <a href="https://www.cesarebordi.it/imagemagick-rgb-to-cmyk-php/">Conversione immagine: Imagemagick RGB to CMYK in PHP</a> sembra essere il primo su <a href="https://www.cesarebordi.it">Cesare Bordi | Innovation Manager &amp; Back-end Developer</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>Spero di poter aiutare i colleghi developer alle prese con la conversione attraverso <strong>Imagemagick RGB to CMYK</strong>.<br />
<span id="more-473"></span></p>
<p><strong>Scenario</strong>: dobbiamo convertire lato server un&#8217;immagine<strong> RGB in CMYK</strong></p>
<p><strong>Problema</strong>: letta la scarna documentazione di <strong>Imagemagick</strong> sulla refernece di <strong>Php</strong> ci imbattiamo in un annoso problema: l&#8217;<strong>immagine ottenuta è in negativo</strong>!!!</p>
<p><strong>Soluzione</strong>: dopo aver letto post su post sui soliti siti senza riuscire a trovare una soluzione e grazie al supporto di Giacomarco, ecco svelato il mistero.</p>
<p>Se si deve convertire un&#8217;immagine occorre usare&nbsp;<strong>transformimagecolorspace</strong>, mentre se si sta generando un&#8217;immagine ex-novo allora si deve utilizzare <strong>transformimagecolorspace:</strong></p>
<pre class="brush: php; title: ; notranslate">$image-&amp;gt;transformimagecolorspace(Imagick::COLORSPACE_CMYK);</pre>
<p>Se invece si sta creando un&#8217;immagine ex-novo allora si deve utilizzare&nbsp;<strong>setImageColorSpace</strong></p>
<pre class="brush: php; title: ; notranslate">$image-&amp;gt;setImageColorSpace(Imagick::COLORSPACE_CMYK);</pre>
<p>Ecco un esempio:</p>
<pre class="brush: php; title: ; notranslate">
$image = new Imagick();
$image-&amp;gt;readImage(rgb.jpg);
$image-&amp;gt;transformimagecolorspace(Imagick::COLORSPACE_CMYK);
$image-&amp;gt;profileImage('icc', file_get_contents(/path/CoatedFOGRA27.icc'));
$image-&amp;gt;writeImage(cmyk.rgb);
</pre>
<p>Per gli amici in lingua inglese: <span lang="en"><strong>[SOLVED] imagemagick convert image RGB to CMYK</strong>!</span></p>
<p>L'articolo <a href="https://www.cesarebordi.it/imagemagick-rgb-to-cmyk-php/">Conversione immagine: Imagemagick RGB to CMYK in PHP</a> sembra essere il primo su <a href="https://www.cesarebordi.it">Cesare Bordi | Innovation Manager &amp; Back-end Developer</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.cesarebordi.it/imagemagick-rgb-to-cmyk-php/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>MySql: cerca e sostituisci in una query per web developer</title>
		<link>https://www.cesarebordi.it/mysql-cerca-e-sostituisci-query-web-developer/</link>
					<comments>https://www.cesarebordi.it/mysql-cerca-e-sostituisci-query-web-developer/#respond</comments>
		
		<dc:creator><![CDATA[cesarebordi]]></dc:creator>
		<pubDate>Fri, 12 Aug 2016 17:21:18 +0000</pubDate>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Programmazione]]></category>
		<category><![CDATA[Server]]></category>
		<category><![CDATA[database]]></category>
		<category><![CDATA[mysql]]></category>
		<category><![CDATA[programmazione]]></category>
		<category><![CDATA[query]]></category>
		<category><![CDATA[tips & tricks]]></category>
		<category><![CDATA[web developer]]></category>
		<category><![CDATA[web master]]></category>
		<category><![CDATA[web project]]></category>
		<guid isPermaLink="false">http://www.cesarebordi.it/?p=381</guid>

					<description><![CDATA[<p>Scenario: nel routine di un web developer o di un web master capita spesso di dover fare un cerca e sostituisci con il database MySql. Credo che qualsiasi...</p>
<p>L'articolo <a href="https://www.cesarebordi.it/mysql-cerca-e-sostituisci-query-web-developer/">MySql: cerca e sostituisci in una query per web developer</a> sembra essere il primo su <a href="https://www.cesarebordi.it">Cesare Bordi | Innovation Manager &amp; Back-end Developer</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p><span style="text-decoration: underline;">Scenario</span>: nel routine di un <strong>web developer</strong> o di un <strong>web master </strong>capita spesso di dover fare un <strong>cerca e sostituisci</strong> con il <strong>database MySql</strong>. <span id="more-381"></span></p>


<p>Credo che qualsiasi <strong>programmatore</strong> si sia trovato nella condizione di dover <strong>cercare</strong> un determinato <strong>valore di un campo</strong> ricorrente in molteplici<strong> record</strong> per <strong>sostituirlo</strong> con uno diverso.</p>



<p>Diciamo ad esempio di voler <strong>sostituire in una tabella</strong> di dati anagrafici il termine &#8220;maschio&#8221; con &#8220;M&#8221; nel campo &#8220;genere&#8221;.</p>



<p>Problema: come fare quindi per eseguire un &#8220;<strong>cerca e sostituisci</strong>&#8221; in massa su tutti i <strong>record interessati</strong> della tabella MySql?</p>



<p>Soluzione: detto fatto, basta sfruttare l&#8217;apposita <strong><a href="http://dev.mysql.com/doc/refman/5.7/en/string-functions.html" target="_blank" rel="noreferrer noopener">string function REPLACE</a> di MySQL</strong> opportunatamente combinata con un <a href="http://dev.mysql.com/doc/refman/5.7/en/update.html" target="_blank" rel="noreferrer noopener"><strong>UPDATE</strong></a>:</p>



<p><strong>UPDATE</strong> `<em>nomeTabella`</em> <strong>SET</strong> `<em>nomeCampo`</em> = <strong>REPLACE</strong>(`<em>nomeCampo`</em>, &#8216;<em>cosaTrovare</em>&#8216;, &#8216;<em>cosaSostituire</em>&#8216;);</p>



<p>Se l&#8217;applichiamo al nostro esempio otterremo:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: sql; title: ; notranslate">
UPDATE `Anagrafica` SET `genere` = REPLACE(`genere`, 'maschio', 'M');
</pre></div><p>L'articolo <a href="https://www.cesarebordi.it/mysql-cerca-e-sostituisci-query-web-developer/">MySql: cerca e sostituisci in una query per web developer</a> sembra essere il primo su <a href="https://www.cesarebordi.it">Cesare Bordi | Innovation Manager &amp; Back-end Developer</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.cesarebordi.it/mysql-cerca-e-sostituisci-query-web-developer/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Sicurezza: abilitare HTTPS in Apache2 su Ubuntu server</title>
		<link>https://www.cesarebordi.it/sicurezza-abilitare-https-in-apache2-su-ubuntu-server/</link>
					<comments>https://www.cesarebordi.it/sicurezza-abilitare-https-in-apache2-su-ubuntu-server/#respond</comments>
		
		<dc:creator><![CDATA[cesarebordi]]></dc:creator>
		<pubDate>Thu, 04 Aug 2016 14:24:27 +0000</pubDate>
				<category><![CDATA[Programmazione]]></category>
		<category><![CDATA[Server]]></category>
		<category><![CDATA[apache]]></category>
		<category><![CDATA[apache2]]></category>
		<category><![CDATA[linux]]></category>
		<category><![CDATA[programmazione]]></category>
		<category><![CDATA[shell]]></category>
		<category><![CDATA[sicurezza]]></category>
		<category><![CDATA[sistemista]]></category>
		<category><![CDATA[terminale]]></category>
		<category><![CDATA[web developer]]></category>
		<category><![CDATA[webserver]]></category>
		<guid isPermaLink="false">http://www.cesarebordi.it/?p=370</guid>

					<description><![CDATA[<p>Scenario: vogliamo rendere uno scambio dati sicure, magari per rafforzare il sistema di autenticazione di un sito web o lo scambio dati fra una webApp, ma anche una...</p>
<p>L'articolo <a href="https://www.cesarebordi.it/sicurezza-abilitare-https-in-apache2-su-ubuntu-server/">Sicurezza: abilitare HTTPS in Apache2 su Ubuntu server</a> sembra essere il primo su <a href="https://www.cesarebordi.it">Cesare Bordi | Innovation Manager &amp; Back-end Developer</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p><span style="text-decoration: underline;">Scenario</span>: vogliamo rendere uno <strong>scambio dati sicure</strong>, magari per rafforzare il <strong>sistema di autenticazione</strong> di un <strong>sito web</strong> o lo <strong>scambio dati</strong> fra una<strong> webApp</strong>, ma anche una <strong>App nativa</strong> e un <strong>server</strong>.</p>
<p>Per fare questo dovremo utilizzare il <strong>protocollo HTTPS</strong> che abbina il comune HTTP ad un ulteriore <strong>protocollo di crittografia asimmetrica</strong>.<br />
HTTPS è infatti l&#8217;acronimo di <strong>HyperText Transfer Protocol over Secure Socket Layer</strong>.<br />
Questo sistema di sicurezza è stato pensato proprio per evitare che attraverso tecniche di <strong>man in the middle</strong> un malintenzionato possa fare<strong> sniffing dei dati</strong> scambiati bidirezionalmente fra server e client.</p>
<p><span style="text-decoration: underline;">Problema</span>: se &#8220;tirar su&#8221; un <strong>server LAMP</strong> è ormai alla portata di tutti i <strong>web developer </strong>grazie alle molte distribuzioni<em> out of the box</em>, abilitare l&#8217;https è già un&#8217;operazione più specificatamente <strong>sistemistica</strong>, ma ugualmente attuabile in pochi minuti.</p>
<p><span style="text-decoration: underline;">Spiegazione</span>: su <strong>Ubuntu Server</strong>, così come in molte altre distribuzioni, il <strong>modulo SSL</strong> è già presente nell&#8217;installazione base di <strong>Apache</strong>.<br />
Bisogna solo attivarlo con il seguente comando che abilita anche la <strong>porta 443</strong> di default per l&#8217;https.</p>
<pre class="brush: bash; title: ; notranslate">sudo a2enmod ssl</pre>
<p>Dovremo quindi predisporre una cartella in cui generare i nostri certificati di sicurezza. Consiglio di creare una sottocartella dentro a quella di apache.</p>
<p>Nel caso di Ubunti dovremo lanciare il comando</p>
<pre class="brush: bash; title: ; notranslate">sudo mkdir /etc/apache2/ssl</pre>
<p>In altre distribuzioni come centOS la sottocartella può essere creata con i comando</p>
<pre class="brush: bash; title: ; notranslate">sudo mkdir /etc/httpd/ssl</pre>
<p>Per ottenere <strong>chiave privata</strong> e <strong>certificato</strong> utilizzeremo <strong>openssl</strong> attraverso il seguente comando, riportando i percorsi corretti, scegliendo la <strong>crittografia RSA</strong> a 2048 bit e una validità di 365 giorni.</p>
<pre class="brush: bash; title: ; notranslate">sudo openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout /etc/apache2/ssl/apache.key -out /etc/apache2/ssl/apache.crt</pre>
<p>Nel caso openssl non fosse presente, si può installare mediante il seguente comando su Ubuntu (o analoghi su altre distro)</p>
<pre class="brush: bash; title: ; notranslate">apt-get install openssl</pre>
<p>La <strong>procedura di creazione dei certificati</strong> pone alcune domande alle quali si può rispondere abbastanza liberamente, es:</p>
<pre class="brush: bash; title: ; notranslate">
Country Name (2 letter code) &#x5B;AU]:IT
State or Province Name (full name) &#x5B;Some-State]:Modena
Locality Name (eg, city) &#x5B;]:Modena
Organization Name (eg, company) &#x5B;Internet Widgits Pty Ltd]:communicationBox
Organizational Unit Name (eg, section) &#x5B;]:Development
Common Name (e.g. server FQDN or YOUR name) &#x5B;]:NomeMioServer
Email Address &#x5B;]:maimaildiriferimento@dominio.it
</pre>
<p>A questo punto il grosso del lavoro è fatto, non resta che settare i <strong>virtual host </strong>per indicare di sfruttare la <strong>cominicazione sicura</strong> sulla porta 443 e chiave e certificato appena creati.</p>
<p>Nella cartella /etc/apache2/sites-available/ è solitamente già presente un file di esempio denominato default-ssl.conf che possiamo modificare o utilizzare come modello per creare il nostro file:</p>
<pre class="brush: bash; title: ; notranslate">
sudo nano /etc/apache2/sites-available/default-ssl.conf
</pre>
<pre class="brush: bash; title: ; notranslate">
&lt;VirtualHost *:80&gt;
        ServerAdmin webmaster@localhost

        DocumentRoot /var/www/html
        &lt;Directory /&gt;
                Options FollowSymLinks
                AllowOverride All
        &lt;/Directory&gt;
        &lt;Directory /var/www/&gt;
                Options -Indexes +FollowSymLinks +MultiViews
                AllowOverride All
                Order allow,deny
                allow from all
        &lt;/Directory&gt;

        ScriptAlias /cgi-bin/ /usr/lib/cgi-bin/
        &lt;Directory &quot;/usr/lib/cgi-bin&quot;&gt;
                AllowOverride None
                Options +ExecCGI -MultiViews +SymLinksIfOwnerMatch
                Order allow,deny
                Allow from all
        &lt;/Directory&gt;

        ErrorLog ${APACHE_LOG_DIR}/error.log

        # Possible values include: debug, info, notice, warn, error, crit,
        # alert, emerg.
        LogLevel warn

        CustomLog ${APACHE_LOG_DIR}/access.log combined

        Alias /doc/ &quot;/usr/share/doc/&quot;
        &lt;Directory &quot;/usr/share/doc/&quot;&gt;
                Options MultiViews FollowSymLinks
                AllowOverride None
                Order deny,allow
                Deny from all
                Allow from 127.0.0.0/255.0.0.0 ::1/128
        &lt;/Directory&gt;

&lt;/VirtualHost&gt;

</pre>
<p>Ora la configurazione è terminata, dobbiamo abilitare come di consueto il virtual host:</p>
<pre class="brush: bash; title: ; notranslate">
sudo a2ensite default-ssl.conf
</pre>
<p>Infine riavviamo il servizio per rendere effettive le modifiche:</p>
<pre class="brush: bash; title: ; notranslate">
sudo service apache2 restart
</pre>
<p>Ora, sincerandosi che il firewall della nostra connessione consenta il traffico sulla porta 443, puntiamo sull&#8217;ip del server, o sul dominio impostato nel virtualhost, ad esempio https://123.123.123.123.<br />
Comparirà un avviso che ci avverte che il certificato non è attendibile, questo è normale in quanto lo abbiamo autogenerato e non acquistato da un ente certificatore. Basterà procedere &#8220;accettando i rischi&#8221; per navigare in maniera sicura. Naturalmente, per siti o app pubbliche, è vivamente consigliato l&#8217;acquisto di un certificato verificato per non &#8220;spaventare&#8221; l&#8217;utente con questo avviso.</p>
<p>L'articolo <a href="https://www.cesarebordi.it/sicurezza-abilitare-https-in-apache2-su-ubuntu-server/">Sicurezza: abilitare HTTPS in Apache2 su Ubuntu server</a> sembra essere il primo su <a href="https://www.cesarebordi.it">Cesare Bordi | Innovation Manager &amp; Back-end Developer</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.cesarebordi.it/sicurezza-abilitare-https-in-apache2-su-ubuntu-server/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>WordPress: escludere una cartella dal rewriting url di Apache</title>
		<link>https://www.cesarebordi.it/wordpress-escludere-una-cartella-dal-rewriting-url-di-apache/</link>
					<comments>https://www.cesarebordi.it/wordpress-escludere-una-cartella-dal-rewriting-url-di-apache/#respond</comments>
		
		<dc:creator><![CDATA[cesarebordi]]></dc:creator>
		<pubDate>Wed, 03 Aug 2016 10:16:39 +0000</pubDate>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Programmazione]]></category>
		<category><![CDATA[Server]]></category>
		<category><![CDATA[apache]]></category>
		<category><![CDATA[apache2]]></category>
		<category><![CDATA[htaccess]]></category>
		<category><![CDATA[linux]]></category>
		<category><![CDATA[programmazione]]></category>
		<category><![CDATA[server]]></category>
		<category><![CDATA[web developer]]></category>
		<category><![CDATA[webserver]]></category>
		<category><![CDATA[wordpress]]></category>
		<guid isPermaLink="false">http://www.cesarebordi.it/?p=358</guid>

					<description><![CDATA[<p>Scenario: molti cms, primo fra tutti WordPress, permettono di impostare la generazione automatica di friendly url per migliorare il seo di un sito web. L&#8217;abilitazione di tale funzione,...</p>
<p>L'articolo <a href="https://www.cesarebordi.it/wordpress-escludere-una-cartella-dal-rewriting-url-di-apache/">WordPress: escludere una cartella dal rewriting url di Apache</a> sembra essere il primo su <a href="https://www.cesarebordi.it">Cesare Bordi | Innovation Manager &amp; Back-end Developer</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p><span style="text-decoration: underline;">Scenario</span>: molti <strong>cms</strong>, primo fra tutti <strong>WordPress</strong>, permettono di impostare la generazione automatica di <strong>friendly url </strong>per migliorare il <strong>seo</strong> di un <strong>sito web.</strong> L&#8217;abilitazione di tale funzione, che sfrutta il <strong>modulo rewrite</strong> (<strong>mod_rewrite.c</strong>) di <strong>Apache</strong>, è una delle configurazioni di base che ogni <strong>web developer</strong> dovrebbe eseguire in fase di installazione della <strong>piattaforma </strong>attraverso l&#8217;apposito <strong>file .htaccess</strong>.</p>
<p>Il <strong>codice</strong> proposto dallo stesso <strong>WordPress</strong> che solitamente si utilizza per <strong>abilitare il rewriting</strong> e far così scomparire dalla url &#8220;index.php&#8221; è il seguente:</p>
<pre class="brush: bash; title: ; notranslate">
&lt;IfModule mod_rewrite.c&gt;
RewriteEngine On
RewriteBase /
RewriteRule ^index\.php$ - &#x5B;L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php &#x5B;L]
&lt;/IfModule&gt;
</pre>
<p>Questa regola eseguirà il rewrite di ogni percorso della url sott&#8217;intendendo la presenza di /index.php</p>
<p><span style="text-decoration: underline;">Problema</span>: può però essere necessario <strong>escludere una cartella</strong> (o più) da questa regola generale per caricare ad esempio file che devono essere accessibili attraverso un link diretto o script di varia utilità.</p>
<p><span style="text-decoration: underline;">Soluzione</span>: è possibile <strong>modificare la regola</strong> in modo da segnalare <strong>una directory</strong> (o più) che faccia <strong>eccezione</strong> rispetto alla regola generale attraverso la seguente istruzione:</p>
<pre class="brush: bash; title: ; notranslate">
RewriteCond %{REQUEST_URI} !^/(Cartella1|Cartella2|Cartella3).*$
</pre>
<p>Ecco come apparirà il blocco di codice completo:</p>
<pre class="brush: bash; title: ; notranslate">
&lt;IfModule mod_rewrite.c&gt;
RewriteEngine On
RewriteBase /
RewriteRule ^index.php$ - &#x5B;L]
RewriteCond %{REQUEST_URI} !^/(Cartella1|Cartella2|Cartella3).*$
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php &#x5B;L]
&lt;/IfModule&gt;
</pre>
<p>L'articolo <a href="https://www.cesarebordi.it/wordpress-escludere-una-cartella-dal-rewriting-url-di-apache/">WordPress: escludere una cartella dal rewriting url di Apache</a> sembra essere il primo su <a href="https://www.cesarebordi.it">Cesare Bordi | Innovation Manager &amp; Back-end Developer</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.cesarebordi.it/wordpress-escludere-una-cartella-dal-rewriting-url-di-apache/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Javascript: come calcolare l&#8217;età</title>
		<link>https://www.cesarebordi.it/javascript-calcolare-eta/</link>
					<comments>https://www.cesarebordi.it/javascript-calcolare-eta/#respond</comments>
		
		<dc:creator><![CDATA[cesarebordi]]></dc:creator>
		<pubDate>Sat, 14 May 2016 16:27:28 +0000</pubDate>
				<category><![CDATA[CSS & JS]]></category>
		<category><![CDATA[Programmazione]]></category>
		<category><![CDATA[data]]></category>
		<category><![CDATA[date]]></category>
		<category><![CDATA[javascrpit]]></category>
		<category><![CDATA[programmazione]]></category>
		<category><![CDATA[web developer]]></category>
		<category><![CDATA[web project]]></category>
		<guid isPermaLink="false">http://www.cesarebordi.it/?p=310</guid>

					<description><![CDATA[<p>Da buon web developer, ho appena terminato l&#8217;implementazione del facebook login così da precompilare alcuni dati richiesti in un form di registrazione. Tra questi il campo &#8220;età&#8220;. Ora,...</p>
<p>L'articolo <a href="https://www.cesarebordi.it/javascript-calcolare-eta/">Javascript: come calcolare l&#8217;età</a> sembra essere il primo su <a href="https://www.cesarebordi.it">Cesare Bordi | Innovation Manager &amp; Back-end Developer</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>Da buon<strong> web developer</strong>, ho appena terminato l&#8217;<strong>implementazione</strong> del <strong><a href="https://developers.facebook.com/docs/facebook-login" target="_blank">facebook login</a></strong> così da precompilare alcuni dati richiesti in un <strong>form di registrazione</strong>. Tra questi il campo &#8220;<strong>età</strong>&#8220;.<span id="more-310"></span></p>
<p>Ora, <strong>calcolare l&#8217;età</strong> sembra banale, ma non lo è.<br />
Non basta fare la differenza fra l&#8217;anno attuale e quello di nascita, bisogna tener conto anche del mese, del giorno e del formato di data che, nel caso di facebook è mm/dd/aaaa.</p>
<p>Ho quindi realizzato una pratica <strong>funzione javascript per calcolare l&#8217;età</strong> che finirà nella mia personale collezione!<br />
L&#8217;unico argomento  richiesto dalla funzione è una data di nascita, in qualsiasi formato.</p>
<pre class="brush: jscript; title: ; notranslate">
function calcAge (birthday) {
    birthday = new Date(birthday);
    today     = new Date();

    var years = (today.getFullYear() - birthday.getFullYear());

    if (today.getMonth() &lt; birthday.getMonth() || 
        today.getMonth() == birthday.getMonth() &amp;&amp; today.getDate() &lt; birthday.getDate()) {
        years--;
    }

    return years;
}
</pre>
<p>&nbsp;</p>
<p>L'articolo <a href="https://www.cesarebordi.it/javascript-calcolare-eta/">Javascript: come calcolare l&#8217;età</a> sembra essere il primo su <a href="https://www.cesarebordi.it">Cesare Bordi | Innovation Manager &amp; Back-end Developer</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.cesarebordi.it/javascript-calcolare-eta/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>CSS mask-image per JPG con effetto PNG</title>
		<link>https://www.cesarebordi.it/sito-web-developer-css-mask-image/</link>
					<comments>https://www.cesarebordi.it/sito-web-developer-css-mask-image/#respond</comments>
		
		<dc:creator><![CDATA[cesarebordi]]></dc:creator>
		<pubDate>Thu, 07 Apr 2016 08:40:00 +0000</pubDate>
				<category><![CDATA[CSS & JS]]></category>
		<category><![CDATA[css]]></category>
		<category><![CDATA[html5]]></category>
		<category><![CDATA[mask-image]]></category>
		<category><![CDATA[ottimizzazione]]></category>
		<category><![CDATA[web developer]]></category>
		<guid isPermaLink="false">http://www.cesarebordi.it/?p=232</guid>

					<description><![CDATA[<p>Da web developer un errore di visualizzazione sul sito web di Apple ha acceso la mia curiosità di indagarne la causa scoprendo un&#8217;interessante tecnica di ottimizzazione grafica. Visualizzando...</p>
<p>L'articolo <a href="https://www.cesarebordi.it/sito-web-developer-css-mask-image/">CSS mask-image per JPG con effetto PNG</a> sembra essere il primo su <a href="https://www.cesarebordi.it">Cesare Bordi | Innovation Manager &amp; Back-end Developer</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p style="text-align: justify;"><img decoding="async" src="http://www.cesarebordi.it/wp-content/uploads/2016/04/css-error-apple-site.jpg" alt="css error sito web Apple" width="100%" /><br />
Da <strong>web developer</strong> un errore di visualizzazione sul <strong>sito web di Apple</strong> ha acceso la mia curiosità di indagarne la causa scoprendo un&#8217;interessante <strong>tecnica di ottimizzazione grafica</strong>.</p>
<p style="text-align: justify;">Visualizzando la <strong>pagina web</strong> scatta una breve animazione che farebbe pensare all&#8217;utilizzo di due <strong>immagini PNG</strong> a 24bit con ombre in trasparenza <strong>animate con transition CSS3.</strong></p>
<p style="text-align: justify;">L&#8217;<strong>ispezione del codice sorgente</strong> mette invece in evidenza una <strong>tecnica di ottimizzazione grafica </strong>volta alla<strong> riduzione delle dimensioni dei file</strong> che sfrutta 4 <strong>tag &lt;figure&gt;</strong>  ai quali vengono assegnati via CSS &#8220;leggère&#8221; immagini JPG: due rappresentano i tablet, due le rispettive ombre.</p>
<p style="text-align: justify;">A questo punto mi sarei aspettato di vedere l&#8217;alone bianco proprio come accaduto su Firefox, ma visualizzando il sito con Safari questo non accade&#8230; come hanno fatto a <strong>scontornare le immagini</strong>? Semplice (mica tanto), attraverso l&#8217;apposita <strong>regola css3 mask-image</strong> che sfrutta un file vettoria SVG, anch&#8217;esso leggerissimo, come maschera. Per approfondimenti rimando a <a href="http://www.html5rocks.com/it/tutorials/masking/adobe/" target="_blank">questo articolo.</a></p>
<p style="text-align: justify;">Il sistema è ingegnoso ed il risparmio in termini di Kb è davvero notevole, di contro la sua realizzazione è piuttosto dispendiosa in termini di tempo di realizzazione ed evidentemente ha qualche problema di compatibilità con Firefox. Devo però ammettere che su un&#8217;altra postazione Firefox rispondeva correttamente.</p>
<p style="text-align: justify;">Spero che questa tecnica possa tornare utile a qualche collega web developer!<br />
Sotto un dettaglio del <strong>codice sorgente</strong> ispezionato:</p>
<p><img fetchpriority="high" decoding="async" class="alignnone" src="http://www.cesarebordi.it/wp-content/uploads/2016/04/css-error-apple-site-code.jpg" alt="web developer mask image css" width="1012" height="595" /></p>
<p>L'articolo <a href="https://www.cesarebordi.it/sito-web-developer-css-mask-image/">CSS mask-image per JPG con effetto PNG</a> sembra essere il primo su <a href="https://www.cesarebordi.it">Cesare Bordi | Innovation Manager &amp; Back-end Developer</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.cesarebordi.it/sito-web-developer-css-mask-image/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
	</channel>
</rss>
