0% found this document useful (0 votes)
71 views24 pages

Creating A Student Register Using React

Uploaded by

Tshepo
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
71 views24 pages

Creating A Student Register Using React

Uploaded by

Tshepo
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 24

Creating a Student Register Using React and Laravel: An

8-Page Comprehensive Guide


Table of Contents
1. Introduction
2. Prerequisites
3. Setting Up the Laravel Backend
4. Designing the Database Schema
5. Creating API Endpoints with Laravel
6. Setting Up the React Frontend
7. Building React Components and Integrating with Laravel
8. Implementing CRUD Operations
9. Authentication and Security
10. Testing and Deployment
11. Conclusion

Introduction
Building a student register is a common requirement for educational institutions and related
applications. Combining Laravel for the backend and React for the frontend leverages the
strengths of both frameworks, providing a robust, scalable, and dynamic application. Laravel
offers a powerful API-building capability, while React ensures a responsive and interactive
user interface. This guide walks you through creating a comprehensive student registration
system using Laravel and React, covering everything from initial setup to deployment.

Prerequisites
Before embarking on this project, ensure you have the following tools and knowledge:

• Basic Knowledge of PHP and Laravel: Understanding Laravel's MVC architecture.


• Basic Knowledge of JavaScript and React: Familiarity with React components, state, and
props.
• Composer Installed: Laravel utilizes Composer for dependency management.
• Node.js and NPM: Required for managing React dependencies.
• Database Server: MySQL, PostgreSQL, or any other supported database.
• Code Editors: VS Code, PHPStorm, or your preferred IDE.
• Git: For version control.
• Postman: For API testing (optional but recommended).

Optional but beneficial: Familiarity with RESTful APIs, Axios for HTTP requests in React,
and basic understanding of authentication mechanisms.
Setting Up the Laravel Backend
1. Install Laravel

Use Composer to create a new Laravel project:

composer create-project --prefer-dist laravel/laravel student-register-


backend

Navigate to the project directory:

cd student-register-backend

2. Configure Environment

Duplicate the .env.example file to .env:

cp .env.example .env

Generate an application key:

php artisan key:generate

3. Set Up Development Server

Start the Laravel development server:

php artisan serve

Visit http://localhost:8000 to verify the setup.

4. Install Laravel Sanctum (For API Authentication)

Laravel Sanctum provides a featherweight authentication system for SPAs (single page
applications):

composer require laravel/sanctum

Publish the Sanctum configuration and migration files:

php artisan vendor:publish --


provider="Laravel\Sanctum\SanctumServiceProvider"

Run migrations:

php artisan migrate


5. Configure CORS

To allow your React frontend to communicate with the Laravel backend, configure CORS.

Open config/cors.php and adjust settings:

return [

'paths' => ['api/*', 'sanctum/csrf-cookie'],

'allowed_methods' => ['*'],

'allowed_origins' => ['http://localhost:3000'], // React's default port

'allowed_origins_patterns' => [],

'allowed_headers' => ['*'],

'exposed_headers' => [],

'max_age' => 0,

'supports_credentials' => true,

];

Designing the Database Schema


1. Database Selection

Choose a relational database system like MySQL. Ensure it's installed and running.

2. Create Database

Create a new database for the project, e.g., student_register.

3. Configure .env

Update the .env file with your database credentials:

DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=student_register
DB_USERNAME=your_username
DB_PASSWORD=your_password

4. Plan Database Schema

For a student register, a basic schema might include:

• Students Table:
o id (primary key)
o first_name
o last_name
o email
o phone
o address
o date_of_birth
o created_at
o updated_at

5. Create Migration

Generate the migration for the students table:

php artisan make:migration create_students_table --create=students

Edit the migration file


(database/migrations/xxxx_xx_xx_create_students_table.php):

public function up()


{
Schema::create('students', function (Blueprint $table) {
$table->id();
$table->string('first_name');
$table->string('last_name');
$table->string('email')->unique();
$table->string('phone')->nullable();
$table->text('address')->nullable();
$table->date('date_of_birth')->nullable();
$table->timestamps();
});
}

Run the migration:

php artisan migrate

Creating API Endpoints with Laravel


1. Create Student Model and Controller

Generate a model with a migration and a resource controller:

php artisan make:model Student -m


