Lesson 139 of 158 – Project User Registration API
88%

Project User Registration API

In this lesson, we will create the user registration API for our Student Management mobile application.

The React Native application will send registration information to the PHP REST API. The PHP API will validate the data, hash the password, and store the new user in the MySQL database.

Project Goal: Create a secure registration API using React Native, Axios, PHP, MySQL, PDO, JSON, and password hashing.

1. Registration Flow

The registration process will follow this flow:

React Native Registration Form
          ↓
       Axios POST
          ↓
      PHP API
          ↓
       Validate
          ↓
   Check Duplicate Email
          ↓
    Hash Password
          ↓
       MySQL
          ↓
     JSON Response

2. Registration API Endpoint

We can create a PHP file named:

register.php

The mobile application will send a POST request:

POST /api/register.php

Registration data will be sent in JSON format.

3. Registration Data

The API will receive information such as:

{
    "name": "Rahul Kumar",
    "email": "rahul@example.com",
    "password": "secret123"
}

The password will never be stored directly in this form.

4. PHP Content Type

Because the API returns JSON, we should set the response Content-Type.

header(
    "Content-Type: application/json"
);

This tells the client that the server response contains JSON.

5. Database Connection

The registration API needs a PDO connection to the student_management database.

require_once '../config/database.php';

The database connection should remain on the server and should never be placed inside the React Native application.

6. Allow Only POST Requests

Registration creates a new record, so the API should accept POST requests.

if ($_SERVER['REQUEST_METHOD'] !== 'POST') {

    http_response_code(405);

    echo json_encode([
        "success" => false,
        "message" => "Method not allowed"
    ]);

    exit;
}

7. Reading JSON Input

JSON request data can be read using php://input.

$input = json_decode(
    file_get_contents("php://input"),
    true
);

The second argument true converts the JSON object into a PHP associative array.

8. Getting User Data

$name = trim($input['name'] ?? '');
$email = trim($input['email'] ?? '');
$password = $input['password'] ?? '';

Using the null coalescing operator helps prevent undefined index errors when a field is missing.

9. Validate Required Fields

Registration should not continue if required fields are missing.

if ($name === '' ||
    $email === '' ||
    $password === '') {

    http_response_code(422);

    echo json_encode([
        "success" => false,
        "message" => "All fields are required"
    ]);

    exit;
}

10. Validate Email

PHP provides filter_var() for basic email validation.

if (!filter_var(
    $email,
    FILTER_VALIDATE_EMAIL
)) {

    http_response_code(422);

    echo json_encode([
        "success" => false,
        "message" => "Invalid email address"
    ]);

    exit;
}

11. Validate Password Length

A minimum password length should be enforced by the server.

if (strlen($password) < 6) {

    http_response_code(422);

    echo json_encode([
        "success" => false,
        "message" =>
            "Password must be at least 6 characters"
    ]);

    exit;
}

12. Check Duplicate Email

The email column is unique in our database. We should check whether the email already exists before inserting a new user.

$stmt = $pdo->prepare(
    "SELECT id
     FROM users
     WHERE email = ?"
);

$stmt->execute([$email]);

if ($stmt->fetch()) {

    http_response_code(409);

    echo json_encode([
        "success" => false,
        "message" => "Email already registered"
    ]);

    exit;
}

13. Why Use HTTP 409?

HTTP status code 409 Conflict is appropriate when the submitted data conflicts with existing data.

In this project, a duplicate email is a good example.

409 Conflict
    ↓
Email already exists

14. Hash the Password

Never save the user's original password.

$passwordHash = password_hash(
    $password,
    PASSWORD_DEFAULT
);

The generated hash should be stored in the database.

15. Insert User into MySQL

$stmt = $pdo->prepare(
    "INSERT INTO users
    (name, email, password, role)
    VALUES (?, ?, ?, ?)"
);

$stmt->execute([
    $name,
    $email,
    $passwordHash,
    'user'
]);

The prepared statement protects the database query from SQL injection.

16. Getting the New User ID

After inserting the user, we can retrieve the generated ID.

$userId = $pdo->lastInsertId();

This ID can be included in a safe registration response.

17. Successful Response

A successful resource creation can return HTTP status 201 Created.

http_response_code(201);

echo json_encode([
    "success" => true,
    "message" => "Registration successful",
    "data" => [
        "id" => $userId,
        "name" => $name,
        "email" => $email
    ]
]);

18. Never Return the Password

The registration response should not contain the password or password hash.

Safe response:

{
    "id": 1,
    "name": "Rahul Kumar",
    "email": "rahul@example.com"
}

The password should remain private.

19. Error Handling

Database operations should be protected with exception handling.

try {

    // Database operation

} catch (PDOException $e) {

    error_log($e->getMessage());

    http_response_code(500);

    echo json_encode([
        "success" => false,
        "message" => "Server error"
    ]);
}

Detailed database errors should not be exposed to mobile users.

20. Complete PHP Registration API

<?php

header(
    "Content-Type: application/json"
);

require_once '../config/database.php';

if ($_SERVER['REQUEST_METHOD'] !== 'POST') {

    http_response_code(405);

    echo json_encode([
        "success" => false,
        "message" => "Method not allowed"
    ]);

    exit;
}

