Lightning Talks
Tirage au sort (Part I)
Inscrivez vous sur t.afup.org pour participer au tirage au sort pour gagner un grand elePHPant AFUP!!
Audrey Neveu
Depuis 2012
+6500 enfants !
L'enVar du décor
Damien Alexandre
12 Factor
So 2011 ou toujours d'actualité ?
@damienalexandre - JoliCode - L'enVar du décor
Chapitre 3
Exposez la
🔐 configuration 🔐
en variable d'environnement
@damienalexandre - JoliCode - L'enVar du décor
-
La configuration d'une application varie d'un déploiement à un autre, le code jamais ;
-
Les variables d'environnement sont facile à changer sans modifier le code, sans vider le cache... ;
-
Les variables d'environnement sont indépendantes du langage et du système d'exploitation.
@damienalexandre - JoliCode - L'enVar du décor
Pourquoi ?
@damienalexandre - JoliCode - L'enVar du décor
# Configuration PHP FPM (par exemple)
[www]
env[DATABASE_HOSTNAME] = 'covfefe'
env[DATABASE_PORT] = '123'
# Dans le code
$db->connect($_SERVER['DATABASE_HOSTNAME'], $_SERVER['DATABASE_PORT']);
# Mais aussi :
getenv('DATABASE_HOSTNAME');
$_ENV['DATABASE_HOSTNAME'];
Comment ?
Aucun fichier à parser, tout au runtime !
@damienalexandre - JoliCode - L'enVar du décor
Est-ce sûr ?
@damienalexandre - JoliCode - L'enVar du décor
Est-ce sûr ?
- Une variable passée à un process sera aussi passée à tous ses enfants (leak) ;
- Considéré dangereux par certains Ops ;
- Au final il y aura toujours des secrets sur le disque 💽 (configuration FPM, Crontab...)
@damienalexandre - JoliCode - L'enVar du décor
Dois-je les utiliser ?
Ça dépend.
- Infrastructure de production ?
- Docker 🐳 ?
- Cloud / Heroku / AWS / GCE ?
- Mutualisé gratuit chez free.fr ?
- Info-géreur "moderne" qui "maîtrise" son sujet ?
Parfois obligatoires, parfois impossible, parfois pas la recommandation...
@damienalexandre - JoliCode - L'enVar du décor
Configurez comme vous êtes !
@damienalexandre - JoliCode - L'enVar du décor
On s'y met ?
Dommage pour votre Klout Hacker News 🤓
@damienalexandre - JoliCode - L'enVar du décor
💣 Les pièges 🎃
Nommer les choses
- Adopter une convention propre à votre application ;
- Préfixer c'est le bien, le monde Unix le fait :
- LC_
- GTK_
- NODE_…
- Upper Snake Case : FORUM_PHP.
@damienalexandre - JoliCode - L'enVar du décor
Déclarer les partout
- PHP-FPM
- Crontabs
- Script de déploiement ou de build
- PHP-CLI...
Oublier une variable c'est le crash assuré.
💣 Les pièges 🎃
@damienalexandre - JoliCode - L'enVar du décor
Le préfixe HTTP_
- PHP expose les headers HTTP dans
$_SERVER
- Ils sont préfixés par "HTTP_"
- PHP expose les variables d'environnement
dans $_SERVER (ainsi que $_ENV...) - Vous souvenez vous de HTTPoxy ?
💣 Les pièges 🎃
@damienalexandre - JoliCode - L'enVar du décor
Thread Safe
- La fonction PHP getenv('MY_VAR')
n'est pas thread safe ; - Dans certaines configurations,
elle ne retourne pas de résultats ; - Lui préférer $_SERVER['MY_VAR'],
plus rapide et plus fiable !
💣 Les pièges 🎃
@damienalexandre - JoliCode - L'enVar du décor
Type string
- Les Env Vars sont toujours des strings
- Attention au type cast PHP 7 !
public function connect(string $hostname, int $port)
{
}
// This will not work properly:
$db->connect($_SERVER['DATABASE_HOSTNAME'], $_SERVER['DATABASE_PORT']);
💣 Les pièges 🎃
@damienalexandre - JoliCode - L'enVar du décor
Mes recommandations
- Utilisez les env vars si le cœur vous en dit ;
- Attention à leur scope et aux process enfants ;
- N'utilisez que $_SERVER pour les lire ;
- N'y exposer que ce qui change entre environnements ;
- Implémentez un .env dans la stack locale.
@damienalexandre - JoliCode - L'enVar du décor
💕 Merci l'AFUP 💕
- Plus d'informations sur notre blog !
- @damienalexandre
Et vous, comment exposez-vous vos
🔐 secrets 🔐 en production ?
Venez me voir à l'apéro communautaire !
Text
Frédéric Bouchery
ISSET
<?php
$isset = 'isset';
var_dump($isset($x));
Fatal error: Uncaught Error: Call to undefined function isset()
Secrêts d'isset - @FredBouchery - Figaro-ccmbenchmark
<?php
var_dump(
isset(UNKNOWN_CONST)
);
Fatal error: Cannot use isset() on the result of an expression
Secrêts d'isset - @FredBouchery - Figaro-ccmbenchmark
<?php
var_dump(
isset($x = null)
);
Fatal error: Cannot use isset() on the result of an expression
Secrêts d'isset - @FredBouchery - Figaro-ccmbenchmark
<?php
$v = 'x';
var_dump(isset($$v));
bool(false)
Secrêts d'isset - @FredBouchery - Figaro-ccmbenchmark
<?php
var_dump(isset($$v));
bool(false)
Secrêts d'isset - @FredBouchery - Figaro-ccmbenchmark
<?php
$s = ' ';
var_dump(
isset(trim($s))
);
Fatal error: Cannot use isset() on the result of an expression
Secrêts d'isset - @FredBouchery - Figaro-ccmbenchmark
<?php
$s = ' ';
var_dump(
empty(trim($s))
);
bool(true)
>= PHP 5.5
Secrêts d'isset - @FredBouchery - Figaro-ccmbenchmark
<?php
isset($x);
isset($array['a']['b']['c']);
isset($x->prop);
Secrêts d'isset - @FredBouchery - Figaro-ccmbenchmark
Variable existe ?
Secrêts d'isset - @FredBouchery - Figaro-ccmbenchmark
<?php
$x = null;
var_dump(isset($x));
bool(false)
Secrêts d'isset - @FredBouchery - Figaro-ccmbenchmark
$var !== null
+
notice
Secrêts d'isset - @FredBouchery - Figaro-ccmbenchmark
<?php
$array = ['belette' => null];
var_dump(
array_key_exists('belette', $array)
);
<?php
$array = [];
isset($array[$x]);
Notice: Undefined variable: x
Secrêts d'isset - @FredBouchery - Figaro-ccmbenchmark
<?php
$array = [];
isset($x, $array[$x]);
Secrêts d'isset - @FredBouchery - Figaro-ccmbenchmark
<?php
$object = new class {
function __get($name) { return 1; }
};
var_dump(
isset($object->x),
$object->x
);
bool(false)
int(1)
Secrêts d'isset - @FredBouchery - Figaro-ccmbenchmark
<?php
$object = new class {
function __get($name) { return 1; }
function __isset($name) { return true; }
};
var_dump(
isset($object->x),
$object->x
);
bool(true)
int(1)
Secrêts d'isset - @FredBouchery - Figaro-ccmbenchmark
<?php
var_dump($x ?? 'default');
string(7) "default"
Secrêts d'isset - @FredBouchery - Figaro-ccmbenchmark
<?php
$id = isset($_GET['id']) ? (int) $_GET['id'] : 0;
$page = isset($_GET['page']) ? (int) $_GET['page'] : 0;
$s = isset($_GET['s']) ? (int) $_GET['s'] : 1;
Secrêts d'isset - @FredBouchery - Figaro-ccmbenchmark
<?php
$_GET += [
'id' => 0,
'page' => 0,
's' => 1
];
$id = (int) $_GET['id'];
$p = (int) $_GET['page'];
$s = (int) $_GET['s'];
Secrêts d'isset - @FredBouchery - Figaro-ccmbenchmark
Text
Merci
https://quiz.ccmbg.com
@FredBouchery
Il était une fois le Web: Épisode 1 - Les User agents
Benjamin Clay
LE WEB
Ep1: Les User Agents
Les User Agents
Merci !
Des questions ?
NCSA_Mosaic/2.0
(Windows 3.1)
NCSA_Mosaic/2.0
(Windows 3.1)
Mozilla/1.0
(Win3.1)
Mosaic Killer
NCSA_Mosaic/2.0
(Windows 3.1)
Mozilla/1.0
(Win3.1)
^Mozilla/.*
NCSA_Mosaic/2.0
(Windows 3.1)
Mozilla/1.0
(Win3.1)
^Mozilla/.*
MSIE/2.0
(Windows 95)
NCSA_Mosaic/2.0
(Windows 3.1)
Mozilla/1.0
(Win3.1)
^Mozilla/.*
MSIE/2.0
(Windows 95)
Mozilla/1.22 (compatible; MSIE 2.0; Windows 95)
Mozilla/1.0
(Win3.1)
Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.1) Gecko/20020826
Mozilla/1.0
(Win3.1)
Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.1) Gecko/20020826
Mozilla/5.0 (Windows; U; Windows NT 5.1; sv-SE; rv:1.7.5) Gecko/20041108 Firefox/1.0
Mozilla/5.0 (Macintosh; U; PPC Mac OS X Mach-O; en-US; rv:1.7.2) Gecko/20040825 Camino/0.8.1
Mozilla/5.0 (Windows; U; Windows NT 5.1; de; rv:1.8.1.8) Gecko/20071008 SeaMonkey/1.0
Mozilla/1.0
(Win3.1)
Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.1) Gecko/20020826
Opera/9.51 (Windows NT 5.1; U; en)
Mozilla/1.0
(Win3.1)
Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.1) Gecko/20020826
Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; en) Opera 9.51
Opera/9.51 (Windows NT 5.1; U; en)
Mozilla/1.0
(Win3.1)
Mozilla/5.0 (Windows; U; Windows NT 5.0; en-US; rv:1.1) Gecko/20020826
Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; en) Opera 9.51
Mozilla/5.0 (Windows NT 6.0; U; en; rv:1.8.1) Gecko/20061208 Firefox/2.0.0 Opera 9.51
Opera/9.51 (Windows NT 5.1; U; en)
KHTML
Konqueror
Mozilla/5.0 (compatible; Konqueror/3.2; Linux) KHTML
KHTML
Konqueror
Mozilla/5.0 (compatible; Konqueror/3.2; Linux) (KHTML, like Gecko)
KHTML
Apple WebKit
Safari
Konqueror
Mozilla/5.0 (Macintosh; U; PPC Mac OS X; de-de) AppleWebKit/85.7 (KHTML, like Gecko) Safari/85.5
Mozilla/5.0 (compatible; Konqueror/3.2; Linux) (KHTML, like Gecko)
KHTML
Apple WebKit
Safari
Konqueror
Mozilla/5.0 (Macintosh; U; PPC Mac OS X; de-de) AppleWebKit/85.7 (KHTML, like Gecko) Safari/85.5
Mozilla/5.0 (compatible; Konqueror/3.2; Linux) (KHTML, like Gecko)
Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US) AppleWebKit/525.13 (KHTML, like Gecko) Chrome/0.2.149.27 Safari/525.13
Opera/9.8 (Windows NT 6.0; U; en) Presto/2.2.0
Opera/9.8 (Windows NT 6.0; U; en) Presto/2.2.0
Opera/9.8 (Windows NT 6.0; U; en) Presto/2.2.0
Opera/10.0 (Windows NT 6.0; U; en) Presto/2.2.0
media-queries // polyfills
media-queries // polyfills
HTMLMediaElement.canPlayType()
media-queries // polyfills
HTMLMediaElement.canPlayType()
- "" (non)
media-queries // polyfills
HTMLMediaElement.canPlayType()
- "" (non)
- "probably"
media-queries // polyfills
HTMLMediaElement.canPlayType()
- "" (non)
- "probably"
- "maybe"
Merci !
🍻
Workflow
Grégoire Pineau
Quand utiliser un worflow ?
Chacune des étapes est nécessaire et garantit la qualité de l’article (véracité du propos, sourcing, soin de l’écriture et de la formulation…)
Ce circuit de production et de publication est une analogie efficace de ce que l’on peut retrouver dans le code
Garantir la qualité
Pourquoi un composant ?
public function setStatus($status)
{
if ($status === $this->status) {
return;
}
if (self::STATUS_PAID === $this->status) {
if (self::STATUS_REFUNDED !== $status) {
throw new \LogicException('Cannot change status of PAID order to anything but REFUNDED.');
}
}
if (self::STATUS_CANCELLED === $this->status) {
if (self::STATUS_PAID !== $status && self::STATUS_REFUSED !== $status) {
throw new \LogicException('Cannot change status of CANCELLED order to anything but PAID or REFUSED.');
}
}
if (self::STATUS_REFUSED === $this->status) {
if (self::STATUS_PAID !== $status && self::STATUS_CANCELLED !== $status) {
throw new \LogicException('Cannot change status of REFUSED order to anything but PAID or CANCELLED.');
}
}
if (self::STATUS_REFUNDED === $this->status) {
throw new \LogicException('Cannot change status of a REFUNDED order');
}
if (self::STATUS_NEW === $this->status) {
if (self::STATUS_REFUNDED === $status) {
throw new \LogicException('Cannot change status of NEW order to REFUNDED.');
}
}
$this->status = $status;
}
OUPS
Hello Workflow
Un workflow c'est une machine à état (*) qui définie
-
des états:
- brouillon
- corrigé
- publié
-
des transitions:
- corriger : brouillon -> corrigé
- publier : relu -> publié
Qu'est ce qu'un workflow ?
* il existe d'autres type de worklow, mais j'ai pas le temps d'en parler ...
À quoi ça ressemble ?
Et dans Symfony ?
$definition = (new DefinitionBuilder())
->addPlaces(['brouillon', 'corrigé', 'publié'])
->addTransition(new Transition('corriger', 'brouillon', 'corrigé'))
->addTransition(new Transition('publier', 'corrigé', 'publié'))
->addTransition(new Transition('depublier', 'publié', 'corrigé'))
->build()
;
La Definition
Le Marking / MarkingStore
Le Marking est l'objet qui contient la liste des états (*) dans lequel est l'article.
Le MarkingStore est l'object qui s'occupe de convertir le Marking dans le format attendu par l'objet Article :
- string[]
- json
- champs de bytes
- ...
* Plusieurs états ? Oui, mais je n'ai pas le temps d'en parler ...
$article = new stdClass();
$article->marking = null;
$markingStore = new SingleStateMarkingStore();
$workflow = new Workflow($definition, $markingStore);
Le Workflow
$workflow->can($article, 'corriger'); // => true
$workflow->can($article, 'publier'); // => false
$workflow->can($article, 'depublier'); // => false
Le Workflow::can
$workflow->apply($article, 'corriger');
$workflow->can($article, 'corriger'); // => false
$workflow->can($article, 'publier'); // => true
$workflow->can($article, 'depublier'); // => false
Le Workflow::apply
C'est tout ?
Non, mais on n'a pas le temps !
- Énormément d'events (EventDispatcher)
- Pour logger ce qu'il se passe : AuditLog
- Pour bloquer des transitions : Droits utilisateurs, ...
- Une intégration avec Twig (moteur de template)
- Un support des réseaux de Pétri : plusieurs états en même temps
- Un Graphviz dumper : pour visualiser son workflow
- Une intégration avec Symfony full stack
- Une démo en ligne: http://bit.ly/workflow-php go go go
- Des slides en FR : http://bit.ly/workflow-slide
- Et plein d'autres choses encore ... mais on n'a pas le temps :(
Merci !
🍻
@lyrixx
Tirage au sort (part II)
Apéro communautaire
Rendez vous au café oz (3 Place Denfert-Rochereau) à partir de 19h30
Le premier verre et le snack est offert par l'AFUP et Blablacar
LT Forum PHP 2017
By metalmumu
LT Forum PHP 2017
shared presentation for lightning talk session of Forum PHP 2017 Paris
- 537