php artisan make:controller API/StudentController --api

2. Define Model Fillable Properties

Open app/Models/Student.php and add the $fillable property:

<?php

namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;

class Student extends Model


{
use HasFactory;

protected $fillable = [
'first_name',
'last_name',
'email',
'phone',
'address',
'date_of_birth',
];
}

3. Define API Routes

Open routes/api.php and add resource routes:

use App\Http\Controllers\API\StudentController;

Route::middleware('auth:sanctum')->group(function () {
Route::apiResource('students', StudentController::class);
});

4. Implement Controller Methods

Open app/Http/Controllers/API/StudentController.php and implement CRUD


methods:

<?php

namespace App\Http\Controllers\API;

use App\Http\Controllers\Controller;
use App\Models\Student;
use Illuminate\Http\Request;

class StudentController extends Controller


{
// Display a listing of students
public function index()
{
return Student::paginate(10);
}

// Store a newly created student


public function store(Request $request)
{
$request->validate([
'first_name' => 'required|string|max:255',
'last_name' => 'required|string|max:255',
'email' => 'required|email|unique:students,email',
'phone' => 'nullable|string|max:20',
'address' => 'nullable|string',
'date_of_birth' => 'nullable|date',
]);
$student = Student::create($request->all());

return response()->json($student, 201);


}

// Display the specified student


public function show(Student $student)
{
return $student;
}

// Update the specified student


public function update(Request $request, Student $student)
{
$request->validate([
'first_name' => 'sometimes|required|string|max:255',
'last_name' => 'sometimes|required|string|max:255',
'email' =>
'sometimes|required|email|unique:students,email,' . $student->id,
'phone' => 'nullable|string|max:20',
'address' => 'nullable|string',
'date_of_birth' => 'nullable|date',
]);

$student->update($request->all());

return response()->json($student, 200);


}

// Remove the specified student


public function destroy(Student $student)
{
$student->delete();

return response()->json(null, 204);


}
}

5. Implement Authentication Routes

To manage user authentication, you can use Laravel Sanctum.

a. Create Authentication Controller

Generate an authentication controller:

php artisan make:controller API/AuthController


b. Define Authentication Methods

Open app/Http/Controllers/API/AuthController.php and implement registration and


login:

<?php

namespace App\Http\Controllers\API;

use App\Http\Controllers\Controller;
use App\Models\User;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Hash;
use Illuminate\Validation\ValidationException;

class AuthController extends Controller


{
// User Registration
public function register(Request $request)
{
$request->validate([
'name' => 'required|string|max:255',
'email' => 'required|email|unique:users,email',
'password' => 'required|string|min:6|confirmed',
]);

$user = User::create([
'name' => $request->name,
'email' => $request->email,
'password' => Hash::make($request->password),
]);

$token = $user->createToken('student-register-token')-
>plainTextToken;

return response()->json([
'user' => $user,
'token' => $token,
], 201);
}

// User Login
public function login(Request $request)
{
$request->validate([
'email' => 'required|email',
'password' => 'required|string',
]);

$user = User::where('email', $request->email)->first();

if (! $user || ! Hash::check($request->password, $user->password))


{
throw ValidationException::withMessages([
'email' => ['The provided credentials are incorrect.'],
]);
}

// Revoke previous tokens...


$user->tokens()->delete();

$token = $user->createToken('student-register-token')-
>plainTextToken;

return response()->json([
'user' => $user,
'token' => $token,
], 200);
}

// User Logout
public function logout(Request $request)
{
$request->user()->currentAccessToken()->delete();

return response()->json([
'message' => 'Logged out successfully.'
], 200);
}
}
c. Define Authentication Routes

Add the following to routes/api.php:

use App\Http\Controllers\API\AuthController;

Route::post('/register', [AuthController::class, 'register']);


Route::post('/login', [AuthController::class, 'login']);

Route::middleware('auth:sanctum')->post('/logout', [AuthController::class,
'logout']);

6. Test Backend API

Use Postman or cURL to test the API endpoints.

• Register: POST http://localhost:8000/api/register


• Login: POST http://localhost:8000/api/login
• CRUD Operations: Use the token received upon login to access protected routes.

Setting Up the React Frontend


1. Initialize React Project

Use Create React App to bootstrap the frontend project.

