diff --git a/docs/cache.txt b/docs/cache.txt index d3fd0f6e6..629065f09 100644 --- a/docs/cache.txt +++ b/docs/cache.txt @@ -14,7 +14,7 @@ Cache and Locks Configuration ------------- -To use MongoDB as a backend for `Laravel Cache and Locks `__, +To use MongoDB as a back end for `Laravel Cache and Locks `__, add a store configuration by specifying the ``mongodb`` driver in ``config/cache.php``: .. code-block:: php diff --git a/docs/fundamentals/atlas-search.txt b/docs/fundamentals/atlas-search.txt index ab957f9fa..a41385fda 100644 --- a/docs/fundamentals/atlas-search.txt +++ b/docs/fundamentals/atlas-search.txt @@ -179,7 +179,7 @@ following optional parameters to ``search()``: * - ``returnStoredSource`` - ``bool`` - Specifies whether to perform a full document lookup on the - backend database or return only stored source fields directly + back end database or return only stored source fields directly from Atlas Search * - ``tracking`` diff --git a/docs/index.txt b/docs/index.txt index 1eb1d8657..0b01b7349 100644 --- a/docs/index.txt +++ b/docs/index.txt @@ -1,3 +1,5 @@ +.. _laravel-docs-landing: + =============== {+odm-long+} =============== diff --git a/docs/quick-start.txt b/docs/quick-start.txt index ebfcb7348..5bd04f353 100644 --- a/docs/quick-start.txt +++ b/docs/quick-start.txt @@ -26,6 +26,7 @@ Quick Start View Data Write Data Next Steps + Tutorial: Build a Back End Overview -------- diff --git a/docs/quick-start/backend-service-tutorial.txt b/docs/quick-start/backend-service-tutorial.txt new file mode 100644 index 000000000..9236c698a --- /dev/null +++ b/docs/quick-start/backend-service-tutorial.txt @@ -0,0 +1,481 @@ +.. _laravel-tutorial-backend-service: + +========================================================== +Tutorial: Build a Back End Service by Using {+odm-long+} +========================================================== + +.. facet:: + :name: genre + :values: tutorial + +.. meta:: + :keywords: php framework, odm, code example, crud + :description: Learn how to set up a back end and perform CRUD operations by using Laravel MongoDB. + +.. contents:: On this page + :local: + :backlinks: none + :depth: 2 + :class: singlecol + +Overview +-------- + +In this tutorial, you create a simple REST back end for a front-end app +by using {+odm-long+}. The tutorial uses Laravel's built-in API routing +features. + +Prerequisites +------------- + +Before you can start this tutorial, you need the following software +installed in your development environment: + +- MongoDB Atlas cluster with sample data loaded. To learn how to create + a cluster, see the :ref:`laravel-quick-start-create-deployment` step + of the Quick Start guide. +- `PHP `__. +- `Composer `__. +- `{+php-extension+} `__. +- A terminal app and shell. For MacOS users, use Terminal or a similar app. + For Windows users, use PowerShell. + +Steps +----- + +.. procedure:: + :style: connected + + .. step:: Create a Laravel project. + + First, create a Laravel project directory. Then, run the following + command to create a new Laravel project called ``laraproject``: + + .. code-block:: bash + + composer create-project laravel/laravel laraproject + + .. step:: Install {+odm-long+}. + + To check that {+odm-long+} is running in the web server, + add a webpage to your Laravel website. In your project, + navigate to ``/routes/web.php`` and add the following route: + + .. code-block:: php + + Route::get('/info', function () { + phpinfo(); + }); + + Then, run the following command in your shell to start + your application: + + .. code-block:: bash + + php artisan serve + + After the application begins running, navigate to + http://127.0.0.1:8000/info to view the PHPinfo page. Scroll down + to or search for the **mongodb** entry to verify that + the {+php-extension+} is installed. + + Run the following command in your shell to install {+odm-long+}: + + .. code-block:: bash + + composer require mongodb/laravel-mongodb:^{+package-version+} + + .. step:: Configure your MongoDB connection. + + Open your project's ``config/database.php`` file and update the + ``connections`` array as shown in the following code: + + .. code-block:: php + + 'connections' => [ + 'mongodb' => [ + 'driver' => 'mongodb', + 'dsn' => '', + 'database' => 'db', + ], + + Ensure that you replace the connection string placeholder + in the preceding code with your connection string before you run + your application. To learn how to locate your connection string, see + :ref:`laravel-quick-start-connection-string` in the Quick Start + guide. + + You can also set the default database connection. At the top of + the ``config/database.php`` file, change 'default' to the following: + + .. code-block:: php + + 'default' => 'mongodb', + + The Laravel application can now connect to the ``db`` database in + your MongoDB cluster. + + .. step:: Create an endpoint to ping your deployment. + + Run the following shell command to set up API routing: + + .. code-block:: bash + + php artisan install:api + + In the newly created ``routes/api.php`` file, add the following + route: + + .. code-block:: php + + // Add the DB use statement to the top of the file. + use Illuminate\Support\Facades\DB; + + Route::get('/ping', function (Request $request) { + $connection = DB::connection('mongodb'); + $msg = 'MongoDB is accessible!'; + try { + $connection->command(['ping' => 1]); + } catch (\Exception $e) { + $msg = 'MongoDB is not accessible. Error: ' . $e->getMessage(); + } + return ['msg' => $msg]; + }); + + Reload the application, then verify that + http://127.0.0.1:8000/api/ping shows the succesful ping message. + + .. step:: Create Eloquent models. + + Laravel is integrated with Eloquent, an ORM that abstracts the + database back end so that you can connect to different databases by + using a common interface. + + Eloquent provides a ``Model`` class to serve as the interface + between your code and a specific collection. Instances of the + ``Model`` classes represent rows of tables in relational + databases. In MongoDB, they are documents in the collection. + + .. tip:: + + You can define fillable fields in your Eloquent models + to enforce a document schema in your application and prevent + errors such as name typos. To learn more, see the + :ref:`laravel-model-mass-assignment` section of the Eloquent + Model Class guide. + + Create an Eloquent model called ``CustomerMongoDB`` by running + the following command from the project root: + + .. code-block:: bash + + php artisan make:model CustomerMongoDB + + Laravel creates the ``CustomerMongoDB`` class in the ``/models`` + directory. By default, models use the ``default`` database + connection, but you can specify which connection to use by adding + the ``$connection`` member to the class. You can also + specify the collection name by adding the ``$collection`` member. + + Ensure you include the ``use`` statement for the MongoDB Eloquent + model. This is necessary to set ``_id`` as the primary key. + + Replace the contents of the ``CustomerMongoDB.php`` file with the + following code: + + .. code-block:: php + + use MongoDB\Laravel\Eloquent\Model; + + class CustomerMongoDB extends Model + { + // the selected database as defined in /config/database.php + protected $connection = 'mongodb'; + + // equivalent to $table for MySQL + protected $collection = 'laracoll'; + + // defines the schema for top-level properties (optional). + protected $fillable = ['guid', 'first_name', 'family_name', 'email', 'address']; + } + + .. step:: Perform CRUD operations. + + After you create your models, you can perform data operations. + + Create the following route in your ``api.php`` file: + + .. code-block:: php + + Route::get('/create_eloquent_mongo/', function (Request $request) { + $success = CustomerMongoDB::create([ + 'guid'=> 'cust_1111', + 'first_name'=> 'John', + 'family_name' => 'Doe', + 'email' => 'j.doe@gmail.com', + 'address' => '123 my street, my city, zip, state, country' + ]); + }); + + After you insert the document, you can retrieve it by using the + ``where()`` method as shown in the following code: + + .. code-block:: php + + Route::get('/find_eloquent/', function (Request $request) { + $customer = CustomerMongoDB::where('guid', 'cust_1111')->get(); + }); + + Eloquent allows you to find data by using complex queries with + multiple matching conditions. + + You can also update and delete data shown in the following routes: + + .. code-block:: php + + Route::get('/update_eloquent/', function (Request $request) { + $result = CustomerMongoDB::where('guid', 'cust_1111')->update( ['first_name' => 'Jimmy'] ); + }); + + Route::get('/delete_eloquent/', function (Request $request) { + $result = CustomerMongoDB::where('guid', 'cust_1111')->delete(); + }); + + At this point, your MongoDB-connected back-end service is + running, but MongoDB provides more functionality to support your + operations. + + .. step:: Perform operations on nested data. + + {+odm-long+} offers MongoDB-specific operations for nested data. + However, adding nested data is also intuitive without using + the ``embedsMany()`` and ``embedsOne()`` methods. + + As shown in the preceding step, you can define top-level schema + attributes. However, it is more complicated when to define these + attribute if your documents include arrays and embedded documents. + + You can create the model's data structures in PHP. In the + following example, the ``address`` field is an object type. + The ``email`` field is an array of strings: + + .. code-block:: php + + Route::get('/create_nested/', function (Request $request) { + $message = "executed"; + $success = null; + + $address = new stdClass; + $address->street = '123 my street name'; + $address->city = 'my city'; + $address->zip= '12345'; + $emails = ['j.doe@gmail.com', 'j.doe@work.com']; + + try { + $customer = new CustomerMongoDB(); + $customer->guid = 'cust_2222'; + $customer->first_name = 'John'; + $customer->family_name= 'Doe'; + $customer->email= $emails; + $customer->address= $address; + $success = $customer->save(); // save() returns 1 or 0 + } + catch (\Exception $e) { + $message = $e->getMessage(); + } + return ['msg' => $message, 'data' => $success]; + }); + + When you access the ``/api/create_nested/`` endpoint, it creates a + document in MongoDB: + + .. code-block:: json + + { + "_id": {...}, + "guid": "cust_2222", + "first_name": "John", + "family_name": "Doe", + "email": [ + "j.doe@gmail.com", + "j.doe@work.com" + ], + "address": { + "street": "123 my street name", + "city": "my city", + "zip": "12345" + }, + "updated_at": { + "$date": "2025-05-27T17:38:28.793Z" + }, + "created_at": { + "$date": "2025-05-27T17:38:28.793Z" + } + } + + .. step:: Use the MongoDB Query API. + + MongoDB provides the Query API for optimized queries. + + You can begin to build a query by using a ``collection`` object. + Eloquent exposes the full capabilities of the underlying database + by using "raw queries," which Laravel sends to the database + without any processing from the Eloquent Query Builder. + + You can perform a raw native MongoDB query from the model as shown + in the following code: + + .. code-block:: php + + $mongodbquery = ['guid' => 'cust_1111']; + + // returns a "Illuminate\Database\Eloquent\Collection" Object + $results = CustomerMongoDB::whereRaw( $mongodbquery )->get(); + + You can also access the native MongoDB collection object and + perform a query that returns objects such as native MongoDB + documents or cursors: + + .. code-block:: php + + $mongodbquery = ['guid' => 'cust_1111', ]; + $mongodb_native_collection = DB::connection('mongodb')->getCollection('laracoll'); + $document = $mongodb_native_collection->findOne( $mongodbquery ); + $cursor = $mongodb_native_collection->find( $mongodbquery ); + + The following code demonstrates multiple ways to perform queries: + + .. code-block:: php + + Route::get('/find_native/', function (Request $request) { + // a simple MongoDB query that looks for a customer based on the guid + $mongodbquery = ['guid' => 'cust_2222']; + + // Option #1 + // ========= + // use Eloquent's whereRaw() function + // returns a "Illuminate\Database\Eloquent\Collection" Object + + $results = CustomerMongoDB::whereRaw( $mongodbquery )->get(); + + // Option #2 & #3 + // ============== + // use the native MongoDB driver Collection object and the Query API + + $mdb_collection = DB::connection('mongodb')->getCollection('laracoll'); + + // find the first document that matches the query + $mdb_bsondoc = $mdb_collection->findOne( $mongodbquery ); // returns a "MongoDB\Model\BSONDocument" Object + + // to convert the MongoDB Document to a Laravel Model, use the Model's newFromBuilder() method + $cust = new CustomerMongoDB(); + $one_doc = $cust->newFromBuilder((array) $mdb_bsondoc); + + // find all documents because you pass an empty query + $mdb_cursor = $mdb_collection->find(); // returns a "MongoDB\Driver\Cursor" object + $cust_array = array(); + foreach ($mdb_cursor->toArray() as $bson) { + $cust_array[] = $cust->newFromBuilder( $bson ); + } + + return ['msg' => 'executed', 'whereraw' => $results, 'document' => $one_doc, 'cursor_array' => $cust_array]; + }); + + The following code demonstrates how to use the ``updateOne()`` + method to update documents: + + .. code-block:: php + + Route::get('/update_native/', function (Request $request) { + $mdb_collection = DB::connection('mongodb')->getCollection('laracoll'); + $match = ['guid' => 'cust_2222']; + $update = ['$set' => ['first_name' => 'Henry', 'address.street' => '777 new street name'] ]; + $result = $mdb_collection->updateOne($match, $update ); + return ['msg' => 'executed', 'matched_docs' => $result->getMatchedCount(), 'modified_docs' => $result->getModifiedCount()]; + }); + + The following code demonstrates how to use the ``deleteOne()`` + method to delete documents: + + .. code-block:: php + + Route::get('/delete_native/', function (Request $request) { + $mdb_collection = DB::connection('mongodb')->getCollection('laracoll'); + $match = ['guid' => 'cust_2222']; + $result = $mdb_collection->deleteOne($match ); + return ['msg' => 'executed', 'deleted_docs' => + $result->getDeletedCount() ]; + }); + + To learn more about how to perform CRUD operations, see the + :ref:`laravel-fundamentals-write-ops` and + :ref:`laravel-fundamentals-read-ops` guides. + + .. step:: Use the aggregation framework. + + An aggregation pipeline is a task in MongoDB's aggregation + framework. You can use the aggregation framework to perform + various tasks such as real-time dashboards and big data analysis. + + An aggregation pipeline consists of multiple stages in which the + output of each stage is the input of the following stage. + This step uses the ``sample_mflix`` from the :atlas:`Atlas sample + datasets `. Laravel allows you to access multiple + MongoDB databases in the same app, so add the ``sample_mflix`` + database connection to ``database.php``: + + .. code-block:: php + + 'mongodb_mflix' => [ + 'driver' => 'mongodb', + 'dsn' => env('DB_URI'), + 'database' => 'sample_mflix', + ], + + Next, create the ``/aggregate/`` API endpoint and define an + aggregation pipeline to retrieve data from the ``movies`` + collection, compute the average movie rating for each genre, and + return a list. + + .. code-block:: php + + Route::get('/aggregate/', function (Request $request) { + $mdb_collection = DB::connection('mongodb_mflix')->getCollection('movies'); + + $stage0 = ['$unwind' => ['path' => '$genres']]; + $stage1 = ['$group' => ['_id' => '$genres', 'averageGenreRating' => ['$avg' => '$imdb.rating']]]; + $stage2 = ['$sort' => ['averageGenreRating' => -1]]; + $aggregation = [$stage0, $stage1, $stage2]; + + $mdb_cursor = $mdb_collection->aggregate( $aggregation ); + + return ['msg' => 'executed', 'data' => $mdb_cursor->toArray() ]; + }); + + {+odm-long+} provides the :ref:`laravel-aggregation-builder` to + build type-safe aggregation pipelines directly from your models. + We recommend using the aggregation builder to perform + aggregations. + + .. step:: Use indexes to optimize query performance. + + You can create indexes to support your queries and improve + performance. To learn more about how to create indexes + programmatically, see the :ref:`laravel-eloquent-indexes` section + of the Schema Builder guide. + +Conclusion +---------- + +In this tutorial, you learned how to create a back-end service by using +Laravel and MongoDB for a front-end web application. +This tutorial also showed how you can use the document model to improve +database efficiency and scalability. You can use the document model with the +MongoDB Query API to create better apps with less downtime. + +You can access the full code for this tutorial in the +:github:`laravel-mongodb-tutorial +` repository on GitHub. + +Navigate through the rest of the :ref:`laravel-docs-landing` +documentation to learn more about {+odm-long+}'s features. diff --git a/docs/quick-start/next-steps.txt b/docs/quick-start/next-steps.txt index 2853777fb..dc155326f 100644 --- a/docs/quick-start/next-steps.txt +++ b/docs/quick-start/next-steps.txt @@ -21,7 +21,11 @@ You can download the web application project by cloning the `laravel-quickstart `__ GitHub repository. -.. tip:: Build a Full Stack Application +.. tip:: Tutorials + + Learn how to implement more CRUD functionality in a {+odm-long+} + application by following the :ref:`Build a Back End Service by Using + {+odm-long+} ` tutorial. Learn how to build a full stack application that uses {+odm-long+} by following along with the `Full Stack Instagram Clone with Laravel and