Sviluppare applicazioni web professionali in PHP 7

di Enrico Zimuel
Senior Software Engineer
Zend Technologies, una società Rogue Wave (USA)


Università Torino, Dipartimento di Informatica, 11 Dic. 2017

Enrico Zimuel

www.sviluppareinphp7.it

PHP

  • PHP: Hypertext Preprocessor
  • Il linguaggio server-side più utilizzato al mondo: PHP è utilizzato dall'83.1% di tutti i siti web (fonte: w3techs.com)
  • Alcuni utenti del PHP: Facebook, Wikipedia, Yahoo, Etsy, Flickr, Digg, etc
  • 22 anni di utilizzo, dal 1995
  • Completamente ad oggetti (OOP) dal PHP 5

L'ecosistema PHP

PHP 7

  • 7.2.0 (30 Nov 2017)
  • 7.1.12 (24 Nov 2017)

Performance

PHPNG, PHP Next Generation

Progetto di Dmitry Stogov (Zend)

Riscrittura completa del sistema di gestione dei dati nel core

Notevoli miglioramenti di performance!

Benchmark


$a = [];
for ($i = 0; $i < 1000000; $i++) {
  $a[$i] = ["hello"];
}
echo memory_get_usage(true);
PHP 5.6 PHP 7
Memoria 428 MB 33 MB
Tempi di esecuzione 0.49 sec 0.06 sec

Altri linguaggi

PHP 7 è anche più veloce di Python 3!

Wordpress

Casi di studio

  • Badoo risparmia un milione di dollari l'anno grazie a PHP 7 (fonte)
  • Tumblr riduzione del 50% della latenza e del carico della CPU, grazie a PHP 7 (fonte)
  • Dailymotion gestisce il doppio del traffico web con la stessa infrastruttura, grazie a PHP 7 (fonte)
Versione Rilascio Supporto attivo Security fix
5.6 28 Ago 2014 19 Gen 2017 31 Dic 2018
7.0 3 Dic 2015 3 Dic 2017 3 Dic 2018
7.1 1 Dic 2016 1 Dic 2018 1 Dic 2019
7.2 30 Nov 2017 30 Nov 2019 30 Nov 2020

PHP 6 ?

Supporto Unicode a livello del linguaggio

Mai rilasciato, progetto abbandonato

Sviluppo di applicazioni professionali in PHP 7

Punti essenziali

  • Scelta del framework di sviluppo
  • Versionamento dei sorgenti
  • Dipendenze con librerie esterne
  • Testare il codice
  • Log e monitoring
  • Gestione degli errori e delle eccezioni
  • File di configurazione
  • Deploy in produzione
  • Persistenza dei dati
  • Sicurezza

Framework di sviluppo

Laravel, Symfony, Zend Framework

Expressive, Lumen, Slim, Silex

Versionamento

Git

github.com, bitbucket.org

Gestione dipendenze

Composer

composer.json:


{
    "require": {
        "monolog/monolog": "1.0.*"
    }
}

Test

PHPUnit


use PHPUnit\Framework\TestCase;

class EmailTest extends TestCase
{
    // ...

    public function testCanBeUsedAsString(): void
    {
        $this->assertEquals(
            'user@example.com',
            Email::fromString('user@example.com')
        );
    }
}

Log e monitoring

error_log()

monolog

Errori ed Eccezioni

set_error_handler(), set_exception_handler()

Throwable: Error, Exception

File di configurazione

Yaml, Json, Xml, Ini, oppure PHP


// config.php
return [
    'db' => [
        'dsn' => 'mysql:dbname=test;host=127.0.0.1',
        'user' => 'test',
        'password' => 'dH34f23q8Bvdrt34'
    ]
];

// index.php
$config = require 'config.php'; // $config['db']['dsn']

Deploy in produzione

Deployer, Ansible

Vagrant, Docker

Persistenza dei dati

PHP Data Objects (PDO)

Object Relational Mapper (ORM): Doctrine, Propel

Sicurezza

Filter Input, Escape Output

password_hash(), password_verify()