Open a new terminal window and run:

npx create-react-app student-register-frontend

Navigate to the project directory:

cd student-register-frontend

2. Install Necessary Dependencies

Install Axios for HTTP requests and React Router for routing:

npm install axios react-router-dom

Optionally, install Bootstrap for styling:


npm install bootstrap

Import Bootstrap in src/index.js:

import 'bootstrap/dist/css/bootstrap.min.css';

3. Set Up Project Structure

Organize your project with the following structure:

src/

├── components/
│ ├── Auth/
│ │ ├── Login.js
│ │ └── Register.js
│ ├── Students/
│ │ ├── StudentList.js
│ │ ├── StudentForm.js
│ │ └── StudentDetail.js
│ └── Layout/
│ └── Navbar.js

├── services/
│ └── api.js

├── App.js
├── index.js
└── ...

4. Configure Axios

Create src/services/api.js to configure Axios:

// src/services/api.js

import axios from 'axios';

const API = axios.create({


baseURL: 'http://localhost:8000/api', // Laravel backend
withCredentials: true,
});

// Add a request interceptor to include the token


API.interceptors.request.use((config) => {
const token = localStorage.getItem('token');
if (token) {
config.headers.Authorization = `Bearer ${token}`;
}
return config;
}, (error) => {
return Promise.reject(error);
});

export default API;


Building React Components and Integrating with Laravel
1. Create Navigation Bar

Create src/components/Layout/Navbar.js:

// src/components/Layout/Navbar.js

import React from 'react';


import { Link } from 'react-router-dom';

const Navbar = () => {


const isLoggedIn = !!localStorage.getItem('token');

const handleLogout = () => {


API.post('/logout')
.then(() => {
localStorage.removeItem('token');
window.location.href = '/login';
})
.catch((error) => {
console.error('Logout failed:', error);
});
};

return (
<nav className="navbar navbar-expand-lg navbar-light bg-light">
<Link className="navbar-brand" to="/">Student Register</Link>
<div className="collapse navbar-collapse">
<ul className="navbar-nav mr-auto">
{isLoggedIn && (
<li className="nav-item">
<Link className="nav-link"
to="/students">Students</Link>
</li>
)}
</ul>
<ul className="navbar-nav ml-auto">
{isLoggedIn ? (
<li className="nav-item">
<button className="btn btn-link nav-link"
onClick={handleLogout}>Logout</button>
</li>
) : (
<>
<li className="nav-item">
<Link className="nav-link"
to="/login">Login</Link>
</li>
<li className="nav-item">
<Link className="nav-link"
to="/register">Register</Link>
</li>
</>
)}
</ul>
</div>
</nav>
);
};

export default Navbar;

2. Create Authentication Components


a. Register Component

Create src/components/Auth/Register.js:

// src/components/Auth/Register.js

import React, { useState } from 'react';


import API from '../../services/api';
import { useHistory } from 'react-router-dom';

const Register = () => {


const history = useHistory();
const [form, setForm] = useState({
name: '',
email: '',
password: '',
password_confirmation: '',
});
const [errors, setErrors] = useState([]);

const handleChange = (e) => {


setForm({...form, [e.target.name]: e.target.value});
};

const handleSubmit = (e) => {


e.preventDefault();
API.post('/register', form)
.then((response) => {
localStorage.setItem('token', response.data.token);
history.push('/students');
})
.catch((error) => {
if (error.response && error.response.data.errors) {
setErrors(error.response.data.errors);
}
});
};

return (
<div className="container mt-5">
<h2>Register</h2>
{errors.length > 0 && (
<div className="alert alert-danger">
<ul>
{Object.keys(errors).map((key) => (
errors[key].map((msg, index) => <li
key={index}>{msg}</li>)
))}
</ul>
</div>
)}
<form onSubmit={handleSubmit}>
<div className="form-group">
<label>Name</label>
<input type="text" name="name" className="form-control"
value={form.name} onChange={handleChange} required />
</div>
<div className="form-group">
<label>Email</label>
<input type="email" name="email" className="form-
control" value={form.email} onChange={handleChange} required />
</div>
<div className="form-group">
<label>Password</label>
<input type="password" name="password" className="form-
control" value={form.password} onChange={handleChange} required />
</div>
<div className="form-group">
<label>Confirm Password</label>
<input type="password" name="password_confirmation"
className="form-control" value={form.password_confirmation}
onChange={handleChange} required />
</div>
<button type="submit" className="btn btn-
primary">Register</button>
</form>
</div>
);
};

