Laravel integration

How to use Vue with Laravel - free starter

This guide will provide you with a free template for a Laravel application, with MySQL database and Vue + Bootstrap 5 front-end.


Prerequisites

Before starting the project make sure to install the following utilities:

  • Node LTS (14.x.x or higher recommended)
  • PHP (7.4.32 or higher recommended)
  • Composer (2.4.2 or higher recommended)
  • Code editor. We recommend VSCode

Creating a new Laravel application

Step 1

Creating MySQL database.

In order to create a new database you need to run the following command:

        
            
          mdb database init -db mysql8
      
        
    
  • Create a new user
  • Provide username, password, database name and description.

CLI will display your username, password, database name and connections string. Now you can go to phpMyAdmin where you will be able to handle the administration of the MySQL database.

Note: the password must contain at least one uppercase letter, one lowercase letter, one number, one special symbol and have minimum length of 8.

Important: Do not close your terminal window until you save your credentials somewhere. This is the only time we will show you your database password. If you won't save it you'll loose it.

Step 2

Create a table.

Go to phpMyAdmin, log in, and add a table, which name will be a plural form of created model. For example on purpose of this tutorial: tasks. Then create a three columns: id (type: int), name (type: text) and description (type: text).

Step 3

Creating Laravel project.

You can initialize a MDB GO starter. Simply run the following command:

        
            
        mdb backend init
      
        
    

and choose Laravel starter from the list that shows up.

After initialization just go to the newly created project directory and open the .env file. After that edit the config values that start with DB_. You should make use of credentials that's been shown to you in the previous step. In my case the updated values look like this:

        
            
        DB_CONNECTION=mysql
        DB_HOST=mysql.db.mdbgo.com
        DB_PORT=3306
        DB_DATABASE=your_database_name
        DB_USERNAME=your_username
        DB_PASSWORD=your_password
      
        
    

Step 4

Navigate to you project direction and install Laravel dependencies using Composer. php-free-laravel is the name from MDB GO starter (you can change whatever you like).

        
            
        composer install
      
        
    

Note: If after this process you got an error bound installation - add to previously used command flag --ignore-platform-req=ext-fileinfo.

Step 5

Create a model. You can use built in Laravel pre-made function: php artisan make:model Task, where Task is your custom name (you can change it whatever you like). Nevertheless this model should being inserted in app/Models directory and looks like this:

        
            
        <?php

        namespace App\Models;
        
        use Illuminate\Database\Eloquent\Factories\HasFactory;
        use Illuminate\Database\Eloquent\Model;
        
        class Task extends Model
        {
            use HasFactory;
            public $timestamps=false;
        }      
      
        
    

Step 6

Now create a controller for handling an endpoints. You can use built in Laravel pre-made function: php artisan make:controller TaskController, where TaskController is your custom name (you can change it whatever you like). Nevertheless this controller should being inserted in app/Http/Controllers directory and looks like this:

        
            
        <?php

        namespace App\Http\Controllers;
        
        use Illuminate\Http\Request;
        use App\Models\Task;
        
        class TaskController extends Controller
        {
            function getTasks() {
                return Task::all();
            }
        
            function addTask(Request $req) {
                $task=new Task;
                $task->id=$req->id;
                $task->name=$req->name;
                $task->description=$req->description;
                $result=$task->save();
        
                return ["Result"=>"Data has been saved"];
            }
        
            function editTask(Request $req) {
                $task= Task::find($req->id);
                $task->name=$req->name;
                $task->description=$req->description;
                $result=$task->save();
        
                return ["Result"=>"Edit successfully"];
            }
        
            function deleteTask($id) {
                $task=Task::find($id);
                $result=$task->delete();
        
                return ["Result"=>"Record has beend deleted"];
            }
        }        
      
        
    

Step 7

Add routes for newly created controller in api.php file (found in routes folder in root directory).

        
            
        Route::get('tasks', [TaskController::class, 'getTasks']);
        Route::post('task', [TaskController::class, 'addTask']);
        Route::put('edit', [TaskController::class, 'editTask']);
        Route::delete('delete/{id}', [TaskController::class, 'deleteTask']);
      
        
    

Step 8

The starter project is ready to use. You don't have to change anything to run the example app for the sake of this tutorial. Simply publish it using the following command:

        
            
        mdb publish -p php-laravel
      
        
    

Note Since we need to install dependencies and run your app, it may take a few moments until it will be available under the provided URL.


Creating MDB Vue application

Note: Don't forget to go back to your root folder before next step. Folders php-free-laravel and mdb5-free-vue should be in the same directory.

Step 1

Create a new vite project with our MDB starter. Run the command below and select MDB5 Free Vue starter.

        
            
            mdb init
        
        
    

Your folder structure should look like this

        
          laravel/
          ├── php-free-laravel
          └── mdb5-free-vue
        
      

Step 2

Let's make some changes to the created vue app. First we need to install axios inside our mdb5-free-vue directory.

        
            
          npm install axios
      
        
    

