Maison >développement back-end >tutoriel php >Une plongée profonde dans les séances de Laravel
Lors de la construction d'une application Laravel, vous êtes presque certain que vous devrez gérer la session à un moment donné. Ils sont la partie fondamentale du développement Web.
Cet article expliquera rapidement quelles sont les sessions, comment elles fonctionnent dans Laravel et comment vous les utilisez dans les applications de Laravel.
Nous allons ensuite aller plus loin et plonger dans la façon d'interagir avec les sessions en utilisant des "classes de session" pour éviter les pièges courants que je rencontre souvent lorsqu'ils traitent avec les applications Laravel.
Enfin, nous apprendrons à tester les données de session dans Laravel.
Par défaut, les applications Web sont apatrides, ce qui signifie que les demandes ne sont généralement pas conscientes les unes des autres. Par conséquent, nous avons besoin d'un moyen de stocker les données entre les demandes. Par exemple, lorsque les utilisateurs se connectent à un site Web, nous devons nous rappeler qu'ils sont connectés lors de leur visite. C'est là que la conversation entre en jeu.
En bref, une session est un moyen sûr de persister les données entre plusieurs demandes.
Les données de session peuvent être utilisées pour stocker le contenu suivant:
Les données de session peuvent être stockées à divers endroits, telles que:
Pour comprendre ce que sont les sessions, voyons comment ils fonctionnent dans Laravel.
Voici quelques exemples de données que vous pourriez trouver dans une session dans une application Laravel:
<code>[ '_token' => 'bKmSfoegonZLeIe8B6TWvSm1dKwftKsvcT40xaaW' '_previous' => [ 'url' => 'https://my-app.com/users' ] '_flash' => [ 'old' => [ 'success', ], 'new' => [] ] 'success' => 'User created successfully.' 'current_team_id' => 123 ]</code>
Décomposons ce que chaque clé pourrait représenter.
Les clés suivantes sont ajoutées par le framework Laravel lui-même:
_token
est utilisée pour empêcher les attaques CSRF. _previous.url
est utilisée pour stocker l'URL demandée précédemment. _flash.old
La valeur est utilisée pour stocker les clés des données de session Flash dans une demande précédente. Dans ce cas, cela signifie que la valeur success
a été flasée dans une demande précédente. _flash.new
La valeur est utilisée pour stocker les clés des données de session Flash dans la demande actuelle. Les clés suivantes sont ajoutées par moi:
success
La valeur est utilisée pour stocker des messages de réussite qui peuvent être affichés à l'utilisateur. current_team_id
est utilisée pour stocker l'ID de l'équipe actuelle que l'utilisateur affiche. Par défaut, Laravel prend en charge les pilotes de session suivants:
cookie
- Les données de session sont stockées dans des cookies sécurisés et cryptés. database
- Les sessions sont stockées dans votre base de données (par exemple MySQL, PostgreSQL, SQLite). memcached
/ redis
- Les données de session sont stockées dans ce stockage de cache rapide. dynamodb
- Les données de session sont stockées dans AWS DynamoDB. file
- Les données de session sont stockées dans storage/framework/sessions
. array
- Les données de session sont stockées dans des tableaux PHP en mémoire et ne sont pas persistées. Certains de ces pilotes ont des exigences de configuration. Donc, avant de les utiliser, assurez-vous de vérifier la documentation de Laravel pour apprendre à les configurer.
Laravel rend l'utilisation de sessions très simple. La documentation explique comment interagir bien avec une session. Mais, examinons rapidement les bases.
Pour notre exemple, nous supposerons que nous construisons un assistant étape par étape couvrant plusieurs pages. Nous stockons l'étape actuelle et les données entrées à chaque étape dans la session. De cette façon, lorsque l'utilisateur termine toutes les étapes, nous pouvons lire toutes les données soumises à la fin de l'assistant.
Pour rendre l'exemple simple, nous utiliserons également la fonction d'assistance session()
. Mais plus tard, nous discuterons de l'utilisation de la classe de façade ou de demande Session
pour accéder aux données de session.
Pour lire les données d'une session, vous pouvez utiliser la méthode get
comme suit:
<code>[ '_token' => 'bKmSfoegonZLeIe8B6TWvSm1dKwftKsvcT40xaaW' '_previous' => [ 'url' => 'https://my-app.com/users' ] '_flash' => [ 'old' => [ 'success', ], 'new' => [] ] 'success' => 'User created successfully.' 'current_team_id' => 123 ]</code>
exécuter le code ci-dessus renvoie la valeur stockée dans la session comme la touche wizard:current_step
. Si la clé n'a pas de valeur stockée dans la session, elle renvoie null
.
Cette méthode vous permet également de définir une valeur par défaut, qui revient:
si la clé n'existe pas:<code>$currentStep = session()->get(key: 'wizard:current_step');</code>
exécuter le code ci-dessus renvoie la valeur stockée dans la session comme la touche wizard:current_step
. Si la clé n'a pas de valeur stockée dans la session, elle renvoie 1
.
Il peut également y avoir des moments où vous souhaitez lire les données de la session et les supprimer en même temps (il ne peut donc pas être accessible). Vous pouvez utiliser la fonction pull
pour ceci:
<code>$currentStep = session()->get(key: 'wizard:current_step', default: 1);</code>
exécuter le code ci-dessus renvoie la valeur stockée dans la session comme la touche wizard:current_step
, puis la supprimera de la session.
Pour écrire des données sur une session, vous pouvez utiliser la fonction put
comme indiqué ci-dessous:
<code>$currentStep = session()->pull(key: 'wizard:current_step');</code>
L'exécution du code ci-dessus stockera le tableau (passé dans le deuxième paramètre) comme valeur de la touche wizard:step_one:form_data
.
De même, vous pouvez également utiliser la méthode push
pour pousser les données vers un tableau dans la session:
<code>session()->put( key: 'wizard:step_one:form_data', value: [ 'name' => 'Ash Allen', 'email' => 'ash@example.com', ], );</code>
Supposons que la clé wizard:step_one:form_data:languages
a les données suivantes:
<code>session()->push( key: 'wizard:step_one:form_data:languages', value: 'javascript', );</code>
Le code ci-dessus (appelant la méthode push
) mettra à jour la valeur de la session:
<code>[ '_token' => 'bKmSfoegonZLeIe8B6TWvSm1dKwftKsvcT40xaaW' '_previous' => [ 'url' => 'https://my-app.com/users' ] '_flash' => [ 'old' => [ 'success', ], 'new' => [] ] 'success' => 'User created successfully.' 'current_team_id' => 123 ]</code>
Si la valeur wizard:step_one:form_data:languages
n'existe pas encore dans la session, utilisez push
pour créer une clé de session et définissez la valeur sur un tableau contenant les valeurs que vous avez transmises.
Laravel fournit également des méthodes d'assistance pratiques qui vous permettent d'augmenter et de diminuer les valeurs d'une session:
Vous pouvez augmenter la valeur de la session comme ceci:
<code>$currentStep = session()->get(key: 'wizard:current_step');</code>
Lorsque nous exécutons le code ci-dessus, si la valeur de session wizard:current_step
est 3, elle augmentera désormais à 4.
Vous pouvez également réduire la valeur de la session comme ceci:
<code>$currentStep = session()->get(key: 'wizard:current_step', default: 1);</code>
Si les valeurs n'existent pas encore dans la session, elles sont traitées comme 0. Par conséquent, l'appel increment
sur la valeur de session vide définit la valeur sur 1. Appelez decrement
sur la valeur de session vide définissez la valeur sur -1.
Les deux méthodes vous permettent de spécifier le nombre d'augmentation ou de diminution:
<code>$currentStep = session()->pull(key: 'wizard:current_step');</code>
Vous pouvez également supprimer les données de la session à l'aide de la méthode forget
:
<code>session()->put( key: 'wizard:step_one:form_data', value: [ 'name' => 'Ash Allen', 'email' => 'ash@example.com', ], );</code>
L'exécution du code ci-dessus supprimera les données appartenant à la clé wizard:current_step
de la session.
Si vous souhaitez supprimer plusieurs clés à la fois, vous pouvez transmettre le tableau des clés à la fonction forget
:
<code>session()->push( key: 'wizard:step_one:form_data:languages', value: 'javascript', );</code>
ou, si vous souhaitez supprimer toutes les données de la session, vous pouvez utiliser la fonction flush
:
<code>[ `php`, ]</code>
Laravel fournit également quelques fonctions d'assistance pratiques pour vérifier si les données existent dans la session.
Vous pouvez utiliser la méthode has
pour vérifier s'il y a une clé dans la session et si sa valeur n'est pas null
:
<code>[ `php`, `javascript`, ]</code>
Si la valeur existe et n'est pas null
, le code ci-dessus retournera true
. Si la valeur est null
ou que la clé n'existe pas, elle retournera false
.
De même, vous pouvez également utiliser la méthode exists
pour vérifier si la clé existe dans la session (quelle que soit la valeur nul):
<code>session()->increment(key: 'wizard:current_step');</code>
Vous pouvez également vérifier si la session n'existe pas du tout:
<code>session()->decrement(key: 'wizard:current_step');</code>
Parfois, vous voulez persister certaines données dans la session, mais uniquement pour la demande suivante. Par exemple, vous voudrez peut-être afficher une notification de réussite à l'utilisateur après que l'utilisateur a soumis le formulaire.
Pour ce faire, vous pouvez utiliser flash
Méthode:
<code>session()->increment(key: 'wizard:current_step', amount: 2); session()->decrement(key: 'wizard:current_step', amount: 2);</code>
Si vous souhaitez exécuter le code ci-dessus, dans la demande suivante, vous pouvez lire la valeur de la session (en utilisant quelque chose comme session()->get('success')
) pour l'affichage. Ensuite, supprimez-le pour qu'il ne soit pas disponible dans la demande suivante.
Il se peut que parfois vous avez des données flash (ajoutées dans une demande précédente) et que vous souhaitez la maintenir à la demande suivante.
Vous pouvez actualiser toutes les données flash à l'aide de la méthode reflash
:
<code>session()->forget(keys: 'wizard:current_step');</code>
ou, si vous souhaitez simplement conserver certaines données flash, vous pouvez utiliser la méthode keep
:
<code>[ '_token' => 'bKmSfoegonZLeIe8B6TWvSm1dKwftKsvcT40xaaW' '_previous' => [ 'url' => 'https://my-app.com/users' ] '_flash' => [ 'old' => [ 'success', ], 'new' => [] ] 'success' => 'User created successfully.' 'current_team_id' => 123 ]</code>
L'exécution du code ci-dessus conservera les valeurs de session Flash success
et error
, mais supprimera toutes les autres données Flash pour la prochaine demande.
Jusqu'à présent, nous n'avons utilisé la fonction d'assistance session()
que dans nos exemples.
mais vous pouvez également utiliser la classe IlluminateSupportFacadesSession
FACADE ou IlluminateHttpRequest
pour interagir avec la session.
Quelle que soit la méthode que vous utilisez, vous pouvez toujours utiliser la même méthode décrite plus tôt dans cet article. Ces méthodes ne sont que différentes façons d'interagir avec les données de session.
Pour utiliser la façade Session
, vous pouvez appeler la méthode comme ceci:
<code>$currentStep = session()->get(key: 'wizard:current_step');</code>
Alternativement, vous pouvez accéder à la session en appelant la méthode IlluminateHttpRequest
injectée dans la méthode du contrôleur. Supposons que vous ayez la méthode du contrôleur suivant: session
<code>$currentStep = session()->get(key: 'wizard:current_step', default: 1);</code>Chaque méthode est complètement efficace, vous pouvez donc décider laquelle vous et votre équipe préférez.
aller un peu plus loin
Ainsi, nous couvrirons maintenant certains pièges potentiels et comment les éviter.
# typo dans la clé de session
Restez avec notre exemple de l'assistant, en supposant que nous voulons stocker l'étape actuelle de la session. Par conséquent, notre code pourrait ressembler à ceci:
<code>$currentStep = session()->pull(key: 'wizard:current_step');</code>Ensuite, plus tard, dans différentes parties de la base de code, nous pourrions vouloir lire l'étape actuelle de la session:
<code>session()->put( key: 'wizard:step_one:form_data', value: [ 'name' => 'Ash Allen', 'email' => 'ash@example.com', ], );</code>Avez-vous vu l'erreur que j'ai commise tout à l'heure? J'ai accidentellement essayé de lire la clé
au lieu de la clé wizard:step
. wizard:current_step
Par conséquent, un moyen utile d'éviter ces fautes de frappe est d'utiliser des constantes ou des méthodes pour générer des clés de session.
Par exemple, si la clé de session est statique, vous pouvez définir une constante (probablement dans la classe de session, nous couvrirons plus tard) comme suit:
<code>session()->push( key: 'wizard:step_one:form_data:languages', value: 'javascript', );</code>Cela signifie que nous réduisons le nombre de chaînes brutes utilisées dans la base de code, ce qui contribue à réduire le nombre de fautes de frappe.
Cependant, parfois vous devrez peut-être générer des clés de session dynamiquement. Par exemple, supposons que nous voulions que notre clé
contienne un champ d'identification d'équipe. Nous pouvons créer une méthode pour générer la clé comme suit: wizard:current_step
<code>[ `php`, ]</code>Comme nous pouvons le voir dans le code ci-dessus, nous générons dynamiquement la clé de session afin qu'elle puisse être utilisée dans différentes méthodes. Par exemple, si nous essayons de trouver l'étape actuelle d'une équipe avec ID 1, la clé sera
. wizard:1:current_step
Un autre piège que je vois lorsqu'il s'agit d'un projet qui existe depuis un certain temps est le conflit clé de session.
Par exemple, imaginez qu'il y a quelques années, vous avez construit un assistant pour créer de nouveaux comptes d'utilisateurs. Vous pouvez donc stocker des données de session comme ceci:
<code>[ '_token' => 'bKmSfoegonZLeIe8B6TWvSm1dKwftKsvcT40xaaW' '_previous' => [ 'url' => 'https://my-app.com/users' ] '_flash' => [ 'old' => [ 'success', ], 'new' => [] ] 'success' => 'User created successfully.' 'current_team_id' => 123 ]</code>
Vous avez maintenant été affecté à la construction d'une nouvelle fonctionnalité qui a également un assistant, et vous avez complètement oublié l'ancien sorcier et la convention de dénomination que vous avez utilisée. Vous pouvez accidentellement utiliser la même clé pour le nouveau sorcier, provoquant des conflits de données et introduire des erreurs potentielles.
Pour éviter cela, j'aime utiliser le nom de la fonction comme préfixe de la touche de session. Donc, pour enregistrer les données de l'assistant pour créer de nouveaux utilisateurs, je pourrais avoir les clés suivantes:
new_user_wizard:current_step
new_user_wizard:step_one:form_data
new_user_wizard:step_two:form_data
Ensuite, dans mon nouveau sorcier pour créer une nouvelle équipe, je pourrais avoir les clés suivantes:
new_team_wizard:current_step
new_team_wizard:step_one:form_data
new_team_wizard:step_two:form_data
Nous expliquerons comment ajouter ces préfixes à la classe de session plus loin dans cet article.
Pouvez-vous me dire quel est le type de données stocké dans cette valeur de session?
<code>$currentStep = session()->get(key: 'wizard:current_step');</code>
Si vous deviez que c'était une instance de AppDataTransferObjectsWizardsFormData
, vous avez raison.
En parlant et en parlant, je veux indiquer clairement que lorsque vous lisez les données d'une session, il n'est pas toujours immédiatement clair quel type de données vous utilisez. Vous finissez par devoir regarder le code qui écrit les données de la session pour déterminer ce que c'est. Cela peut être distrayant et long et long et peut entraîner des erreurs.
Vous pouvez ajouter des commentaires ou des blocs de documents au code qui lit les données de session. Mais ce n'est qu'un indice. Si le commentaire n'est pas tenu à jour (si le type de données de session change), cela n'aide pas et augmente la probabilité d'erreurs.
Une autre méthode que j'aime utiliser consiste à lire les données de session à l'intérieur de la méthode et à ajouter le type de retour à la méthode. De cette façon, vous pouvez vous assurer que le type de données que vous utilisez est correct. Cela aide également votre IDE et les personnes qui lisent le code.
Par exemple, regardons ce code:
<code>$currentStep = session()->get(key: 'wizard:current_step', default: 1);</code>
Nous pouvons maintenant voir que la méthode stepOneFormData
renvoie une instance AppDataTransferObjectsWizardsFormData
. Cela illustre clairement le type de données que nous utilisons. Nous pouvons ensuite appeler cette méthode dans le contrôleur comme ceci:
<code>$currentStep = session()->pull(key: 'wizard:current_step');</code>
Comme nous l'avons vu dans les sections précédentes, il y a des pièges faciles (mais courants) lors de l'utilisation de sessions à Laravel.
En utilisant des "classes de session", chacun de ces pièges peut être évité (ou du moins réduit). J'aime utiliser des classes de session pour résumer la logique de traitement des données de session liée à une seule fonction en un seul endroit.
Par exemple, supposons que nous ayons un sorcier pour créer des utilisateurs et un autre pour créer des équipes. Je vais créer une classe de session pour chacun de ces sorciers:
AppSessionsUsersNewUserWizardSession
AppSessionsTeamsNewTeamWizardSession
En utilisant la classe de session, vous pouvez:
L'utilisation de cette approche basée sur la classe lors du traitement des données de session m'économise d'innombrables fois lorsque vous travaillez avec de grands projets Laravel. Il s'agit d'une méthode simple qui peut avoir un grand impact.
Dans l'exemple précédent, j'ai déjà suggéré d'utiliser une classe de session. Mais jetons un aperçu plus approfondi de la façon dont j'aime construire ces cours.
Supposons que nous ayons la classe de session suivante pour le nouvel assistant utilisateur. À première vue, cela pourrait être un peu écrasant, mais regardons le code et décomposons-le:
<code>[ '_token' => 'bKmSfoegonZLeIe8B6TWvSm1dKwftKsvcT40xaaW' '_previous' => [ 'url' => 'https://my-app.com/users' ] '_flash' => [ 'old' => [ 'success', ], 'new' => [] ] 'success' => 'User created successfully.' 'current_team_id' => 123 ]</code>
Dans la classe ci-dessus AppSessionsUsersWizardSession
, nous définissons d'abord le constructeur qui accepte l'instance IlluminateContractsSessionSession
. Ce faisant, Laravel injectera automatiquement une instance de session en nous lorsque nous analysons la classe AppSessionsUsersWizardSession
du conteneur de service. Je vais vous montrer comment faire cela dans le contrôleur plus tard.
Nous définissons ensuite 5 méthodes publiques de base:
getCurrentStep
- Revenez à l'étape actuelle de l'assistant. S'il n'y a pas d'étape de configuration, la valeur par défaut est 1
. setCurrentStep
- Étapes actuelles dans l'assistant de configuration. setFormDataForStep
- Définissez les données de formulaire pour l'étape donnée dans l'assistant. Cette méthode prend le numéro de pas et AppDataTransferObjectsWizardsUsersFormData
Exemple. getFormDataForStep
- Obtenez les données de formulaire pour l'étape donnée dans l'assistant. Cette méthode prend un numéro de pas et renvoie l'instance AppDataTransferObjectsWizardsUsersFormData
ou si les données n'existent pas. null
flush
L'avantage supplémentaire de l'utilisation de ces méthodes de génération de clés est que nous pouvons facilement préfixer les clés pour éviter les conflits. Dans cet exemple, nous définissons le préfixe de toutes les touches pour
en utilisant la méthode sessionKey
. new_user_wizard:
Maintenant que cette classe est définie, voyons comment nous interagissons avec elle dans le contrôleur:
<code>[ '_token' => 'bKmSfoegonZLeIe8B6TWvSm1dKwftKsvcT40xaaW' '_previous' => [ 'url' => 'https://my-app.com/users' ] '_flash' => [ 'old' => [ 'success', ], 'new' => [] ] 'success' => 'User created successfully.' 'current_team_id' => 123 ]</code>
Comme nous le voyons, dans l'exemple ci-dessus, nous injectons la classe AppSessionsUsersWizardSession
dans notre méthode de contrôleur. Laravel analysera automatiquement l'instance de session pour nous.
Ensuite, nous pouvons interagir avec lui comme nous le ferions avec n'importe quelle autre classe.
Au début, cela peut sembler trop abstract et nécessite plus de maintenance de code. Cependant, à mesure que le projet se développe, les invites de type, les types de retour, les méthodes de génération de clés et même les méthodes de dénomination (rendant vos opérations plus descriptives) sont très utiles.
Comme toute autre partie de la base de code, vous devez vous assurer que vous avez une couverture des données de session pour vous assurer que les champs corrects sont en cours de lecture et d'écriture.
L'un des grands avantages de l'utilisation de classes de session est que vous pouvez facilement écrire des tests de style unité centralisé pour chaque méthode de la classe.
Par exemple, nous pouvons écrire quelques tests pour la méthode AppSessionsUsersWizardSession
de la classe getFormDataForStep
. Pour rappel, voici la méthode:
<code>$currentStep = session()->get(key: 'wizard:current_step');</code>
Nous pouvons tester plusieurs scénarios ici:
AppDataTransferObjectsWizardsUsersFormData
pour l'étape. null
. Notre classe de test peut ressembler à ceci:
<code>$currentStep = session()->get(key: 'wizard:current_step', default: 1);</code>
Dans la classe de test ci-dessus, nous avons deux tests couvrant les deux cas que nous avons mentionnés précédemment.
Ces tests de style d'unité sont idéaux pour s'assurer que votre classe de session est correctement configurée pour lire et écrire des données de session. Mais ils ne vous font pas nécessairement croire qu'ils sont correctement utilisés dans le reste de la base de code. Par exemple, vous pourriez appeler getFormDataForStep(1)
et vous devez appeler getFormDataForStep(2)
.
Pour cette raison, vous pouvez également envisager d'affirmer les données de session dans vos tests fonctionnels (celui que vous écrivez généralement pour votre contrôleur).
Par exemple, supposons que vous ayez la méthode de base suivante dans votre contrôleur et qu'elle passera à l'étape suivante de l'assistant:
<code>$currentStep = session()->pull(key: 'wizard:current_step');</code>
Dans la méthode ci-dessus, nous lisons d'abord l'étape actuelle de la session. Nous stockons ensuite les données de formulaire pour l'étape actuelle de la session. Enfin, nous incrémentons l'étape actuelle et redirigeons vers l'étape suivante de l'assistant.
Nous supposerons que notre classe AppHttpRequestsUsersWizardNextStepRequest
est responsable de la validation des données du formulaire et renvoie l'instance toDto
lorsque nous appelons la méthode AppDataTransferObjectsWizardsUsersFormData
.
Nous supposerons également que la méthode du contrôleur nextStep
est accessible via une demande postale à la route /users/wizard/next-step
(nommée users.wizard.next-step
).
Nous pouvons vouloir rédiger le test suivant pour nous assurer que les données de formulaire sont correctement stockées dans la session:
<code>[ '_token' => 'bKmSfoegonZLeIe8B6TWvSm1dKwftKsvcT40xaaW' '_previous' => [ 'url' => 'https://my-app.com/users' ] '_flash' => [ 'old' => [ 'success', ], 'new' => [] ] 'success' => 'User created successfully.' 'current_team_id' => 123 ]</code>
Dans le test ci-dessus, nous utilisons certaines données de formulaire pour émettre une demande post-demande à la route /users/wizard/next-step
. Vous remarquerez peut-être que nous utilisons withSession
. Cette méthode nous permet de définir les données de session afin que nous puissions affirmer qu'il est lu correctement.
Nous affirmons ensuite que l'utilisateur est redirigé vers l'étape suivante de l'assistant et que l'étape actuelle de la session est définie sur 3
. Nous affirmons également que les données de formulaire pour Step 2
sont correctement stockées dans la session.
Comme nous l'avons vu dans nos tests, nous lisons également de la session de deux manières:
assertSessionHas
pour vérifier si les données de session sont correctement définies. session()
pour lire directement les données de session. Les deux méthodes fonctionnent, vous pouvez donc décider laquelle vous préférez. J'ai utilisé les deux méthodes dans le test ci-dessus pour vous montrer que vous avez plusieurs options.
J'espère que cet article vous aidera à bien comprendre ce que sont les sessions et comment elles fonctionnent à Laravel. J'espère également qu'ils vous donnent quelques idées sur la façon d'interagir avec les données de session en utilisant des méthodes basées sur la classe pour éviter certains pièges courants.
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!