lunedì, 21 Aprile 2025

[php] Configurare php.ini per l’upload dei file

L’upload dei file, nel PHP, dipende da diverse parametri, alcuni diretti ed altri indiretti, configurabili nel php.ini.

Anzitutto individuiamo il file di configurazione in uso. Per farlo è sufficiente utilizzare, in una pagina php, l’istruzione phpinfo();

Otterremo un output simile a questo:

Nel mio caso specifico, sotto Plesk, il file si trova in /opt/plesk/php/7.3/etc/php.ini

In una configurazione predefinita di Ubuntu Server 19.10 avremmo qualcosa di simile invece:

Il percorso del file php.ini in questo caso è /etc/php/7.3/apache2/php.ini

Detto questo modifichiamo il suddetto file individuando le seguenti istruzioni:

upload_max_filesize

Questo è il parametro principale, quello che riguarda la massima dimensione di un file in upload. Di solito si trova impostato a 2M oppure 8M. Se volessimo consentire un upload di 20MB dovremmo metterlo a: upload_max_filesize = 20M

post_max_size

Questo parametro indica la massima dimensione dell’intestazione di POST, nel caso specifico se volessimo aumentare il valore a 20MB dovremmo digitare: post_max_size = 20M

Attenzione, perché il POST contiene non solo il file in upload, ma anche altre istruzioni. Con una dimensione di 20MB significa che il massimo file caricabile sarà probabilmente attorno ai 19MB, perché una parte del post è utilizzata per inviare anche altre istruzioni, per quanto in genere ridotte e piccole. Un’istruzione più corretta potrebbe essere: post_max_size = 21M

max_file_uploads

Questo parametro definisce invece il numero massimo di file caricabili. Di predefinito è impostato su 20, quindi si potranno caricare al massimo 20 file in una volta. Se volessimo consentire il caricamento simultaneo di 50 file, potremmo impostarlo come: max_file_uploads = 50

 

A queste, che sono le istruzioni specificatamente dedicate al caricamento dei file, se ne aggiungono altre che sono strettamente connesse.

memory_limit

Il limite di memoria allocabile dal processo di PHP per l’esecuzione delle operazioni. Nel caso di grossi caricamenti questo limite potrebbe dover essere aumentato. Di solito il valore è 128M, ovvero 128MB, se volessimo aumentare il valore a 256MB dovremmo scrivere: memory_limit = 256MB

max_execution_time

Il massimo tempo di esecuzione del processo PHP. Di predefinito è impostato su 30 secondi, il che vuol dire che se l’upload impiega più tempo il PHP chiuderà l’operazione allo scadere del limite del tempo. Possiamo aumentare questo valore, per esempio su 10 minuti (60 secondi x 10), digitando: max_execution_time = 600

max_input_time

Come prima, anche questo parametro concorre col precedente. Se il tempo massimo di esecuzione è inferiore a questo parametro il processo di input verrà comunque interrotto; viceversa se questo valore è basso l’input verrà interrotto secondo quest’ultimo parametro. Se vogliamo dare anche qui 10 minuti per il massimo tempo di input digitiamo: max_input_time = 600

 

Riassumiamo infine tutte quante le variabili assieme:

[php] Costruire un oggetto iterabile che possa essere percorso con foreach, grazie alle interfacce Iterator, ArrayAccess e Countable

Oggi propongo un semplice esercizio in PHP dove vogliamo costruire un oggetto iterabile che sia accessibile come un vettore e percorribile da foreach.

Immaginiamo di avere due classi Studente e Scuola, quello che vogliamo ottenere è il qualcosa di analogo a questo:

L’output sarà così:

in tutto ci sono 4 studenti
0 -> Squall
1 -> Zell
2 -> Rinoa
3 -> Edea

Anzitutto cominciamo costruendo la classe Studente. Questa è molto semplice e non ha nulla di particolare, la possiamo costruire come vogliamo ed in particolare, ai fini dell’esercizio, la farò con una sola proprietà e due metodi (set e get).

Adesso costruiamo Scuola implementando i metodi Iterator, ArrayAccess, Countable.

Le tre interfacce permettono di implementare diverse proprietà. Affinché l’oggetto costruito con Scuola sia percorribile dal foreach usiamo l’interfaccia Iterator.

L’interfaccia implementa i seguenti metodi astratti:

Si suppone che la nostra classe abbia una proprietà “posizione“, per cui si possa ricavare un valore da questa posizione corrente con current(). Il metodo key() dovrà restituire tale posizione corrente, next() permetterà di andare alla posizione successiva, mentre rewind() consentirà di ripartire dalla posizione iniziale. Infine il metodo valid() verificherà se nella posizione attuale esiste o meno un oggetto.

Cominciamo allora costruendo la classe nel modo seguente:

Per rendere la classe operativa aggiungiamo anche un altro paio di metodi. In particolare:

Con il controllo if( $studente instanceof Studente ) vogliamo assicurarci che l’oggetto aggiunto tramite il metodo add() sia del tipo Studente. Se il tipo non è quello giusto solleviamo un errore del tipo InvalidArgumentException dove avvisiamo l’utente.

Significa che la forma:

Produrrà un errore del tipo Fatal error: Uncaught InvalidArgumentException: l'oggetto deve essere di tipo Studente in iterator.php:92 Stack trace: #0 iterator.php(87): Scuola->erroreOggettoNonValido() #1 iterator.php(98): Scuola->add('Squall') #2 {main} thrown in iterator.php on line 92

L’operazione valida sarà invece:

A questo punto l’oggetto è già iterabile mediante foreach, che può essere chiamato nel modo seguente:

Vogliamo dare la possibilità di aggiungere gli oggetti anche alla maniera di $scuola[] = new Studente("Edea");

Per farlo implementiamo la nostra classe Scuola anche su ArrayAccess. L’interfaccia ArrayAccess richiede i seguenti metodi:

Quindi implementiamoli nella nostra classe Scuola alla maniera seguente:

Anche qui usiamo if( $value instanceof Studente ) per verificare che l’oggetto sia di tipo Studente. Nel metodo offsetGet() utilizziamo il null coalescing operator per restituire null nel caso in cui l’oggetto non esista.

A questo punto l’istruzione $scuola[] = new Studente("Edea"); diventa utilizzabile, mentre $scuola[] = "Edea"; produce il solito errore Fatal error: Uncaught InvalidArgumentException: l'oggetto deve essere di tipo Studente in...

Infine vogliamo poter usare il metodo count($scuola) sul nostro oggetto, ottenendo il conteggio di tutti gli studenti inseriti. Se lo usiamo senza ulteriori implementazioni il risultato sarebbe sempre e comunque 1.

