German (Deutsch) translation by Federicco Ancie (you can also view the original English article)
Die Anwendung, die wir erstellen, ist eine einfache Werbetafel, auf der Benutzer sich registrieren, Aufgaben veröffentlichen und eine Belohnung für ihre Fertigstellung anbieten können. Andere Benutzer können die vorhandenen Aufgaben anzeigen, die Aufgabe sich selbst zuweisen und die angebotene Belohnung erhalten.
Die Aufgaben enthalten grundlegende Daten wie Titel, Beschreibung und Belohnung (als erforderliche Parameter) sowie ein optionales Fälligkeitsdatum und Notizen. Das Benutzerprofil besteht einfach aus dem Namen, der E-Mail-Adresse und der Website des Benutzers. Also lasst uns anfangen.
Datenbank-Setup
Zunächst werden wir für die App-Daten MongoDB als Datenbankserver verwenden. MongoDB ist eine dokumentenorientierte Datenbank und die führende NoSQL-Datenbank. Es ist wirklich skalierbar und schnell, was es großartig macht, große Datenmengen zu verwalten.
MongoDB ist eine dokumentenorientierte Datenbank und die führende NoSQL-Datenbank.
Um MongoDB in dieser Anwendung zu verwenden, verwende ich einen MongoDB CodeIgniter-Treiber, den ich vor einiger Zeit geschrieben habe. Es ist nur ein Wrapper des MongoDB-PHP-Treibers, um den SQL ActiveRecord des Frameworks nachzuahmen. Sie finden die Quelldateien für diesen Treiber in meinem öffentlichen Repository. Damit dieser Treiber ordnungsgemäß funktioniert, stellen Sie sicher, dass der MongoDB-Treiber des PHP installiert ist. Wenn Sie dies nicht tun, führen Sie die folgenden Schritte aus, damit er funktioniert.
Bitte beachten Sie, dass die Erläuterung der Treiber in CodeIgniter und dergleichen nicht in diesem Lernprogramm enthalten ist. Wenn Sie Zweifel haben, lesen Sie die Dokumentation. Sie müssen nur die "mongo_db.php"
verschieben im Ordner "config"
in den Ordner "config"
Ihrer Anwendung und im Ordner "Mongo_db"
im Ordner "libraries"
in den Ordner "libraries"
in Ihrer Anwendung.
Datenbankkonfiguration
Die einzige Datei, die wir an dieser Stelle bearbeiten müssen, ist "mongo_db.php"
. Datei unter dem Ordner "config"
, da meine mongo
-Installation alle Standardparameter enthält, werde ich nur Zeile 40 bearbeiten und ihr den Namen der Datenbank geben, die ich verwenden möchte:
1 |
$config['mongo_db'] = 'billboard'; |
Das ist es für die Datenbank. Einer der vielen Vorteile von MongoDB ist, dass die Dokumente keine vordefinierte Struktur haben. Sie funktionieren also, ohne dass wir vor der Verwendung etwas einrichten müssen. Unsere Datenbank muss nicht einmal vorhanden sein. MongoDB wird sie erstellen on the fly, wenn wir es brauchen.
Globale Konfiguration
Abgesehen von Ihren regulären Konfigurationsoptionen, zu denen gegebenenfalls die base_url
und die index_page
gehören sollten, müssen wir die string- und date hilfe auf Autoload setzen. Ich werde Sie nicht durch dieses Thema führen, da wir im Zweifelsfall noch viel mehr zu besprechen haben, wenn Sie sich auf die Dokumentation beziehen.
Abgesehen von den Helfern müssen wir die Verschlüsselungsklasse einrichten, da wir sie für unsere App verwenden werden.
URL-Behandlung
Dies wird ein RESTful-Service sein, und wir brauchen eine Möglichkeit, die an den Server kommenden Anforderungen zu übernehmen und entsprechend zu behandeln. Wir könnten eine vorhandene Bibliothek verwenden (was übrigens großartig ist), aber für die Zwecke dieser Demonstration werde ich die Funktionalität, die ich benötige, mithilfe der Kernfunktionen von CodeIgniter erstellen.
Bearbeitung von RESTful-Anfragen
Insbesondere werden wir die Möglichkeit nutzen, die Kernklassen zu erweitern. Wir beginnen mit dem Controller. Für den Hauptteil dieser Erweiterung verwenden wir die Methode "_remap"
im Basis-Controller, damit alle Controller unserer App sie verwenden können. Beginnen Sie mit dem Erstellen einer MY_Controller.php
-Datei im Ordner "core"
im Ordner "application"
. Wir erstellen diese Datei wie jeden anderen CodeIgniter-Controller wie folgt:
1 |
<?php
|
2 |
if( !defined( 'BASEPATH' ) ) exit( 'No direct script access allowed' ); |
3 |
|
4 |
class MY_Controller extends CI_Controller { |
5 |
|
6 |
}
|
In diesem Controller verwenden wir jetzt die CodeIgniter _remap-Methode, um jede an den Server gesendete Anforderung vorzuverarbeiten. Fügen Sie in der soeben erstellten Klasse die folgende Methode hinzu:
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 |
}
|
Ein paar Dinge, die hier zu beachten sind: Zunächst einmal gibt es einige REST-Verben, die wir ignorieren (wie PATCH). Da ich das Erstellen einer REST-App demonstriere, möchte ich keine Dinge hinzufügen, die dies möglicherweise komplexer machen als es muss sein. Zweitens berücksichtigen wir nicht den Fall, dass ein Controller keine bestimmte Methode implementiert, was sehr wahrscheinlich ist, dass dies passieren könnte. Jetzt könnten wir eine Standardmethode hinzufügen, um solche Anforderungen zu verarbeiten, aber damit wir nicht zu viel Komplexität hinzufügen, lassen wir es so. Drittens erhalten wir eine param
-Variable in der Methodendeklaration. Lassen Sie uns das ansprechen, und dann erkläre ich die OPTIONS
-Anforderung. Fügen Sie über der switch-Anweisung den folgenden Code hinzu:
1 |
if ( preg_match( "/^(?=.*[a-zA-Z])(?=.*[0-9])/", $param ) ) { |
2 |
$id = $param; |
3 |
} else { |
4 |
$id = null; |
5 |
}
|
Dieser reguläre Ausdruck entspricht jeder Zeichenfolge, die aus Groß- und Kleinbuchstaben sowie beliebigen Zahlen besteht. Dies wird verwendet, um zu überprüfen, ob eine MongoDB _id-Zeichenfolge als Parameter angegeben wird. Dies ist wiederum weder der sicherste noch die gründlichste Überprüfung, aber der Einfachheit halber behalten wir sie unverändert bei.
OPTIONEN Anfrage
Da wir einen Webdienst und eine Clientanwendung als separate Teile erstellen, ist es sinnvoll, dass beide auf verschiedenen Domänen gehostet werden. Daher werden wir CORS im Back-End aktivieren. Dies bedeutet unter anderem, dass unsere Die App reagiert ordnungsgemäß auf OPTIONS
-Anfragen.
Wenn eine mit BackboneJS (und einigen anderen Frameworks) erstellte Webanwendung versucht, eine asynchrone Anforderung an einen Remoteserver zu senden, sendet sie eine OPTIONS
-Anforderung, bevor die eigentliche Anforderung gesendet wird, die gesendet werden soll. Unter anderem teilt der Client dem Server mit, von wo er die Anforderung sendet, welche Art von Anforderung er senden soll und welchen Inhalt er erwartet. Danach ist es Sache des Servers, dem Client eine Antwort zu senden, in der er die Anforderung bestätigt oder ablehnt.
Da unser Back-End-Service, unabhängig davon, welcher Controller aufgerufen wird, diese OPTIONS
-Anforderung empfängt, ist es sinnvoll, die Methode zu implementieren, um darauf in unserem Basis-Controller zu antworten. Fügen Sie die folgende Methode unter (oder über) der _remap
-Methode in unserem Controller hinzu.
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 |
}
|
Im Idealfall würden wir nur einigen Domains erlauben, Anfragen an uns zu stellen. Wir würden den Header request_headers
überprüfen, um festzustellen, ob wir ihn akzeptieren, und den Client auf den erwarteten Inhaltstyp prüfen, um festzustellen, ob wir ihn unterstützen, aber auch dies ist eine nicht so komplexe App und wir überspringen diese Randfälle.
Ausgabe verwalten
Um unseren Basis-Controller fertigzustellen, erstellen wir eine Methode, mit der jeder Controller seine Ergebnisse an den Client zurücksendet. Fügen Sie in der Basis-Controller-Klasse die folgende Methode hinzu:
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 |
}
|
Damit BackboneJS die Serverantwort verarbeiten kann, muss es wissen, dass sein Host vom Server akzeptiert wird, daher der Allow-Origin
-Header. Wenn das Ergebnis fehlerhaft ist, setzen wir einen Status-Header, der dies anzeigt. Dieser status
wird klarer, wenn wir die Back-End-Modelle erstellen. Als nächstes verwenden wir den parse_data
-Helfer, eine private Methode (die wir gleich schreiben werden), aber lassen Sie mich dies vorerst überspringen. Dann setzen wir den Inhaltstyp als JSON und codieren die Antwort schließlich als JSON-Objekt . Auch hier könnten (und sollten) wir andere Ausgabeformate (wie XML) unterstützen.
Erstellen wir nun die Hilfsmethode parse_data
(und ich erkläre sie anschließend) und fügen dem Basis-Controller den folgenden Code hinzu:
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 |
}
|
Beachten Sie zunächst, dass wir die Daten nur für Arrays und Objekte analysieren und dies rekursiv tun. Diese Voranalyse hat damit zu tun, dass MongoDB Datumsangaben und IDs als Objekte verwendet, unsere Kunden diese Informationen jedoch nicht benötigen. Für den Fall von IDs benötigen wir nur den Zeichenfolgenwert, daher den Methodenaufruf toString
. Dann hat der Wert die Eigenschaft '$id'. Anschließend konvertieren wir die Daten in ein day.month.year
-Format. Dies geschieht zur Vereinfachung des Entwurfs der Clientanwendung. Dies ist wiederum nicht der flexibelste Ansatz, funktioniert jedoch für dieses Beispiel.
Eingabe verarbeiten
Da wir JSON an die Clientanwendung zurücksenden, ist es nur logisch, dass wir auch Daten im JSON-Format akzeptieren. CodeIgniter unterstützt dies standardmäßig nicht wie Laravel. Tatsächlich unterstützt CodeIgniter nicht einmal das put
und delete
von Parametern. Dies liegt hauptsächlich daran, dass das Framework nicht für einen RESTful-Service vorgesehen ist, der Aufwand für die Anpassung jedoch im Vergleich zu den Vorteilen, zumindest aus meiner Sicht, minimal ist.
Wir werden also zunächst die JSON-Daten unterstützen, die BackboneJS sendet. Erstellen Sie eine neue Datei im Ordner "core"
, diesmal mit dem Namen "MY_Input.php"
. und es wird die folgende Grundstruktur haben:
1 |
<?php
|
2 |
if( !defined( 'BASEPATH' ) ) exit( 'No direct script access allowed' ); |
3 |
|
4 |
class MY_Input extends CI_Input { |
5 |
|
6 |
}
|
Jedes Mal, wenn wir $this->input
in unserer Anwendung verwenden, verweisen wir auf diese Klasse. Wir erstellen einige neue Methoden und überschreiben einige vorhandene. Zunächst werden wir die Unterstützung für JSON-Daten hinzufügen und der neuen Klasse die folgende Methode hinzufügen.
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
ist eine statische Variable, die zum Speichern der vom Client gesendeten Anforderungszeichenfolge / -daten verwendet wird. Es ist statisch, um es objektunabhängig zu machen, sodass wir jederzeit von jedem Controller darauf zugreifen können. Die Daten werden aus dem stream php://input
und nicht aus dem globalen $_POST
abgerufen. Dies geschieht, um die über PUT
- und DELETE
-Anforderungen gesendeten Daten ebenfalls zu erhalten. Schließlich wird die erhaltene Nutzlast überprüft, um festzustellen, ob es sich um ein Array, ein JSON-codiertes Objekt oder eine Abfragezeichenfolge handelt, und sie wird entsprechend verarbeitet. Das Ergebnis wird dann als Objekt zurückgegeben.
Damit diese Methode funktioniert, müssen wir die statische Variable $request_params
erstellen und ihre Deklaration oben in der Klasse hinzufügen.
1 |
private static $request_params = null; |
Regelmäßige Anfragen bearbeiten
Als Nächstes müssen wir die post
-Methode der regulären Eingabeklasse überschreiben, um die neue JSON-Nutzlast anstelle der globalen $_POST
-Nutzlast zu verwenden. Fügen Sie der neuen Eingabeklasse die folgende Methode hinzu.
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 |
}
|
Dies entspricht fast der post
-Methode aus der ursprünglichen CI_Input
-Klasse, mit dem Unterschied, dass unsere neue JSON-Methode anstelle der globalen $_POST
-Methode zum Abrufen der Post-Daten verwendet wird. Machen wir jetzt dasselbe für die PUT
-Methode.
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 |
}
|
Und dann brauchen wir noch die DELETE
-Methode:
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 |
}
|
Technisch gesehen sind diese zusätzlichen Methoden wirklich nicht erforderlich, da die post
-Methode die Parameter in den PUT
- und DELETE
-Anforderungen verarbeiten kann, aber semantisch ist es besser (meiner Meinung nach).
Dies ist alles, was wir für unsere benutzerdefinierte Eingabeklasse benötigen. Auch hier ignorieren wir Randfälle wie mehrteilige Anforderungen, obwohl es nicht sehr schwierig ist, diese zu verarbeiten und die hier erhaltene Funktionalität beizubehalten, aber der Einfachheit halber werden wir sie so lassen, wie sie ist.
Basismodell
Um die Erweiterung der Kernklassen zu beenden, erstellen wir ein Basismodell, auf das jedes Modell in der App erweitert wird. Dies dient nur dazu, die Wiederholung allgemeiner Aufgaben für jedes Modell zu vermeiden. Wie bei jeder anderen Erweiterung der Kernklasse ist auch hier unser Barebone-Basismodell:
1 |
<?php
|
2 |
if( !defined( 'BASEPATH' ) ) exit( 'No direct script access allowed' ); |
3 |
|
4 |
class MY_Model extends CI_Model { |
5 |
|
6 |
}
|
Dieses Basismodell dient nur zum Festlegen und Abrufen von Fehlern. Fügen Sie die folgende Methode hinzu, um einen Modellfehler festzulegen:
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 |
}
|
Wie Sie sehen können, verwendet diese Methode eine Instanzvariable $error
. Fügen wir ihre Deklaration also oben in unsere Basismodellklasse ein.
1 |
protected $_error; |
Um die Struktur zu erhalten, erstellen wir abschließend die Getter-Methode für diese Eigenschaft.
1 |
public function get_error() { |
2 |
return $this->_error; |
3 |
}
|
Sitzungen bearbeiten
Sitzungscontroller
Im letzten Teil dieses Tutorials erstellen wir den Controller und das Modell für Benutzersitzungen.
Der Controller für unsere Sitzung antwortet auf alle POST
-Anforderungen an unsere Session
-Ressource, da die Sitzung nach der Erstellung nicht abgerufen oder direkt aktualisiert werden kann. Dieser Controller antwortet nur auf POST
- und DELETE
-Anforderungen. Beachten Sie, dass das Senden einer anderen Anforderung an die Ressource zu einem Serverfehler führt. Wir behandeln hier keine Randfälle. Dies kann jedoch leicht vermieden werden, indem überprüft wird, ob die aufgerufene Methode in unserer Datei MY_Controller
vorhanden ist, und ein Standardmethodenname festgelegt wird wenn die Ressource die Anforderung nicht unterstützt.
Nachfolgend finden Sie die Struktur für unseren Session
Controller:
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 |
}
|
Beachten Sie, dass dieser Controller die MY_Controller
-Klasse anstelle der regulären CI_Controller
-Klasse erweitert. Wir tun dies, um die _remap
-Methode und andere Funktionen zu verwenden, die wir zuvor erstellt haben. OK, jetzt fangen wir mit dem Konstruktor an.
1 |
public function __construct() { |
2 |
parent::__construct(); |
3 |
|
4 |
$this->load->model( 'session_model', 'model' ); |
5 |
}
|
Dieser einfache Konstruktor ruft nur seinen übergeordneten Konstruktor auf (wie es jeder Controller in CodeIgniter tun muss) und lädt dann das Modell des Controllers. Der Code für die save
-Methode lautet wie folgt.
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 |
}
|
Und dann der Code für die Methode 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 |
}
|
Beide Methoden delegieren die vorliegende Aufgabe einfach an das Modell, das die eigentliche Datenmanipulation übernimmt. In einer realen Anwendung würde die erforderliche Datenvalidierung und Sitzungsprüfung in der Steuerung durchgeführt, und die allgemeinen Aufgaben wie die Sitzungsprüfung sollten in der Basissteuerung implementiert werden.
Sitzungsmodell
Fahren wir nun mit dem Sitzungsmodell fort. Hier ist seine Grundstruktur:
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 |
}
|
Wie der Controller erweitert dieses Modell die MY_Model
-Klasse anstelle der regulären CI_Model
-Klasse. Dies geschieht, um die zuvor erstellten allgemeinen Methoden zu verwenden. Beginnen wir wieder mit dem Konstruktor.
1 |
public function __construct() { |
2 |
$this->load->driver( 'mongo_db' ); |
3 |
}
|
In diesem Fall laden wir einfach den Mongo_db-Treiber, den wir zuvor besprochen haben. Jetzt fahren wir mit der Methode fort, die für die Zerstörung der Sitzung zuständig ist.
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 |
}
|
Bei dieser Methode prüfen wir, ob es eine Sitzung für die angegebene Sitzungs-ID gibt, und versuchen in diesem Fall, diese zu entfernen, indem wir eine Erfolgsmeldung senden, wenn alles in Ordnung ist, oder einen Fehler setzen und false zurückgeben, wenn etwas schief geht. Beachten Sie, dass wir bei Verwendung der session_id die spezielle Methode $this->mongo_db->gen_id
verwenden. Dies liegt daran, dass IDs in MongoDB, wie bereits erwähnt, Objekte sind. Daher verwenden wir die ID-Zeichenfolge, um sie zu erstellen.
Lassen Sie uns abschließend die Methode create
schreiben, die den ersten Teil dieser Tutorialserie abschließt.
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 |
}
|
Zunächst überprüfen wir, ob der angegebenen E-Mail ein Benutzer zugeordnet ist. Dann dekodieren wir das dem Benutzer zugeordnete salt
(was ich im zweiten Teil dieser Serie erläutern werde, wenn wir uns mit der Benutzerregistrierung befassen) und überprüfen, ob das angegebene Passwort mit dem gespeicherten Passwort des Benutzers übereinstimmt.
Anschließend entfernen wir alle vorherigen Sitzungen, die dem Benutzer zugeordnet sind, und erstellen ein neues Sitzungsobjekt. Wenn wir die Sitzung gründlich überprüfen würden, würden wir diesem Objekt Dinge wie user_agent, ip_address, last_activity usw. hinzufügen. Schließlich senden wir die Sitzungs- und Benutzer-IDs für die neue Sitzung an den Client zurück.
Abschluss
Dies war ein ziemlich langes Tutorial, wir haben viele Themen behandelt und wir haben noch mehr zu behandeln. Hoffentlich haben Sie jetzt ein besseres Verständnis für RESTful- oder zustandslose Services und wie Sie einen solchen Service mit CodeIgniter erstellen, und möglicherweise haben Sie auch einige neue Ideen aufgegriffen, die Sie der Kernfunktionalität des Frameworks geben können.