false
lorsqu’il rencontre une erreur.
Cela peut, par exemple, poser des problèmes avec des requêtes invalides que l’on pense avoir été jouées correctement.
Il est possible de modifier le comportement de PDO quant à sa gestion des erreurs en modifiant l’attribut gérant le mode d’erreur de l’instance que l’on utilise :
$pdo = new PDO(...);
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
PDO::ERRMODE_EXCEPTION
permet de renvoyer l’erreur sous forme d’exceptionPDO::ERRMODE_WARNING
permet de renvoyer l’erreur sous forme warningVous êtes en train de jouer avec une instance DigitalOcean qui pointe vers un-truc.evaneos.fr
et vous vous retrouvez à re-créer votre instance.
Vous souhaitez accéder à votre instance avec ssh badass@un-truc.evaneos.fr
quand, tout à coup, SSH se met à râler :
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@ WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED! @
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
IT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY!
Someone could be eavesdropping on you right now (man-in-the-middle attack)!
It is also possible that a host key has just been changed.
The fingerprint for the ECDSA key sent by the remote host is
SHA256:LQtMWzkR45zMvYHGNwfBdueYYFC64eb+33OA/tGM2yd.
Please contact your system administrator.
Add correct host key in /Users/someone/.ssh/known_hosts to get rid of this message.
Offending ECDSA key in /Users/someone/.ssh/known_hosts:22
ECDSA host key for un-truc.evaneos.fr has changed and you have requested strict checking.
Host key verification failed
Plutôt que de vous expliquer vaguement ce qui se cache derrière ce message, je vous redirige vers un thread StackExchange.
Petit avertissement : lisez bien la section Bottom line.
La première solution qui vous vient à l’esprit est d’aller éditer le fichier ~/.ssh/known_hosts
à la main et supprimer la ligne 22.
Ca fonctionne mais il y a de fortes chances que vous trouviez ça assez pénible.
Il y a, cependant, une solution bien plus simple :
ssh-keygen -R un-truc.evaneos.fr
Voici un petit extract de man ssh-keygen
pour expliquer ce que fait cette commande :
-R hostname
Removes all keys belonging to hostname from a known_hosts file.
Notez que le paramètre ${hostname}
peut être un nom d’hôte comme une adresse IP.
Lorsque vous faites un ls
dans un répertoire le process va commencer par établir une liste de tous les fichiers présents dans le répertoire. Puis essaiera de les sortir sur STDOUT
ordonnés par ordre alphabétique. Là, on sent le truc venir. Bien que ça ne pose aucun problème en règle générale, avant même de commencer à output le résultat, ls
va charger en mémoire l’intégralité des chemins des fichiers qu’il essaie de lister.
La suite, est évidemment, une occupation en RAM délirante et un CPU qui prend le tarif de sa vie (un excellent moyen de crasher une machine) et le mieux pire là dedans, c’est que vous ne verrez pas apparaître, ne serait-ce que, la première ligne du résultat.
Une solution est d’utiliser find
, qui, à l’inverse de ls
travaille de façon incrémentale.
❯ find . -maxdepth 1
L’ennui c’est que find
prendra beaucoup de temps à executer la commande à cause des tests qu’il fait pour matcher les fichiers que l’on recherche
Si l’on revient sur ls
rapidement, et que l’on s’interesse à son man
, on découvre quelques options qui pourraient nous aider.
-1 (The numeric digit ``one''.) Force output to be one entry per line. This is the default
when output is not to a terminal.
-f Output is not sorted. This option turns on the -a option.
Le -1
c’est bonus, on affiche simplement le nom du fichier sur une ligne complète
❯ ls -1
2018-01-25-Obtenir-un-tableau-dobjets-indexe-par-id-avec-pdo.md
2018-01-25-aller-plus-loin-avec-beberlei-assert.md
2018-01-25-composer-and-symfony-polyfill.md
2018-02-06-Libérer-de-lespace-disque-avec-docker-system-prune.md
2018-02-06-behat-phpunit-bootstrap-zero-config.md
2018-02-06-travailler-avec-une-version-non-publiee-dune-librarie-avec-composer.md
2018-02-09-Utiliser-les-methodes-d-intersection-par-valeurs.md
2018-02-09-afficher-du-code-dans-les-textarea-github.md
2018-02-13-ouvrir-une-issue-github-depuis-le-code.md
2018-02-20-git-diff-github-style.md
2018-03-12-taches-asynchrones-avec-zsh.md
2018-03-28-antigen-le-gestionnaire-de-paquets-pour-zsh.md
2018-04-22-diviser-une-chaine-de-caractères-en-es6.md
2018-05-30-voir-lhistorique-des-modifications-dune-methode-avec-git.md
2018-07-18-lister-un-gros-repertoire.md
On l’a vu plus haut, l’inconvénient de ls
est qu’il charge en mémoire avant de faire des opérations de tri. Grâce au flag -f
on s’affranchit de cette contrainte et ls
retournera les résultats au fur et à mesure sur STDOUT
❯ ls -f1
.
..
2018-02-20-git-diff-github-style.md
2018-02-13-ouvrir-une-issue-github-depuis-le-code.md
2018-04-22-diviser-une-chaine-de-caractères-en-es6.md
2018-03-28-antigen-le-gestionnaire-de-paquets-pour-zsh.md
2018-01-25-Obtenir-un-tableau-dobjets-indexe-par-id-avec-pdo.md
...
Et pourquoi s’arrêter là ! Une autre astuce, est d’invoquer le binaire directement, afin de s’assurer qu’aucune conf obscure ne vienne faire des opérations que l’on aurai pas anticipé (genre le truc qui met de jolies couleurs sur les outputs, ou encore les variables d’environnement ayant un impact sur ls
).
❯ \/bin/ls -f1
.
..
2018-02-20-git-diff-github-style.md
2018-02-13-ouvrir-une-issue-github-depuis-le-code.md
2018-04-22-diviser-une-chaine-de-caractères-en-es6.md
2018-03-28-antigen-le-gestionnaire-de-paquets-pour-zsh.md
2018-01-25-Obtenir-un-tableau-dobjets-indexe-par-id-avec-pdo.md
...
Enfin, vu que l’on parle de millions d’entrées, plutôt que d’output sur STDOUT
on va gentillement envoyer tout ça dans un fichier texte.
❯ \/bin/ls -f1 > ./mon-fichier.txt
Victoire ! Non seulement ça fonctionne mais en plus c’est “presque sans douleur”. La limitation avec cette approche c’est les I/O qui prennent très très cher. Si vous avez un process genre NGinx à côté, pensez à bien le monitorer.
Moyen mnémotechnique pour s’en souvenir : -f1
, parce que ça trace 🏎 !
git log
permet de voir les logs des commits. Il est possible de ne s’intéresser qu’au changement pour une méthode particulière d’une classe grâce à l’option -L
, git log -L :<methodName>:<file>
.
Par exemple git log -L :listItineraries:/src/controllers/ItineraryController.php
indiquera toutes les modifications de la méthode ItineraryController::listItineraries
.
Pour que cela fonctionne il faut indiquer à Git comment traiter les fichiers .php
en ajoutant à la racine du projet un
fichier .gitattributes
contenant :
*.php diff=php
Il est également possible d’indiquer une plage de lignes sous la forme git log -L <start>,<end>:<file>
, ou même une regex avec git log -L :<regex>:<file>
.
split
qui nous renvoie un tableau de chaque caractère.
const cake = 'cake';
const slicedCake = cake.split('');
// ['c', 'a', 'k', 'e' ]
Depuis la version ES2015, il est possible d’utiliser l’opérateur de décomposition (spread operator) afin de diviser une chaîne de caractères.
const cake = 'cake';
const slicedCake = [...cake];
// ['c', 'a', 'k', 'e' ]
Ou encore via la méthode statique Array.from
.
const cake = 'cake';
const slicedCake = Array.from(cake);
// ['c', 'a', 'k', 'e']
En quelques mots : c’est un outil efficace pour étendre les capacités de votre shell, tout en conservant une config lisible et maintenable.
# dans ~/.zshrc
# Initialisation d'Antigen
source /usr/local/share/antigen/antigen.zsh
# Récupération de "bundles"
antigen bundle zsh-users/zsh-autosuggestions
antigen bundle zsh-users/zsh-syntax-highlighting
# Ajout d'un thème.
antigen theme sindresorhus/pure
# Appliquer l'ensemble des changements
antigen apply
brew install antigen
echo "source /usr/local/share/antigen/antigen.zsh" >> $HOME/.zshrc
curl -L git.io/antigen > $HOME/.antigen/antigen.zsh
echo "source $HOME/.antigen/antigen.zsh" >> $HOME/.zshrc
La liste des approches pour installer antigen est disponible dans le wiki du repo.
Antigen permet l’installation de bundles depuis :
Son mode de fonctionnement est assez simple. Lorsque vous utilisez la commande antigen bundle user/repo
, antigen fait un clone du repo et exécute les fichiers *.plugin.zsh
s’y trouvant.
# dans ~/.zshrc
# Initialisation d'Antigen
source /usr/local/share/antigen/antigen.zsh
# Récupération de "bundles" depuis github
antigen bundle zsh-users/zsh-autosuggestions
antigen bundle zsh-users/zsh-syntax-highlighting
# Appliquer l'ensemble des changements
antigen apply
# dans ~/.zshrc
# Initialisation d'Antigen
source /usr/local/share/antigen/antigen.zsh
# Chargement de oh-my-zsh comme librairie par défaut (robbyrussell/oh-my-zsh).
antigen use oh-my-zsh
# Récupération de "bundles" depuis la librairie par défaut
antigen bundle git
antigen bundle brew
# Appliquer l'ensemble des changements
antigen apply
Avec quelques lignes, on peut rapidement se composer une config assez robuste et prête à l’emploi.
~/.zshrc
# Init antigen
source /usr/local/share/antigen/antigen.zsh
# Chargement de oh-my-zsh comme librairie par défaut (robbyrussell/oh-my-zsh).
antigen use oh-my-zsh
# Récupération de "bundles" depuis la librairie par défaut
antigen bundle git
antigen bundle colorize
antigen bundle colored-man-pages
# Récupération de "bundles" depuis github
antigen bundle zsh-users/zsh-autosuggestions
antigen bundle zsh-users/zsh-syntax-highlighting
# Ajout d'un thème.
antigen theme sindresorhus/pure
# Appliquer l'ensemble des changements
antigen apply
source /usr/local/share/antigen/antigen.zsh
antigen use oh-my-zsh
antigen bundle git
antigen bundle pip
antigen bundle command-not-found
antigen bundle docker-compose
antigen bundle github
antigen bundle colorize
antigen bundle zsh-users/zsh-syntax-highlighting
antigen bundle zsh-users/zsh-autosuggestions
antigen bundle bobsoppe/zsh-ssh-agent
antigen bundle desyncr/auto-ls
antigen theme refined
antigen apply
CURRENT_DIR=$(dirname $0)
source $HOME/.antigen/antigen.zsh
antigen use oh-my-zsh
antigen bundle z
antigen bundle zsh-users/zsh-syntax-highlighting
antigen bundle zsh-users/zsh-autosuggestions
antigen bundle zsh-users/zsh-completions
antigen bundle mafredri/zsh-async
export ANTIGEN_LOG=~/antigen.log
antigen bundle $CURRENT_DIR/zsh/themes/killer-theme.zsh-theme --no-local-clone
antigen apply
source /usr/local/share/antigen/antigen.zsh
antigen use oh-my-zsh
antigen bundle git
antigen bundle node
antigen bundle kubectl
antigen bundle brew
antigen bundle colorize
antigen bundle colored-man-pages
antigen bundle mafredri/zsh-async
antigen bundle zsh-users/zsh-autosuggestions
antigen bundle zsh-users/zsh-syntax-highlighting
antigen theme sindresorhus/pure
antigen apply
L’inconvénient c’est qu’à force de l’enrichir, le prompt devient de plus en plus lent et un shell peut vite prendre plusieurs secondes à démarrer.
Pour ma part, avec l’utilisation de docker-machine
, je dois, à chaque démarrage de mon shell, exécuter la commande eval $(docker-machine env)
afin de rendre disponible les variables nécessaires à docker
. C’est long, c’est lourd et c’est synchrone !
La solution que j’ai trouvé s’appelle simplement mafredri/zsh-async. Cette lib est utilisée notamment par le thème zsh sindresorhus/pure pour gérer l’affichage du nom de la branche du dossier courant et de son status.
On installe tout ça et go.
# on ajoute simplement le bundle dans le fichier .zshrc :
antigen bundle mafredri/zsh-async
git clone https://github.com/mafredri/zsh-async.git $HOME/.zsh-async
echo "source $HOME/.zsh-async/async.zsh && async_init" >> $HOME/.zshrc
zsh-async
utilise un principe de workers, de callbacks et de jobs. Étape par étape ça donne :
La petite subtilité, c’est que la tâche exéctutée dans un job appartiendra à un autre contexte et ne pourra donc pas faire d’export
dans le shell courant (entre autre).
# on créer un nouveau worker
async_start_worker docker_machine_init
# on définit notre callback qui aura pour mission d'évaluer le résultat du job dans le shell courant
docker_machine_callback() {
# $3 correspond à l'output sur stdout
eval $3
# on détruit le worker
async_stop_worker docker_machine_init # 😇
}
# on attache notre callback au worker
async_register_callback docker_machine_init docker_machine_callback
# enfin on lance la tâche que l'on souhaite exécuter
async_job docker_machine_init docker-machine env
En faisant un petit comparatif sur cette seule tâche, on gagne en moyenne 680ms (étant sur macOS j’ai utilisé un script perl qui lui même prend un peu de temps).
time_now() {
perl -MTime::HiRes -e 'printf("%.0f\n",Time::HiRes::time()*1000)'
}
start=$(time_now)
# did some stuff
end=$(time_now)
echo runtime=$((end-start))
Lorsque j’utilise zsh-async
, l’initialisation du job prend en moyenne 20ms. Alors que l’exécution de la tâche docker-machine env
elle même prend pratiquement 700ms.
Lors du lancement d’un nouveau shell, les variables sont indisponibles, docker
ne peut pas se connecter au daemon. Puis, au bout d’une petite seconde, les variables sont exportés par la fonction de callback et la même commande retourne bien les valeurs attendues.
Last login: Mon Mar 12 11:47:33 on ttys009
~
❯ docker info | head
Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running?
~
❯ docker info | head
Containers: 32
Running: 31
Paused: 0
Stopped: 1
Images: 25
Server Version: 17.06.0-ce
Storage Driver: zfs
Zpool: boot2docker-data
Zpool Health: ONLINE
Parent Dataset: boot2docker-data/docker
git diff
en local renvoient vers une UI HTML aussi plaisante que celle de Github, intéressant n’est-ce pas ?
Tout se trouve dans cette librairie npm
(et son repository).
Voyons ensemble comment paramétrer ce petit utilitaire.
L’installation se fait simplement sous macOs :
# Brew
/usr/bin/ruby -e "$(curl -fsSL \
https://raw.githubusercontent.com/Homebrew/install/master/install \
)"
# Dépendance de la lib
brew install node
# La librairie en elle-même
npm install -g pretty-diff
Quant au paramétrage, je vous donne mon avis, probablement biaisé, à prendre ou à laisser donc.
La librairie n’étant pas standard, vous aurez la majorité des options et arguments de git diff
à portée de main mais pas tous. Je vous conseille donc de ne pas écraser diff
dans votre .gitconfig
.
Pour nuancer mon avis, je vous partage mon expérience : je suis en télétravail et fais beaucoup de pair avec mes collègues en partageant mon terminal sous tmux
; le fait d’avoir l’output de git diff
en ligne de commande s’avère pratique pour faire le tour, ensemble avec mon/mes collègue.s, des modifications de notre commit.
Ma solution est un alias git et quelques alias shell, tout ce qu’il y a de plus classique :
# Alias git
git config --global alias.pretty-diff pretty-diff
# Alias shell
alias gd="git pretty-diff"
alias gds="git pretty-diff --staged"
Le comportement de pretty-diff
est très similaire à celui du diff
standard :
Le tout dans une UI très sympathique :
]]>Dans un précédent article nous avons vu comment rendre facile l’inclusion de code dans nos descriptions sur Github.
Cela nous facilite un peu la vie mais on peut faire encore plus simple.
Github nous permet d’ouvrir une issue directement depuis le code !
Dans la vue d’un fichier il est possible de sélectionner une ligne, ou même plusieurs lignes de codes en maintenant la touche MAJ
enfoncée.
Un menu contextuel est disponible avec différentes options. On peut copier les lignes directement.
Il est aussi possible d’obtenir le permalien qu’on pourra coller dans une description.
On peut aussi faire un git blame
sur les lignes concernées.
Ce qui nous intéresse est la possibilité de créer une issue. Github va automatiquement inclure les lignes de codes dans la description !
]]>Vous savez probablement afficher du code sur…
une ligne:
`console.log('Bonjour');`
ou bien sur plusieurs:
```
console.log('Bonjour');
console.log('A bientôt');
```
Github nous permet d’indiquer de quel langage il s’agit afin de profiter de la coloration syntaxique:
```javascript
var prenom = 'quentin';
console.log('bonjour ' + prenom);
```
Permettre de copier-coller du code bien formaté est un bon début. Cependant, en plus de devoir dupliquer une information, nous manquons cruellement de contexte. Par exemple dans quel fichier le code est-il écrit ?
Bien-sûr on peut ajouter un lien pointant vers le fichier et même la ligne en question:
```javascript
Counter.propTypes = {
```
Le code est [ici](https://github.com/Evaneos/vitaminjs/blob/master/examples/counter/Counter/index.jsx#L14)
On peut même pointer vers un bloc de code:
```javascript
Counter.propTypes = {
value: PropTypes.number.isRequired,
onIncrement: PropTypes.func.isRequired,
onDecrement: PropTypes.func.isRequired,
};
```
Le code est [ici](https://github.com/Evaneos/vitaminjs/blob/master/examples/counter/Counter/index.jsx#L14-L18)
Github surligne en jaune les lignes concernées:
C’est pas mal mais on peut mieux faire.
En utilisant le hash de commit, Github traduit le lien et intègre directement le code concerné!
https://github.com/Evaneos/vitaminjs/blob/1a7b74528160833a9a1d1571b302f1c920f1951f/examples/counter/Counter/index.jsx#L14-L18
Attention, il faut utiliser le hash entier.
]]>array_intersect
permet de calculer l’intersection de deux tableaux (ou plus), contenant des valeurs scalaires.
$tableau1 = ['un', 'deux', 'trois', 'quatre' ];
$tableau2 = ['un', 'deux', 'quatre', 'cinq'];
array_intersect($tableau1, $tableau2); //retourne le tableau suivant:
['un', 'deux', 'quatre' ];
Pour faire l’intersection de deux tableaux d’objets, on pourrait utiliser la méthode array_uintersect
(http://php.net/manual/fr/function.array-uintersect.php), qui permet d’utiliser une fonction de rappel.
class Objet
{
private $arg;
public function __construct($arg){
$this->arg = $arg;
}
public function egal($another){
return $another instanceof self && $another->arg === $this->arg;
}
}
$tableau1 = [new Objet('un'), new Objet('deux'), new Objet('trois'), new Objet('quatre') ];
$tableau2 = [new Objet('un'), new Objet('deux'), new Objet('quatre'), new Objet('cinq')];
array_uintersect($tableau1, $tableau2, function ($objet1, $objet2) { return $objet1->egal($objet2); });
//retourne le tableau suivant:
[new Objet('un'), new Objet('deux'), new Objet('trois'), new Objet('quatre') ];
Ce qui n’est pas ce à quoi on pourrait s’attendre, cette fonction ne s’utilise pas de cette manière.
Si on lit plus attentivement la documentation : La fonction de comparaison doit retourner un entier inférieur à, égal à, ou supérieur à 0 si le premier argument est considéré comme, respectivement, inférieur à, égal à, ou supérieur au second. Notez qu'avant PHP 7.0.0, cet entier devait être dans l'intervalle -2147483648 à 2147483647
.
On pourrait penser qu’il suffit de comparer l’égualité des deux objets, retourner 0 quand ils sont égaux et autres choses quand ils ne le sont pas :
$tableau1 = [new Objet('un'), new Objet('deux'), new Objet('trois'), new Objet('quatre') ];
$tableau2 = [new Objet('un'), new Objet('deux'), new Objet('quatre'), new Objet('cinq')];
array_uintersect($tableau1, $tableau2, function ($objet1, $objet2) { return $objet1->egal($objet2) ? 0 : 1; });
//retourne le tableau suivant:
[ new Objet('quatre') ];
En fait, la fonction array_uintersect
commence par ordonner les deux tableaux, en utilisant la fonction de rappel. Il faut donc bien respecter les valeurs de retours attendus par la méthode de rappel. Pour l’intersection des deux objets, ça peut être plus difficile de définir si un objet est supérieur a l’autre, et vice-versa, le plus simple est sûrement d’implémenter la méthode __toString
et d’utiliser la méthode array_intersect
:
class Objet
{
private $arg;
public function __construct($arg){
$this->arg = $arg;
}
public function egal($another){
return $another instanceof self && $another->arg === $this->arg;
}
public function __toString(){
return $this->arg;
}
}
$tableau1 = [new Objet('un'), new Objet('deux'), new Objet('trois'), new Objet('quatre') ];
$tableau2 = [new Objet('un'), new Objet('deux'), new Objet('quatre'), new Objet('cinq')];
array_intersect($tableau1, $tableau2); //retourne le tableau suivant:
[new Objet('un'), new Objet('deux'), new Objet('quatre') ];
]]>
Une solution peut-être de créer un alias composer vers la branche du repository de la librairie qui nous intéresse.
Par exemple, si l’on veut utiliser la branche branch-name
en tant que version 0.7.0
de la librairie author\library
on peut modifier le fichier composer.json
pour indiquer dans le bloc require
"author/library": "dev-branch-name as 0.7.0"
.
Il est important de noter que le nom de la branche est préfixé de dev-
.
bootstrap.php
qui initialise l’environnement pour chacun des outils.
Composer à la rescousse, il nous permet d’autoloader directement le fichier en environnement de développement :
"autoload-dev": {
"psr-4": {
...
},
"files": [
"tests/bootstrap.php" //notre fameux bootstrap
]
}
compose dump-autoload
permettra d’inclure directement le fichier bootstrap.php
avant de lancer les tests. Désormais il n’est plus nécessaire de configurer les outils de tests indépendamment.
docker system prune
de temps à autre permet de libérer de l’espace disque. Afin de connaitre l’espace potentiellement gagnable, docker system df
permet de connaitre l’utilisation de l’espace disque.
TYPE TOTAL ACTIVE SIZE RECLAIMABLE
Images 263 68 90.85GB 57.18GB (62%)
Containers 184 4 14.42GB 14.42GB (100%)
Local Volumes 106 76 29.82GB 91.38MB (0%)
Build Cache 0B 0B
docker system prune
retire :
À utiliser avec précaution si vous ne voulez pas perdre vos données locales.
]]> "replace": {
"symfony/polyfill-iconv": "*",
"symfony/polyfill-php71": "*",
"symfony/polyfill-php72": "*",
"symfony/polyfill-php70": "*",
"symfony/polyfill-php56": "*",
"symfony/polyfill-mbstring": "*",
"symfony/polyfill-intl-icu": "*"
}
Enfin il suffit de jouer la commande composer update
afin de les supprimer. À vous d’ajuster les polyfills à supprimer en fonction de votre version de PHP.
beberlei/assert
, qui sert à se protéger contre les paramètres invalides proposes des combinaisons utiles.
Par exemple il est possible d’ajouter nullOr
au nom d’une assertion (ex: nullOrString
) afin de valider que l’on a bien une valeur null
ou le type attendu.
Il est également possible de préfixer all
les types Traversable
(ex: allIsInstanceOf
) pour s’assurer que tous les éléments correspondent bien au type attendu.
La combinaison des deux fonctionne également, il suffit de mettre le A
en minuscule (ex: nullOrallString
).
La library propose également de chainer différentes assertions, par exemple:
Assert::thatAll($coolArray)
->nullOr()
->string('You\'re messing up dude');
fetchAll
de PDO dispose de plusieurs options intéressantes pour récupérer un tableau d’objets depuis la base de données :
Cette option utilise le premier champ de la requète comme clé du tableau retourné.
$sql = <<<SQL
SELECT id, id, name
FROM users
WHERE id IN (12, 78)
SQL;
$sth = $pdo->prepare($sql);
$sth->execute([]);
$users = $sth->fetchAll(\PDO::FETCH_UNIQUE);
/* $users = [
12 => ['id' => 12, 'name' => 'Maitre Jojo'],
78 => ['id' => 78, 'name' => 'Maitre Pierre'],
];
*/
Cette option permet d’hydrater un objet de la classe définie :
class User {}
$sql = <<<SQL
SELECT id, id, name
FROM users
WHERE id IN (12, 78)
SQL;
$sth = $pdo->prepare($sql);
$sth->execute([]);
$users = $sth->fetchAll(\PDO::FETCH_CLASS, User::class);
/* $users = [
0 => User('id' => 12, name => 'Maitre Jojo'),
1 => User('id' => 78, 'name' => 'Maitre Pierre'),
];
*/
En utilisant un pipe |
il est possible de cummuler les options :
class User {}
$sql = <<<SQL
SELECT id, id, name
FROM users
WHERE id IN (12, 78)
SQL;
$sth = $pdo->prepare($sql);
$sth->execute([]);
$users = $sth->fetchAll(\PDO::FETCH_UNIQUE|\PDO::FETCH_CLASS, User::class);
/* $users = [
12 => User('id' => 12, name => 'Maitre Jojo'),
78 => User('id' => 78, 'name' => 'Maitre Pierre'),
];
*/
Petite appartée, PDO::FETCH_KEY_PAIR
permet de retourner un tableau de clé => valeur. La requête ne doit selectionner que 2 champs.