L’interfaccia Countable richiede un unico metodo:

Implementiamolo nel modo seguente:

Probabilmente sarebbe stato più carino implementare un metodo interno alla classe, magari un contatore che tenesse conto delle aggiunte, ma ai fini dell’esercizio ci accontentiamo di chiamare count sul vettore interno degli studenti.

Fatto tutto questo vediamo il risultato finale così ottenuto:

[wordpress] Got error ‘crayon-syntax-highlighter/crayon_langs.class.php on line 340

Problema: Dopo l’aggiornamento al PHP 7.3 il plugin per WordPress Crayon Syntax Highlighter, utilizzato per evidenziare codici di programmazione, smette di funzionare e blocca la visualizzazione delle pagine nelle quali è utilizzato.

Soluzione: Modificare due file per rendere compatibile il riconoscimento per espressioni regolari con le nuove definizioni di PCRE2

L’errore che si presenta è tipo il seguente: AH01071: Got error 'crayon-syntax-highlighter/crayon_langs.class.php on line 340PHP message: PHP Warning: preg_replace(): Compilation failed: invalid range in character class at offset 4 in

Purtroppo il plugin, per quanto buono, non è aggiornato da 4 anni.

In particolare presenta problemi con l’aggiornamento del PHP alla versione 7.3, per via delle nuove definizioni PCRE2 ed in particolare proprio per la presenza di un segno – (meno), proprio come trattato nel precedente articolo.

Per risolvere il problema facciamo nel modo seguente. Posizioniamoci nella cartella del plugin /wp-content/plugins/crayon-syntax-highlighter/

Modifichiamo il file crayon_langs.class.php alla riga 340

Sostituiamo la riga con:

Modifichiamo il file crayon_formatter.class.php alla riga 118

Sostituiamo le due righe con:

Fatto tutto questo il problema sarà risolto e potremo continuare ad usare il plugin.

Differenze e novità tra PHP5 e PHP7, con esempi di programmazione

Con la scusa di un po’ di esercizio vediamo anche quali sono le principali differenze tra (l’ormai vecchio) PHP 5 e il nuovo PHP 7 (che comunque è in circolazione già da un bel po’).

1. Sintassi flessibile per Heredoc e Newdoc
2. Operatore Spaceship
3. Null Coalesce Operator
4. Virgola finale negli argomenti di funzione
5. Migrazione a PCRE2
6. Unicode Codepoint Escape Syntax
7. Chiamata di errore nella codifica JSON
8. Exceptions per i fatal errors
9. Classi anonime
10. Dichiarazione del tipo di dato restituito
11. Metodo is_countable()
12. Primi e ultimi valori e chiavi di un array
13. Il metodo Closure->call
14. Prestazioni migliorate

1. Sintassi flessibile per Heredoc e Newdoc

Nell’ultimo aggiornamento del PHP 7.3 viene introdotta la possibilità di terminare il heredoc con UNA indentazione. Sottolineo UNA perché la cosa è un po’ comica, visto che una doppia indentazione (due tabulazioni) oppure degli spazi producono comunque errore.

In sostanza prima si doveva scrivere così:

Adesso è possibile scrivere così:

Questa singola tabulazione certo non farà la felicità assoluta di nessuno, però permette di aggiungere un po’ di chiarezza al codice (sebbene personalmente continui a trovarla una novità abbastanza inutile, tale qual’è).

2. Operatore Spaceship

A differenza della precedente, questa è una novità effettivamente significativa.

Viene introdotto l’operatore <=>, chiamato spaceship, che fa le veci (quasi ma non del tutto) della funzione strcmp. Questo velocizza la scrittura e ottimizza la sintassi, riducendo così il numero di passaggi a volte necessari.

Avendo il seguente codice:

Avremo il seguente output:

a <=> b : -1
mario <=> maria : 1
marii <=> mario : -1
maria <=> mario : -1
mario <=> luigi : 1
1 <=> 2 : -1
2 <=> 1 : 1
3 <=> 3 : 0

Utilizzando invece strcmp avremmo avuto il seguente codice:

Ed il seguente output:

a <=> b : -1
mario <=> maria : 14
marii <=> mario : -6
maria <=> mario : -14
mario <=> luigi : 1
1 <=> 2 : -1
2 <=> 1 : 1
3 <=> 3 : 0

Come si può notare il comportamento non è identico, se consideriamo i valori numerici e non i segni.

Per riprodurre il comportamento dell’operatore spaceship in PHP 5 potremmo immaginare di scrivere una funzione simile a questa:

Applicandola all’elenco precedente:

Avremo gli stessi risultati di <=> in PHP 7:

a <=> b : 0
mario <=> maria : 1
marii <=> mario : -1
maria <=> mario : -1
mario <=> luigi : 1
1 <=> 2 : -1
2 <=> 1 : 1
3 <=> 3 : 0

Immaginiamo dunque di voler scrivere una funzione di ordinamento per un array. In PHP 5 avremmo potuto scrivere:

Mentre in PHP 7 possiamo sintetizzare con:

Entrambi i casi produrranno un output ordinato come il seguente:

Array ( [0] => 1 [1] => 2 [2] => 3 [3] => 4 [4] => 7 [5] => 8 )

Inutile dire che per entrambi gli esempi avremmo potuto incorporare direttamente una funzione anonima dentro ad usort in questo modo:

Infine nel PHP 5 l’uso dell’operatore spaceship produrrebbe un errore di questo tipo:

Parse error: syntax error, unexpected '>' in /index.php on line 16

3. Null Coalesce Operator

In PHP 7 viene introdotto il null coalescing operator ??, proseguendo così le implementazioni sull’if lineare, già introdotte nel PHP 5.3 con l’Elvis operator ?:.

In generale sappiamo che possiamo scrivere un’istruzione con if lineare (o operatore ternario) di questo tipo:

Questa istruzione equivale a scrivere:

In generale questa istruzione può essere utilizzata per riassegnare la medesima variabile in uno dei due casi. Per esempio immaginiamo di voler scrivere:

Con l’Elvis operator possiamo sintetizzare la scrittura nel modo seguente:

Quello che viene assegnato è l’argomento del test. Se l’argomento del test comprende operatori logici viene assegnato il risultato dell’operazione logica.

Per capire meglio immaginiamo di voler trovare il più grande valore tra quelli dati (ci sarebbero altri mille modi, ma per lo scopo dell’esercizio prendiamo questo):

Il risultato di questa operazione darà ovviamente come risultato 8.

Se lo riscrivessimo con l’Elvis operator potremmo avere qualcosa del genere:

