Student Register with Laravel & Vue.js
Student Register with Laravel & Vue.js
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:
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
cd student-register-backend
2. Configure Environment
cp .[Link] .env
Laravel Sanctum provides a lightweight authentication system for SPAs (Single Page
Applications):
Run migrations:
To allow your [Link] frontend to communicate with the Laravel backend, configure CORS.
return [
'max_age' => 0,
];
Choose a relational database system like MySQL. Ensure it's installed and running.
2. Create Database
3. Configure .env
DB_CONNECTION=mysql
DB_HOST=[Link]
DB_PORT=3306
DB_DATABASE=student_register
DB_USERNAME=your_username
DB_PASSWORD=your_password
• 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
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
protected $fillable = [
'first_name',
'last_name',
'email',
'phone',
'address',
'date_of_birth',
];
}
use App\Http\Controllers\API\StudentController;
Route::middleware('auth:sanctum')->group(function () {
Route::apiResource('students', StudentController::class);
});
<?php
namespace App\Http\Controllers\API;
use App\Http\Controllers\Controller;
use App\Models\Student;
use Illuminate\Http\Request;
$student->update($request->all());
<?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;
$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',
]);
$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
use App\Http\Controllers\API\AuthController;
Route::middleware('auth:sanctum')->post('/logout', [AuthController::class,
'logout']);
Use Vue CLI to bootstrap the frontend project. If you don't have Vue CLI installed, install it
globally:
cd student-register-frontend
Install Axios for HTTP requests and Vue Router for routing:
npm install axios vue-router
// src/[Link]
[Link](BootstrapVue);
[Link](IconsPlugin);
[Link] = false;
// Set up Axios
[Link] = '[Link]
[Link] = true;
new Vue({
router,
render: h => h(App),
}).$mount('#app');
src/
│
├── components/
│ ├── Auth/
│ │ ├── [Link]
│ │ └── [Link]
│ ├── Students/
│ │ ├── [Link]
│ │ ├── [Link]
│ │ └── [Link]
│ └── Layout/
│ └── [Link]
│
├── router/
│ └── [Link]
│
├── services/
│ └── [Link]
│
├── [Link]
├── [Link]
└── ...
Create 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-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]
[Link](Router);
// 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;
Create 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>
<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]:
<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>
<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>
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]:
<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>
<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]:
<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]:
<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>
• Navigate to /students/create.
• Fill out the form and submit.
• The student will be added to the database and appear in the student list.
• Navigate to /students.
• View the list of students with pagination.
• Click on a student's "View" button to see detailed information.
• 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)
5. Authentication
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.
3. Validating Inputs
Both frontend and backend should validate user inputs to prevent malicious data from being
processed.
4. Error Handling
Ensure that your application uses HTTPS to encrypt data transmitted between the client and
server.
// tests/Feature/[Link]
namespace Tests\Feature;
use App\Models\User;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Tests\TestCase;
$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.
// tests/unit/[Link]
[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);
});
[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');
});
await flushPromises();
Run tests:
2. Deployment
a. Deploy Laravel Backend
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]).
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.