export default Register;


b. Login Component

Create src/components/Auth/Login.js:

// src/components/Auth/Login.js

import React, { useState } from 'react';


import API from '../../services/api';
import { useHistory } from 'react-router-dom';

const Login = () => {


const history = useHistory();
const [form, setForm] = useState({
email: '',
password: '',
});
const [errors, setErrors] = useState([]);

const handleChange = (e) => {


setForm({...form, [e.target.name]: e.target.value});
};

const handleSubmit = (e) => {


e.preventDefault();
API.post('/login', form)
.then((response) => {
localStorage.setItem('token', response.data.token);
history.push('/students');
})
.catch((error) => {
if (error.response && error.response.data.errors) {
setErrors(error.response.data.errors);
}
});
};

return (
<div className="container mt-5">
<h2>Login</h2>
{errors.length > 0 && (
<div className="alert alert-danger">
<ul>
{Object.keys(errors).map((key) => (
errors[key].map((msg, index) => <li
key={index}>{msg}</li>)
))}
</ul>
</div>
)}
<form onSubmit={handleSubmit}>
<div className="form-group">
<label>Email</label>
<input type="email" name="email" className="form-
control" value={form.email} onChange={handleChange} required />
</div>
<div className="form-group">
<label>Password</label>
<input type="password" name="password" className="form-
control" value={form.password} onChange={handleChange} required />
</div>
<button type="submit" className="btn btn-
primary">Login</button>
</form>
</div>
);
};

export default Login;

3. Create Student Components


a. Student List Component

Create src/components/Students/StudentList.js:

// src/components/Students/StudentList.js

import React, { useEffect, useState } from 'react';


import API from '../../services/api';
import { Link } from 'react-router-dom';