Purtroppo però il risultato non sarebbe più 8, bensì 1, e questo indipendentemente dal fatto che 1 esista nell’array. E’ 1 perché 1 è true, il risultato di una delle operazioni di test. (il penultimo massimo è 8, quindi 8 è maggiore di 2? sì, vero, quindi 1!)

Praticamente serve solo quando il risultato che vogliamo valutare è tra true o false, stringa nulla o meno, ecc.

A questo si aggiunge il null coalescing operator che integra il controllo della nullità della variabile, sostituendosi alla funzione isset. Immaginiamo di avere:

Questo può diventare ora:

Il comportamento è identico. Il risultato è che le seguenti due scritture sono fondamentalmente uguali, eccetto per un dettaglio:

La prima non produce una notice, mentre la seconda ci segnala qualcosa del tipo:

Notice: Undefined index: valore in index.php on line 9

Facciamo un altro esempio con entrambe:

La prima scrittura restituisce Mario senza ulteriori errori, l’oggetto non è dichiarato, quanto l’attributo; la seconda produce ancora due notice:

Notice: Undefined variable: studente in index.php on line 15

Notice: Trying to get property 'nome' of non-object in index.php on line 15

A questo punto potremmo anche scrivere:

Per dichiarare l’oggetto laddove inesistente, mentre la seguente scrittura produrrebbe sempre una notice:

A questo punto potremmo scrivere altre due equivalenze, dal punto di vista del risultato:

Ovviamente possiamo sfruttare l’operatore per altre aggregazioni del tipo:

Dove il risultato è 42, ovvero il primo valore non null della sequenza.

4. Virgola finale negli argomenti di funzione

Adesso è possibile dimenticarsi una virgola dopo l’ultimo argomento di una funzione, senza che il PHP si agiti per questo 🙄

Mentre sia nel PHP 5 che nel PHP 7 la seguente dicitura non provocava problemi:

Provare a fare lo stesso con una funzione, che accetti argomenti predefiniti o meno, provoca un errore:

Nel PHP 5 entrambe le funzioni avrebbero prodotto un errore del tipo:

Parse error: syntax error, unexpected ')' in index.php on line 12

Personalmente non la trovo un’innovazione strepitosa, ma va bene, adesso sappiamo che c’è.

5. Migrazione a PCRE2

Il PHP utilizza in generale PCRE per l’interpretazione delle espressioni regolari. Nel PHP 7.3 è stato finalmente introdotto l’utilizzo del PCRE2 che ha aspetti un po’ più stringenti e severi sulla sintassi. Facciamo un esempio, immaginando di avere una stringa dalla quale vogliamo trovare tutte le parole, compreso il simbolo (meno) e il . (punto); nel PHP 5 entrambe le seguenti scritture sarebbero state valide:

Soprassediamo sul fatto che i caratteri speciali verranno saltati e considerati alla stregua di spazi, ma il risultato sarà qualcosa di simile a:

 

Usando la prima espressione regolare all’interno di un programma come il Notepad++ avremmo ottenuto un errore:

Mentre la seconda è valida. Adesso anche nel PHP 7.3 la seconda espressione è l’unica valida, mentre la prima non funziona producendo un errore del tipo:

Warning: preg_match_all(): Compilation failed: invalid range in character class at offset 3 in index.php on line 10

Giusto per curiosità, se si volessero prendere anche i caratteri speciali potremmo utilizzare la seguente espressione regolare:

6. Unicode Codepoint Escape Syntax

Visto che si parla di stringhe facciamo un piccolo appunto a proposito dei riferimenti ai caratteri Unicode. Adesso è possibile specificarli direttamente nelle stringhe di testo con la sintassi \u{XXX}. Maggiori approfondimenti si possono trovare qui sul sito ufficiale. Questo significa che scrivendo:

Nel PHP 5 vedremo la stringa tale e quale:

\u{202E}Testo inverso

Mentre nel PHP 7 vedremo:

‮Testo inverso

Il carattere in questione è il U+202E RIGHT-TO-LEFT OVERRIDE

Si possono usare tutti i caratteri unicode, anche quelli associati agli smile, per cui echo "\u{1F602}"; produrrà ?

7. Chiamata di errore nella codifica JSON

Adesso è finalmente possibile forzare il JSON a sollevare un errore in caso di stringhe non (de)codificabili. E’ possibile infatti scrivere nel modo seguente:

Senza l’aggiunta di JSON_THROW_ON_ERROR non ci sarebbe nessuna segnalazione di errore. Grazie a tale istruzione otteniamo invece il seguente errore fatale:

Fatal error: Uncaught JsonException: Syntax error in index.php:8 Stack trace: #0 index.php(8): json_decode('stringa JSON no...', NULL, 512, 4194304) #1 {main} thrown in index.php on line 8

8. Exceptions per i fatal errors

A proposito di errori, finalmente è stato migliorato il sistema di cattura delle eccezioni con try… catch. Primo era sostanzialmente, per farla breve, necessario chiamare throw new Exception(); per sollevare un’eccezione. Adesso è possibile intercettare anche le eccezioni di sistema. Nel caso precedente l’eccezione è intercettabile con:

Come altro esempio immaginiamo di chiamare una funzione non esistente:

Nel dobbiamo usare Error per intercettare l’errore, e mentre nel PHP 5 avremmo comunque avuto il seguente output:

Fatal error: Call to undefined function funzione() in index.php on line 9

Mentre nel PHP 7 avremmo il seguente valore, prodotto dal nostro echo:

errore: Call to undefined function funzione()

9. Classi anonime

Tra le varie novità vi è la possibilità di implementare classi anonime. Cominciamo dall’esempio più semplice:

Nel PHP 5 questo produrrebbe un errore del tipo:

Parse error: syntax error, unexpected 'class' (T_CLASS) in index.php on line 7

Alla classe anonima possono essere passati anche degli argomenti per il costruttore, nel modo seguente:

L’output invece che Mario sarà Luigi. Le classi anonime possono anche estendere altre classi, come ad esempio:

Oppure implementarle:

Senza implementare il metodo stampaNome() avremmo il seguente errore:

Fatal error: Class class@anonymous contains 1 abstract method and must therefore be declared abstract or implement the remaining methods (Studente::stampaNome) in index.php on line 11

10. Dichiarazione del tipo di dato restituito

Il PHP 7 introduce la possibilità di forzare il tipo di dato restituito da una funzione. Immaginiamo di voler scrivere una funzione somma che restituisca solamente valori interi. Nella maniera classica avremmo scritto:

Passando come argomento 2.5 e 3 il risultato sarebbe stato 5.5, un float. Per forzare l’output di un intero avremmo potuto scrivere:

In PHP 7 è possibile anche scrivere:

Sintassi che nel PHP 5 avrebbe prodotto il seguente errore:

Parse error: syntax error, unexpected ':', expecting '{' in index.php on line 7

11. Metodo is_countable()

In PHP 7 è possibile verificare se un oggetto sia “conteggiabile” ovvero sia del tipo Countable. Immaginiamo la seguente serie di istruzioni:

Essendo Studenti conteggiabile viene stampato il conteggio. Nel PHP 5 avremmo ovviamente avuto un errore del tipo:

Fatal error: Call to undefined function is_countable() in index.php on line 19

Facciamo un altro esempio di funzione implementabile su Countable e dove ci può tornare utile il nuovo metodo:

In questo caso non abbiamo bisogno di chiamare la funzione count() all’interno di public function count(), ma possiamo tenere traccia della quantità di voci aggiunte al vettore $studenti tramite un contatore interno.

12. Primi e ultimi valori e chiavi di un array

Immaginiamo di avere un array di questo tipo:

Alla maniera precedente avremmo potuto scrivere:

In questo modo avremmo ottenuto un output del genere:

primo valore: 1
prima chiave: a
ultimo valore: 100
ultima chiave: c

Questo implica anche che stiamo spostando il cursore nella posizione attuale dell’array. Se provassimo a scrivere:

Il risultato non sarebbe corretto e avremmo:

primo valore: 1
ultimo valore: 100
prima chiave: c
ultima chiave: c

Quindi questa scrittura sarebbe stata impossibile. Ora, con il PHP 7.3 è possibile scrivere nel modo seguente:

Le funzioni proposte sono attualmente: array_key_first(), array_key_last() and array_value_first(), array_value_last() anche se sono state introdotte, nel PHP 7.3 solamente quelle riguardanti le chiavi. Maggiori dettagli sulla questione qui: PHP RFC: array_key_first(), array_key_last() and array_value_first(), array_value_last()

13. Il metodo Closure->call

Nel PHP 7 viene introdotta una semplificazione nell’atto di binding delle closure.

 

Se sembra che tutti si stia dicendo cose a caso vediamo un esempio:

Notiamo che la funzione scritta su $closure va ad integrare la classe, potendo interagire con tutte le sue variabili interne anche se private.

14. Prestazioni migliorate

Infine il PHP 7 introduce notevoli implementazioni in termini di performance. Di seguito riporto i risultati di benchmark ottenuti grazie a benchmark-php su un medesimo server, ma con due diverse versioni di PHP. In particolare la versione PHP 7.3 introduce notevole stabilità nell’esecuzione e nel mantenimento delle performance.

PHP 7.3.5 PHP 5.6.40

 

[wordpress] Cambiare le bandierine per le lingue di PolyLang

Per cambiare le immagini delle bandiere delle lingue del plugin PolyLang è sufficiente procedere nella maniera seguente:

  1. Creare dei file PNG (*.png), JPG (*.jpg) o SVG (*.svg) nominandoli secondo il codice della lingua, ad esempio: it_IT per italiano, en_GB o en_US per inglese (dipende quale si è scelto nelle impostazioni di PolyLang), de_DE per il tedesco ecc
  2. Creare la cartella /wp-content/polylang (la cartella non esiste di predefinito)
  3. Caricare nella cartella i file delle bandiere creati in precedenza
  4. Andare su WordPress in Bacheca > Lingue > Impostazioni > Modifiche dell’URL > Impostazioni, senza dover apportare modifiche premere su Salva modifiche

A questo punto le nuove bandiere saranno visibili al posto di quelle predefinite.

[excel] Calcolare tutte le possibili combinazioni con ripetizione usando le matrici in Excel

Obiettivo: dato un insieme di elementi distinti n vogliamo calcolare tutte le possibili combinazioni che si possono formare con k degli n elementi dati, dove k \in \mathbb{N}

Secondo il calcolo combinatorio il numero di combinazioni con ripetizione che possiamo ottenere si calcola con la seguente formula:

C'_{(n,k)}=\left(\begin{matrix} n+k-1 \\ k \end{matrix} \right)=\frac{(n+k-1)!}{k!(n-1)!}

Con Excel vogliamo ottenere una matrice contenente tutti gli elementi, dove ogni elemento può essere testuale o numerico. A tale scopo utilizzeremo le caratteristiche sul calcolo matriciale introdotte recentemente in Office365 e le seguenti funzioni: INDICE, INDIRETTO, MATR.TRASPOSTA, RIPETI, UNICI, STRINGA.ESTRAI, FILTRO

Prima di procedere ricordiamo che UNICI e FILTRO sono per ora disponibili solo con Office365. Inoltre useremo il # (cancelletto) nella costruzione dei riferimenti, per prendere gli intervalli dinamici generati dalle matrici.

Definiamo quindi anzitutto gli elementi n e il numero di ripetizioni k in questo modo:

Nella riga 1 potremo aggiungere altri elementi a piacere, mentre in B2 inseriremo il numero di ripetizioni desiderate. Per praticità ho chiamato gli elementi A, B e C.

Cominciamo allora calcolando anzitutto il numero di elemento n nella cella B3:

Adesso vogliamo determinare il numero di disposizioni con ripetizione possibili, ovvero tutti i modi in cui possiamo disporre gli n elementi presi a gruppi di k, dove conta l’ordine.

Per chi non fosse pratico dell’argomento se abbiamo i suddetti 3 elementi, allora nelle combinazioni con ripetizione ABC e ACB sono la stessa combinazione (contengono ciascuna tutti e 3 gli elementi), mentre nelle disposizioni con ripetizione ABC e ACB sono elementi distinti.

Il numero totale di disposizioni con ripetizione sarà dato dalla formula:

D'_{(n,k)}=n^k

Che tradotta in Excel possiamo scrivere in B5 come:

Date queste informazioni calcoliamo tutti gli elementi possibili con la seguente formula in B11:

Questa genererà un risultato come il seguente:

L’idea è fondamentalmente quella di generare una matrice di riferimenti agli elementi dati in modo ordinato. Con 3 elementi presi 3 per volta avremo in tutto 27 disposizioni con ripetizione. Generiamo allora una matrice colonna con valori [1…27]. Nella prima colonna da [1…9] avremo il primo elemento, da [10…18] avremo il secondo elemento e così via. Siccome il primo elemento corrisponde a 1 e il secondo a 2, questo significa che presi i valori da [1…27] li dovremo dividere in 3 parti di 9 elementi ciascuna.

Questo lo potremmo ottenere scrivendo:

