Quoi de neuf sur Symfony et PHP ? - Prisma Media

Quoi de neuf sur Symfony et PHP ? - Prisma Media

Revue des nouveautés de PHP 5.5 à 7.2
Nouveaux composants Symfony, introduction à Symfony Flex
Présentation destinée aux développeurs Prisma Media.

5a3c823a1badc6b0815aeea42cc93b72?s=128

Jérôme Tamarelle

July 06, 2017
Tweet

Transcript

  1. What’s New ? PHP et Symfony Romain JACQUART & Jérôme

    TAMARELLE — jeudi 6 juillet 2017
  2. Au programme... 1. Piqûre de rappel concernant PHP 5.5 et

    5.6 2. Les nouveautés PHP 7.0 et 7.1 3. Les nouveaux composants Symfony 4. Que nous réserve Symfony 4 ?
  3. PHP 5.5 Juin 2013

  4. 5% De gain de performance entre PHP 5.4 et PHP

    5.5
  5. Générateur — mot clé yield • Permet d’implémenter un itérateur,

    sans la complexité d’implémenter l’interface Iterator • Réduit la mémoire requise lors de la construction d’un jeu de données http://php.net/manual/en/language.generators.overview.php
  6. Générateur — mot clé yield Un exemple avec @dataProvider de

    PHPUnit /** * @dataProvider myData */ public function testSomething($data, $expected) { // ... } public function myData() { yield ['data1', 'expected_data1']; yield ['data2', 'expected_data2']; yield ['data3', 'expected_data3']; } http://php.net/manual/en/language.generators.overview.php
  7. Ajout du mot clé finally Dans un try / catch,

    il est possible d’ajouter un bloc finally, dont le code sera exécuté quel que soit le résultat try { // Code à tester } catch (Exception $e) { // Code en cas d'exception } finally { // Code exécuté dans tous les cas } http://php.net/manual/en/language.exceptions.php
  8. Résolution de classe ::class Il est possible de récupérer le

    FQN (Fully Qualified Name) d’une classe, grâce à ::class namespace Name\Space; class ClassName {} echo ClassName::class; // Name\Space\ClassName" use App\Security\Hasher; $this->prophesize(Hasher::class); http://php.net/manual/en/language.oop5.basic.php#language.oop5.basic.class.class
  9. list() dans les foreach Il est possible d’utiliser list() directement

    depuis un foreach, afin d’y extraire des variables distinctes $array = [ [1, 2], [3, 4], ]; foreach ($array as list($a, $b)) { echo "A: $a; B: $b\n"; } // A: 1; B: 2 // A: 3; B: 4 http://php.net/manual/en/control-structures.foreach.php#control-structures.foreach.list
  10. Expressions arbitraires dans un empty() empty() supporte désormais tout autre

    type que des variables function always_empty() { return ''; } if (empty(always_empty())) { // Ce code sera exécuté } http://php.net/manual/en/function.empty.php#refsect1-function.empty-parameters
  11. Il est désormais possible de déréférencer directement des array et

    des string Déréférencement littéral des array et string [1, 2, 3][0] // Retourne 1 'PHP'[0] // Retourne P range(10, 20)[3]; // 13 http://php.net/manual/en/migration55.new-features.php#migration55.new-features.const-dereferencing
  12. Nouvelle fonction array_column() $records = [ ['id' => 12, 'name'

    => 'John'], ['id' => 15, 'name' => 'Sally'], ['id' => 24, 'name' => 'Jane'], ]; $names = array_column($records, 'name'); // ['John', 'Sally', 'Jane'] $names = array_column($records, 'name', 'id'); // [12 => 'John', 15 => 'Sally', 24 => 'Jane'] http://php.net/manual/en/function.array-column.php Retourne les valeurs d’une colonne d’un tableau Le troisième argument permet de garder les clés
  13. Nouvelle API de hachage • password_get_info() — Retourne des informations

    à propos du hachage fourni • password_hash() — Crée une clé de hachage pour un mot de passe • password_needs_rehash() — Vérifie que le hachage fourni est conforme à l'algorithme et aux options spécifiées • password_verify() — Vérifie qu'un mot de passe correspond à un hachage http://php.net/manual/en/book.password.php
  14. PHP 5.6 Août 2014

  15. 5% De gain de performance entre PHP 5.5 et PHP

    5.6
  16. Une constante peut maintenant évaluer des expressions scalaires Mais également

    contenir des tableaux Expressions de constante const UN = 1; // 1 const DEUX = UN * 2; // 2 const TROIS = DEUX + 1; // 3 const TOTAL = 'Total: '.(UN + DEUX + TROIS); // "Total: 6" const NUMBERS = [UN, DEUX, TROIS]; // [1, 2, 3] http://php.net/manual/en/language.constants.syntax.php
  17. L’opérateur … peut être utilisé pour créer une fonction variable

    (variadic function), remplaçant func_get_args() Fonctions variables avec … function fn($req, $opt = null, ...$params) { var_dump($req, $opt, $params); } fn(1); // 1, null, [] fn(1, 2); // 1, 2, [] fn(1, 2, 3); // 1, 2, [3] fn(1, 2, 3, 4); // 1, 2, [3, 4] fn(1, 2, 3, 4, 5); // 1, 2, [3, 4, 5] http://php.net/manual/en/functions.arguments.php#functions.variable-arg-list
  18. L’opérateur … (ou splat) peut être utilisé pour décompresser des

    tableaux et des objets Traversable, dans la liste d’arguments Décompression des arguments avec … function add($a, $b, $c) { return $a + $b + $c; } $operators = [2, 3]; echo add(1, ...$operators); // 6 http://php.net/manual/en/migration56.new-features.php#migration56.new-features.splat
  19. Les fonctions array_replace() et array_merge() sont variables Aussi avec array_replace()

    http://php.net/manual/en/migration56.new-features.php#migration56.new-features.splat $configs = [ ['key1' => 'first array', 'key2' => 0], ['key1' => 'second array'], ]; // Avant PHP 5.6 array_replace($configs[0], $configs[1]); // Après PHP 5.6 array_replace(...$configs); // ['key1' => 'second array', 'key2' => 0]
  20. L’opérateur use supporte l’import de fonctions et constantes use const

    et use function namespace Name\Space { const FOO = 42; function fn() { echo "Hello"; } } namespace { use const Name\Space\FOO; use function Name\Space\fn; echo FOO; // 42 fn(); // Hello } http://php.net/manual/en/language.namespaces.importing.php
  21. PHP 7.0 Décembre 2015

  22. 57% De gain de performance entre PHP 5.6 et PHP

    7.0
  23. Gestion des erreurs • La plupart des erreurs fatales ont

    été remplacées par des levées d’exceptions (ParseError, TypeError…) • Ces exceptions héritent toutes de la classe Error, qui elle-même implémente l’interface Throwable • Throwable est la nouvelle interface de base pour tout objet pouvant être lancé par le mot clé throw http://php.net/manual/en/language.errors.php7.php
  24. Gestionnaire d’erreur (exception handler) • Comme pour toutes exceptions, ces

    Error vont remonter jusqu’au premier bloc catch • Si aucun bloc catch n’a été trouvé, le gestionnaire d’erreur défini par set_exception_handler() sera appelé • Si aucun gestionnaire d’erreur n’a été défini et qu’il n’y a pas de gestionnaire par défaut, alors une erreur fatale — à l’ancienne – sera lancée http://php.net/manual/en/language.errors.php7.php
  25. Un gestionnaire d’erreur n’est plus certain de recevoir uniquement des

    objets Exception Gestionnaire d’erreur Exception vs Error // Ne fonctionne qu’en PHP 5 function handler(Exception $e) { ... } set_exception_handler('handler'); // Compatible PHP 5 et 7 function handler($e) { ... } // Ne fonctionne qu’en PHP 7 function handler(Throwable $e) { ... } http://php.net/manual/en/function.set-exception-handler.php
  26. 4 types scalaires ont été ajoutés, afin d’enrichir le typage

    actuel : string, int, float et bool Typage scalaire des paramètres function fn(string $a, int $b, float $c, bool $d) { var_dump($a, $b, $c, $d); } fn('Hello', 4, 2.5, true); // string(5) "Hello" // int(4) // float(2.5) // bool(true) fn('Hello', 'World', 2.5, true); // Fatal error: Uncaught TypeError: Argument 2 passed // to fn() must be of the type integer, string given http://php.net/manual/en/functions.arguments.php#functions.arguments.type-declaration
  27. Il est possible de typer la valeur de retour d’une

    fonction Ce typage implique un transtypage de la valeur retournée Déclaration des types de retour function greet(string $name): string { return "Hello $name!"; } var_dump(greet('World')); // string(12) "Hello World!" function sum($a, $b): float { return $a + $b; } var_dump(sum(1, 2)); // float(3) http://php.net/manual/en/functions.returning-values.php#functions.returning-values.type-declaration
  28. Retourne la première valeur, depuis la gauche vers la droite,

    qui existe et différente de NULL Opérateur d’union nul (null coalescing) $username = $_GET['user'] ?? 'anonymous'; // Est l'équivalent de : $username = isset($_GET['user']) ? $_GET['user'] : 'anonymous'; // Il peut être chaîné : $username = $_GET['user'] ?? $_POST['user'] ?? 'anonymous'; http://php.net/manual/en/language.operators.comparison.php
  29. Retourne -1, 0 ou 1 lorsque $a est respectivement inférieur,

    égal ou supérieur à $b Opérateur combiné (spaceship operator) // Entiers echo 1 <=> 2; // -1 echo 1 <=> 1; // 0 echo 2 <=> 1; // 1 // Strings echo 'a' <=> 'b'; // -1 echo 'a' <=> 'a'; // 0 echo 'b' <=> 'a'; // 1 // Tableaux echo [1, 2] <=> [1, 3]; // -1 echo [1, 2] <=> [1, 2]; // 0 echo [1, 2] <=> [1, 1]; // 1 http://php.net/manual/en/language.operators.comparison.php
  30. Il est possible de définir une constante dont la valeur

    est un tableau Définition de constante avec un tableau define('ANIMALS', [ 'dog', 'cat', 'bird', ]); echo ANIMALS[1]; // "cat" http://php.net/manual/en/language.constants.syntax.php
  31. list() assigne désormais les variables dans le sens normal de

    définition, contrairement au sens inverse Changements concernant list() list($a[], $a[], $a[]) = [1, 2, 3]; var_dump($a); // PHP 5: [3, 2, 1] // PHP 7: [1, 2, 3] http://php.net/manual/en/function.list.php
  32. Il n’est plus possible d’utiliser un list() vide Changements concernant

    list() $a = [1, 2, 3]; list() = $a; list(,,) = $a; list($x, list(), $y) = $a; // Fatal error: Cannot use empty list http://php.net/manual/en/function.list.php
  33. Les classes, fonctions et constantes d’un même namespace peuvent être

    groupées lors de l’import Déclarations groupées avec use // Avant PHP 7 use Name\Space\ClassA; use Name\Space\ClassB as B; use function Name\Space\fnA; use function Name\Space\fnB; use const Name\Space\CONST_A; use const Name\Space\CONST_B; // Après PHP 7 use Name\Space\{ClassA, ClassB as B}; use function Name\Space\{fnA, fnB}; use const Name\Space\{CONST_A, CONST_B}; http://php.net/manual/en/language.namespaces.importing.php#language.namespaces.importing.group
  34. Il est possible de créer des classes anonymes grâce à

    new class, lorsque de simples objets uniques ont besoin d’être créés Classes anonymes $logger = new class { public function log($msg) { echo $msg; } }; var_dump($logger); // object(class@anonymous)#1 (0) {} $logger->log('Hello world'); // Hello world http://php.net/manual/en/language.oop5.anonymous.php
  35. Celles-ci peuvent étendre et implémenter d’autres classes Classes anonymes use

    Psr\Log\AbstractLogger; $logger = new class extends AbstractLogger { public function log($level, $message, array $context = []) { echo "[$level] $message"; } }; $logger->info('Hello World!'); // [info] Hello World! http://php.net/manual/en/language.oop5.anonymous.php
  36. Un return final peut être récupéré avec Generator::getReturn() mais uniquement

    après avoir passé tous les yield du générateur return final d’un générateur $generator = (function () { yield 1; yield 2; return 'The end!'; })(); foreach ($generator as $value) { echo "$value "; } // 1 2 echo $generator->getReturn(); // "The end!" http://php.net/manual/en/generator.getreturn.php
  37. Permet d’obtenir les valeurs d’un autre générateur, d’un objet Traversable

    ou d’un tableau Délégation du générateur avec yield from function count_to_ten() { yield 1; yield from new ArrayIterator([2, 3, 4]); yield from five_to_ten(); } function five_to_ten() { yield from [5, 6, 7, 8, 9, 10]; } foreach (count_to_ten() as $num) { echo "$num "; } // 1 2 3 4 5 6 7 8 9 10 http://php.net/manual/en/language.generators.syntax.php#control-structures.yield.from
  38. Adieu mysql_query() Les extensions mysql et mssql ont été retirées

    Il n’est donc plus possible d’utiliser les fonctions associées, comme : mysql_connect(), mysql_query(), mysql_fetch_array()... Alternatives : PDO ou mysqli http://php.net/manual/en/ref.mysql.php - http://php.net/manual/en/ref.mssql.php
  39. Adieu ereg_replace() Le support des expressions rationnelles avancées de POSIX

    a été supprimé Il n’est donc plus possible d’utiliser les fonctions associées, comme : ereg(), ereg_replace(), split()... Alternative : les expressions rationnelles Perl (PCRE) http://php.net/manual/en/ref.regex.php
  40. PHP 7.1 Décembre 2016

  41. 30% De gain de performance entre PHP 7.0 et PHP

    7.1
  42. Le type des paramètres d’une fonction peut être marqué comme

    nullable en le préfixant de ? Ajout du nullable avec ? function fn(?string $name) { var_dump($name); } fn('Hello'); // string(5) "Hello" fn(null); // NULL fn(); // Fatal error: Uncaught ArgumentCountError: // Too few arguments to function fn() http://php.net/manual/en/functions.arguments.php#functions.arguments.type-declaration
  43. Et également sur le type de retour d’une fonction Ajout

    du nullable avec ? function fn(?string $name): ?string { return $name; } var_dump(fn('Hello')); // string(5) "Hello" var_dump(fn(null)); // NULL http://php.net/manual/en/functions.arguments.php#functions.arguments.type-declaration
  44. Les fonctions de type void ne doivent rien retourner Ajout

    du type de retour void function no_return(): void { // valide } function empty_return(): void { return; // valide } function returns_one(): void { return 1; // Fatal error: A void function must not return a value } function returns_null(): void { return null; // Fatal error: A void function must not return a value } https://wiki.php.net/rfc/void_return_type
  45. La notation courte des tableaux peut être utilisée en remplacement

    du list() Déstructuration symétrique de tableau $data = [ [12, 'John'], [15, 'Doe'], ]; [$id, $name] = $data[0]; // Identique à : list($id, $name) = $data[0]; // Ou dans un foreach foreach ($data as [$id, $name]) { var_dump($id, $name); } https://wiki.php.net/rfc/short_list_syntax
  46. La visibilité d’une constante de classe est maintenant supportée Visibilité

    des constantes de classe class Demo { public const CONST_A = 1; protected const CONST_B = 2; private const CONST_C = 3; } var_dump(Demo::CONST_A); // int(1) var_dump(Demo::CONST_B); // Fatal error: Uncaught Error: Cannot access protected const var_dump(Demo::CONST_C); // Fatal error: Uncaught Error: Cannot access private const http://php.net/manual/en/language.oop5.constants.php
  47. A l’image du pseudo-type callable, celui-ci n’accepte que des tableaux

    ou objets Traversable Pseudo-type iterable function foo(iterable $iterable) { foreach ($iterable as $value) { // ... } } function bar(): iterable { return [1, 2, 3]; } function generator(): iterable { yield 1; yield 2; } http://php.net/manual/en/language.types.iterable.php
  48. Il est possible d’attraper plusieurs exceptions, dans un même bloc

    catch avec | Multi catch d’Exception try { // Code à tester } catch (FirstException | SecondException $e) { // Code traitant l'exception } http://php.net/manual/en/language.exceptions.php#language.exceptions.catch
  49. Des clés peuvent être spécifiées dans un list() afin de

    faciliter le mapping Support des clés dans un list() $data = [ ['id' => 1, 'name' => 'Tom'], ['id' => 2, 'name' => 'Fred'], ]; // list() style list('id' => $id, 'name' => $nickname) = $data[0]; // [] style ['id' => $id, 'name' => $nickname] = $data[0]; // foreach [] style foreach ($data as ['id' => $id, 'name' => $nickname]) { // Code traitant $id et $nickname } http://php.net/manual/en/function.list.php
  50. Possible de fournir un offset négatif lors d’une manipulation de

    string Offset de string négatif $string = 'bar'; echo "Le dernier caractère de '$string' est '$string[-1]'."; // "Le dernier caractère de 'bar' est 'r'." http://php.net/manual/en/language.types.string.php#language.types.string.substr
  51. Une exception est levée, plutôt qu’un warning, lors d’un appel

    à une fonction personnalisée où il manque des arguments Exception lors d’un manque d’argument function fn($param) { var_dump($param); } fn(); // Avant PHP 7.1 : // Warning: Missing argument 1 for fn() // Après PHP 7.1 : // Fatal Error: Uncaught ArgumentCountError: // Too few arguments to function fn() http://php.net/manual/en/migration71.incompatible.php#migration71.incompatible.too-few-arguments-exception
  52. La construction d’un DateTime sur l’heure courante prend en compte

    les microsecondes DateTime gère les microsecondes var_dump(new DateTime() == new DateTime()); // Avant PHP 7.1 : bool(true) // Après PHP 7.1 : bool(false) http://php.net/manual/en/migration71.incompatible.php#migration71.incompatible.datetime-microseconds
  53. Performances

  54. Performances Résultat immédiat d’une montée de version https://twitter.com/acasademont/status/710444965596426241

  55. Performances Résultat immédiat d’une montée de version https://www.cloudways.com/blog/php-5-6-vs-php-7-symfony-benchmarks/

  56. PHPUnit

  57. Utilisation des namespace avec PSR-4 Toutes les classes du coeur

    de PHPUnit 6.0 ont été renommées pour utiliser les namespaces // Avant PHPUnit 6.0 class SerialiserTest extends \PHPUnit_Framework_TestCase { public function testSerialize() {} } // Depuis PHPUnit 6.0 use PHPUnit\Framework\TestCase; class SerialiserTest extends TestCase { public function testSerialize() {} } https://thephp.cc/news/2017/02/migrating-to-phpunit-6
  58. Symfony Assets

  59. JSON Manifest — Symfony 3.3 http://symfony.com/blog/new-in-symfony-3-3-manifest-based-asset-versioning / webpack-manifest-plugin # app/config/config.yml

    framework: assets: json_manifest_path: '%kernel.root_dir%/../web/build/manifest.json' { "css/app.css": "build/css/app.b91642.css", "images/logo.png": "build/images/logo.136309.png" } <link href="{{ asset('/css/app.css') }}"> <img src="{{ asset('images/logo.png') }}" />
  60. WebLink Component • Transmet au navigateur des liens de ressources

    à pré-charger, en passant des headers HTTP Link • Utile pour le “Server Push” HTTP/2 • Intègre les helpers Twig link(), preload(), dns_prefetch(), preconnect(), prefetch(), prerender() http://symfony.com/blog/new-in-symfony-3-3-weblink-component
  61. Webpack Encore — Abandon de Assetic • Assetic c’est totalement

    dépassé • Objectif : faciliter la prise en main de webpack https://www.npmjs.com/package/@symfony/webpack-encore Symfony ne seraient-ils pas en train de se disperser ? https://symfony.com/blog/introducing-webpack-encore-for-asset-management
  62. Symfony Dependency Injection

  63. Autowire Définir un service sans déclarer explicitement les dépendances namespace

    AppBundle\Service; class TwitterClient { function __construct(HttpClient $client) {} function setLogger(LoggerInterface $log) {} } https://symfony.com/doc/current/service_container/autowiring.html services: _defaults: autowire: true autoconfigure: true public: false AppBundle\Service\TwitterClient: public: true
  64. Chargement automatique Détection automatique des nouvelles classes et enregistrement des

    services http://symfony.com/doc/master/service_container/3.3-di-changes.html # app/config/services.yml services: App\Service\: resource: 'src/AppBundle/Service' App\Controller\: resource: 'src/AppBundle/Controller' public: true tags: ['controller.service_arguments']
  65. Symfony Components

  66. Cache — Symfony 3.1 Implémente PSR-16 Complète Doctrine\Cache • Invalidation

    par tags • Expiration Intégré au framework $cache = new TagAwareAdapter( // Adapter for cached items new FilesystemAdapter(), // Adapter for tags new RedisAdapter('redis://localhost') ); $item = $cache->getItem('cache_key'); $item->tag(['tag_2', 'tag_3']); $cache->save($item); $cache->invalidateTags(['tag_1', 'tag_3']); http://symfony.com/doc/current/components/cache.html — https://symfony.com/blog/new-in-symfony-3-1-cache-component
  67. Workflow — Symfony 3.2 Flux de travail Article Démo :

    Flux de travail d’un article (sources) https://symfony.com/doc/current/components/workflow.html
  68. WebServerBundle — Symfony 3.3 Extrait du FrameworkBundle : activé uniquement

    en dev. http://symfony.com/blog/new-in-symfony-3-3-webserverbundle
  69. Dotenv — Symfony 3.3 Défini des valeurs par défaut pour

    les variables d’environnement parameters.yml remplacé par le fichier .env # .env DEBUG=true DATABASE_URL=mysql://root@127.0.0.1:3306/symfony https://symfony.com/doc/current/components/dotenv.html # config.yml doctrine: dbal: url: '%env(DATABASE_URL)%'
  70. Lock — Symfony 3.4 Verrouille l’accès à une ressource pendant

    un temps déterminé pour éviter les traitements parallèles $store = new MemcachedStore($memcached, $ttl) $factory = new Factory($store); $lock = $factory->createLock('pdf-generation'); if ($lock->acquire()) { // The resource "pdf-generation" is locked. $lock->release(); } http://symfony.com/blog/new-in-symfony-3-3-lock-component
  71. Symfony 4

  72. Variables d’environnement • Recommandation du 12 factor Application Manifesto •

    Plus standard que le fichier parameters.yml • bin/console --env=prod devient SYMFONY_ENV=prod bin/console • 1 seul fichier de contrôleur public/index.php configuré par nginx
  73. Nouvelle structure de répertoires Nouveauté Symfony 3.4 : %kernel.project_dir% donne

    la racine du projet Conception bundle-less .env (remplace parameters.yml) config/ packages/ doctrine.yaml bundles.php routing.yaml public/ (remplace web) index.php src/ Controllers/ Kernel.php templates/ (remplace views) base.html.twig tests/ var/ (cache, logs) Makefile http://fabien.potencier.org/symfony4-directory-structure.html
  74. Symfony Flex • Skeleton épuré : juste un composer.json •

    Plugin composer pour configurer les packages installés en utilisant des recipes officielles ou contribuées par la communauté • Impose des conventions
  75. None
  76. Merci pour votre écoute