In this lesson, we will create the Student Profile API for our Student Management mobile application.
This API will allow an authenticated user to retrieve the profile information of a student using the student's ID. The PHP REST API will verify the JWT, validate the student ID, fetch the student record from MySQL using PDO, and return the profile as JSON.
React Native Student Screen
↓
Student ID
↓
Axios GET Request
↓
students/profile.php?id=5
↓
JWT Verification
↓
Validate Student ID
↓
Find Student
↓
MySQL / PDO
↓
JSON Profile
↓
React Native Profile Screen
A Student Profile API returns information about one specific student.
GET /api/student_profile.php?id=5
The API uses the student ID to find the corresponding record.
GET /api/student_profile.php?id=5
Here, 5 represents the student's database ID.
header(
"Content-Type: application/json"
);
This tells the mobile application that the API response contains JSON data.
require_once '../config/database.php';
The API uses the existing PDO connection to communicate with MySQL.
if ($_SERVER['REQUEST_METHOD'] !== 'GET') {
http_response_code(405);
echo json_encode([
"success" => false,
"message" => "Method not allowed"
]);
exit;
}
The profile endpoint should accept GET requests.
Student profile information may be private. Therefore, the API should require authentication.
Authorization:
Bearer YOUR_JWT_TOKEN
The token is sent by the React Native application.
$headers = getallheaders();
$authorization =
$headers['Authorization']
?? '';
The PHP API reads the Authorization header sent with the request.
if (
!preg_match(
'/Bearer\s(\S+)/',
$authorization,
$matches
)
) {
http_response_code(401);
echo json_encode([
"success" => false,
"message" =>
"Authentication required"
]);
exit;
}
$token = $matches[1];
use Firebase\JWT\JWT;
use Firebase\JWT\Key;
try {
$decoded = JWT::decode(
$token,
new Key(
$secretKey,
'HS256'
)
);
} catch (Exception $e) {
http_response_code(401);
echo json_encode([
"success" => false,
"message" =>
"Invalid or expired token"
]);
exit;
}
Only a valid token should be allowed to access the protected profile endpoint.
$id = filter_input(
INPUT_GET,
'id',
FILTER_VALIDATE_INT
);
The ID is received from the query parameter.
if (!$id || $id <= 0) {
http_response_code(400);
echo json_encode([
"success" => false,
"message" =>
"Valid student ID is required"
]);
exit;
}
Validating the ID prevents invalid values from reaching the database query.
$stmt = $pdo->prepare(
"SELECT id, name, email,
mobile, course, address
FROM students
WHERE id = ?"
);
$stmt->execute([$id]);
$student = $stmt->fetch(
PDO::FETCH_ASSOC
);
The query returns only the required profile fields.
if (!$student) {
http_response_code(404);
echo json_encode([
"success" => false,
"message" =>
"Student not found"
]);
exit;
}
HTTP 404 indicates that the requested student does not exist.
http_response_code(200);
echo json_encode([
"success" => true,
"data" => $student
]);
The student information is returned inside the data
property.
{
"success": true,
"data": {
"id": 5,
"name": "Rahul Kumar",
"email": "rahul@example.com",
"mobile": "9876543211",
"course": "React Native",
"address": "Patna"
}
}
<?php
header(
"Content-Type: application/json"
);
require_once '../config/database.php';
require_once __DIR__ .
'/vendor/autoload.php';
use Firebase\JWT\JWT;
use Firebase\JWT\Key;
$secretKey =
'CHANGE_THIS_TO_A_LONG_RANDOM_SECRET';
if ($_SERVER['REQUEST_METHOD'] !== 'GET') {
http_response_code(405);
echo json_encode([
"success" => false,
"message" => "Method not allowed"
]);
exit;
}
$headers = getallheaders();
$authorization =
$headers['Authorization']
?? '';
if (
!preg_match(
'/Bearer\s(\S+)/',
$authorization,
$matches
)
) {
http_response_code(401);
echo json_encode([
"success" => false,
"message" =>
"Authentication required"
]);
exit;
}
$token = $matches[1];
try {
JWT::decode(
$token,
new Key(
$secretKey,
'HS256'
)
);
$id = filter_input(
INPUT_GET,
'id',
FILTER_VALIDATE_INT
);
if (!$id || $id <= 0) {
http_response_code(400);
echo json_encode([
"success" => false,
"message" =>
"Valid student ID is required"
]);
exit;
}
$stmt = $pdo->prepare(
"SELECT id, name, email,
mobile, course, address
FROM students
WHERE id = ?"
);
$stmt->execute([$id]);
$student = $stmt->fetch(
PDO::FETCH_ASSOC
);
if (!$student) {
http_response_code(404);
echo json_encode([
"success" => false,
"message" =>
"Student not found"
]);
exit;
}
http_response_code(200);
echo json_encode([
"success" => true,
"data" => $student
]);
} catch (Exception $e) {
error_log($e->getMessage());
http_response_code(401);
echo json_encode([
"success" => false,
"message" =>
"Invalid or expired token"
]);
}
interface Student {
id: number;
name: string;
email: string;
mobile: string;
course: string;
address: string;
}
This interface represents the student profile returned by the API.
interface StudentProfileResponse {
success: boolean;
data: Student;
}
This gives TypeScript information about the structure of the API response.
const response =
await api.get<StudentProfileResponse>(
"/student_profile.php",
{
params: {
id: studentId
}
}
);
const student =
response.data.data;
The Axios instance can automatically send the JWT through the configured request interceptor.
const [student, setStudent] =
useState<Student | null>(null);
const [loading, setLoading] =
useState(true);
const [error, setError] =
useState("");
The profile can initially be null while the API request
is loading.
const loadProfile =
async (studentId: number) => {
try {
setLoading(true);
setError("");
const response =
await api.get<StudentProfileResponse>(
"/student_profile.php",
{
params: {
id: studentId
}
}
);
setStudent(
response.data.data
);
} catch (error) {
setError(
"Unable to load profile"
);
} finally {
setLoading(false);
}
};
{loading && (
<ActivityIndicator />
)}
{student && (
<View>
<Text>
{student.name}
</Text>
<Text>
{student.email}
</Text>
<Text>
{student.mobile}
</Text>
<Text>
{student.course}
</Text>
<Text>
{student.address}
</Text>
</View>
)}
catch (error) {
if (
axios.isAxiosError(error) &&
error.response
) {
if (
error.response.status === 401
) {
// Token expired
// Redirect to login
} else if (
error.response.status === 404
) {
setError(
"Student not found"
);
} else {
setError(
"Unable to load profile"
);
}
}
}
Method: GET
URL:
https://example.com/api/student_profile.php?id=5
Header:
Authorization: Bearer YOUR_JWT_TOKEN
Successful Response:
{
"success": true,
"data": {
"id": 5,
"name": "Rahul Kumar",
"email": "rahul@example.com",
"mobile": "9876543211",
"course": "React Native",
"address": "Patna"
}
}
Authentication answers: Who are you?
Authorization answers: What are you allowed to access?
For example, an admin may be allowed to view any student profile, while a student account may only be allowed to view its own profile.
JWT
↓
Identify User
↓
Check Role / Ownership
↓
Allow Profile Access
Student Profile Screen
↓
Student ID
↓
Axios GET
↓
JWT Authorization
↓
PHP REST API
↓
Verify JWT
↓
Validate ID
↓
Check Authorization
↓
PDO SELECT
↓
MySQL
↓
JSON Student Profile
↓
TypeScript Student
↓
React Native UI
The Student Profile API provides a protected way for the mobile application to retrieve one student's information.
?id=.Question: Which HTTP method should be used to retrieve a student profile?