In questo modo generiamo [1…27] e dividiamo per 9, poi arrotondiamo per eccesso il risultato. Ne seguirà che, arrotondati per eccesso, 1/9 ⇒ 1, 9/9 ⇒ 1, 10/9 ⇒ 2, 18/9 ⇒ 2, 19/9 ⇒ 3, 27/9 ⇒ 3. Avremo insomma tre intervalli fatti, rispettivamente, di [1…1], [2…] e [3…3], ciascuno di 9 sottoelementi.

Nell’immagine di seguito vediamo la schematizzazione di ciò che vogliamo ottenere:

Per ciascun gruppo della prima colonna vorremo ottenere, nella seconda colonna, altri 3 sottogruppi, per ciascuno dei quali, nella terza colonna, vorremo ottenere altri 3 sottogruppi (questa volta di dimensione 1). Quindi i gruppi saranno 1, 3 e 9. Questi sono anche i valori per i quali dobbiamo sezionare gli intervalli delle colonne.

Per generare questi valori usiamo:

La matrice trasposta ci serve per metterli in riga, anziché in colonna. Dividiamo infine la prima colonna per questa riga.

Fatto questo spostiamoci in I10 e digitiamo:

In questo modo riportiamo semplicemente gli elementi scritti da B1 in poi.

In I11 calcoliamo quante volte appare ciascun elemento della matrice in B11#:

NB: grazie al cancelletto selezioniamo tutta la matrice generata da B11.

Il risultato che avremo sarà:

Nella prima riga A è presente 3 volte, gli altri due elementi 0 volte. Nella seconda riga abbiamo 2 A e 1 B, ecc.

In questo caso stiamo semplicemente usando la funzione CONTA.PIÙ.SE su righe successive, per ciascuno dei valori immessi.

A questo punto, sapendo quanti sono i singoli valori, possiamo usare la funzione RIPETI per riscriverli. Tale funzione ripete un dato valore per n volte. Quindi in P11 scriviamo:

Otterremo un risultato come il seguente:

Adesso facciamo una mossa un po’ astrusa. Siccome sappiamo che per ogni riga ci sono k elementi, ovvero 3 elementi, concateniamo tutta la matrice in una singola stringa e la spezziamo in pezzi da 3 elementi per volta. Verrà quindi una lunghissima stringa che comincerà con AAAAABAACAABABBABCAAC… e che verrà spezzata in AAA, AAB, AAC, AAB, ABB ecc.

Per farlo in W11 digitiamo:

La parte di formula con:

Genera una matrice colonna tipo:

La usiamo per spezzare la stringa in parti da 3 a partire dal 1° carattere, il 4° carattere, il 7° carattere ecc.

Il risultato che otterremo saranno tutte le disposizioni con ripetizione di cui parlavamo prima:

Per ottenere le combinazioni con ripetizione che stavamo cercando possiamo fare in due modi.

1. Utilizzando la funzione UNICI

In Z11 scriviamo:

E ricaviamo immediatamente l’elenco ridotto delle combinazioni in questo modo:

Questa è la maniera più semplice e veloce.

2. Utilizzando la funzione FILTRO

Questo è un modo un pizzico più complicato. Per ciascuno dei valori in W11# vogliamo calcolare la presenza del valore stesso nelle righe precedenti. Per farlo utilizzeremo la funzione SCARTO, aumentando la altezza della colonna della matrice di controllo via via che scendiamo. A questa applicheremo il CONTA.SE per vedere se il valore attuale, cioè ciascun valore della matrice, è presente nella sottomatrice precedente calcolata con SCARTO. Confrontando questo valore con 1, ovvero che debba comparire una sola volta, costruiremo la matrice colonna per il filtro da applicare alla funzione FILTRO.

La formula quindi sarà:

In entrambi i casi il risultato sarà identico:

Dal seguente link è possibile scaricare il file Excel con tutti i calcoli già fatti: combinazioni semplici

[PCSX2] Giocare a Harry Potter e il prigioniero di Azkaban per PS2 su PC con PCSX2

Harry Potter e il prigioniero di Azkaban uscì per PS2 nel 2004. Se avete ancora il gioco, ma non una PlayStation2 e volete provare a giocarci da PC una possibile soluzione è utilizzando l’emulatore PCSX2.

Ringrazio @Memento_Gallery per la foto

Prima di procedere premetto che questo è uno di quei giochi (tutta la serie di Harry Potter per PS2 sembra essere affetta dal medesimo problema) che sugli emulatori dà più rogne che altro.

Anzitutto vediamo di cosa abbiamo bisogno:

  1. Emulatore PCSX2 v1.5.0-dev-3362 (quella su cui ho testato la presente soluzione)
  2. Emulatore joystick PS4 DS4Windows (se intendete usare un DualShock 4 come il sottoscritto, altrimenti basta un qualunque controller compatibile con Windows)
  3. BIOS originale della PS2 da utilizzare su PSCX2 (rimando a internet su come procurarselo)
  4. File ISO del gioco. Se avete il gioco su DVD come il sottoscritto, potete masterizzare un file ISO direttamente dal computer inserendo il gioco nel lettore.

Prima di cominciare scarichiamo ed installiamo il PCSX2.

Possiamo lasciare tutte le impostazioni sui parametri predefiniti, finché non si arriverà alla scelta del BIOS della PS2. A quel punto selezioniamo la cartella dove abbiamo il file del BIOS e scegliamo la versione che preferiamo, io ho quella Europea naturalmente.

A questo punto configuriamo l’emulatore con i parametri riportati di seguito.

Anzitutto andiamo su Configurazione > Impostazioni emulazione > Speed Hack

image.png

Qui spuntiamo la voce MTVU (microVU1 multi-threaded).

Andiamo su Configurazione > Video (GS) > Impostazioni plugin… e configuriamo i parametri nel modo seguente:

image.png

Clicchiamo su Advanced Settings and Hacks e modifichiamo i parametri come i seguenti:

image.png

A questo punto andiamo su Configurazione > Audio (SPU2) > Impostazioni plugin… ed impostiamo i parametri come quelli di seguito:

image.png

Fatto questo possiamo caricare la ISO ed avviare il gioco.

Se state usando un controller PS4 consiglio di avviare DS4Windows prima dell’emulatore, per far sì che lo veda come un controller standard di Windows.

[excel] Sommare tariffe giornaliere diverse in base alla data utilizzando le matrici in Excel

Obiettivo: Immaginiamo di voler calcolare il costo dei pernottamenti in un albergo dove le tariffe variano in base alla stagione (nello specifico in base ai mesi) e si ha una data di ingresso e il numero di notti.

