French (Français) translation by Soleil (you can also view the original English article)
L'application que nous créons sera un simple panneau d'affichage, où les utilisateurs peuvent s'inscrire, poster des tâches et offrir une récompense pour son achèvement. Les autres utilisateurs peuvent voir les tâches existantes, se les attribuer et obtenir la récompense offerte.
Les tâches auront des données de base telles qu'un titre, une description et une récompense (selon les paramètres requis), ainsi qu'une date d'échéance et des notes facultatives. Le profil de l'utilisateur se composera simplement du nom de l'utilisateur, de l'email et du site Web Alors, commençons.
Configuration de la base de données
Tout d'abord, pour les données d'application, nous allons utiliser MongoDB en tant que serveur de base de données. MongoDB est une base de données orientée document et la base de données NoSQL leader sur le marché. Il est vraiment évolutif et rapide, ce qui facilite la gestion de grandes quantités de données.
MongoDB est une base de données orientée document et la principale base de données NoSQL.
Pour utiliser MongoDB dans cette application, je vais utiliser un pilote MongoDB CodeIgniter que j'ai écrit il y a quelque temps. Il s'agit simplement d'un wrapper du pilote PHP MongoDB pour imiter SQL ActiveRecord du framework. Vous pouvez trouver les fichiers source de ce pilote dans mon référentiel public. Pour que ce pilote fonctionne correctement, assurez-vous que le pilote MongoDB de PHP est installé. Sinon, procédez comme suit pour le faire fonctionner.
Veuillez noter que l'explication des pilotes dans CodeIgniter et que cela est hors du propos de ce tutoriel, consultez la documentation si vous avez des doutes. Il vous suffit de déplacer le "mongo_db.php"
dans le dossier "config"
du dossier "config"
de votre application et le dossier "Mongo_db"
du dossier "libraries"
dans le dossier "libraries"
de votre application.
Configuration de la base de données
Le seul fichier que nous devons éditer à ce stade est le "mongo_db.php"
fichier sous le dossier "config"
, comme mon installation mongo
a tous les paramètres par défaut, je vais juste éditer la ligne 40 et lui donner le nom de la base de données que je veux utiliser:
1 |
$config['mongo_db'] = 'billboard'; |
C’est tout pour la base de données. L’un des nombreux avantages de MongoDB est que les documents n’ont pas de structure prédéfinie. Il fonctionne donc sans que nous ayons à configurer quoi que ce soit avant de l’utiliser. à la volée quand on en a besoin.
Configuration globale
Outre vos options de configuration habituelles, qui devraient inclure le paramètre base_url
et, le cas échéant, la page_index
, nous devons définir les aides string et date sur autoload. Je ne vais pas vous expliquer cela, car nous avons beaucoup plus à couvrir, en cas de doute, consultez la documentation.
Outre les assistants, nous devons configurer la classe de chiffrement, car nous allons l'utiliser pour notre application.
Gestion des URL
Cela va être un service RESTful et nous avons besoin d'un moyen de prendre les requêtes qui arrivent sur le serveur et de les traiter en conséquence. Nous pourrions utiliser une bibliothèque existante (ce qui est excellent en passant), mais pour les besoins de cette démonstration, je vais créer la fonctionnalité dont j'ai besoin à l'aide des fonctionnalités principales de CodeIgniter.
Traitement des demandes RESTful
En particulier, nous allons utiliser la possibilité d’élargir les classes de base. Nous allons commencer par le contrôleur. Pour la partie principale de cette extension, nous utilisons la méthode "_remap"
dans le contrôleur de base afin que tous les contrôleurs de notre application puissent l'utiliser. Commencez par créer un fichier MY_Controller.php
dans le dossier "core"
du dossier "application"
. Nous le créons comme tout autre contrôleur CodeIgniter, comme suit:
1 |
<?php
|
2 |
if( !defined( 'BASEPATH' ) ) exit( 'No direct script access allowed' ); |
3 |
|
4 |
class MY_Controller extends CI_Controller { |
5 |
|
6 |
}
|
Maintenant, dans ce contrôleur, nous allons utiliser la méthode CodeIgniter _remap pour prétraiter chaque requête adressée au serveur. Dans la classe que nous venons de créer, ajoutez la méthode suivante:
1 |
public function _remap( $param ) { |
2 |
$request = $_SERVER['REQUEST_METHOD']; |
3 |
|
4 |
switch( strtoupper( $request ) ) { |
5 |
case 'GET': |
6 |
$method = 'read'; |
7 |
break; |
8 |
case 'POST': |
9 |
$method = 'save'; |
10 |
break; |
11 |
case 'PUT': |
12 |
$method = 'update'; |
13 |
break; |
14 |
case 'DELETE': |
15 |
$method = 'remove'; |
16 |
break; |
17 |
case 'OPTIONS': |
18 |
$method = '_options'; |
19 |
break; |
20 |
}
|
21 |
|
22 |
$this->$method( $id ); |
23 |
}
|
Tout d'abord, il y a quelques verbes REST que nous ignorons (comme PATCH), puisque je montre la construction d'une application REST, je ne veux pas ajouter d'éléments qui pourraient rendre cela plus complexe ça doit être. Deuxièmement, nous ne prenons pas en compte le cas où un contrôleur ne met pas en œuvre une méthode particulière, ce qui est très probable. Nous pourrions maintenant ajouter une méthode par défaut pour gérer de telles demandes, mais pour ne pas ajouter trop de complexité, laissons les choses comme ceci. Troisièmement, nous recevons une variable param
dans la déclaration de méthode, abordons-la, puis nous expliquerons la requête OPTIONS
. Au-dessus de l'instruction switch, ajoutez le code suivant:
1 |
if ( preg_match( "/^(?=.*[a-zA-Z])(?=.*[0-9])/", $param ) ) { |
2 |
$id = $param; |
3 |
} else { |
4 |
$id = null; |
5 |
}
|
Cette expression régulière correspond à toute chaîne composée de lettres majuscules et minuscules et de chiffres. Ceci est utilisé pour vérifier si une chaîne MongoDB _id est donnée en paramètre. Encore une fois, ce n'est ni la méthode la plus sûre ni la plus complète, mais par souci de simplicité, nous la conserverons telle quelle.
OPTIONS Demande
Étant donné que nous construisons un service Web et une application client en tant que parties distinctes, il est logique que les deux systèmes soient hébergés sur des domaines différents. Nous activerons donc CORS dans le back-end. Cela signifie, entre L'application répondra correctement aux demandes OPTIONS
.
Lorsqu'une application Web créée avec BackboneJS (et certains autres frameworks) tente d'envoyer une requête asynchrone à un serveur distant, elle envoie une requête OPTIONS
avant d'envoyer la requête à laquelle elle est censée être envoyée. Entre autres choses, le client indique au serveur d'où il envoie la demande, quel type de demande il est sur le point d'envoyer et le contenu qu'il attend. Ensuite, il appartient au serveur d’envoyer une réponse au client dans laquelle il accuse réception ou le refuse.
Étant donné que notre service principal, quel que soit le contrôleur appelé, recevra cette demande OPTIONS
, il est logique d'implémenter la méthode pour y répondre dans notre contrôleur de base. Ajoutez la méthode suivante au-dessous (ou au-dessus) de la méthode _remap
dans notre contrôleur.
1 |
private function _options() { |
2 |
$this->output->set_header( 'Access-Control-Allow-Origin: *' ); |
3 |
$this->output->set_header( "Access-Control-Allow-Methods: POST, GET, PUT, DELETE, OPTIONS" ); |
4 |
$this->output->set_header( 'Access-Control-Allow-Headers: content-type' ); |
5 |
$this->output->set_content_type( 'application/json' ); |
6 |
$this->output->set_output( "*" ); |
7 |
}
|
Idéalement, nous autoriserions seulement certains domaines à nous envoyer des requêtes, nous vérifierions l’en-tête request_headers
pour voir si nous l’acceptons et le type de contenu attendu, par le client, pour voir si nous le prenons en charge, mais là encore, est une application pas si complexe et nous sautons ces cas extrêmes.
Gestion de la production
Pour terminer notre contrôleur de base, créons une méthode que chaque contrôleur utilisera pour renvoyer ses résultats au client. Dans la classe du contrôleur de base, ajoutez la méthode suivante:
1 |
protected function _format_output( $output = null ) { |
2 |
$this->output->set_header( 'Access-Control-Allow-Origin: *' ); |
3 |
|
4 |
if( isset( $output->status ) && $output->status == 'error' ) { |
5 |
$this->output->set_status_header( 409, $output->desc ); |
6 |
}
|
7 |
$this->_parse_data( $output ); |
8 |
|
9 |
$this->output->set_content_type( 'application/json' ); |
10 |
$this->output->set_output( json_encode( $output ) ); |
11 |
}
|
Encore une fois, pour que BackboneJS puisse traiter la réponse du serveur, il doit savoir que son hôte est accepté par le serveur, d'où l'en-tête Allow-Origin
. Ensuite, si le résultat est erroné, nous définissons un en-tête d'état l'indiquant. Ces status
deviendront plus claires lorsque nous créerons les modèles de back-end. Nous utilisons ensuite l'assistant parse_data
, qui sera une méthode privée (que nous écrirons dans un instant), mais laissez-moi l'ignorer pour le moment, puis définissez le type de contenu sur JSON et, finalement, codons la réponse sous forme d'objet JSON. . Là encore, nous pourrions (et devrions) prendre en charge d’autres formats de sortie (comme XML).
Créons maintenant la méthode d'assistance parse_data
(et je l'expliquerai plus tard), ajoutons le code suivant au contrôleur de base:
1 |
private function _parse_data( &$data ) { |
2 |
if ( ! is_array( $data ) && ! is_object( $data ) ) |
3 |
return $data; |
4 |
|
5 |
foreach ( $data as $key => $value ) { |
6 |
if ( is_object( $value ) || is_array( $value ) ) { |
7 |
if( is_object( $data ) ) { |
8 |
$data->{$key} = $this->_parse_data( $value ); |
9 |
} else { |
10 |
$data[ $key ] = $this->_parse_data( $value ); |
11 |
}
|
12 |
}
|
13 |
|
14 |
if ( isset( $value->sec ) ) { |
15 |
if( is_object( $data ) ) { |
16 |
$data->{$key} = date( 'd.m.Y', $value->sec ); |
17 |
} else { |
18 |
$data[ $key ] = date( 'd.m.Y', $value->sec ); |
19 |
}
|
20 |
}
|
21 |
|
22 |
if ( is_object( $value ) && isset( $value->{'$id'} ) ) { |
23 |
if( is_object( $data ) ) { |
24 |
$data->{$key} = $value->__toString(); |
25 |
} else { |
26 |
$data[ $key ] = $value->__toString(); |
27 |
}
|
28 |
}
|
29 |
}
|
30 |
|
31 |
return $data; |
32 |
}
|
Tout d'abord, notez que nous n'analysons les données que pour les tableaux et les objets, et nous le faisons de manière récursive. Cette analyse préalable est liée au fait que MongoDB utilise des dates et des identifiants comme objets, mais que nos clients n’ont pas besoin de ces informations. Maintenant, pour le cas des ID, nous avons juste besoin de sa valeur de chaîne, d'où l'appel de la méthode toString
, alors la valeur a une propriété '$ id'. Ensuite, nous convertissons les dates au format day.month.year
. Ceci est fait pour faciliter la conception de l'application client. Encore une fois, ce n'est pas l'approche la plus flexible mais elle fonctionne pour cet exemple.
Traitement des entrées
Puisque nous renvoyons JSON à l'application cliente, il est logique que nous acceptions également les données au format JSON. CodeIgniter ne prend pas cela en charge par défaut, contrairement à Laravel. En fait, CodeIgniter ne supporte même pas les paramètres put
et delete
. Cela est principalement dû au fait que le cadre n'est pas destiné à un service RESTful. Cependant, les efforts nécessaires pour l'adapter sont minimes par rapport aux avantages, du moins de mon point de vue.
Nous allons donc commencer par prendre en charge les données JSON envoyées par BackboneJS. Créez un nouveau fichier dans le dossier "core"
, cette fois il s'appellera "MY_Input.php"
et il aura la structure de base suivante:
1 |
<?php
|
2 |
if( !defined( 'BASEPATH' ) ) exit( 'No direct script access allowed' ); |
3 |
|
4 |
class MY_Input extends CI_Input { |
5 |
|
6 |
}
|
Maintenant, chaque fois que nous utiliserons $this->input
dans notre application, nous ferons référence à cette classe, nous allons créer de nouvelles méthodes et en remplacer quelques-unes. Tout d'abord, nous allons ajouter le support pour les données JSON, ajoutez la méthode suivante à la nouvelle classe.
1 |
public function json() { |
2 |
if ( !self::$request_params ) { |
3 |
$payload = file_get_contents( 'php://input' ); |
4 |
|
5 |
if ( is_array( $payload ) ) { |
6 |
self::$request_params = $payload; |
7 |
} else if ( ( substr( $payload, 0, 1 ) == "{" ) && ( substr( $payload, ( strlen( $payload ) - 1 ), 1 ) == "}" ) ) { |
8 |
self::$request_params = json_decode( $payload ); |
9 |
} else { |
10 |
parse_str( $payload, self::$request_params ); |
11 |
}
|
12 |
}
|
13 |
|
14 |
return (object) self::$request_params; |
15 |
}
|
$request_params
est une variable statique utilisée pour stocker la chaîne de requête / les données envoyées par le client. Il est statique afin de le rendre indépendant des objets afin que nous puissions y accéder depuis n'importe quel contrôleur à tout moment. Les données sont obtenues à partir du flux php://input
plutôt que du flux global $_POST
. Ceci est fait pour obtenir les données envoyées via les requêtes PUT
et DELETE
. Enfin, la charge obtenue est inspectée pour vérifier s'il s'agit d'un tableau, d'un objet codé JSON ou d'une chaîne de requête et est traitée en conséquence. Le résultat est ensuite renvoyé sous forme d'objet.
Pour que cette méthode fonctionne, nous devons créer la variable statique $request_params
, ajouter sa déclaration en haut de la classe.
1 |
private static $request_params = null; |
Traitement des demandes régulières
Ensuite, nous devons redéfinir la méthode post
de la classe d'entrée standard pour utiliser la nouvelle charge JSON au lieu de la variable globale $_POST
. Ajoutez la méthode suivante à la nouvelle classe d'entrée.
1 |
public function post( $index = NULL, $xss_clean = FALSE ) { |
2 |
$request_vars = ( array ) $this->json(); |
3 |
if ( $index === NULL && !empty( $request_vars ) ) { |
4 |
$post = array(); |
5 |
foreach( array_keys( $request_vars ) as $key ) { |
6 |
$post[$key] = $this->_fetch_from_array( $request_vars, $key, $xss_clean ); |
7 |
}
|
8 |
return $post; |
9 |
}
|
10 |
return $this->_fetch_from_array( $request_vars, $index, $xss_clean ); |
11 |
}
|
C'est presque la même chose que la méthode post
de la classe CI_Input
d'origine, à la différence qu'elle utilise notre nouvelle méthode JSON au lieu de la variable globale $_POST
pour extraire les données post. Faisons maintenant la même chose pour la méthode PUT
.
1 |
public function put( $index = NULL, $xss_clean = FALSE ) { |
2 |
$request_vars = ( array ) $this->json(); |
3 |
if ( $index === NULL && !empty( $request_vars ) ) { |
4 |
$put = array(); |
5 |
foreach( array_keys( $request_vars ) as $key ) { |
6 |
$put[$key] = $this->_fetch_from_array( $request_vars, $key, $xss_clean ); |
7 |
}
|
8 |
return $put; |
9 |
}
|
10 |
return $this->_fetch_from_array( $request_vars, $index, $xss_clean ); |
11 |
}
|
Et puis nous avons aussi besoin de la méthode DELETE
:
1 |
public function delete( $index = NULL, $xss_clean = FALSE ) { |
2 |
$request_vars = ( array ) $this->json(); |
3 |
if ( $index === NULL && !empty( $request_vars ) ) { |
4 |
$delete = array(); |
5 |
foreach( array_keys( $request_vars ) as $key ) { |
6 |
$delete[$key] = $this->_fetch_from_array( $request_vars, $key, $xss_clean ); |
7 |
}
|
8 |
return $delete; |
9 |
}
|
10 |
return $this->_fetch_from_array( $request_vars, $index, $xss_clean ); |
11 |
}
|
Maintenant techniquement, ces méthodes supplémentaires sont inutiles, car la méthode post
peut gérer les paramètres dans les requêtes PUT
et DELETE
, mais sémantiquement, c'est mieux (à mon avis).
C'est tout ce dont nous avons besoin pour notre classe d'entrée personnalisée. Encore une fois, nous ignorons les cas extrêmes ici, comme les demandes multipart, même s'il n'est pas très difficile de les gérer et de conserver les fonctionnalités obtenues ici, mais, par souci de simplicité, nous les conserverons tels quels.
Modèle de base
Pour terminer l'extension des classes principales, créons un modèle de base sur lequel chaque modèle de l'application sera étendu, ceci afin d'éviter toute répétition de tâches communes pour chaque modèle. Comme toute autre extension de classe principale, voici notre modèle de base barebones:
1 |
<?php
|
2 |
if( !defined( 'BASEPATH' ) ) exit( 'No direct script access allowed' ); |
3 |
|
4 |
class MY_Model extends CI_Model { |
5 |
|
6 |
}
|
Ce modèle de base servira uniquement à définir et à récupérer des erreurs. Ajoutez la méthode suivante pour définir une erreur de modèle:
1 |
protected function _set_error( $desc, $data = null ) { |
2 |
$this->_error = new stdClass(); |
3 |
$this->_error->status = 'error'; |
4 |
$this->_error->desc = $desc; |
5 |
if ( isset( $data ) ) { |
6 |
$this->_error->data = $data; |
7 |
}
|
8 |
}
|
Comme vous pouvez le constater, cette méthode utilise une variable d'instance $error
, ajoutons donc sa déclaration au sommet de notre classe de modèle de base.
1 |
protected $_error; |
Enfin, pour la garder structurée, créons la méthode getter pour cette propriété.
1 |
public function get_error() { |
2 |
return $this->_error; |
3 |
}
|
Manipulation des sessions
Contrôleur de session
Pour la dernière partie de ce tutoriel, nous allons créer le contrôleur et le modèle pour gérer les sessions utilisateur.
Le contrôleur de notre session va répondre à toute demande POST
adressée à notre ressource Session
, car la session ne peut pas être extraite après la création, ni mise à jour directement, ce contrôleur répond uniquement aux demandes POST
et DELETE
. Veuillez noter que l'envoi de toute autre demande à la ressource entraînera une erreur de serveur. Nous ne traitons pas ici les cas extrêmes, mais ceci pourrait être facilement évité en vérifiant si la méthode appelée existe dans notre fichier MY_Controller
et en définissant un nom de méthode par défaut. si la ressource ne supporte pas la demande.
Vous trouverez ci-dessous la structure de notre contrôleur de Session
:
1 |
<?php
|
2 |
if ( !defined( 'BASEPATH' ) ) exit( 'No direct script access allowed' ); |
3 |
|
4 |
class Session extends MY_Controller { |
5 |
|
6 |
public function __construct() {} |
7 |
|
8 |
public function save() {} |
9 |
|
10 |
public function remove( $id = null ) {} |
11 |
}
|
Notez que ce contrôleur étend la classe MY_Controller
au lieu de la classe CI_Controller
habituelle. Nous le faisons pour utiliser la méthode _remap
et les autres fonctionnalités que nous avons créées précédemment. OK, alors commençons par le constructeur.
1 |
public function __construct() { |
2 |
parent::__construct(); |
3 |
|
4 |
$this->load->model( 'session_model', 'model' ); |
5 |
}
|
Ce constructeur simple appelle simplement son constructeur parent (comme tous les contrôleurs de CodeIgniter doivent le faire), puis charge le modèle du contrôleur. Le code de la méthode save
est le suivant.
1 |
public function save() { |
2 |
$result = $this->model->create(); |
3 |
if ( !$result ) { |
4 |
$result = $this->model->get_error(); |
5 |
}
|
6 |
$this->_format_output( $result ); |
7 |
}
|
Et puis le code pour la méthode remove
:
1 |
public function remove( $id = null ) { |
2 |
$result = $this->model->destroy( $id ); |
3 |
if ( !$result ) { |
4 |
$result = $this->model->get_error(); |
5 |
}
|
6 |
$this->_format_output( $result ); |
7 |
}
|
Les deux méthodes délèguent simplement la tâche en question au modèle, qui gère la manipulation des données. Dans une application du monde réel, la validation des données et le contrôle de session nécessaires seraient effectués dans le contrôleur, et les tâches courantes telles que le contrôle de session devraient être implémentées dans le contrôleur de base.
Modèle de session
Passons maintenant au modèle de session. Voici sa structure de base:
1 |
<?php
|
2 |
if ( !defined( 'BASEPATH' ) ) exit( 'No direct script access allowed' ); |
3 |
|
4 |
class Session_Model extends MY_Model { |
5 |
|
6 |
public function __construct() {} |
7 |
|
8 |
public function create() {} |
9 |
|
10 |
public function destroy( $id ) {} |
11 |
}
|
À l'instar du contrôleur, ce modèle étend la classe MY_Model
à la place de la classe CI_Model
standard. Cette opération est en cours afin d'utiliser les méthodes courantes que nous avons créées précédemment. Encore une fois, commençons par le constructeur.
1 |
public function __construct() { |
2 |
$this->load->driver( 'mongo_db' ); |
3 |
}
|
Dans ce cas, nous chargeons simplement le pilote Mongo_db, dont nous avons déjà parlé. Nous allons maintenant continuer avec la méthode en charge de la destruction de la session.
1 |
public function destroy( $id ) { |
2 |
$filters = array( '_id' => $this->mongo_db->gen_id( $id ) ); |
3 |
|
4 |
$query = $this->mongo_db->get_where( 'sessions', $filters ); |
5 |
if ( $query->num_rows() == 0 ) { |
6 |
$this->_set_error( 'INVALID_CREDENTIALS' ); |
7 |
return false; |
8 |
}
|
9 |
|
10 |
$this->mongo_db->remove( 'sessions', $filters ); |
11 |
return 'SESSION_TERMINATED'; |
12 |
}
|
Dans cette méthode, nous vérifions s'il existe une session pour l'ID de session donné et, le cas échéant, nous essayons de la supprimer, en envoyant un message de réussite si tout va bien ou en définissant une erreur et en renvoyant la valeur false en cas de problème. Notez que lors de l'utilisation de session_id, nous utilisons la méthode spéciale $this->mongo_db->gen_id
, car, comme je l'ai mentionné précédemment, les identifiants dans MongoDB sont des objets, nous utilisons donc la chaîne id pour les créer.
Enfin, écrivons la méthode create
qui encapsulera la première partie de cette série de tutoriels.
1 |
public function create() { |
2 |
$query = $this->mongo_db->get_where( 'users', array( 'email' => $this->input->post( 'email' ) ) ); |
3 |
if ( $query->num_rows() != 1 ) { |
4 |
$this->_set_error( 'INVALID_CREDENTIALS' ); |
5 |
return false; |
6 |
}
|
7 |
|
8 |
$this->load->library( 'encrypt' ); |
9 |
$user = $query->row(); |
10 |
$salt = $this->encrypt->decode( $user->salt ); |
11 |
if ( $user->pass != sha1( $this->input->post( 'pass' ) . $salt ) ) { |
12 |
$this->_set_error( 'INVALID_CREDENTIALS' ); |
13 |
return false; |
14 |
}
|
15 |
|
16 |
$this->mongo_db->remove( 'sessions', array( 'user_id' => $user->_id->__toString() ) ); |
17 |
|
18 |
$session = array( |
19 |
'timestamp' => now(), |
20 |
'user_id' => $user->_id->__toString(), |
21 |
'persistent' => $this->input->post( 'persistent' ) |
22 |
);
|
23 |
|
24 |
if ( !$this->mongo_db->insert( 'sessions', $session ) ) { |
25 |
$this->_set_error( 'ERROR_REGISTERING_SESSION' ); |
26 |
return false; |
27 |
}
|
28 |
|
29 |
$result = new stdClass(); |
30 |
$result->id = $this->mongo_db->insert_id(); |
31 |
$result->user_id = $user->_id->__toString(); |
32 |
|
33 |
return $result; |
34 |
}
|
Tout d’abord, nous vérifions qu’un utilisateur est associé à l’email donné. Ensuite, nous décodons le salt
associé à l'utilisateur (ce que j'expliquerai dans la deuxième partie de cette série lorsque nous couvrirons l'enregistrement de l'utilisateur) et vérifierons que le mot de passe donné correspond au mot de passe stocké par l'utilisateur.
Nous supprimons ensuite toute session précédente associée à l'utilisateur et créons un nouvel objet de session. Si nous vérifions minutieusement la session, nous ajouterions des éléments tels que le champ user_agent, ip_address, last_activity, etc. Enfin, nous renvoyons au client la session et les identifiants d’utilisateur de la nouvelle session.
Conclusion
Ce tutoriel a été plutôt long, nous avons abordé de nombreux sujets et nous en avons encore beaucoup à couvrir. J'espère que vous avez maintenant une meilleure compréhension des services RESTful ou sans état et de la création d'un tel service avec CodeIgniter. Vous avez peut-être également retenu de nouvelles idées que vous pouvez donner aux fonctionnalités de base du cadre.