DEV Community

MongoDB Guests for MongoDB

Posted on • Originally published at laravel-news.com

Introduction to MongoDB & Laravel-MongoDB Setup

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?

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:

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
Enter fullscreen mode Exit fullscreen mode

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                                             │
 └───────────────────────────────┘
Enter fullscreen mode Exit fullscreen mode

Step 2: Generate application key

Navigate to your project directory and generate the application key:

cd developer-blog
php artisan key:generate
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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'),
       ],
   ]
]
Enter fullscreen mode Exit fullscreen mode

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"
Enter fullscreen mode Exit fullscreen mode

Step 6: Start your application

Launch the Laravel development server:

php artisan serve
Enter fullscreen mode Exit fullscreen mode

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();
}
Enter fullscreen mode Exit fullscreen mode

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;
    }
}
Enter fullscreen mode Exit fullscreen mode

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);
    }
}
Enter fullscreen mode Exit fullscreen mode

** Quick tip**: You can also generate model files using Laravel's Artisan command:

 php artisan make:model Post
Enter fullscreen mode Exit fullscreen mode

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...']
            ]
        ]);
    }
}
Enter fullscreen mode Exit fullscreen mode

Step 2: Run the seeder

php artisan db:seed --class=BlogContentSeeder
Enter fullscreen mode Exit fullscreen mode

Pro tip: Generate seeder files using:

php artisan make:seeder BlogContentSeeder
Enter fullscreen mode Exit fullscreen mode

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
    }
}
Enter fullscreen mode Exit fullscreen mode

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');
});
Enter fullscreen mode Exit fullscreen mode

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]]
    ]);
});
Enter fullscreen mode Exit fullscreen mode

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
});
Enter fullscreen mode Exit fullscreen mode

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:

  1. MongoDB Atlas for cloud deployment.
  2. Aggregation pipelines for complex data analysis.
  3. MongoDB transactions for data consistency.
  4. 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)