diff --git a/docs/fundamentals/write-operations.txt b/docs/fundamentals/write-operations.txt index 5afcc5010..349372923 100644 --- a/docs/fundamentals/write-operations.txt +++ b/docs/fundamentals/write-operations.txt @@ -9,7 +9,7 @@ Write Operations :values: tutorial .. meta:: - :keywords: insert, insert one, update, update one, upsert, delete, delete many, code example, mass assignment, eloquent model + :keywords: insert, insert one, code example, mass assignment, eloquent model .. contents:: On this page :local: @@ -27,28 +27,15 @@ inserting, updating, and deleting data based on specified criteria. This guide shows you how to perform the following tasks: - :ref:`laravel-fundamentals-insert-documents` -- Modify Documents +- :ref:`laravel-fundamentals-modify-documents` - Delete Documents -.. _laravel-fundamentals-insert-documents: - -Insert Documents ----------------- - -In this section, you can learn how to insert documents into MongoDB collections -from your Laravel application by using the {+odm-long+}. - -When you insert the documents, ensure the data does not violate any -unique indexes on the collection. When inserting the first document of a -collection or creating a new collection, MongoDB automatically creates a -unique index on the ``_id`` field. +.. _laravel-fundamentals-write-sample-model: -For more information on creating indexes on MongoDB collections by using the -Laravel schema builder, see the :ref:`laravel-eloquent-indexes` section -of the Schema Builder documentation. +Sample Model +~~~~~~~~~~~~ -This section uses the following example model class to demonstrate how to -use Eloquent models to perform insert operations: +The write operations in this guide reference the following Eloquent model class: .. literalinclude:: /includes/fundamentals/write-operations/Concert.php :language: php @@ -65,6 +52,23 @@ use Eloquent models to perform insert operations: data types. To learn more, see `Attribute Casting `__ in the Laravel documentation. +.. _laravel-fundamentals-insert-documents: + +Insert Documents +---------------- + +In this section, you can learn how to insert documents into MongoDB collections +from your Laravel application by using the {+odm-long+}. + +When you insert the documents, ensure the data does not violate any +unique indexes on the collection. When inserting the first document of a +collection or creating a new collection, MongoDB automatically creates a +unique index on the ``_id`` field. + +For more information on creating indexes on MongoDB collections by using the +Laravel schema builder, see the :ref:`laravel-eloquent-indexes` section +of the Schema Builder documentation. + To learn more about Eloquent models in {+odm-short+}, see the :ref:`laravel-eloquent-models` section. @@ -75,13 +79,16 @@ These examples show how to use the ``save()`` Eloquent method to insert an instance of a ``Concert`` model as a MongoDB document. When the ``save()`` method succeeds, you can access the model instance on -which you called the method. If the operation fails, the model instance is -assigned ``null``. +which you called the method. + +If the operation fails, the model instance is assigned ``null``. This example code performs the following actions: - Creates a new instance of the ``Concert`` model - Assigns string values to the ``performer`` and ``venue`` fields +- Assigns an array of strings to the ``genre`` field +- Assigns a number to the ``ticketsSold`` field - Assigns a date to the ``performanceDate`` field by using the ``Carbon`` package - Inserts the document by calling the ``save()`` method @@ -93,7 +100,7 @@ This example code performs the following actions: :end-before: end model insert one You can retrieve the inserted document's ``_id`` value by accessing the model's -``id`` member as shown in the following code example: +``id`` member, as shown in the following code example: .. literalinclude:: /includes/fundamentals/write-operations/WriteOperationsTest.php :language: php @@ -103,7 +110,7 @@ You can retrieve the inserted document's ``_id`` value by accessing the model's If you enable mass assignment by defining either the ``$fillable`` or ``$guarded`` attributes, you can use the Eloquent model ``create()`` method -to perform the insert in a single call as shown in the following example: +to perform the insert in a single call, as shown in the following example: .. literalinclude:: /includes/fundamentals/write-operations/WriteOperationsTest.php :language: php @@ -122,17 +129,19 @@ multiple instances of a ``Concert`` model as MongoDB documents. This bulk insert method reduces the number of calls your application needs to make to save the documents. -When the ``insert()`` method succeeds, it returns the value ``1``. If it -fails, it throws an exception. + +When the ``insert()`` method succeeds, it returns the value ``1``. + +If it fails, it throws an exception. The example code saves multiple models in a single call by passing them as an array to the ``insert()`` method: .. note:: - This example wraps the dates in the `MongoDB\BSON\UTCDateTime <{+phplib-api+}/class.mongodb-bson-utcdatetime.php>`__ - class to convert it to a type MongoDB can serialize because Laravel - skips attribute casting on bulk insert operations. + This example wraps the dates in the `MongoDB\\BSON\\UTCDateTime <{+phplib-api+}/class.mongodb-bson-utcdatetime.php>`__ + class to convert it to a type MongoDB can serialize because Laravel + skips attribute casting on bulk insert operations. .. literalinclude:: /includes/fundamentals/write-operations/WriteOperationsTest.php :language: php @@ -140,3 +149,102 @@ an array to the ``insert()`` method: :start-after: begin model insert many :end-before: end model insert many +.. _laravel-fundamentals-modify-documents: + +Modify Documents +---------------- + +In this section, you can learn how to modify documents in your MongoDB +collection from your Laravel application. Use update operations to modify +existing documents or to insert a document if none match the search criteria. + +You can persist changes on an instance of an Eloquent model or use +Eloquent's fluent syntax to chain an update operation on methods that +return a Laravel collection object. + +This section provides examples of the following update operations: + +- :ref:`Update a document ` +- :ref:`Update multiple documents ` + +.. _laravel-modify-documents-update-one: + +Update a Document Examples +~~~~~~~~~~~~~~~~~~~~~~~~~~ + +You can update a document in the following ways: + +- Modify an instance of the model and save the changes by calling the ``save()`` + method. +- Chain methods to retrieve an instance of a model and perform updates on it + by calling the ``update()`` method. + +The following example shows how to update a document by modifying an instance +of the model and calling its ``save()`` method: + +.. literalinclude:: /includes/fundamentals/write-operations/WriteOperationsTest.php + :language: php + :dedent: + :start-after: begin model update one save + :end-before: end model update one save + +When the ``save()`` method succeeds, the model instance on which you called the +method contains the updated values. + +If the operation fails, {+odm-short+} assigns the model instance a null value. + +The following example shows how to update a document by chaining methods to +retrieve and update the first matching document: + +.. literalinclude:: /includes/fundamentals/write-operations/WriteOperationsTest.php + :language: php + :dedent: + :start-after: begin model update one fluent + :end-before: end model update one fluent + +.. note:: + + The ``orderBy()`` call sorts the results by the ``_id`` field to + guarantee a consistent sort order. To learn more about sorting in MongoDB, + see the :manual:`Natural order ` + glossary entry in the {+server-docs-name+}. + +When the ``update()`` method succeeds, the operation returns the number of +documents updated. + +If the retrieve part of the call does not match any documents, {+odm-short+} +returns the following error: + +.. code-block:: none + :copyable: false + + Error: Call to a member function update() on null + +.. _laravel-modify-documents-update-multiple: + +Update Multiple Documents Example +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +To perform an update on one or more documents, chain the ``update()`` +method to the results of a method that retrieves the documents as a +Laravel collection object, such as ``where()``. + +The following example shows how to chain calls to retrieve matching documents +and update them: + +.. literalinclude:: /includes/fundamentals/write-operations/WriteOperationsTest.php + :language: php + :dedent: + :start-after: begin model update multiple + :end-before: end model update multiple + +When the ``update()`` method succeeds, the operation returns the number of +documents updated. + +If the retrieve part of the call does not match any documents in MongoDB, +{+odm-short+} returns the following error: + +.. code-block:: none + :copyable: false + + Error: Call to a member function update() on null diff --git a/docs/includes/fundamentals/write-operations/Concert.php b/docs/includes/fundamentals/write-operations/Concert.php index 9eaa51139..69b36b9a5 100644 --- a/docs/includes/fundamentals/write-operations/Concert.php +++ b/docs/includes/fundamentals/write-operations/Concert.php @@ -7,6 +7,6 @@ class Concert extends Model { protected $connection = 'mongodb'; - protected $fillable = ['performer', 'venue', 'performanceDate']; + protected $fillable = ['performer', 'venue', 'genres', 'ticketsSold', 'performanceDate']; protected $casts = ['performanceDate' => 'datetime']; } diff --git a/docs/includes/fundamentals/write-operations/WriteOperationsTest.php b/docs/includes/fundamentals/write-operations/WriteOperationsTest.php index 365d86dd3..a868c1fe8 100644 --- a/docs/includes/fundamentals/write-operations/WriteOperationsTest.php +++ b/docs/includes/fundamentals/write-operations/WriteOperationsTest.php @@ -27,6 +27,8 @@ public function testModelInsert(): void $concert = new Concert(); $concert->performer = 'Mitsuko Uchida'; $concert->venue = 'Carnegie Hall'; + $concert->genres = ['classical']; + $concert->ticketsSold = 2121; $concert->performanceDate = Carbon::create(2024, 4, 1, 20, 0, 0, 'EST'); $concert->save(); // end model insert one @@ -56,6 +58,8 @@ public function testModelInsertMassAssign(): void $insertResult = Concert::create([ 'performer' => 'The Rolling Stones', 'venue' => 'Soldier Field', + 'genres' => [ 'rock', 'pop', 'blues' ], + 'ticketsSold' => 59527, 'performanceDate' => Carbon::create(2024, 6, 30, 20, 0, 0, 'CDT'), ]); // end model insert one mass assign @@ -81,11 +85,15 @@ public function testModelInsertMany(): void [ 'performer' => 'Brad Mehldau', 'venue' => 'Philharmonie de Paris', + 'genres' => [ 'jazz', 'post-bop' ], + 'ticketsSold' => 5745, 'performanceDate' => new UTCDateTime(Carbon::create(2025, 2, 12, 20, 0, 0, 'CET')), ], [ 'performer' => 'Billy Joel', 'venue' => 'Madison Square Garden', + 'genres' => [ 'rock', 'soft rock', 'pop rock' ], + 'ticketsSold' => 12852, 'performanceDate' => new UTCDateTime(Carbon::create(2025, 2, 12, 20, 0, 0, 'CET')), ], ]; @@ -97,4 +105,113 @@ public function testModelInsertMany(): void $this->assertEquals(2, count($results)); } + + /** + * @runInSeparateProcess + * @preserveGlobalState disabled + */ + public function testModelUpdateSave(): void + { + require_once __DIR__ . '/Concert.php'; + Concert::truncate(); + + // insert the model + Concert::create([ + 'performer' => 'Brad Mehldau', + 'venue' => 'Philharmonie de Paris', + 'genres' => [ 'jazz', 'post-bop' ], + 'ticketsSold' => 5745, + 'performanceDate' => new UTCDateTime(Carbon::create(2025, 2, 12, 20, 0, 0, 'CET')), + ]); + + // begin model update one save + $concert = Concert::first(); + $concert->venue = 'Manchester Arena'; + $concert->ticketsSold = 9543; + $concert->save(); + // end model update one save + + $result = Concert::first(); + $this->assertInstanceOf(Concert::class, $result); + + $this->assertNotNull($result); + $this->assertEquals('Manchester Arena', $result->venue); + $this->assertEquals('Brad Mehldau', $result->performer); + $this->assertEquals(9543, $result->ticketsSold); + } + + /** + * @runInSeparateProcess + * @preserveGlobalState disabled + */ + public function testModelUpdateFluent(): void + { + require_once __DIR__ . '/Concert.php'; + Concert::truncate(); + + // insert the model + Concert::create([ + 'performer' => 'Brad Mehldau', + 'venue' => 'Philharmonie de Paris', + 'genres' => [ 'jazz', 'post-bop' ], + 'ticketsSold' => 5745, + 'performanceDate' => new UTCDateTime(Carbon::create(2025, 2, 12, 20, 0, 0, 'CET')), + ]); + + // begin model update one fluent + $concert = Concert::where(['performer' => 'Brad Mehldau']) + ->orderBy('_id') + ->first() + ->update(['venue' => 'Manchester Arena', 'ticketsSold' => 9543]); + // end model update one fluent + + $result = Concert::first(); + $this->assertInstanceOf(Concert::class, $result); + + $this->assertNotNull($result); + $this->assertEquals('Manchester Arena', $result->venue); + $this->assertEquals('Brad Mehldau', $result->performer); + $this->assertEquals(9543, $result->ticketsSold); + } + + /** + * @runInSeparateProcess + * @preserveGlobalState disabled + */ + public function testModelUpdateMultiple(): void + { + require_once __DIR__ . '/Concert.php'; + Concert::truncate(); + + // insert the model + Concert::create([ + 'performer' => 'Brad Mehldau', + 'venue' => 'Philharmonie de Paris', + 'genres' => [ 'jazz', 'post-bop' ], + 'ticketsSold' => 5745, + 'performanceDate' => new UTCDateTime(Carbon::create(2025, 2, 12, 20, 0, 0, 'CET')), + ]); + + Concert::create([ + 'performer' => 'The Rolling Stones', + 'venue' => 'Soldier Field', + 'genres' => [ 'rock', 'pop', 'blues' ], + 'ticketsSold' => 59527, + 'performanceDate' => Carbon::create(2024, 6, 30, 20, 0, 0, 'CDT'), + ]); + // begin model update multiple + Concert::whereIn('venue', ['Philharmonie de Paris', 'Soldier Field']) + ->update(['venue' => 'Concertgebouw', 'ticketsSold' => 0]); + // end model update multiple + + $results = Concert::get(); + + foreach ($results as $result) { + $this->assertInstanceOf(Concert::class, $result); + + $this->assertNotNull($result); + $this->assertEquals('Concertgebouw', $result->venue); + $this->assertEquals(0, $result->ticketsSold); + } + } }