Lesson 1
Integrating a Database into Your Laravel Application
Integrating a Database into Your Laravel Application

Welcome to the next step in making your Laravel ToDo application more robust and enterprise-ready! In this lesson, you will learn how to integrate a database into your app, which will form the backbone for storing and managing data efficiently. Database integration is crucial for any modern web application, as it allows you to handle and manipulate data on a large scale.

Previously, you explored setting up a basic MVC structure within Laravel, which laid the foundation for our app. Now, let's move on to anchoring the application with a database to store your ToDo items persistently.

What You'll Learn

In this segment, you will learn how to connect a Laravel application to a database using configuration files. You'll also get an overview of setting up the database schema and modeling data with Laravel's Eloquent ORM.

First, let's remind ourselves of the .env file used in Laravel for environment configuration. This is where we specify the database connection details. Here's an example of the database configuration in the .env file:

Plain text
1DB_CONNECTION=sqlite 2DB_HOST=127.0.0.1 3DB_PORT=3306 4DB_DATABASE=database_name 5DB_USERNAME=db_username 6DB_PASSWORD=db_password

Let's see what each of these configurations does:

  • DB_CONNECTION: Specifies the type of database. Laravel supports multiple databases like MySQL, SQLite, and PostgreSQL. In this example, it’s set to SQLite, which is file-based and simpler for development.
  • DB_HOST and DB_PORT: Define where the database server is running. For local development, 127.0.0.1 (localhost) is often used, and 3306 is the default port for MySQL. SQLite, however, doesn’t require a host or port since it’s a file-based database.
  • DB_DATABASE: The name of the database (or the path for SQLite). For MySQL, PostgreSQL, and other server-based databases, this is the database name. For SQLite, provide a file path like database/database.sqlite.
  • DB_USERNAME and DB_PASSWORD: The username and password used to connect to the database. SQLite doesn’t use these credentials, but they are required for MySQL or PostgreSQL.

Note: Laravel’s .env file is designed to support various database types, not just SQLite. Including settings like DB_HOST and DB_PORT allows you to switch between different database types (e.g., MySQL, PostgreSQL) by simply changing DB_CONNECTION in the .env file. This way, if you move from SQLite (for local development) to MySQL (for production), you won’t need to restructure the entire file—just update a few values. By default, the .env template includes these database settings to maintain consistency across projects, regardless of the chosen database. While SQLite ignores host, port, username, and password settings, having these fields pre-defined in the .env file provides flexibility, consistency, and prepares the application for easy database transitions.

To understand how Laravel interacts with the database, let's look at the database configuration file located at config/database.php. This file contains the database connection settings for different environments, such as mysql, sqlite, pgsql, and sqlsrv.

Here's an example of the database configuration for SQLite:

php
1'sqlite' => [ 2 'driver' => 'sqlite', 3 'url' => env('DATABASE_URL'), 4 'database' => env('DB_DATABASE', database_path('database.sqlite')), 5 'prefix' => '', 6 'foreign_key_constraints' => env('DB_FOREIGN_KEYS', true), 7],

In this configuration, the database key specifies the path to the SQLite database file. By default, it's set to database.sqlite in the database directory. You can change this path to store the database file in a different location. We'll not modify this configuration in our practices, as the default settings are sufficient for our ToDo app.

Now, let's see how Laravel interacts with the database using Eloquent, the ORM provided by Laravel. Eloquent allows you to define models that represent database tables and interact with them using object-oriented syntax. Let's create a model for the Todo table in our database:

php
1namespace App\Models; 2use Illuminate\Database\Eloquent\Factories\HasFactory; 3 4class Todo extends Model 5{ 6 use HasFactory; 7 protected $fillable = ['title', 'description']; 8}

In this model, we define the Todo class that extends the Model class provided by Laravel.

The use HasFactory statement enables the factory pattern for creating model instances. Factories are used to generate fake data for testing purposes.

The fillable property specifies the columns that can be mass-assigned when creating a new Todo instance - mass assignment is the process of assigning an array of attributes to a model, like the SQL INSERT statement with multiple columns.

With the model in place, we can now interact with the Todo table in the database using Eloquent. This interaction will happen in the service layer of our application, where we'll define methods to create, read, update, and delete Todo items. Let's see how the service layer will interact with the database:

