Laravel is famous for Eloquent ORM which typically works with relational databases like MySQL. But what if you want to choose a NoSQL solution like MongoDB? This article will show you how to start with MongoDB in Laravel.
Why and When MongoDB?
MongoDB is a NoSQL (Not only SQL) database that stores large volumes of data in the form of JSON-like documents that can change structure over time.
The alternatives are relational databases, like MySQL, which is a free, open-source database system that stores data in tables containing rows and columns.
The main difference between MongoDB and MySQL is that you don't need any prior schema structure, and it scales horizontally.
MySQL is an excellent choice if you have structured data and need a traditional relational database. Systems like financial, e-commerce, etc., would be better with MySQL.
MongoDB is better with unstructured data like social networks, media, real-time analytics, etc.
MongoDB Server Install
MongoDB has two server editions: Community and Enterprise. Both editions can be installed on almost any operating system or using Docker. To install MongoDB locally, check the official installation documentation.
The alternative way is to use the cloud version called MongoDB Atlas, which is not free but comes with a free tier.
Install MongoDB In Laravel
Here's a general structure of how MongoDB works with Laravel Eloquent:
Notice: Remember that you need the PHP MongoDB extension to be installed and enabled.
To use MongoDB in your Laravel application, first, you must install the official package, which extends the same model and query builder APIs from Eloquent.
composer require mongodb/laravel-mongodb
Next, we need to register the MongoDB Service Provider.
bootstrap/app.php:
return [ App\Providers\AppServiceProvider::class, MongoDB\Laravel\MongoDBServiceProvider::class, ];
We must create a database connection in the config/database.php
file.
You can connect to your MongoDB deployment by providing a connection URI, also called a connection string. See the connection guide for more details.
config/database.php:
return [ // ... 'connections' => [ 'sqlite' => [ 'driver' => 'sqlite', 'url' => env('DB_URL'), 'database' => env('DB_DATABASE', database_path('database.sqlite')), 'prefix' => '', 'foreign_key_constraints' => env('DB_FOREIGN_KEYS', true), ], 'mongodb' => [ 'driver' => 'mongodb', // Replace "mongodb://localhost:27017" with the actual connection string 'dsn' => env('DB_DSN', 'mongodb://localhost:27017'), 'database' => env('DB_DATABASE', 'laravel'), ], // ... ], // ... ];
Finally, we need to set that connection as a default in the environment file.
.env:
// ... DB_CONNECTION=mongodb DB_HOST=127.0.0.1DB_PORT=3306DB_DATABASE=projectDB_USERNAME=rootDB_PASSWORD= // ...
Now, we can use MongoDB as a database in our application. There are some differences, so let's see how to use MongoDB.
Migrations
While you don't need Migrations when using MongoDB, you still can use them, for example, to add an index. To use Migrations, you must use the Blueprint
class from MongoDB instead of Illuminate
.
use Illuminate\Database\Migrations\Migration;use Illuminate\Database\Schema\Blueprint; use MongoDB\Laravel\Schema\Blueprint; use Illuminate\Support\Facades\Schema; return new class extends Migration{ public function up(): void { Schema::create('posts', function (Blueprint $collection) { $collection->index('title'); }); }};
This Migration will create a collection called posts
and add an index.
A collection in MongoDB is the same as a table in MySQL.
For more information on the Schema Builder, check the official documentation.
Models and Relationships
Every Model must extend the Model
class from the MongoDB.
use Illuminate\Database\Eloquent\Model; use MongoDB\Laravel\Eloquent\Model; class Post extends Model{ // ...}
You can change the collection name by overwriting the $collection
protected property.
use MongoDB\Laravel\Eloquent\Model; class Post extends Model{ protected $collection = 'postings'; // ...}
When defining relationships and type-hinting, the classes must also be from the MongoDB.
use MongoDB\Laravel\Eloquent\Model;use Illuminate\Database\Eloquent\Relations\BelongsTo; use MongoDB\Laravel\Relations\BelongsTo; use Illuminate\Database\Eloquent\Factories\HasFactory; class Post extends Model{ // ... public function category(): BelongsTo { return $this->belongsTo(Category::class); }}
For example, getting the first post result would look like this:
\App\Models\Post::with('category')->first()->toJson()
{ "_id": "66387efc667555726d0f8f99", "created_at": "2024-05-06T06:55:56.466000Z", "updated_at": "2024-05-06T06:55:56.466000Z", "title": "debitis quis dolorem", "category_id": "66387efc667555726d0f8f98", "category": { "_id": "66387efc667555726d0f8f98", "name": "non sed assumenda", "updated_at": "2024-05-06T06:55:56.466000Z", "created_at": "2024-05-06T06:55:56.466000Z" }}
For more, check the official documentation.
Authentication
First, you must change the extended class in the User Model to the one from the MongoDB package to allow users to authenticate your application.
app/Models/User.php:
// use Illuminate\Contracts\Auth\MustVerifyEmail;use Illuminate\Database\Eloquent\Factories\HasFactory;use Illuminate\Foundation\Auth\User as Authenticatable; use MongoDB\Laravel\Auth\User as Authenticatable; use Illuminate\Notifications\Notifiable; class User extends Authenticatable{ // ...}
Next, by default, Laravel uses the database
session driver. If you want to use a database as a session driver, you must create a custom session driver. Alternatively, change the session driver, for example, to file
.
.env:
// ... SESSION_DRIVER=file SESSION_LIFETIME=120SESSION_ENCRYPT=falseSESSION_PATH=/SESSION_DOMAIN=null // ...
MongoDB supports several authentication mechanisms like SCRAM, X.509, AWS IAM. Check out MongoDB security documentation for more details.
Final Notes
There are some Laravel features that MongoDB doesn't support. You can check the full MongoDB's compatibility with Laravel features in the official documentation.
In addition to storing data, MongoDB can be used for other features such as queue, cache, locks, and sessions. For more on using MongoDB in Laravel applications, check the official documentation.
very good. but unfortunately some popular packages like passport, sanctum, spatie role permission not support mongodb. only solution I found is changing all laravel model used in vendor for these package to mogodb model.