$input = json_decode(
    file_get_contents("php://input"),
    true
);

$name = trim($input['name'] ?? '');
$email = trim($input['email'] ?? '');
$password = $input['password'] ?? '';

if ($name === '' ||
    $email === '' ||
    $password === '') {

    http_response_code(422);

    echo json_encode([
        "success" => false,
        "message" => "All fields are required"
    ]);

    exit;
}

if (!filter_var(
    $email,
    FILTER_VALIDATE_EMAIL
)) {

    http_response_code(422);

    echo json_encode([
        "success" => false,
        "message" => "Invalid email address"
    ]);

    exit;
}

if (strlen($password) < 6) {

    http_response_code(422);

    echo json_encode([
        "success" => false,
        "message" =>
            "Password must be at least 6 characters"
    ]);

    exit;
}

$stmt = $pdo->prepare(
    "SELECT id FROM users WHERE email = ?"
);

$stmt->execute([$email]);

if ($stmt->fetch()) {

    http_response_code(409);

    echo json_encode([
        "success" => false,
        "message" => "Email already registered"
    ]);

    exit;
}

$passwordHash = password_hash(
    $password,
    PASSWORD_DEFAULT
);

$stmt = $pdo->prepare(
    "INSERT INTO users
    (name, email, password, role)
    VALUES (?, ?, ?, ?)"
);

$stmt->execute([
    $name,
    $email,
    $passwordHash,
    'user'
]);

$userId = $pdo->lastInsertId();

http_response_code(201);

echo json_encode([
    "success" => true,
    "message" => "Registration successful",
    "data" => [
        "id" => $userId,
        "name" => $name,
        "email" => $email
    ]
]);

21. React Native Registration Form

The mobile application can contain three main input fields.

Name
Email
Password

React Native state can store their values.

const [name, setName] =
    useState("");

const [email, setEmail] =
    useState("");

const [password, setPassword] =
    useState("");

22. Registration Request Interface

TypeScript can define the structure of the registration request.

interface RegisterRequest {
    name: string;
    email: string;
    password: string;
}

This helps prevent incorrect request data from being sent.

23. Registration Response Interface

interface RegisterResponse {
    success: boolean;
    message: string;
    data?: {
        id: number;
        name: string;
        email: string;
    };
}

The data property is optional because an unsuccessful response may contain only an error message.

24. Axios Registration Request

const response =
    await api.post<RegisterResponse>(
        "/register.php",
        {
            name,
            email,
            password
        }
    );

console.log(response.data);

Axios sends the object as JSON when the appropriate content type is configured.

25. Handling Registration Errors

try {

    const response =
        await api.post<RegisterResponse>(
            "/register.php",
            {
                name,
                email,
                password
            }
        );

    console.log(
        response.data.message
    );

} catch (error) {

    console.log(
        "Registration failed"
    );
}

A reusable Axios error handler can later provide better messages for validation, duplicate email, and network errors.

26. Testing with Postman

Before connecting React Native, test the registration API using Postman.

Method: POST

URL:

https://example.com/api/register.php

Body → raw → JSON:

{
    "name": "Rahul Kumar",
    "email": "rahul@example.com",
    "password": "secret123"
}

27. Registration Response Examples

Success:

{
    "success": true,
    "message": "Registration successful",
    "data": {
        "id": 1,
        "name": "Rahul Kumar",
        "email": "rahul@example.com"
    }
}

Duplicate email:

{
    "success": false,
    "message": "Email already registered"
}

28. Registration Security

  • Use HTTPS in production.
  • Validate all data on the server.
  • Use prepared SQL statements.
  • Hash passwords using password_hash().
  • Never return passwords in API responses.
  • Do not store database credentials in React Native.
  • Do not trust only client-side validation.
  • Return safe server error messages.
  • Use appropriate HTTP status codes.

29. Complete Registration Flow

Registration Screen
        ↓
TypeScript Validation
        ↓
Axios POST
        ↓
PHP register.php
        ↓
Read JSON
        ↓
Validate Input
        ↓
Check Duplicate Email
        ↓
password_hash()
        ↓
PDO INSERT
        ↓
HTTP 201
        ↓
JSON Response
        ↓
React Native

30. Registration API Project Summary

We have now designed the complete registration process for the Student Management application.

  • React Native collects registration information.
  • Axios sends a POST request.
  • PHP reads the JSON request.
  • The server validates the data.
  • Duplicate email is detected.
  • The password is securely hashed.
  • PDO inserts the user into MySQL.
  • The API returns a JSON response.
  • The password is never returned to the mobile application.

In the next lesson, we will create the user login API that verifies the registered user's email and password.

📌 Key Points

  • Registration uses the HTTP POST method.
  • JSON data is read using php://input.
  • Server-side validation is required.
  • Duplicate emails should return HTTP 409.
  • Validation errors can return HTTP 422.
  • Passwords must be hashed using password_hash().
  • PDO prepared statements should be used for INSERT queries.
  • Successful registration can return HTTP 201.
  • Password and password hash must not be returned in the response.
  • React Native can use Axios and TypeScript interfaces for registration.

🧠 Quick Quiz

Question: Which PHP function should be used to securely hash a user's password before storing it in MySQL?