Una soluzione a questo esercizio l’ho già proposta sul blog di Mummu Academy, giocando un po’ con le matrici: [EXCEL] SOMMARE TARIFFE GIORNALIERE DIVERSE PER DATA USANDO LE MATRICI IN EXCEL

La soluzione che propongo qui è più semplice e sintetica e fa uso sempre del calcolo matriciale in Excel.

Come nel suddetto esercizio la nostra base di partenza è un foglio in Excel contenente i seguenti dati:

I dati che vogliamo generare sono quelli dell’intervallo G2:G6.

Anzitutto vogliamo ottenere una matrice contenente tutte le date di pernottamento. Per farlo prenderemo ciascuna data di partenza e sommeremo i giorni corrispondenti. Se dobbiamo sommare 5 notti allora alla data di partenza dovremo sommare il vettore [0, 1, 2, 3, 4]. Faccio notare come il vettore parta da 0. Questo perché, nel caso di Mario Rossi, i pernottamenti li avremo nei giorni [21/06/2019, 22/06/2019, 23/06/2019, 24/06/2019, 25/06/2019]. La prima data deve essere anche quella di arrivo.

Generiamo quindi anzitutto il vettore dei giorni come detto prima, sfruttando RIF.RIGA e INDIRETTO nel modo seguente:

Questo genererà un vettore simile a questo:

Adesso possiamo sommare a questo vettore la data di partenza:

Il vettore che potremo vedere a schermo (grazie anche alle nuove funzionalità di espansione di Excel) sarà come il seguente:

Dall’elenco delle date vogliamo adesso estrarre il mese corrispondente utilizzando la funzione MESE.

Il risultato dell’operazione sarà simile a questo:

Il numero 6 rappresenta il mese di giugno. Se applicassimo questa formula a Chiara Celesti vedremmo un risultato simile a questo:

Faccio notare come alla fine del mese di dicembre si passi da 12 a 1, ovvero a gennaio.

A questo punto possiamo usare il CERCA.VERT su ciascuno di questi valori per ricavare la tariffa che ci interessa. La formula diventerà dunque:

In questo modo otterremo un vettore contenente la tariffa per ogni singolo giorno. Non ci resta che usare la SOMMA.

La formula diventerà quindi:

A questo punto possiamo espandere la formula da G2 a G6. Se abbiamo fatto tutto correttamente otterremo i seguenti risultati:

[FIFA20] Configurazione firewall di Fastweb per consentire la connessione online

Premetto che non dovrebbe essere necessario aggiungere il gioco al firewall del router di Fastweb e che, la maggior parte dei problemi di connessione, dipende dai server della EA o altri elementi mistici fuori dalla nostra comprensione umana.

A tale proposito rimando agli articoli dove ho affrontato la cosa in modo più generale:

[FIFA19] La connessione con l’avversario si è interrotta

[FIFA20] La connessione con l’avversario si è interrotta

Qui voglio vedere quali sono le porte che devono essere aperte sul router e, nel caso specifico, come configurare il router di Fastweb.

Anzitutto il modello del mio router è un MediaAccess TG788vn v2 della Technicolor (quelli recenti in dotazione con Fastweb).

Per accedere al router, se non sappiamo come fare, procediamo nella maniera seguente. Premiamo WIN+R e digitiamo cmd.

Si aprirà il Prompt dei comandi. Digitiamo ipconfig e premiamo INVIO.

Dovremmo vedere qualcosa di simile:

L’indirizzo Gateway predefinito è l’indirizzo del router. Nel mio caso aprirò quindi il browser per andare sul web e digiterò: http://192.168.1.254

Si aprirà la schermata di accesso al router. I dati di accesso predefiniti dovrebbero essere:

username: fastweb

password: lasciare vuoto

Nel caso di dubbi si possono trovare i manuali online sul sito stesso di Fastweb, come questo qui: Technicolor TG788VN

Una volta dentro il router spostiamoci su Casella degli strumenti > Condivisione giochi e applicazioni

Clicchiamo su Crea un nuovo gioco o una nuova applicazione

Si aprirà una schermata nella quale dovremo immettere le porte da assegnare allo specifico gioco o applicazione.

Per l’elenco delle porta necessarie a tale scopo si può consultare il sito della EA: Aprire le porte per risolvere i problemi di connessione

Nel caso specifico di FIFA le porte da aprire sono le seguenti:

Le porte che devono essere aperte per FIFA20 da PC sono: UDP 3659, 9565, 9570, 9000 – 9999, TCP 3569, 9946, 9988, 10000 – 20000, 42124.

Configuriamo quindi le porte per il dispositivo che ci interessa, io le configurerò per il gioco da PC, nel modo seguente:

Quando è tutto pronto clicchiamo su Applica in cima, dopo aver assegnato un nome al gioco. Torniamo alla schermata precedente e selezioniamo Assegna un gioco o un’applicazione a un dispositivo di rete locale.

Selezioniamo dal menu a tendina il gioco appena configurato e il nome del nostro dispositivo (nel mio caso è il nome del mio computer) e premiamo su Applica.

Faccio notare che devono essere attive le opzioni Usa UPnP e Usa attivazione estesa.

Se abbiamo fatto tutto correttamente possiamo tornare a provare a giocare.

Installare Ubuntu 19.10 con webserver pronto all’uso [per esordienti assoluti]

Abbiamo già visto come installare Ubuntu 18.04.2 LTS e Ubuntu 16.04.2 LTS predisponendoli per fare da webserver. Oggi voglio ripetere la procedura con Ubuntu 19.10.

Prima di andare avanti vorrei far notare come questa non sia una versione LTS, ossia una distribuzione con supporto a lungo termine, quindi ne sconsiglio caldamente l’installazione per progetti di lunga portata.

Detto ciò proseguiamo come di consueto utilizzando VirtualBox ai fini di questa guida, benché la procedura sarebbe analoga per chiunque lo volesse installare su una macchina fisica.

Gli argomenti trattati saranno:

  1. Configurazione ed installazione Ubuntu Server 19.10
  2. Installazione e configurazione Apache
  3. Installazione e configurazione MySQL
  4. Installazione e configurazione PHP
  5. Installazione di phpMyAdmin
  6. Ulteriori configurazioni

1. Configurazione Ubuntu Server 19.10

Anzitutto andiamo sul sito ufficiale di Ubuntu e procuriamoci la ISO per l’installazione. Assicuriamoci di selezionare la versione server e poi premiamo download:

A questo punto andiamo a creare la nostra macchina virtual con VirtualBox. All’interno di VirtualBox premiamo su CTRL+N per avviare l’installazione di una nuova macchina.