php
1<?php 2 3namespace App\Services; 4 5use App\Models\Todo; 6use Illuminate\Support\Facades\DB; 7 8class TodoService 9{ 10 public function create($title, $description = null) 11 { 12 return Todo::create(compact('title', 'description')); 13 } 14 15 public function findAll() 16 { 17 return Todo::all(); 18 } 19 20 public function findOne($id) 21 { 22 return Todo::find($id); 23 } 24 25 public function update($id, $title, $description) 26 { 27 $todo = Todo::find($id); 28 if ($todo) { 29 $todo->update(compact('title', 'description')); 30 } 31 return $todo; 32 } 33 34 public function delete($id) 35 { 36 return Todo::destroy($id); 37 } 38}

In this service class, we define the following methods:

  • create: Creates a new Todo item in the database using the Todo::create method with the provided title and description. The compact function creates an array from the provided variables to pass as arguments to the create method.
  • findAll: Retrieves all Todo items from the database using the Todo::all method.
  • findOne: Retrieves a single Todo item by its ID using the Todo::find method with the provided ID.
  • update: Updates a Todo item by its ID with the provided title and description. The Todo::update method is called on the retrieved Todo instance with the new title and description.
  • delete: Deletes a Todo item by its ID using the Todo::destroy method.

Note, that the controller will not change much from the previous lesson, as it will still interact with the service layer to handle requests and responses. The service layer will handle the database interactions using the Eloquent model:

php
1<?php 2 3namespace App\Http\Controllers; 4 5use App\Services\TodoService; 6use Illuminate\Http\Request; 7 8class TodoController extends Controller 9{ 10 protected $todoService; 11 12 public function __construct(TodoService $todoService) 13 { 14 $this->todoService = $todoService; 15 } 16 17 public function index() 18 { 19 $todos = $this->todoService->findAll(); 20 return view('todos.index', ['title' => 'ToDo List', 'todos' => $todos]); 21 } 22 23 public function show($id) 24 { 25 $todo = $this->todoService->findOne($id); 26 return view('todos.show', ['title' => 'Todo Details', 'todo' => $todo]); 27 } 28 29 public function store(Request $request) 30 { 31 $this->todoService->create($request->title, $request->description); 32 return redirect('/todos'); 33 } 34 35 public function update($id, Request $request) 36 { 37 $this->todoService->update($id, $request->title, $request->description); 38 return redirect('/todos'); 39 } 40 41 public function destroy($id) 42 { 43 $this->todoService->delete($id); 44 return redirect('/todos'); 45 } 46}

In this controller, we inject the TodoService instance into the constructor to interact with the database. The controller methods call the corresponding methods in the service layer to handle the CRUD operations for Todo items.

This is the moment, to pause and appreciate the beauty of the MVC architecture in action, where the controller acts as the intermediary between the user interface and the database and doesn't contain any business logic. So when we move our data from the JSON file to the database, we don't need to change the controller logic, only the service layer.

Finally, we'll use the same routing logic as before to handle the requests and direct them to the controller methods:

php
1<?php 2 3use App\Http\Controllers\TodoController; 4 5Route::get('/todos', [TodoController::class, 'index']); 6Route::get('/todos/{id}', [TodoController::class, 'show']); 7Route::post('/todos', [TodoController::class, 'store']); 8Route::put('/todos/{id}', [TodoController::class, 'update']); 9Route::delete('/todos/{id}', [TodoController::class, 'destroy']);

With this setup, we have successfully integrated a database into our Laravel application and defined the database schema and data models using Eloquent. The service layer interacts with the database using the Eloquent model, and the controller handles the requests and responses, following the MVC architecture.

Why It Matters

Integrating a database with your Laravel application is essential for many reasons. It enables you to store data persistently, support complex queries, and provide reliable performance for large datasets. With database integration, your application can scale and handle real-world data management needs.

Additionally, mastering database integration will not only make your ToDo app more robust but also empower you with skills that are highly valued in the software industry. From building applications that manage user profiles to e-commerce sites, a firm grasp of database interaction is vital.

Prepared to level up your Laravel application? Let's dive into practice and bring your app to life with powerful database capabilities!

Enjoy this lesson? Now it's time to practice with Cosmo!
Practice is how you turn knowledge into actual skills.