Storing files in a database makes managing large amounts of data easier, particularly if they are interrelated with a record. For example – A profile picture or documents of a user, product images, etc.
In this tutorial, I show how you can upload and store file to the MySQL database in the Laravel 9 project and also show how you can retrieve them.
Contents
- Database Configuration
- Table structure
- Model
- Controller – Store file to Table
- Route
- View – Upload Form and Display files
- Output
- Conclusion
1. Database Configuration
Open .env
file.
Specify the host, database name, username, and password.
DB_CONNECTION=mysql DB_HOST=127.0.0.1 DB_PORT=3306 DB_DATABASE=tutorial DB_USERNAME=root DB_PASSWORD=
2. Table structure
- Create a new table
files
using migration.
php artisan make:migration create_files_table
- Now, navigate to
database/migrations/
folder from the project root. - Find a PHP file that ends with
create_files_table
and open it. - Define the table structure in the
up()
method.
public function up() { Schema::create('files', function (Blueprint $table) { $table->id(); $table->string('name',60); $table->string('filepath'); $table->timestamps(); }); }
- Run the migration –
php artisan migrate
- The table is been created.
3. Model
- Create
Files
Model.
php artisan make:model Files
- Open
app/Models/Files.php
file. - Specify mass assignable Model attributes – name, and filepath using the
$fillable
property.
Completed Code
<?php namespace App\Models; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; class Files extends Model { use HasFactory; protected $fillable = [ 'name','filepath' ]; }
4. Controller – Store file to Table
- Create
PagesController
controller.
php artisan make:controller PagesController
- Include
Validator
,Session
andFiles
model.
Create 2 methods –
- index() – Fetch all records from the
files
table and assign to$data['files']
. Using this display the files list in the view.
Load index
view and pass $data
.
- submitform() – This method calls on
<form >
submit.
Define validation for the submitted values. If not validated then return to the page with errors.
If validate then upload the file to uploads
folder. Assign the uploaded file path to $filepath
variable.
Insert a record into the files
table. Here, store $request->name
to name
field and $filepath
to filepath
field.
Set SESSION
flash and redirect to /
.
Completed Code
<?php namespace App\Http\Controllers; use Illuminate\Http\Request; use Illuminate\Support\Facades\Validator; use Session; use App\Models\Files; class PagesController extends Controller { public function index(){ // Fetch all records $files = Files::select('*')->get(); $data['files'] = $files; return view('index',$data); } // Submit form public function submitform(Request $request){ $validator = Validator::make($request->all(), [ 'name' => 'required', 'file' => 'required|mimes:png,jpg,jpeg,pdf,docx|max:2048' ]); if ($validator->fails()) { return redirect()->Back()->withInput()->withErrors($validator); }else{ if($request->file('file')) { $file = $request->file('file'); $filename = $file->hashName(); // File upload location $location = 'uploads'; // Upload file $file->move($location,$filename); // File path $filepath = url('uploads/'.$filename); // Insert record $insertData_arr = array( 'name' => $request->name, 'filepath' => $filepath ); Files::create($insertData_arr); // Session Session::flash('alert-class', 'alert-success'); Session::flash('message','Record inserted successfully.'); }else{ // Session Session::flash('alert-class', 'alert-danger'); Session::flash('message','Record not inserted'); } } return redirect('/'); } }
5. Route
- Open
routes/web.php
file. - Define 2 routes –
- / – Load
index
view. - /submitform – This is a POST type route to handle form submit.
- / – Load
<?php use Illuminate\Support\Facades\Route; use App\Http\Controllers\PagesController; Route::get('/', [PagesController::class, 'index']); Route::post('/submitform',[PagesController::class,'submitform'])->name('submitform');
6. View – Upload Form and Display files
Create index.blade.php
file in resources/views/
folder.
Create a <form method="post" action="{{ route('submitform') }}" enctype="multipart/form-data">
. In the <form >
create a textbox, file element, and submit button.
Retrieve files –
Using <table >
to list all files. Read records by loop on $files
.
Check file extension of file path if it is image type then assign true
to $isImage
.
If $isImage
is true
then display the file using <img >
tag otherwise use <a>
tag.
Completed Code
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <meta name="csrf-token" content="{{ csrf_token() }}"> <title>How to upload and store file to MySQL database – Laravel 9</title> <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/css/bootstrap.min.css" > </head> <body> <div class="container"> <div class="row"> <div class="col-md-8 mt-5" style="margin: 0 auto;"> <!-- Alert message (start) --> @if(Session::has('message')) <div class="alert {{ Session::get('alert-class') }} "> {{ Session::get('message') }} </div> @endif <!-- Alert message (end) --> <form method="post" action="{{ route('submitform') }}" enctype="multipart/form-data"> @csrf <div class="form-group mb-4"> <label class="control-label col-sm-2" for="name">Name:</label> <div class="col-sm-10"> <input type="text" class="form-control" placeholder="Enter Name" name="name" value="{{ old('name') }}"> </div> <!-- Error --> @if($errors->has('name')) <div class='text-danger mt-2'> * {{ $errors->first('name') }} </div> @endif </div> <div class="form-group mb-4"> <label class="control-label col-sm-2" for="file">File:</label> <div class="col-sm-10"> <input type="file" name="file" class="form-control"> </div> <!-- Error --> @if($errors->has('file')) <div class='text-danger mt-2'> * {{ $errors->first('file') }} </div> @endif </div> <div class="form-group "> <div class="col-sm-offset-2 col-sm-10"> <button type="submit" class="btn btn-info">Submit</button> </div> </div> </form> </div> </div> <!-- File list --> <div class="row"> <div class="col-md-12"> <table class="table"> <thead> <tr> <th>Name</th> <th>File</th> </tr> </thead> <tbody> @foreach($files as $file) @php $ext = strtolower(pathinfo($file->filepath, PATHINFO_EXTENSION)); $imgext_arr = array("jpg","jpeg","png"); $isImage = false; if(in_array($ext,$imgext_arr)){ $isImage = true; } @endphp <tr> <td>{{ $file->name }}</td> <td> @if($isImage) <img src="{{ $file->filepath }}" width="100px" height="100px;"> @else <a href="{{ $file->filepath }}" target="_blank">View file</a> @endif </td> </tr> @endforeach </tbody> </table> </div> </div> </div> </body> </html>
7. Output
8. Conclusion
In the example, I saved a single file to the database at a time but you can modify the code to store multiple files in the database.
For this, you can either separate them by a comma before inserting, store the file path in an Array then serialize it for insertion or you can insert a new record for each file.
There are other ways of directly storing files in the database are – binary form or base64 but they can be inefficient. Instead, store the file on the server and save its path to the database which I did in the tutorial.
If you found this tutorial helpful then don't forget to share.