· 8 years ago · Dec 02, 2017, 12:00 PM
1CREATE TABLE IF NOT EXISTS "user" (
2 "id" INTEGER PRIMARY KEY AUTOINCREMENT,
3 "username" TEXT UNIQUE,
4 "passwordHash" TEXT
5);
6
7public function insertUser( $username, $passwordHash ) {
8 try {
9 $stmt = $this->db->prepare( '
10 INSERT INTO "user" ("username", "passwordHash")
11 VALUES (:username, :passwordHash);
12 ' );
13 $stmt->execute( [
14 'username' => $username,
15 'passwordHash' => $passwordHash
16 ] );
17
18 // return the id of the newly created user
19 return $this->db->lastInsertId();
20 }
21 catch( PDOException $e ) {
22 // in sqlite an error code 19 indicates a constraint violation
23 if( $e->errorInfo[ 1 ] === 19 ) {
24 // if the constraint that is violated is user.username
25 if( false !== strpos( $e->errorInfo[ 2 ], 'user.username' ) ) {
26 // throw a custom exception that we could deem recoverable
27 throw new UserAlreadyExistsException( $username, $e );
28 }
29 }
30
31 // an unknown error occurred, re-throw the original exception
32 throw $e;
33 }
34}
35
36class UserAlreadyExistsException extends RuntimeException {
37 private $username;
38
39 public function __construct( $username, $previous = null ) {
40 parent::__construct( 'User already exists', 0, $previous );
41 $this->username = $username;
42 }
43
44 public function getUsername() {
45 return $this->username;
46 }
47}
48
49try {
50 $username = $_POST[ 'username' ];
51 $passwordHash = password_hash( $_POST[ 'password' ], PASSWORD_BCRYPT );
52 $ourPretendObjectFromAbove->insertNewUser( $username, $passwordHash );
53}
54// catch a known, recoverable, exception
55catch( UserAlreadyExistsException $e ) {
56 // not a fatal exception: show the user the following error message somehow
57 $errorMessage = sprintf( 'Username %s is already taken', $e->getUsername() );
58}
59// catch any other exception
60catch( Exception $e ) {
61 // unexpected / fatal exception: needs immediate developer's attention
62 $logger->logException( $e );
63 $mailer->mailDeveloper( $e );
64 header( 'HTTP/1.1 500 Internal Server Error', true, 500 );
65 // show the user the following error message somehow
66 $errorMessage = 'An internal error occurred. Our developers will take a look at it';
67}