This tutorial was written by Vandyck Lai.
What you'll learn
By the end of this tutorial, you'll be able to:
- Understand MongoDB fundamentals and its advantages over traditional SQL databases.
- Set up a Laravel project with MongoDB integration.
- Create polymorphic models using MongoDB.
- Build a complete developer blog application with CRUD operations.
- Implement advanced features like search and content categorization.
What is MongoDB?
MongoDB is a NoSQL (not only SQL) database that stores data as documents. A document, by definition, is a data structure storing property and value pairs, similar to JSON objects. This makes MongoDB incredibly flexible for:
- Dynamic data schemas suited for polymorphism.
- Data locality—“data that is accessed together should be stored together."
- High performance with BSON (Binary JSON) storage format.
Why choose MongoDB over traditional SQL?
What does NoSQL offer that traditional SQL doesn’t?
Key advantages:
- Smaller storage footprint: BSON format is more efficient than rigid SQL tables.
- No NULL value issues: MongoDB naturally handles sparse data.
- Simplified queries: Aggregation pipelines replace complex SQL JOINs.
- Better scalability: Horizontal scaling is built-in.
Real-world example: In our developer blog application, we can store different content types (posts, articles, tutorials) in the same collection while maintaining different schemas for each type—something that would require multiple tables and complex JOINs in SQL.
Laravel + MongoDB = ✨
Prerequisites
Before we begin, make sure you have:
- PHP 8.2+.
- Composer and Laravel CLI.
- MongoDB Atlas.
That’s how simple it is to get started!
To have an idea of what we will be building, here’s a video demo.
Project setup
Step 1: Create a new Laravel project
Open your terminal and run the following command:
laravel new developer-blog
You'll see an interactive setup prompt. Choose these options:
_ _
| | | |
| | __ _ _ __ __ ___ _____| |
| | / _` | '__/ _` \ \ / / _ \ |
| |___| (_| | | | (_| |\ V / __/ |
|______\__,_|_| \__,_| \_/ \___|_|
┌ Would you like to install a starter kit? ──────┐
│ - No starter kit │
────────────────────────────────┘
┌ Which testing framework do you prefer? ───────┐
│ - Pest │
└───────────────────────────────┘
Step 2: Generate application key
Navigate to your project directory and generate the application key:
cd developer-blog
php artisan key:generate
Why this matters: The application key is used for encrypting session data and other sensitive information in your Laravel application. Learn more.
Step 3: Install MongoDB Laravel package
Install the official MongoDB package for Laravel.
composer require mongodb/laravel-mongodb
Package info: This package provides MongoDB integration for Laravel's Eloquent ORM, allowing you to use familiar Laravel syntax with MongoDB.
Step 4: Configure database connection
Update your config/database.php
file to include MongoDB as the default connection:
return [
'default' => env('DB_CONNECTION', 'mongodb'),
...
'connections' => [
...
'mongodb' => [
'driver' => 'mongodb',
'dsn' => env('DB_URI'),
'database' => env('DB_DATABASE', 'laravel'),
],
]
]
Step 5: Environment configuration
Update your .env file with MongoDB connection details:
DB_CONNECTION=mongodb
DB_URI="YOUR_MONGODB_URI"
DB_DATABASE="YOUR_MONGODB_DB_NAME"
Step 6: Start your application
Launch the Laravel development server:
php artisan serve
You can now access your application at http://127.0.0.1:8000
.
Building the models (polymorphic design)
Understanding the architecture
We'll create a polymorphic content system where different content types (posts, articles, tutorials) share common properties but have their own specific fields. This demonstrates MongoDB's flexibility perfectly.
Step 1: Create the base content model
Create the abstract base model that all content types will inherit from:
File: app/Models/Content.php
<?php
namespace App\\Models;
use MongoDB\\Laravel\\Eloquent\\Model;
abstract class Content extends Model
{
protected $connection = 'mongodb'; // Use MongoDB connection
protected $collection = 'contents'; // Single collection for all types
protected $casts = [
'tags' => 'array', // MongoDB handles arrays natively!
];
public function scopePublished($query)
{
return $query->where('status', 'published');
}
abstract public function getContentType();
}
Key concepts: You can store all content types in one collection with different schemas.
Step 2: Create content type models
Using the abstract base model, we can now create models with different types and attributes.
File: app/Models/Article.php
<?php
namespace App\\Models;
class Article extends Content
{
protected $attributes = ['type' => 'article'];
// Article-specific fields
protected $fillable = [..., 'category', 'featured_image', 'seo_title'];
public function getContentType()
{
return 'article';
}
// Automatic SEO fallback
public function getSeoTitleAttribute($value)
{
return $value ?: $this->title;
}
}
File: app/Models/Tutorial.php
<?php
namespace App\\Models;
class Tutorial extends Content
{
protected $attributes = ['type' => 'tutorial'];
protected $casts = [
'prerequisites' => 'array', // MongoDB handles nested arrays
'steps' => 'array',
];
public function scopeByDifficulty($query, $level)
{
return $query->where('difficulty_level', $level);
}
}
** Quick tip**: You can also generate model files using Laravel's Artisan command:
php artisan make:model Post
Database seeding (optional but recommended)
Let's create sample data to work with during development. This helps you see the application in action immediately.
Step 1: Create the seeder
File: database/seeders/BlogContentSeeder.php
<?php
namespace Database\\Seeders;
use App\\Models\\Post;
use App\\Models\\Article;
use App\\Models\\Tutorial;
class BlogContentSeeder extends Seeder
{
public function run()
{
// Create sample Posts
Post::create([
'title' => 'Getting Started with MongoDB in Laravel',
'tags' => ['mongodb', 'laravel', 'nosql'],
'status' => 'published',
'author_name' => 'John Doe',
]);
// Create sample Tutorial with array fields
Tutorial::create([
'title' => 'MongoDB Setup Guide',
'difficulty_level' => 'beginner',
'prerequisites' => ['Basic PHP knowledge', 'Laravel fundamentals'],
'steps' => [
['title' => 'Install MongoDB', 'content' => 'Download and install...'],
['title' => 'Configure Laravel', 'content' => 'Update config files...']
]
]);
}
}
Step 2: Run the seeder
php artisan db:seed --class=BlogContentSeeder
Pro tip: Generate seeder files using:
php artisan make:seeder BlogContentSeeder
Building the controllers
Controllers handle the business logic and connect your models to views. Let's create controllers that showcase MongoDB's powerful query capabilities.
Key controller methods
File: app/Http/Controllers/BlogController.php
<?php
namespace App\Http\Controllers;
use App\Models\{Post, Article, Tutorial};
class BlogController extends Controller
{
public function index()
{
// Fetch all content types and merge them
$posts = Post::published()->get();
$articles = Article::published()->get();
$tutorials = Tutorial::published()->get();
$content = collect()
->merge($posts)
->merge($articles)
->merge($tutorials)
->sortByDesc('published_at');
return view('blog.index', compact('content'));
}
public function show($type, $id)
{
// Dynamic model resolution based on type
$content = match ($type) {
'post' => Post::findOrFail($id),
'article' => Article::findOrFail($id),
'tutorial' => Tutorial::findOrFail($id),
default => abort(404)
};
return view('blog.show', compact('content'));
}
public function search(Request $request)
{
$query = $request->get('q');
// MongoDB's flexible text search across multiple fields
$searchClosure = function($q) use ($query) {
$q->where('title', 'like', "%{$query}%")
->orWhere('body', 'like', "%{$query}%")
->orWhere('tags', 'in', [$query]); // Search in array field
};
$posts = Post::published()->where($searchClosure)->get();
// ... repeat for other types
}
}
Register routes
File: routes/web.php
<?php
use App\Http\Controllers\BlogController;
Route::prefix('blog')->name('blog.')->group(function() {
Route::get('/', [BlogController::class, 'index'])->name('index');
Route::get('/search', [BlogController::class, 'search'])->name('search');
Route::get('/{type}/{id}', [BlogController::class, 'show'])
->name('show')
->where('type', 'post|article|tutorial');
});
And to develop the UI, just work with the blade.php files as you have completed the logics development.
Advanced MongoDB features
Working with arrays and nested documents
MongoDB excels at handling complex data structures:
// Querying array fields
$tutorials = Tutorial::where('tags', 'in', ['beginner', 'mongodb'])->get();
// Aggregation pipeline example
$tagStats = Tutorial::raw(function($collection) {
return $collection->aggregate([
['$unwind' => '$tags'],
['$group' => [
'_id' => '$tags',
'count' => ['$sum' => 1]
]],
['$sort' => ['count' => -1]]
]);
});
Performance optimization
Add indexes to improve query performance:
use MongoDB\Laravel\Schema\Blueprint;
Schema::connection('mongodb')->table('contents', function (Blueprint $table) {
$table->index('type');
$table->index('status');
$table->index('tags');
$table->text(['title', 'body']); // Text index for search
});
Conclusion
You've successfully built a complete Laravel application with MongoDB that demonstrates:
- Polymorphic data modeling with a shared collection.
- Flexible schema design that adapts to different content types.
- Powerful querying capabilities including array field searches.
- Full CRUD operations with MongoDB and Laravel.
Next steps
Ready to take your MongoDB + Laravel skills further? Consider exploring:
- MongoDB Atlas for cloud deployment.
- Aggregation pipelines for complex data analysis.
- MongoDB transactions for data consistency.
- Full-text search with MongoDB's text indexes.
Additional resources
- Laravel MongoDB package documentation
- MongoDB official documentation
- Laravel Eloquent documentation
Complete project
The full source code for this tutorial is available on GitHub.
Frequently asked questions
Q: I'm getting "zsh: command not found: laravel".
A: Head to Stack Overflow for guidance!
Q: Having MongoDB connection issues?
A: Learn more about configuring IP access list entries.
Q: How do I add more fields to my models later?
A: Simply add the field names to the $fillable
array in your model. MongoDB's schema-less nature means no migrations are needed!
Hope this tutorial helps you understand the power and flexibility of combining Laravel with MongoDB. Happy coding!
Top comments (0)