Remove style.css file (don't forget to delete it from main.ts file) and remove HelloWorld file from components directory.

Step 3

Let's create a .env file inside a mdb5-free-vue directory. We have to add VITE_ before the name of your variable, because it's the only way to expose them to Vite-processed code. Don't forget to change URL to the one you created earlier.

        
            
          VITE_API = "LINK_TO_YOUR_BACKEND_APP"
      
        
    

Step 4

Add new content to Home.vue file inside the views directory.

Since our starter database contains some sample models and routes, let's use them. We will create an application that will show a list of tasks. We also intend to create a functonality for adding new tasks, changing their content and removing them.

We have already prepared the code for you, so go ahead and copy and paste it into App.vue.

Ok, so what's actually going on there. We use MDB components, MDBBtn, MDBModal, MDBListGroup, MDBInputs and few other. The modal will be responsible to show inputs that will allow you to add, edit and send tasks to the database. The Manage tasks button, gives possibilty to modify or remove tasks. At the end, the list group will display our data.

        
            
        <template>
          <MDBContainer class="mt-5">
            <MDBRow class="pt-5">
              <MDBCol class="text-center">
                <MDBBtn color="primary" @click="taskModal = true">Add task</MDBBtn>
              </MDBCol>
            </MDBRow>
            <MDBRow class="mt-3 p-5" style="min-height: 40vh">
              <MDBCol class="d-flex justify-content-center align-items-center">
                <div v-if="taskList.length === 0">
                  Nothing to display. Add a few tasks.
                </div>
                <MDBListGroup v-else class="list-group-light" style="min-width: 22rem">
                  <MDBListGroupItem
                    class="d-flex justify-content-between align-items-center gap-5"
                    v-for="task in taskList"
                    :key="task.id"
                  >
                    <div>
                      <div class="fw-bold">
                        {{ task.name }}
                      </div>
                      <div class="text-muted">{{ task.description }}</div>
                    </div>
                    <div>
                      <MDBIcon
                        class="text-primary me-3"
                        title="edit"
                        icon="pen"
                        style="cursor: pointer"
                        @click="() => editModal(task)"
                      />
                      <MDBIcon
                        class="text-danger"
                        title="delete"
                        icon="trash"
                        style="cursor: pointer"
                        @click="() => deleteTask(task.id)"
                      />
                    </div>
                  </MDBListGroupItem>
                </MDBListGroup>
              </MDBCol>
            </MDBRow>
          </MDBContainer>
          <MDBModal
            id="addNewTaskModal"
            tabindex="-1"
            labelledby="addNewTaskModalLabel"
            v-model="taskModal"
          >
            <MDBModalHeader>
              <MDBModalTitle id="exampleModalLabel">{{
                isEdited.edited ? "Edit task" : "Add task"
              }}</MDBModalTitle>
            </MDBModalHeader>
            <MDBModalBody>
              <form>
                <div class="my-4">
                  <MDBInput
                    label="Name"
                    type="text"
                    v-model="newTaskName"
                    counter
                    :maxlength="60"
                  />
                </div>
                <div class="my-4">
                  <MDBInput
                    label="Description"
                    type="text"
                    v-model="newTaskDesc"
                    counter
                    :maxlength="255"
                  />
                </div>
              </form>
            </MDBModalBody>
            <MDBModalFooter>
              <MDBBtn
                color="secondary"
                @click="
                  {
                    resetInputs();
                    taskModal = false;
                  }
                "
                >Close</MDBBtn
              >
              <MDBBtn
                color="primary"
                @click="handleSaveChanges"
                :disabled="!canSendData"
                >{{ isEdited.edited ? "Save changes" : "Add task" }}</MDBBtn
              >
            </MDBModalFooter>
          </MDBModal>
        </template>
      
        
    
        
            
        <script setup lang="ts">
          import { ref, onMounted, computed } from "vue";
          import {
            MDBContainer,
            MDBRow,
            MDBCol,
            MDBListGroup,
            MDBListGroupItem,
            MDBBtn,
            MDBModal,
            MDBModalTitle,
            MDBModalHeader,
            MDBModalBody,
            MDBModalFooter,
            MDBInput,
            MDBIcon,
          } from "mdb-vue-ui-kit";
          import axios from "axios";
          
          interface SingleTask {
            id: number;
            name: string;
            description: string;
          }
          
          const taskList = ref<SingleTask[]>([]);
          const taskModal = ref(false);
          const newTaskName = ref("");
          const newTaskDesc = ref("");
          const isEdited = ref({ edited: false, value: -1 });
          const API_URL = ref("");
          
          const canSendData = computed(() => {
            if (newTaskName.value.trim() === "" || newTaskDesc.value.trim() === "") {
              return false;
            }
            return true;
          });
          
          const resetInputs = () => {
            newTaskName.value = "";
            newTaskDesc.value = "";
            isEdited.value = { edited: false, value: -1 };
          };
          
          const handleSaveChanges = async () => {
            if (!canSendData.value) {
              return;
            }
          
            isEdited.value.edited
              ? updateTask(isEdited.value.value, newTaskName.value, newTaskDesc.value)
              : createTask(
                newTaskName.value,
                newTaskDesc.value,
                Math.ceil(Math.random() * 1000000)
              );
            resetInputs();
            taskModal.value = false;
          };
          
          const editModal = (task: SingleTask) => {
            newTaskName.value = task.name;
            newTaskDesc.value = task.description;
            isEdited.value = { edited: true, value: task.id };
          
            taskModal.value = true;
          };
          
          const getTaskList = () => {
            axios
              .get(`${API_URL.value}tasks`)
              .then((res) => (taskList.value = res.data));
          };
          
          const createTask = (name: string, description: string, id: number) => {
            const data = { name, description, id };
            axios.post(`${API_URL.value}task`, data).then(() => {
              getTaskList();
            });
          };
          
          const deleteTask = (id: number) => {
            axios.delete(`${API_URL.value}delete/${id}`).then(() => {
              getTaskList();
            });
          };
          
          const updateTask = (id: number, name: string, description: string) => {
            const data = { name, description };
            axios.put(`${API_URL.value}edit`, data).then(() => {
              getTaskList();
            });
          };
          
          onMounted(() => {
            API_URL.value = import.meta.env.VITE_API;
            getTaskList();
          });
        </script>
      
        
    

If you haven't done it already, run npm start in your terminal. The app should be fully functional and should work correctly with backend.

Step 5

Now you can publish your project on MDB GO

        
            
        mdb publish
      
        
    

Optimization

If you want to further optimize your application please visit: