Relational databases are the default for most Laravel projects, and for good reason. But many real systems also hold data that does not fit neatly into rows and columns: product catalogs with varying attributes, event logs, user activity feeds, and content with nested structures. MongoDB's document model handles these cases naturally, and the official Laravel integration lets you work with it using the Eloquent patterns you already know.
This guide walks through a complete, working practice environment on a fresh Ubuntu 24.04 machine: MongoDB 8.0, the PHP MongoDB extension, a new Laravel 13 project, and your first CRUD and aggregation queries. It also covers the one build error that trips up many developers during the extension install, so you can avoid losing an hour to it.
What You Will Build
By the end, you will have:
- MongoDB 8.0 running as a system service
- The PHP
mongodbextension compiled and enabled - A Laravel 13 project connected to MongoDB through
mongodb/laravel-mongodb - A
Productmodel with create, read, update, and delete operations working - A first aggregation pipeline running from Laravel
Prerequisites: Ubuntu 24.04, a user with sudo access, and basic familiarity with PHP and the terminal. Ubuntu 24.04 ships with PHP 8.3, which satisfies Laravel 13's requirements.
Step 1: Install MongoDB 8.0
MongoDB is not in Ubuntu's default repositories, so add the official MongoDB repository first.
sudo apt-get update && sudo apt-get install -y gnupg curl
curl -fsSL https://www.mongodb.org/static/pgp/server-8.0.asc | \
sudo gpg -o /usr/share/keyrings/mongodb-server-8.0.gpg --dearmor
echo "deb [ arch=amd64,arm64 signed-by=/usr/share/keyrings/mongodb-server-8.0.gpg ] https://repo.mongodb.org/apt/ubuntu noble/mongodb-org/8.0 multiverse" | \
sudo tee /etc/apt/sources.list.d/mongodb-org-8.0.list
sudo apt-get update
sudo apt-get install -y mongodb-org
sudo systemctl enable --now mongod
Verify that the service is running and responding:
systemctl status mongod --no-pager
mongosh --eval 'db.runCommand({ ping: 1 })'
You should see Active: active (running) and { ok: 1 }. If mongod fails to start, sudo journalctl -u mongod -n 50 will show why.
Step 2: Prepare PHP
Install the PHP packages Laravel needs, plus the build tools required to compile the MongoDB extension.
sudo apt install -y php8.3-cli php8.3-xml php8.3-mbstring php8.3-curl \
php8.3-zip php8.3-sqlite3 php8.3-dev php-pear libssl-dev pkg-config unzip
Install Composer if you do not already have it:
sudo apt install -y composer
Step 3: Install the PHP MongoDB Extension
The Laravel package is built on the official mongodb PHP extension, so nothing works without it. Install it through PECL:
sudo pecl channel-update pecl.php.net
yes '' | sudo pecl install mongodb
Then enable it:
echo "extension=mongodb.so" | sudo tee /etc/php/8.3/mods-available/mongodb.ini
sudo phpenmod mongodb
php --ri mongodb
If the last command prints MongoDB support => enabled along with a version number, the extension is ready.
The Pitfall: Do Not Answer "yes" to PECL's Prompts
During installation, PECL asks several configuration questions. The safe approach is to accept the default for every one of them by pressing Enter, which is exactly what yes '' does above.
A common mistake is answering yes to these three:
- Enable developer flags? This turns on strict compiler settings that can turn harmless warnings into build failures.
- Enable code coverage? Unnecessary for normal use.
-
Use system libraries for libbson, libmongoc, and libmongocrypt? This is the one that breaks most builds. Ubuntu's packaged
libbsonis older than the version the extension requires, so the build stops with an error likeCould not find system library for libbson >= 2.5.6.
With the defaults, the extension compiles against its own bundled libraries and builds cleanly. If you already ran the install with the wrong answers, run sudo phpdismod mongodb to silence the load warnings, clear the cache with sudo pecl clear-cache, and reinstall with the defaults.
Also note that the PHP CLI and PHP-FPM read separate configuration. If you later serve the app through FPM or Apache, restart that service after enabling the extension.
Step 4: Create the Laravel Project
composer create-project laravel/laravel mongo-practice
cd mongo-practice
composer require mongodb/laravel-mongodb
Composer selects a compatible version of the package automatically. If it reports a version conflict with Laravel 13, check the package's releases page for the supported version range.
Step 5: Configure the Connection
Add your connection details to .env:
MONGODB_URI=mongodb://127.0.0.1:27017
MONGODB_DATABASE=practice
Then add a mongodb connection to the connections array in config/database.php:
'mongodb' => [
'driver' => 'mongodb',
'dsn' => env('MONGODB_URI', 'mongodb://127.0.0.1:27017'),
'database' => env('MONGODB_DATABASE', 'practice'),
],
Leave DB_CONNECTION set to sqlite for now. Laravel's sessions, cache, and migrations will keep using the default database, while only the models you explicitly point at MongoDB will use the mongodb connection. This separation keeps a practice project simple and avoids surprises.
Step 6: Create Your First Model
php artisan make:model Product
Replace the generated class with a MongoDB-aware model:
<?php
namespace App\Models;
use MongoDB\Laravel\Eloquent\Model;
class Product extends Model
{
protected $connection = 'mongodb';
protected $collection = 'products';
protected $fillable = ['name', 'price', 'category', 'tags', 'specs'];
}
The key difference from a standard Eloquent model is the base class. Import MongoDB\Laravel\Eloquent\Model instead of Illuminate\Database\Eloquent\Model. Everything else, including $fillable, casts, and query builder methods, will feel familiar.
MongoDB creates the database and collection automatically on the first write, so there is no migration to run.
Step 7: Practice with Tinker
Open Laravel's REPL:
php artisan tinker
Create
use App\Models\Product;
Product::create([
'name' => 'Laptop',
'price' => 85000,
'category' => 'electronics',
'tags' => ['work', 'portable'],
'specs' => ['ram' => '16GB', 'storage' => '512GB'],
]);
Notice that tags is an array and specs is a nested object. In a relational database, these would typically need extra tables or JSON columns. Here they are first-class values.
Read
Product::where('price', '>', 50000)->get();
Product::where('specs.ram', '16GB')->first(); // dot notation for nested fields
Product::whereIn('tags', ['work'])->get(); // match inside arrays
Update and Delete
Product::where('name', 'Laptop')->update(['price' => 80000]);
Product::where('name', 'Laptop')->delete();
Verify in the MongoDB Shell
Open a second terminal and inspect the raw documents:
mongosh
use practice
db.products.find().pretty()
This is the most valuable habit for learning. Run a query in Laravel, then look at what actually landed in MongoDB. Seeing both sides builds an accurate mental model of how documents are stored.
Step 8: Your First Aggregation Pipeline
Aggregation is where MongoDB becomes a serious analytics tool. A pipeline passes documents through ordered stages, each transforming the data. This example calculates the average price per category:
Product::raw(fn ($collection) => $collection->aggregate([
['$group' => [
'_id' => '$category',
'avgPrice' => ['$avg' => '$price'],
'count' => ['$sum' => 1],
]],
['$sort' => ['avgPrice' => -1]],
]))->toArray();
The $group stage buckets documents by category and computes the aggregates, and $sort orders the results. From here, the stages worth learning next are $match (filtering early, which improves performance), $project (reshaping output), $unwind (flattening arrays), and $lookup (joining collections).
Troubleshooting Reference
| Symptom | Likely Cause and Fix |
|---|---|
Class "MongoDB\Client" not found |
The extension is not enabled for the PHP binary you are using. Run sudo phpenmod mongodb and restart FPM if applicable. |
pecl install fails with a libbson error |
You answered yes to the system-libraries prompt. Reinstall using the defaults. |
PHP warns it cannot load mongodb.so
|
The .ini file exists but the extension was never built. Run sudo phpdismod mongodb, then reinstall. |
mongod will not start |
Check sudo journalctl -u mongod -n 50 for the specific error. |
| Queries return nothing | Confirm the database name in .env matches the one you are inspecting in mongosh. |
Where to Go Next
With a working environment, the most productive next steps are:
- Data modeling. Learn when to embed documents versus reference them. This decision shapes performance more than any other.
-
Indexing. Create indexes for your query patterns and use
explain()to confirm they are used. -
Deeper aggregation. Build multi-stage pipelines with
$match,$lookup, and$unwindagainst realistic seeded data. - Transactions and replica sets. Multi-document transactions require a replica set, even in local development.
Conclusion
Setting up MongoDB with Laravel on Ubuntu comes down to three moving parts: the database service, the PHP extension, and the Laravel package. Most of the friction sits in the extension build, and it disappears once you accept PECL's defaults. From there, you work with documents through the same Eloquent interface you already use every day, while gaining flexible schemas, nested data, and a powerful aggregation framework.
Top comments (0)