Creating a Student Register Using Laravel and Vue.
js: 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 [Link] Frontend
7. Building Vue Components and Integrating with Laravel
8. Implementing CRUD Operations
9. Authentication and Security
10. Testing and Deployment
11. Conclusion
Introduction
Building a student register system is a common requirement for educational institutions and
related applications. Combining Laravel for the backend and [Link] for the frontend
leverages the strengths of both frameworks, providing a robust, scalable, and dynamic
application. Laravel offers a powerful API-building capability, while [Link] ensures a
responsive and interactive user interface. This guide walks you through creating a
comprehensive student registration system using Laravel and [Link], 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 [Link]: Familiarity with Vue components, directives, and
lifecycle hooks.
• Composer Installed: Laravel utilizes Composer for dependency management.
• [Link] and NPM: Required for managing [Link] 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 [Link],
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 .[Link] file to .env:
cp .[Link] .env
Generate an application key:
php artisan key:generate
3. Set Up Development Server
Start the Laravel development server:
php artisan serve
Visit [Link] to verify the setup.
4. Install Laravel Sanctum (For API Authentication)
Laravel Sanctum provides a lightweight 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 [Link] frontend to communicate with the Laravel backend, configure CORS.
Open config/[Link] and adjust settings:
return [
'paths' => ['api/*', 'sanctum/csrf-cookie'],
'allowed_methods' => ['*'],
'allowed_origins' => ['[Link] // Vue'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=[Link]
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/[Link] 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/[Link] 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/[Link] 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/[Link] 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/[Link]:
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 [Link]
• Login: POST [Link]
• CRUD Operations: Use the token received upon login to access protected routes.
Setting Up the [Link] Frontend
1. Initialize Vue Project
Use Vue CLI to bootstrap the frontend project. If you don't have Vue CLI installed, install it
globally:
npm install -g @vue/cli
Create a new Vue project:
vue create student-register-frontend
Navigate to the project directory:
cd student-register-frontend
Choose the default preset or customize it as per your requirements.
2. Install Necessary Dependencies
Install Axios for HTTP requests and Vue Router for routing:
npm install axios vue-router
Optionally, install BootstrapVue for styling:
npm install bootstrap bootstrap-vue
Import BootstrapVue in src/[Link]:
// src/[Link]
import Vue from 'vue';
import App from './[Link]';
import router from './router';
import axios from 'axios';
import { BootstrapVue, IconsPlugin } from 'bootstrap-vue';
import 'bootstrap/dist/css/[Link]';
import 'bootstrap-vue/dist/[Link]';
[Link](BootstrapVue);
[Link](IconsPlugin);
[Link] = false;
// Set up Axios
[Link] = '[Link]
[Link] = true;
// Add a request interceptor to include the token
[Link]((config) => {
const token = [Link]('token');
if (token) {
[Link] = `Bearer ${token}`;
}
return config;
}, (error) => {
return [Link](error);
});
new Vue({
router,
render: h => h(App),
}).$mount('#app');
3. Set Up Project Structure
Organize your project with the following structure:
src/
│
├── components/
│ ├── Auth/
│ │ ├── [Link]
│ │ └── [Link]
│ ├── Students/
│ │ ├── [Link]
│ │ ├── [Link]
│ │ └── [Link]
│ └── Layout/
│ └── [Link]
│
├── router/
│ └── [Link]
│
├── services/
│ └── [Link]
│
├── [Link]
├── [Link]
└── ...
Building Vue Components and Integrating with Laravel
1. Create Navigation Bar
Create src/components/Layout/[Link]:
<!-- src/components/Layout/[Link] -->
<template>
<b-navbar toggleable="lg" type="light" variant="light">
<b-navbar-brand href="#">Student Register</b-navbar-brand>
<b-navbar-toggle target="nav-collapse"></b-navbar-toggle>
<b-collapse id="nav-collapse" is-nav>
<b-navbar-nav>
<b-nav-item v-if="isLoggedIn" to="/students">Students</b-nav-item>
</b-navbar-nav>
<b-navbar-nav class="ml-auto">
<b-nav-item v-if="!isLoggedIn" to="/login">Login</b-nav-item>
<b-nav-item v-if="!isLoggedIn" to="/register">Register</b-nav-item>
<b-nav-item-dropdown v-if="isLoggedIn" right>
<template v-slot:button-content>
{{ [Link] }}
</template>
<b-dropdown-item @click="logout">Logout</b-dropdown-item>
</b-nav-item-dropdown>
</b-navbar-nav>
</b-collapse>
</b-navbar>
</template>
<script>
import axios from 'axios';
export default {
name: 'Navbar',
data() {
return {
user: {},
};
},
computed: {
isLoggedIn() {
return !;
},
},
methods: {
logout() {
[Link]('/logout')
.then(() => {
[Link]('token');
this.$[Link]('/login');
})
.catch(error => {
[Link]('Logout failed:', error);
});
},
fetchUser() {
[Link]('/user')
.then(response => {
[Link] = [Link];
})
.catch(error => {
[Link]('Error fetching user:', error);
});
},
},
created() {
if ([Link]) {
[Link]();
}
},
};
</script>
<style scoped>
/* Add any custom styles here */
</style>
2. Configure Routing
Create src/router/[Link]:
// src/router/[Link]
import Vue from 'vue';
import Router from 'vue-router';
import Register from '../components/Auth/[Link]';
import Login from '../components/Auth/[Link]';
import StudentList from '../components/Students/[Link]';
import StudentForm from '../components/Students/[Link]';
import StudentDetail from '../components/Students/[Link]';
[Link](Router);
const router = new Router({
mode: 'history',
routes: [
{
path: '/',
redirect: '/students',
},
{
path: '/register',
name: 'Register',
component: Register,
meta: { requiresGuest: true },
},
{
path: '/login',
name: 'Login',
component: Login,
meta: { requiresGuest: true },
},
{
path: '/students',
name: 'StudentList',
component: StudentList,
meta: { requiresAuth: true },
},
{
path: '/students/create',
name: 'StudentCreate',
component: StudentForm,
meta: { requiresAuth: true },
},
{
path: '/students/edit/:id',
name: 'StudentEdit',
component: StudentForm,
meta: { requiresAuth: true },
},
{
path: '/students/:id',
name: 'StudentDetail',
component: StudentDetail,
meta: { requiresAuth: true },
},
{
path: '*',
redirect: '/students',
},
],
});
// Navigation Guards
[Link]((to, from, next) => {
const isLoggedIn = !;
if ([Link](record => [Link])) {
if (!isLoggedIn) {
next('/login');
} else {
next();
}
} else if ([Link](record => [Link])) {
if (isLoggedIn) {
next('/students');
} else {
next();
}
} else {
next();
}
});
export default router;
3. Create Authentication Components
a. Register Component
Create src/components/Auth/[Link]:
<!-- src/components/Auth/[Link] -->
<template>
<div class="container mt-5">
<h2>Register</h2>
<b-alert variant="danger" show v-if="[Link]">
<ul>
<li v-for="(error, index) in errors" :key="index">{{ error }}</li>
</ul>
</b-alert>
<b-form @[Link]="handleRegister">
<b-form-group label="Name" label-for="name">
<b-form-input
id="name"
v-model="[Link]"
required
placeholder="Enter your name"
></b-form-input>
</b-form-group>
<b-form-group label="Email" label-for="email">
<b-form-input
id="email"
type="email"
v-model="[Link]"
required
placeholder="Enter your email"
></b-form-input>
</b-form-group>
<b-form-group label="Password" label-for="password">
<b-form-input
id="password"
type="password"
v-model="[Link]"
required
placeholder="Enter your password"
></b-form-input>
</b-form-group>
<b-form-group label="Confirm Password" label-
for="password_confirmation">
<b-form-input
id="password_confirmation"
type="password"
v-model="form.password_confirmation"
required
placeholder="Confirm your password"
></b-form-input>
</b-form-group>
<b-button type="submit" variant="primary">Register</b-button>
</b-form>
</div>
</template>
<script>
import axios from 'axios';
export default {
name: 'Register',
data() {
return {
form: {
name: '',
email: '',
password: '',
password_confirmation: '',
},
errors: [],
};
},
methods: {
handleRegister() {
[Link]('/register', [Link])
.then(response => {
[Link]('token', [Link]);
this.$[Link]('/students');
})
.catch(error => {
if ([Link] && [Link]) {
[Link] = [Link]([Link]).flat();
}
});
},
},
};
</script>
<style scoped>
/* Add any custom styles here */
</style>
b. Login Component
Create src/components/Auth/[Link]:
<!-- src/components/Auth/[Link] -->
<template>
<div class="container mt-5">
<h2>Login</h2>
<b-alert variant="danger" show v-if="[Link]">
<ul>
<li v-for="(error, index) in errors" :key="index">{{ error }}</li>
</ul>
</b-alert>
<b-form @[Link]="handleLogin">
<b-form-group label="Email" label-for="email">
<b-form-input
id="email"
type="email"
v-model="[Link]"
required
placeholder="Enter your email"
></b-form-input>
</b-form-group>
<b-form-group label="Password" label-for="password">
<b-form-input
id="password"
type="password"
v-model="[Link]"
required
placeholder="Enter your password"
></b-form-input>
</b-form-group>
<b-button type="submit" variant="primary">Login</b-button>
</b-form>
</div>
</template>
<script>
import axios from 'axios';
export default {
name: 'Login',
data() {
return {
form: {
email: '',
password: '',
},
errors: [],
};
},
methods: {
handleLogin() {
[Link]('/login', [Link])
.then(response => {
[Link]('token', [Link]);
this.$[Link]('/students');
})
.catch(error => {
if ([Link] && [Link]) {
[Link] = [Link]([Link]).flat();
}
});
},
},
};
</script>
<style scoped>
/* Add any custom styles here */
</style>
4. Create Student Components
a. Student List Component
Create src/components/Students/[Link]:
<!-- src/components/Students/[Link] -->
<template>
<div class="container mt-5">
<h2>Students</h2>
<b-button variant="primary" class="mb-3"
@click="$[Link]('/students/create')">Add New Student</b-button>
<b-table striped hover :items="students" :fields="fields">
<template #cell(actions)="row">
<b-button size="sm" variant="info"
@click="viewStudent([Link])">View</b-button>
<b-button size="sm" variant="warning" class="ml-2"
@click="editStudent([Link])">Edit</b-button>
<b-button size="sm" variant="danger" class="ml-2"
@click="deleteStudent([Link])">Delete</b-button>
</template>
</b-table>
<b-pagination
v-if="pagination.last_page > 1"
v-model="pagination.current_page"
:total-rows="[Link]"
:per-page="pagination.per_page"
@change="fetchStudents"
align="center"
class="my-0"
></b-pagination>
</div>
</template>
<script>
import axios from 'axios';
export default {
name: 'StudentList',
data() {
return {
students: [],
fields: [
{ key: 'id', label: 'ID' },
{ key: 'first_name', label: 'First Name' },
{ key: 'last_name', label: 'Last Name' },
{ key: 'email', label: 'Email' },
{ key: 'phone', label: 'Phone' },
{ key: 'actions', label: 'Actions' },
],
pagination: {
current_page: 1,
last_page: 1,
total: 0,
per_page: 10,
},
};
},
methods: {
fetchStudents(page = 1) {
[Link](`/students?page=${page}`)
.then(response => {
[Link] = [Link];
[Link] = {
current_page: [Link].current_page,
last_page: [Link].last_page,
total: [Link],
per_page: [Link].per_page,
};
})
.catch(error => {
[Link]('Error fetching students:', error);
});
},
viewStudent(id) {
this.$[Link](`/students/${id}`);
},
editStudent(id) {
this.$[Link](`/students/edit/${id}`);
},
deleteStudent(id) {
if (confirm('Are you sure you want to delete this student?')) {
[Link](`/students/${id}`)
.then(() => {
[Link]([Link].current_page);
})
.catch(error => {
[Link]('Error deleting student:', error);
});
}
},
},
created() {
[Link]();
},
};
</script>
<style scoped>
/* Add any custom styles here */
</style>
b. Student Form Component
Create src/components/Students/[Link]:
<!-- src/components/Students/[Link] -->
<template>
<div class="container mt-5">
<h2>{{ isEdit ? 'Edit' : 'Add' }} Student</h2>
<b-alert variant="danger" show v-if="[Link]">
<ul>
<li v-for="(error, index) in errors" :key="index">{{ error }}</li>
</ul>
</b-alert>
<b-form @[Link]="handleSubmit">
<b-form-group label="First Name" label-for="first_name">
<b-form-input
id="first_name"
v-model="form.first_name"
required
placeholder="Enter first name"
></b-form-input>
</b-form-group>
<b-form-group label="Last Name" label-for="last_name">
<b-form-input
id="last_name"
v-model="form.last_name"
required
placeholder="Enter last name"
></b-form-input>
</b-form-group>
<b-form-group label="Email" label-for="email">
<b-form-input
id="email"
type="email"
v-model="[Link]"
required
placeholder="Enter email"
></b-form-input>
</b-form-group>
<b-form-group label="Phone" label-for="phone">
<b-form-input
id="phone"
v-model="[Link]"
placeholder="Enter phone number"
></b-form-input>
</b-form-group>
<b-form-group label="Address" label-for="address">
<b-form-textarea
id="address"
v-model="[Link]"
placeholder="Enter address"
rows="3"
></b-form-textarea>
</b-form-group>
<b-form-group label="Date of Birth" label-for="date_of_birth">
<b-form-input
id="date_of_birth"
type="date"
v-model="form.date_of_birth"
></b-form-input>
</b-form-group>
<b-button type="submit" variant="success">{{ isEdit ? 'Update' :
'Save' }}</b-button>
</b-form>
</div>
</template>
<script>
import axios from 'axios';
export default {
name: 'StudentForm',
data() {
return {
form: {
first_name: '',
last_name: '',
email: '',
phone: '',
address: '',
date_of_birth: '',
},
errors: [],
};
},
computed: {
isEdit() {
return !!this.$[Link];
},
},
methods: {
fetchStudent() {
[Link](`/students/${this.$[Link]}`)
.then(response => {
[Link] = [Link];
})
.catch(error => {
[Link]('Error fetching student:', error);
});
},
handleSubmit() {
if ([Link]) {
[Link](`/students/${this.$[Link]}`, [Link])
.then(() => {
this.$[Link]('/students');
})
.catch(error => {
if ([Link] && [Link]) {
[Link] =
[Link]([Link]).flat();
}
});
} else {
[Link]('/students', [Link])
.then(() => {
this.$[Link]('/students');
})
.catch(error => {
if ([Link] && [Link]) {
[Link] =
[Link]([Link]).flat();
}
});
}
},
},
created() {
if ([Link]) {
[Link]();
}
},
};
</script>
<style scoped>
/* Add any custom styles here */
</style>
c. Student Detail Component
Create src/components/Students/[Link]:
<!-- src/components/Students/[Link] -->
<template>
<div class="container mt-5" v-if="student">
<h2>Student Details</h2>
<b-card>
<b-card-text><strong>Name:</strong> {{ student.first_name }} {{
student.last_name }}</b-card-text>
<b-card-text><strong>Email:</strong> {{ [Link] }}</b-card-
text>
<b-card-text><strong>Phone:</strong> {{ [Link] || 'N/A' }}</b-
card-text>
<b-card-text><strong>Address:</strong> {{ [Link] || 'N/A'
}}</b-card-text>
<b-card-text><strong>Date of Birth:</strong> {{ student.date_of_birth
|| 'N/A' }}</b-card-text>
<b-button variant="primary" @click="$[Link]('/students')">Back
to List</b-button>
</b-card>
</div>
<div class="container mt-5" v-else>
<p>Loading...</p>
</div>
</template>
<script>
import axios from 'axios';
export default {
name: 'StudentDetail',
data() {
return {
student: null,
};
},
methods: {
fetchStudent() {
[Link](`/students/${this.$[Link]}`)
.then(response => {
[Link] = [Link];
})
.catch(error => {
[Link]('Error fetching student:', error);
});
},
},
created() {
[Link]();
},
};
</script>
<style scoped>
/* Add any custom styles here */
</style>
5. Configure Routing in [Link]
Edit src/[Link]:
<!-- src/[Link] -->
<template>
<div id="app">
<Navbar />
<router-view></router-view>
</div>
</template>
<script>
import Navbar from './components/Layout/[Link]';
export default {
name: 'App',
components: {
Navbar,
},
};
</script>
<style>
/* Add any global styles here */
</style>
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 ([Link]) and backend (Laravel).
• Frontend: Use Vue Router navigation guards 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.
• 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/[Link]
namespace Tests\Feature;
use App\Models\User;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Tests\TestCase;
class StudentTest extends TestCase
{
use RefreshDatabase;
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' => '[Link]@[Link]',
]);
$response->assertStatus(201)
->assertJson([
'first_name' => 'Jane',
'last_name' => 'Doe',
'email' => '[Link]@[Link]',
]);
$this->assertDatabaseHas('students', [
'email' => '[Link]@[Link]',
]);
}
}
Run tests:
php artisan test
b. Frontend Testing
Use Jest and Vue Test Utils to write tests for your [Link] components.
Example test for the Login component:
// tests/unit/[Link]
import { shallowMount } from '@vue/test-utils';
import Login from '@/components/Auth/[Link]';
import axios from 'axios';
import flushPromises from 'flush-promises';
[Link]('axios');
describe('[Link]', () => {
it('renders login form', () => {
const wrapper = shallowMount(Login);
expect([Link]('h2').text()).toBe('Login');
expect([Link]('input[type="email"]').exists()).toBe(true);
expect([Link]('input[type="password"]').exists()).toBe(true);
});
it('handles successful login', async () => {
const mockToken = 'test-token';
[Link]({
data: { token: mockToken },
});
const wrapper = shallowMount(Login, {
mocks: {
$router: {
push: [Link](),
},
},
});
[Link]('input[type="email"]').setValue('test@[Link]');
[Link]('input[type="password"]').setValue('password');
[Link]('form').trigger('[Link]');
await flushPromises();
expect([Link]('token')).toBe(mockToken);
expect([Link].$[Link]).toHaveBeenCalledWith('/students');
});
it('displays errors on failed login', async () => {
[Link]({
response: {
data: {
errors: {
email: ['The provided credentials are incorrect.'],
},
},
},
});
const wrapper = shallowMount(Login);
[Link]('input[type="email"]').setValue('wrong@[Link]');
[Link]('input[type="password"]').setValue('wrongpassword');
[Link]('form').trigger('[Link]');
await flushPromises();
expect([Link]).toContain('The provided credentials are
incorrect.');
expect([Link]('.alert').isVisible()).toBe(true);
});
});
Run tests:
npm run test:unit
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 [Link] Frontend
1. Choose a Hosting Provider: Options include Netlify, Vercel, AWS Amplify, GitHub
Pages, etc.
2. Build the Vue App:
3. npm run build
4. Deploy the dist Folder:
o Upload the dist folder to your chosen hosting provider.
5. Configure Environment Variables:
o Ensure the Vue app points to the correct backend API URL. You can set this in
environment variables during the build process.
6. Set Up Routing:
o Configure the hosting provider to handle client-side routing (e.g., redirect all routes
to [Link]).
3. Configure CORS for Production
Update config/[Link] in Laravel to allow the production frontend domain:
'allowed_origins' => ['[Link]
Run php artisan config:cache to apply changes.
Conclusion
Creating a student register application using [Link] 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 [Link] 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
• [Link] Documentation
• Laravel Sanctum Documentation
• Axios Documentation
• Vue Router Documentation
• BootstrapVue Documentation
Feel free to explore these resources to deepen your understanding and enhance your
application further.