const StudentList = () => {


const [students, setStudents] = useState([]);
const [pagination, setPagination] = useState({});

useEffect(() => {
fetchStudents();
}, []);

const fetchStudents = (url = '/students') => {


API.get(url)
.then((response) => {
setStudents(response.data.data);
setPagination({
current_page: response.data.current_page,
last_page: response.data.last_page,
});
})
.catch((error) => {
console.error('Error fetching students:', error);
});
};

const handleDelete = (id) => {


if (window.confirm('Are you sure you want to delete this
student?')) {
API.delete(`/students/${id}`)
.then(() => {
setStudents(students.filter(student => student.id !==
id));
})
.catch((error) => {
console.error('Error deleting student:', error);
});
}
};

const renderPagination = () => {


const pages = [];
for(let i = 1; i <= pagination.last_page; i++) {
pages.push(
<li key={i} className={`page-item ${i ===
pagination.current_page ? 'active' : ''}`}>
<button className="page-link" onClick={() =>
fetchStudents(`/students?page=${i}`)}>{i}</button>
</li>
);
}
return (
<nav>
<ul className="pagination">
{pages}
</ul>
</nav>
);
};

return (
<div className="container mt-5">
<h2>Students</h2>
<Link to="/students/create" className="btn btn-primary mb-
3">Add New Student</Link>
<table className="table table-bordered">
<thead>
<tr>
<th>ID</th>
<th>Name</th>
<th>Email</th>
<th>Phone</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
{students.map(student => (
<tr key={student.id}>
<td>{student.id}</td>
<td>{student.first_name}
{student.last_name}</td>
<td>{student.email}</td>
<td>{student.phone}</td>
<td>
<Link to={`/students/${student.id}`}
className="btn btn-info btn-sm mr-2">View</Link>
<Link to={`/students/edit/${student.id}`}
className="btn btn-warning btn-sm mr-2">Edit</Link>
<button className="btn btn-danger btn-sm"
onClick={() => handleDelete(student.id)}>Delete</button>
</td>
</tr>
))}
</tbody>
</table>
{renderPagination()}
</div>
);
};

export default StudentList;


b. Student Form Component

Create src/components/Students/StudentForm.js:

// src/components/Students/StudentForm.js

import React, { useState, useEffect } from 'react';


import API from '../../services/api';
import { useHistory, useParams } from 'react-router-dom';

const StudentForm = () => {


const history = useHistory();
const { id } = useParams();
const isEdit = !!id;
const [form, setForm] = useState({
first_name: '',
last_name: '',
email: '',
phone: '',
address: '',
date_of_birth: '',
});
const [errors, setErrors] = useState([]);

useEffect(() => {
if (isEdit) {
API.get(`/students/${id}`)
.then((response) => {
setForm(response.data);
})
.catch((error) => {
console.error('Error fetching student:', error);
});
}
}, [id, isEdit]);
const handleChange = (e) => {
setForm({...form, [e.target.name]: e.target.value});
};

const handleSubmit = (e) => {


e.preventDefault();
if (isEdit) {
API.put(`/students/${id}`, form)
.then(() => {
history.push('/students');
})
.catch((error) => {
if (error.response && error.response.data.errors) {
setErrors(error.response.data.errors);
}
});
} else {
API.post('/students', form)
.then(() => {
history.push('/students');
})
.catch((error) => {
if (error.response && error.response.data.errors) {
setErrors(error.response.data.errors);
}
});
}
};

return (
<div className="container mt-5">
<h2>{isEdit ? 'Edit' : 'Add'} Student</h2>
{errors.length > 0 && (
<div className="alert alert-danger">
<ul>
{Object.keys(errors).map((key) => (
errors[key].map((msg, index) => <li
key={index}>{msg}</li>)
))}
</ul>
</div>
)}
<form onSubmit={handleSubmit}>
<div className="form-group">
<label>First Name</label>
<input type="text" name="first_name" className="form-
control" value={form.first_name} onChange={handleChange} required />
</div>
<div className="form-group">
<label>Last Name</label>
<input type="text" name="last_name" className="form-
control" value={form.last_name} onChange={handleChange} required />
</div>
<div className="form-group">
<label>Email</label>
<input type="email" name="email" className="form-
control" value={form.email} onChange={handleChange} required />
</div>
<div className="form-group">
<label>Phone</label>
<input type="text" name="phone" className="form-
control" value={form.phone} onChange={handleChange} />
</div>
<div className="form-group">
<label>Address</label>
<textarea name="address" className="form-control"
value={form.address} onChange={handleChange}></textarea>
</div>
<div className="form-group">
<label>Date of Birth</label>
<input type="date" name="date_of_birth"
className="form-control" value={form.date_of_birth} onChange={handleChange}
/>
</div>
<button type="submit" className="btn btn-success">{isEdit ?
'Update' : 'Save'}</button>
</form>
</div>
);
};

export default StudentForm;


c. Student Detail Component

Create src/components/Students/StudentDetail.js:

// src/components/Students/StudentDetail.js

import React, { useEffect, useState } from 'react';


import API from '../../services/api';
import { useParams, Link } from 'react-router-dom';

const StudentDetail = () => {


const { id } = useParams();
const [student, setStudent] = useState(null);

useEffect(() => {
API.get(`/students/${id}`)
.then((response) => {
setStudent(response.data);
})
.catch((error) => {
console.error('Error fetching student:', error);
});
}, [id]);

if (!student) {
return <div className="container mt-5">Loading...</div>;
}

return (
<div className="container mt-5">
<h2>Student Details</h2>
<div className="card">
<div className="card-body">
<h5 className="card-title">{student.first_name}
{student.last_name}</h5>
<p className="card-text"><strong>Email:</strong>
{student.email}</p>
<p className="card-text"><strong>Phone:</strong>
{student.phone || 'N/A'}</p>
<p className="card-text"><strong>Address:</strong>
{student.address || 'N/A'}</p>
<p className="card-text"><strong>Date of
Birth:</strong> {student.date_of_birth || 'N/A'}</p>
<Link to="/students" className="btn btn-primary">Back
to List</Link>
</div>
</div>
</div>
);
};

export default StudentDetail;

4. Configure Routing in App.js

Edit src/App.js:

// src/App.js

import React from 'react';


import { BrowserRouter as Router, Route, Switch, Redirect } from 'react-
router-dom';

import Navbar from './components/Layout/Navbar';


import Register from './components/Auth/Register';
import Login from './components/Auth/Login';
import StudentList from './components/Students/StudentList';
import StudentForm from './components/Students/StudentForm';
import StudentDetail from './components/Students/StudentDetail';

const App = () => {


const isLoggedIn = !!localStorage.getItem('token');

return (
<Router>
<Navbar />
<Switch>
<Route exact path="/">
<Redirect to="/students" />
</Route>
<Route path="/register">
{isLoggedIn ? <Redirect to="/students" /> : <Register
/>}
</Route>
<Route path="/login">
{isLoggedIn ? <Redirect to="/students" /> : <Login />}
</Route>
<Route exact path="/students">
{isLoggedIn ? <StudentList /> : <Redirect to="/login"
/>}
</Route>
<Route path="/students/create">
{isLoggedIn ? <StudentForm /> : <Redirect to="/login"
/>}
</Route>
<Route path="/students/edit/:id">
{isLoggedIn ? <StudentForm /> : <Redirect to="/login"
/>}
</Route>
<Route path="/students/:id">
{isLoggedIn ? <StudentDetail /> : <Redirect to="/login"
/>}
</Route>
<Route path="*">
<div className="container mt-5">
<h2>404 - Not Found</h2>
<p>The page you are looking for does not exist.</p>
</div>
</Route>
</Switch>
</Router>
);
};

export default App;

5. Handle API Logout in Navbar

Update Navbar.js to import and use API:

// src/components/Layout/Navbar.js

import React from 'react';


import { Link } from 'react-router-dom';
import API from '../../services/api';

const Navbar = () => {


const isLoggedIn = !!localStorage.getItem('token');

const handleLogout = () => {


API.post('/logout')
.then(() => {
localStorage.removeItem('token');
window.location.href = '/login';
})
.catch((error) => {
console.error('Logout failed:', error);
});
};

return (
<nav className="navbar navbar-expand-lg navbar-light bg-light">
<Link className="navbar-brand" to="/">Student Register</Link>
<div className="collapse navbar-collapse">
<ul className="navbar-nav mr-auto">
{isLoggedIn && (
<li className="nav-item">
<Link className="nav-link"
to="/students">Students</Link>
</li>
)}
</ul>
<ul className="navbar-nav ml-auto">
{isLoggedIn ? (
<li className="nav-item">
<button className="btn btn-link nav-link"
onClick={handleLogout}>Logout</button>
</li>
) : (
<>
<li className="nav-item">
<Link className="nav-link"
to="/login">Login</Link>
</li>
<li className="nav-item">
<Link className="nav-link"
to="/register">Register</Link>
</li>
</>
)}
</ul>
</div>
</nav>
);
};

export default Navbar;

Implementing CRUD Operations


With the components in place, you can perform the following operations:

1. Create (Add a New Student)

• Navigate to /students/create.
• Fill out the form and submit.
• The student will be added to the database and appear in the student list.

2. Read (View Students)

• Navigate to /students.
• View the list of students with pagination.
• Click on a student's "View" button to see detailed information.

3. Update (Edit a Student)

• Navigate to /students/edit/{id}.
• Modify the desired fields and submit.
• The changes will reflect in the student list and detail view.

4. Delete (Remove a Student)

• Click the "Delete" button next to a student in the list.


• Confirm the deletion.
• The student will be removed from the database and the list.
5. Authentication

• Register a new user via /register.


• Login via /login to obtain an authentication token.
• Only authenticated users can access the student management features.
• Logout to invalidate the token and restrict access.

Authentication and Security


1. Protecting Routes

Ensure that only authenticated users can access certain routes. This is handled both in the
frontend (React) and backend (Laravel).

• Frontend: Use React Router to redirect unauthenticated users to the login page.
• Backend: Use Laravel Sanctum's auth:sanctum middleware to protect API routes.

2. Handling Tokens Securely

• Store the authentication token in localStorage or HTTP-only cookies.


• For enhanced security, consider using HTTP-only cookies to prevent XSS attacks.

3. Validating Inputs

Both frontend and backend should validate user inputs to prevent malicious data from being
processed.

• Frontend: Provide immediate feedback to users for incorrect inputs.


• Backend: Enforce validation rules to ensure data integrity.

4. Error Handling

Gracefully handle errors both on the frontend and backend.

• Frontend: Display user-friendly error messages.


• Backend: Return meaningful HTTP status codes and error messages.

5. Implementing HTTPS

Ensure that your application uses HTTPS to encrypt data transmitted between the client and
server.
Testing and Deployment
1. Testing the Application
a. Backend Testing

Use PHPUnit to write tests for your Laravel API.

Example test for creating a student:

// tests/Feature/StudentTest.php

public function test_create_student()


{
$user = User::factory()->create();
$token = $user->createToken('test-token')->plainTextToken;

$response = $this->withHeaders([
'Authorization' => 'Bearer ' . $token,
])->postJson('/api/students', [
'first_name' => 'Jane',
'last_name' => 'Doe',
'email' => '[email protected]',
]);

$response->assertStatus(201)
->assertJson([
'first_name' => 'Jane',
'last_name' => 'Doe',
'email' => '[email protected]',
]);

$this->assertDatabaseHas('students', [
'email' => '[email protected]',
]);
}

Run tests:

php artisan test


b. Frontend Testing

Use Jest and React Testing Library to write tests for your React components.

Example test for the Login component:

// src/components/Auth/Login.test.js

import React from 'react';


import { render, screen, fireEvent } from '@testing-library/react';
import Login from './Login';
import { BrowserRouter } from 'react-router-dom';
import API from '../../services/api';

jest.mock('../../services/api');

test('renders login form', () => {


render(
<BrowserRouter>
<Login />
</BrowserRouter>
);

expect(screen.getByLabelText(/Email/i)).toBeInTheDocument();
expect(screen.getByLabelText(/Password/i)).toBeInTheDocument();
});

test('handles successful login', async () => {


API.post.mockResolvedValue({
data: { token: 'test-token' }
});

render(
<BrowserRouter>
<Login />
</BrowserRouter>
);

fireEvent.change(screen.getByLabelText(/Email/i), { target: { value:


'[email protected]' } });
fireEvent.change(screen.getByLabelText(/Password/i), { target: { value:
'password' } });

fireEvent.click(screen.getByText(/Login/i));

// Add assertions for redirection or token storage


});

Run tests:

npm test

2. Deployment
a. Deploy Laravel Backend

1. Choose a Hosting Provider: Options include DigitalOcean, AWS, Heroku, Laravel Forge, etc.
2. Server Setup:
o Install necessary software: PHP, Composer, Nginx/Apache, MySQL, etc.
3. Clone Repository:
o Use Git to clone your project to the server.
4. Install Dependencies:
5. composer install
6. Configure Environment:
o Set up the .env file with production credentials.
7. Run Migrations and Seeders:
8. php artisan migrate --force
9. php artisan db:seed --force
10. Set Permissions:
11. sudo chown -R www-data:www-data /path-to-your-project
12. sudo chmod -R 775 storage
13. sudo chmod -R 775 bootstrap/cache
14. Configure Web Server:
o Set up Nginx or Apache to serve the Laravel application.
15. Set Up SSL:
o Use Let's Encrypt or another provider to secure your application with HTTPS.

b. Deploy React Frontend

1. Choose a Hosting Provider: Options include Netlify, Vercel, AWS Amplify, GitHub Pages, etc.
2. Build the React App:
3. npm run build
4. Deploy the Build Folder:
o Upload the build folder to your chosen hosting provider.
5. Configure Environment Variables:
o Ensure the React app points to the correct backend API URL.
6. Set Up Routing:
o Configure the hosting provider to handle client-side routing (e.g., redirect all routes
to index.html).

3. Configure CORS for Production

Update config/cors.php in Laravel to allow the production frontend domain:

'allowed_origins' => ['https://your-frontend-domain.com'],

Run php artisan config:cache to apply changes.

Conclusion
Creating a student register application using React for the frontend and Laravel for the
backend combines the strengths of both technologies, resulting in a robust, scalable, and user-
friendly system. Laravel handles the server-side logic, API creation, and database
interactions, while React provides a dynamic and responsive user interface. By following this
comprehensive guide, you can develop a full-stack application that efficiently manages
student data with secure authentication, seamless CRUD operations, and a polished user
experience.

Additional Resources:

• Laravel Documentation
• React Documentation
• Laravel Sanctum Documentation
• Axios Documentation
• React Router Documentation
• Bootstrap Documentation

Feel free to explore these resources to deepen your understanding and enhance your
application further.

You might also like