Diamo un nome alla macchina e scegliamo eventualmente il percorso di installazione, come nell’immagine di sopra. Assicuriamoci anche che il tipo sia settato su Linux e la Versione su Ubuntu (64-bit). Premiamo su Successivo.

Selezioniamo la quantità di memoria da destinare alla macchina virtuale (1GB è più che sufficiente). Ancora Successivo.

Lasciamo l’opzione selezionata Crea subito un nuovo disco fisso virtuale per crearne uno nuovo e andiamo avanti.

Se non abbiamo esigenze specifiche lasciamo il tipo di disco su VDI e procediamo avanti.

Lasciamo l’allocazione del disco su Allocato dinamicamente. In questo modo il disco crescerà solo in presenza di file effettivi, occupando meno spazio sulla macchina ospite. Andiamo avanti.

Diamo un po’ di spazio ad Ubuntu, visto che comunque andrà ad occupare solo quello necessario, mettendo il disco su 20GB.

A questo punto nell’elenco delle nostre macchine virtuali vedremo comparire quella con Ubuntu.

Una volta selezionata spostiamoci in alto e clicchiamo sul tasto verde Avvia per farla partire.

Al primo avvio ci verrà chiesto se caricare una ISO per l’avvio della macchina virtuale. Clicchiamo sulla cartellina gialla e poi selezioniamo la ISO che abbiamo scaricato in precedenza, se abbiamo fatto tutto bene, prima di procedere avanti, vedremo una situazione simili alla seguente:

Aspettiamo che compaia la sezione della selezione della lingua. Tanto per cambiare manca l’italiano, perciò proseguirò in inglese (o per fare uno scherzo proseguo in croato!).

Premiamo INVIO. Ci potrebbe chiedere se vogliamo aggiornare l’installer, diciamo di sì premendo di nuovo INVIO.

Adesso ci verrà chiesto il layout della tastiera. Dal momento che sto usando una tastiera italiana dovrò impostare il layout su Italian, come nell’immagine in alto, altrimenti potrei avere problemi specialmente con i caratteri speciali. Per farlo mi sposto in alto con le frecce direzionali e seleziono il menu premendo SPAZIO. Una volta trovata la voce giusta premo nuovamente INVIO. Dopodiché posso tornare alla voce Done e premere INVIO per procedere.

Mi verrà chiesto di configurare la rete, posso premere nuovamente INVIO e andare avanti.

Sulle impostazioni del proxy, a meno di non essere a conoscenza di diversa configurazione, lascio tutto com’è e premo INVIO.

L’indirizzo del mirror per la repository lo posso lasciare tale e quale, premendo ancora INVIO.

Alla voce successiva seleziono la seconda opzione, quella di configurazione dell’intero disco con utilizzo di LVM. Per approfondimenti sull’argomento consiglio LVM, gestore logico dei volumi su Ubuntu [per pinguini alle prime armi]

Mi verrà chiesto quale disco utilizzare, avendone uno soltanto non ho molto da scegliere, in caso contrario potrei selezionare il disco sul quale intendo installare le partizioni principali del server.

A questo punto mi verrà proposto un riassunto di tutte le modifiche che saranno applicate al disco. Se non ho altre esigenze posso premere INVIO e procedere.

Comparirà un avviso che mi segnalerà che l’intero contenuto del disco adesso verrà cancellato e sostituito con la nuova installazione; mi sposto con le frecce direzionali su Continue e premo INVIO.

Adesso inseriamo il nostro nome, scegliamo un nome per il server e username e password, compilando i campi come di seguito.

Una volta compilati tutti i campi premiamo INVIO.

A questo punto ci viene chiesto se vogliamo installare anche il server OpenSSH, che ci permetterà di collegarci in SSH al nostro server. Premiamo la SPAZIO per selezionare l’opzione e poi premiamo INVIO. Prima di premere invio la configurazione dovrebbe apparire come la seguente.

Saltiamo la selezione di snaps per il server (ovvero configurazioni preconfezionate, come viene spiegato alle singole voci). Spostiamoci in basso e selezioniamo semplicemente Done e poi premiamo INVIO.

Se abbiamo fatto tutto bene comincerà un’installazione come la seguente:

Una volta terminata ci verrà chiesto di riavviare il sistema e rimuovere il supporto di installazione. Premiamo semplicemente INVIO.

Se ci dovessero essere problemi con l’unmounting del cdrom, e dovesse comparire una schermata come quella di seguito, sarà sufficiente premere INVIO un’altra volta per dire al sistema di procedere comunque (VirtualBox avrà già smontato l’ISO per conto suo probabilmente).

A questo punto ci si dovrebbe trovare di fronte ad una schermata simile alla seguente:

Faccio notare che continua a persistere il ridicolo problema delle ultimissime versioni di Ubuntu, per cui la schermata di login appare prima che sia terminato il processo di avvio, cosa che riempie la shell di output anche dopo l’apparizione del prompt di ingresso.

Per effettuare il login sarà sufficiente premere nuovamente INVIO e poi digitare il nome utente e la password che abbiamo creato in precedenza.

Adesso, prima di procedere, voglio configurare la scheda di rete di VirtualBox, in modo da poter utilizzare Putty per collegarmi alla macchina virtuale. Lo faccio principalmente per poter copiare ed incollare i comandi sul terminale, cosa non possibile dall’interfaccia di VirtualBox stesso.

Per spegnere il sistema operativo digitiamo quindi:

Una volta spenta la macchina virtuale torniamo sull’interfaccia di VirtualBox e andiamo su File > Preferenze (che possiamo aprire anche premendo CTRL+G)

Andiamo su Rete e clicchiamo sul piccolo pulsante della scheda con il più verde sulla destra che ci permetterà di creare una nuova Rete con NAT da far utilizzare alla nostra macchina virtuale.

Configuriamo la rete nel modo seguente:

Clicchiamo su Inoltro del porte e configuriamo le porte da inoltrare dalla scheda di rete virtuale sul nostro computer alla rete interna di VirtualBox.

Configuriamo l’inoltro delle seguenti porte:

 

Stiamo dando per scontato che la macchina virtuale si troverà all’indirizzo 10.0.2.4 della rete interna (che è tipicamente l’indirizzo predefinito che viene assegnato dal DHCP di VirtualBox).

Detto questo premiamo OK su tutte le finestre aperte e torniamo alla nostra macchina virtuale. Dopo averla selezionata premiamo il tasto Impostazioni (vicino a quello di Avvio).

Dalla schermata delle Impostazioni andiamo su Rete e selezioniamo Rete con Nat, scegliendo dal menu sottostante la Rete Ubuntu che abbiamo creato prima.