OpenSSL: openssl_encrypt/decrypt, Sodium

Novità 7.1

Tipo Nullable

  • Per parametri e valori di ritorno di funzioni
  • Sintassi: aggiunta del ? prima del tipo
  • null può essere passato come argomento,
    o restituito come valore

Example


function hi(?string $name): ?string
{
    return $name ? 'Hello ' . $name : null;
}

echo hi(null); // returns null
echo hi('Enrico'); // returns 'Hello Enrico'
echo hi(); // Fatal error

Ritorno di tipo Void


function swap(&$left, &$right): void
{
    if ($left === $right) {
        return;
    }
    $tmp   = $left;
    $left  = $right;
    $right = $tmp;
}

$a = 1;
$b = 2;
var_dump(swap($a, $b), $a, $b);

Iterable

  • Aggiunto lo pseudo-tipo iterable
  • Accetta array o Traversable
  • Utilizzato in parametri e ritorno di funzioni

Esempio


function foo(iterable $iterable): void
{
    foreach ($iterable as $value) {
        var_dump($value);
    }
}

foo([1,2,3]);
foo(new ArrayIterator([1,2,3]));

Costanti di classe


class ConstDemo
{
    const CONST_A = 1; // public
    public const CONST_B    = 2;
    protected const CONST_C = 3;
    private const CONST_D   = 4;
}

Catch multipli


try {
   // Some code...
} catch (ExceptionA | ExceptionB $e) {
   // Handle exceptions A or B
} catch (\Exception $e) {
   // ...
}

Indici negativi


var_dump("abcdef"[-2]); // string(1) "e"
var_dump("abcdef"[-7]); // string(0) "", PHP Notice
// strpos
var_dump(strpos("aabbcc", "b", -3)); // int(3)

// get the last character of a string
$last = substr($foo, -1); // before PHP 7.1
$last = $foo[-1];

OpenSSL AEAD

Cifratura e autenticazione (Authenticated Encryption)

Supporto modalità GCM e CCM

GCM è 3 volte più veloce di CCM. Dettagli benchmark

Più informazioni su Authenticated Encryption in PHP 7.1

Funzionalità deprecate

Mcrypt

Utilizzare OpenSSL al suo posto

PHP 7.2

  • 7.2.0 (30 Nov 2017)

Alcune novità

Performance

PHP 7.2 è 20% più veloce di 7.0 e 10% di 7.1
Fonte: benchmark di Michael Larabel

Tipo Object

Utilizzabile come parametro e ritorno di tipo


function foo(object $obj): string {
    return $obj->var;
}

function bar(MyClass $arg): object {
    return $arg;
}

Type overriding

E' possibile omettere il tipo di un parametro su classi astratte estese:


abstract class A
{
    abstract function test(string $s);
}

abstract class B extends A
{
    abstract function test($s) : int;
}

SQL sent

Aggiunta informazione di debug su PDO: la query SQL generata da PDOStatement


$pdo = new PDO(
    'mysql:dbname=test;host=localhost',
    'user',
    'password'
);
$sth = $pdo->prepare(
    "SELECT * FROM user WHERE active=:active"
);
$sth->execute(['active' => true]);
$sth->debugDumpParams();

SQL sent (2)


SQL: [39] SELECT * FROM user WHERE active = :active
Sent SQL: [35] SELECT * FROM user WHERE active='1'
Params:  1
Key: Name: [7] :active
paramno=-1
name=[7] ":active"
is_param=1
param_type=2

Argon2

Supporto algoritmo Argon2i per l'hash delle password


$password = 'test';
$hash = password_hash($password, PASSWORD_ARGON2I);
var_dump($hash);

$hash conterrà una stringa di 98 caratteri

Sodium

Supporto crittografia moderna con la nuova estesione Sodium basata sulla libreria libsodium

Grazie!

Contatti: enrico [at] zimuel.it

Web: www.zimuel.it

Twitter: @ezimuel



Creative Commons License
Questa presentazione è rilasciata con licenza
Creative Commons Attribution-ShareAlike 3.0 Unported License.
Presentazione realizzata con reveal.js