Fatto tutto questo premiamo OK e avviamo di nuovo la nostra macchina virtuale. Una volta che sarà ripartita apriamo Putty e digitiamo come indirizzo di connessione 192.168.56.1

Premiamo OK. Se abbiamo fatto tutto correttamente ci verrà chiesto di effettuare la connessione.

Apparirà una schermata che ci chiederà di copiare la chiave di crittografia. Premiamo .

Inseriamo le credenziali e siamo pronti a procedere oltre.

2. Installazione e configurazione Apache

Adesso procediamo con l’installazione di Apache. Aggiorniamo anzitutto tutti i riferimenti della repository digitando:

Dopodiché digitiamo:

Alla domanda se proseguire digitiamo Y e poi premiamo INVIO. Aspettiamo che l’installazione termini. Se tutto è andato bene aprendo l’indirizzo http://192.168.56.1/ dal nostro browser dovremmo vedere la schermata predefinita del webserver Apache nel modo seguente:

3. Installazione e configurazione MySQL

Adesso installiamo il Server MySQL per il database. Per farlo digitiamo:

Come al solito confermiamo l’installazione con Y e aspettiamo che sia terminata.

Una volta terminata l’installazione digitiamo:

Questo avvierà una procedura di configurazione del nostro database, durante la quale ci verranno richieste diverse cose. Alle varie domande rispondiamo rispettivamente:

Press y|Y for Yes, any other key for No: Y

Please enter 0 = LOW, 1 = MEDIUM and 2 = STRONG: 2

(dove: STRONG Length >= 8, numeric, mixed case, special characters and dictionary file)

New password: 4y!7dz=6/%lF-4fes2=lkpl|E^DTL*  (questo è un esempio di password che possiamo mettere, questa password ha una qualità di 180bit e una lunghezza di 30 caratteri)

Se la passowrd è buona ci verrà detto qualcosa come:

Estimated strength of the password: 100

Proseguiamo:

Do you wish to continue with the password provided?(Press y|Y for Yes, any other key for No) : Y

Remove anonymous users? (Press y|Y for Yes, any other key for No) : Y

Disallow root login remotely? (Press y|Y for Yes, any other key for No) : Y

Remove test database and access to it? (Press y|Y for Yes, any other key for No) : Y

Reload privilege tables now? (Press y|Y for Yes, any other key for No) : Y

Fatto questo il database è pronto per essere utilizzato.

L’utente predefinito del database sarà root e la password quella che abbiamo scelto prima.

4. Installazione e configurazione PHP

Adesso installiamo il PHP, aggiungendo la libreria per Apache e quella per il database MySQL.

Faccio notare che in questo modo verrà installato l’ultimo PHP disponibile, che nel mio caso specifico, come si può vedere anche dall’immagine di seguito, è il PHP 7.3.

Una volta installato il PHP verifichiamo che sotto Apache siano configurate le pagine predefinite come index.php per l’esecuzione. Digitiamo:

Se va tutto bene sotto la voce DirectoryIndex dovremmo trovare, tra gli altri file, anche index.php. Se così non fosse lo aggiungiamo come nell’immagine seguente:

Nel caso avessimo modificato il file salviamo il tutto premendo CTRL+O, altrimenti direttamente CTRL+X per uscire dall’editor.

Fatte tutte queste belle cose riavviamo Apache.

5. Installazione di phpMyAdmin

Per installare il phpMyAdmin utilizzeremo il composer, per cui installiamolo digitando:

Il composer è uno strumento per la gestione delle dipendenze e delle librerie del PHP, che ci permette di installare progetti in PHP come è per l’appunto il phpMyAdmin.

A questo punto installiamo il minimo indispensabile per usare il phpMyAdmin digitando:

Riavviamo Apache digitando come al solito:

Fatto tutto questo possiamo procedere con l’installazione vera e propria. Spostiamoci anzitutto dentro a /var/www:

Assegniamo il nostro utente alla cartella html (che è la cartella predefinita del nostro webserver raggiungibile dall’indirizzo di prima):

Entriamo dentro con:

A questo punto installiamo qui il nostro phpMyAdmin, che creerà una sua cartella alla quale assegneremo successivamente Apache come utente. In realtà la cartella del phpMyAdmin potrebbe essere creata a nostro piacimento in qualsiasi posizione, purché abbia un senso per noi. Tradizionalmente viene inserito sotto etc oppure share. Io l’ho inserito direttamente sotto www per una questione di ordine. (Qualora la si dovesse mettere altrove dovremmo ricordarci di aggiungere il percorso anche ai VirtualHost)

ATTENZIONE! composer non va lanciato come root/super user, quindi non va utilizzato sudo anteposto al commando. 

Aspettiamo con pazienza l’esito dell’installazione che potrebbe richiedere qualche minuto, soprattutto all’inizio quando non sembra succedere niente di che. Se tutto è andato bene vedremo un output come quello di seguito.

In caso di errore assicuriamoci di aver installato tutte le librerie per il PHP come di sopra e di aver riavviato Apache.

Prima di testare il phpMyAdmin così installato ripristiniamo sulla cartella html l’utente predefinito di Apache digitando:

A questo punto digitiamo nel browser http://192.168.56.1/phpmyadmin/

Se abbiamo fatto tutto bene dovremmo vedere qualcosa come questo:

Provando ad inserire root e la password creata in precedenza potremmo incorrere nel seguente errore:

Nessun problema. Torniamo sul terminale e digitiamo:

Inseriamo la password creata in precedenza per l’utente root. (per capirsi nel mio caso la password era 4y!7dz=6/%lF-4fes2=lkpl|E^DTL*)

Creiamo un utente apposito per gestire il database da phpMyAdmin. Per farlo eseguiamo la seguente sequenza di query:

L’utente così creato sarà:

username: admin

password: HGOqXovUhyZJ4}08}eg-lAiOM])}@lYt

Proviamo ad accedere con tali dati da http://192.168.56.1/phpmyadmin/

Nel caso dovesse apparire l’errore mysqli::real_connect(): The server requested authentication method unknown to the client [caching_sha2_password] eseguiamo i seguenti due comandi sul database.

Se è andato tutto bene possiamo riprovare ad accedere e vedremo una situazione simile a questa.

6. Ulteriori configurazioni

A questo punto abbiamo finito la configurazione principale e dovremmo fare ancora qualche implementazione, configurando cose come:

  1. Sistemare il Firewall
  2. Mettere in sicurezza Apache
  3. Configurare fail2ban ed altri eventuali servizi
  4. Aggiungere un VirtualHost al webserver