Skip to content

Commit 014c7f4

Browse files
author
Chris Cho
authored
DOCSP-35947: write operations modify documents (#2808)
* DOCSP-35948: Write operations - modify documents
1 parent 4459b55 commit 014c7f4

File tree

3 files changed

+254
-29
lines changed

3 files changed

+254
-29
lines changed

docs/fundamentals/write-operations.txt

Lines changed: 136 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ Write Operations
99
:values: tutorial
1010

1111
.. meta::
12-
:keywords: insert, insert one, update, update one, upsert, delete, delete many, code example, mass assignment, eloquent model
12+
:keywords: insert, insert one, code example, mass assignment, eloquent model
1313

1414
.. contents:: On this page
1515
:local:
@@ -27,28 +27,15 @@ inserting, updating, and deleting data based on specified criteria.
2727
This guide shows you how to perform the following tasks:
2828

2929
- :ref:`laravel-fundamentals-insert-documents`
30-
- Modify Documents
30+
- :ref:`laravel-fundamentals-modify-documents`
3131
- Delete Documents
3232

33-
.. _laravel-fundamentals-insert-documents:
34-
35-
Insert Documents
36-
----------------
37-
38-
In this section, you can learn how to insert documents into MongoDB collections
39-
from your Laravel application by using the {+odm-long+}.
40-
41-
When you insert the documents, ensure the data does not violate any
42-
unique indexes on the collection. When inserting the first document of a
43-
collection or creating a new collection, MongoDB automatically creates a
44-
unique index on the ``_id`` field.
33+
.. _laravel-fundamentals-write-sample-model:
4534

46-
For more information on creating indexes on MongoDB collections by using the
47-
Laravel schema builder, see the :ref:`laravel-eloquent-indexes` section
48-
of the Schema Builder documentation.
35+
Sample Model
36+
~~~~~~~~~~~~
4937

50-
This section uses the following example model class to demonstrate how to
51-
use Eloquent models to perform insert operations:
38+
The write operations in this guide reference the following Eloquent model class:
5239

5340
.. literalinclude:: /includes/fundamentals/write-operations/Concert.php
5441
:language: php
@@ -65,6 +52,23 @@ use Eloquent models to perform insert operations:
6552
data types. To learn more, see `Attribute Casting <https://laravel.com/docs/{+laravel-docs-version+}/eloquent-mutators#attribute-casting>`__
6653
in the Laravel documentation.
6754

55+
.. _laravel-fundamentals-insert-documents:
56+
57+
Insert Documents
58+
----------------
59+
60+
In this section, you can learn how to insert documents into MongoDB collections
61+
from your Laravel application by using the {+odm-long+}.
62+
63+
When you insert the documents, ensure the data does not violate any
64+
unique indexes on the collection. When inserting the first document of a
65+
collection or creating a new collection, MongoDB automatically creates a
66+
unique index on the ``_id`` field.
67+
68+
For more information on creating indexes on MongoDB collections by using the
69+
Laravel schema builder, see the :ref:`laravel-eloquent-indexes` section
70+
of the Schema Builder documentation.
71+
6872
To learn more about Eloquent models in {+odm-short+}, see the :ref:`laravel-eloquent-models`
6973
section.
7074

@@ -75,13 +79,16 @@ These examples show how to use the ``save()`` Eloquent method to insert an
7579
instance of a ``Concert`` model as a MongoDB document.
7680

7781
When the ``save()`` method succeeds, you can access the model instance on
78-
which you called the method. If the operation fails, the model instance is
79-
assigned ``null``.
82+
which you called the method.
83+
84+
If the operation fails, the model instance is assigned ``null``.
8085

8186
This example code performs the following actions:
8287

8388
- Creates a new instance of the ``Concert`` model
8489
- Assigns string values to the ``performer`` and ``venue`` fields
90+
- Assigns an array of strings to the ``genre`` field
91+
- Assigns a number to the ``ticketsSold`` field
8592
- Assigns a date to the ``performanceDate`` field by using the ``Carbon``
8693
package
8794
- Inserts the document by calling the ``save()`` method
@@ -93,7 +100,7 @@ This example code performs the following actions:
93100
:end-before: end model insert one
94101

95102
You can retrieve the inserted document's ``_id`` value by accessing the model's
96-
``id`` member as shown in the following code example:
103+
``id`` member, as shown in the following code example:
97104

98105
.. literalinclude:: /includes/fundamentals/write-operations/WriteOperationsTest.php
99106
:language: php
@@ -103,7 +110,7 @@ You can retrieve the inserted document's ``_id`` value by accessing the model's
103110

104111
If you enable mass assignment by defining either the ``$fillable`` or
105112
``$guarded`` attributes, you can use the Eloquent model ``create()`` method
106-
to perform the insert in a single call as shown in the following example:
113+
to perform the insert in a single call, as shown in the following example:
107114

108115
.. literalinclude:: /includes/fundamentals/write-operations/WriteOperationsTest.php
109116
:language: php
@@ -122,21 +129,122 @@ multiple instances of a ``Concert`` model as MongoDB documents. This bulk
122129
insert method reduces the number of calls your application needs to make
123130
to save the documents.
124131

125-
When the ``insert()`` method succeeds, it returns the value ``1``. If it
126-
fails, it throws an exception.
132+
133+
When the ``insert()`` method succeeds, it returns the value ``1``.
134+
135+
If it fails, it throws an exception.
127136

128137
The example code saves multiple models in a single call by passing them as
129138
an array to the ``insert()`` method:
130139

131140
.. note::
132141

133-
This example wraps the dates in the `MongoDB\BSON\UTCDateTime <{+phplib-api+}/class.mongodb-bson-utcdatetime.php>`__
134-
class to convert it to a type MongoDB can serialize because Laravel
135-
skips attribute casting on bulk insert operations.
142+
This example wraps the dates in the `MongoDB\\BSON\\UTCDateTime <{+phplib-api+}/class.mongodb-bson-utcdatetime.php>`__
143+
class to convert it to a type MongoDB can serialize because Laravel
144+
skips attribute casting on bulk insert operations.
136145

137146
.. literalinclude:: /includes/fundamentals/write-operations/WriteOperationsTest.php
138147
:language: php
139148
:dedent:
140149
:start-after: begin model insert many
141150
:end-before: end model insert many
142151

152+
.. _laravel-fundamentals-modify-documents:
153+
154+
Modify Documents
155+
----------------
156+
157+
In this section, you can learn how to modify documents in your MongoDB
158+
collection from your Laravel application. Use update operations to modify
159+
existing documents or to insert a document if none match the search criteria.
160+
161+
You can persist changes on an instance of an Eloquent model or use
162+
Eloquent's fluent syntax to chain an update operation on methods that
163+
return a Laravel collection object.
164+
165+
This section provides examples of the following update operations:
166+
167+
- :ref:`Update a document <laravel-modify-documents-update-one>`
168+
- :ref:`Update multiple documents <laravel-modify-documents-update-multiple>`
169+
170+
.. _laravel-modify-documents-update-one:
171+
172+
Update a Document Examples
173+
~~~~~~~~~~~~~~~~~~~~~~~~~~
174+
175+
You can update a document in the following ways:
176+
177+
- Modify an instance of the model and save the changes by calling the ``save()``
178+
method.
179+
- Chain methods to retrieve an instance of a model and perform updates on it
180+
by calling the ``update()`` method.
181+
182+
The following example shows how to update a document by modifying an instance
183+
of the model and calling its ``save()`` method:
184+
185+
.. literalinclude:: /includes/fundamentals/write-operations/WriteOperationsTest.php
186+
:language: php
187+
:dedent:
188+
:start-after: begin model update one save
189+
:end-before: end model update one save
190+
191+
When the ``save()`` method succeeds, the model instance on which you called the
192+
method contains the updated values.
193+
194+
If the operation fails, {+odm-short+} assigns the model instance a null value.
195+
196+
The following example shows how to update a document by chaining methods to
197+
retrieve and update the first matching document:
198+
199+
.. literalinclude:: /includes/fundamentals/write-operations/WriteOperationsTest.php
200+
:language: php
201+
:dedent:
202+
:start-after: begin model update one fluent
203+
:end-before: end model update one fluent
204+
205+
.. note::
206+
207+
The ``orderBy()`` call sorts the results by the ``_id`` field to
208+
guarantee a consistent sort order. To learn more about sorting in MongoDB,
209+
see the :manual:`Natural order </reference/glossary/#std-term-natural-order>`
210+
glossary entry in the {+server-docs-name+}.
211+
212+
When the ``update()`` method succeeds, the operation returns the number of
213+
documents updated.
214+
215+
If the retrieve part of the call does not match any documents, {+odm-short+}
216+
returns the following error:
217+
218+
.. code-block:: none
219+
:copyable: false
220+
221+
Error: Call to a member function update() on null
222+
223+
.. _laravel-modify-documents-update-multiple:
224+
225+
Update Multiple Documents Example
226+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
227+
228+
To perform an update on one or more documents, chain the ``update()``
229+
method to the results of a method that retrieves the documents as a
230+
Laravel collection object, such as ``where()``.
231+
232+
The following example shows how to chain calls to retrieve matching documents
233+
and update them:
234+
235+
.. literalinclude:: /includes/fundamentals/write-operations/WriteOperationsTest.php
236+
:language: php
237+
:dedent:
238+
:start-after: begin model update multiple
239+
:end-before: end model update multiple
240+
241+
When the ``update()`` method succeeds, the operation returns the number of
242+
documents updated.
243+
244+
If the retrieve part of the call does not match any documents in MongoDB,
245+
{+odm-short+} returns the following error:
246+
247+
.. code-block:: none
248+
:copyable: false
249+
250+
Error: Call to a member function update() on null

docs/includes/fundamentals/write-operations/Concert.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,6 @@
77
class Concert extends Model
88
{
99
protected $connection = 'mongodb';
10-
protected $fillable = ['performer', 'venue', 'performanceDate'];
10+
protected $fillable = ['performer', 'venue', 'genres', 'ticketsSold', 'performanceDate'];
1111
protected $casts = ['performanceDate' => 'datetime'];
1212
}

docs/includes/fundamentals/write-operations/WriteOperationsTest.php

Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@ public function testModelInsert(): void
2727
$concert = new Concert();
2828
$concert->performer = 'Mitsuko Uchida';
2929
$concert->venue = 'Carnegie Hall';
30+
$concert->genres = ['classical'];
31+
$concert->ticketsSold = 2121;
3032
$concert->performanceDate = Carbon::create(2024, 4, 1, 20, 0, 0, 'EST');
3133
$concert->save();
3234
// end model insert one
@@ -56,6 +58,8 @@ public function testModelInsertMassAssign(): void
5658
$insertResult = Concert::create([
5759
'performer' => 'The Rolling Stones',
5860
'venue' => 'Soldier Field',
61+
'genres' => [ 'rock', 'pop', 'blues' ],
62+
'ticketsSold' => 59527,
5963
'performanceDate' => Carbon::create(2024, 6, 30, 20, 0, 0, 'CDT'),
6064
]);
6165
// end model insert one mass assign
@@ -81,11 +85,15 @@ public function testModelInsertMany(): void
8185
[
8286
'performer' => 'Brad Mehldau',
8387
'venue' => 'Philharmonie de Paris',
88+
'genres' => [ 'jazz', 'post-bop' ],
89+
'ticketsSold' => 5745,
8490
'performanceDate' => new UTCDateTime(Carbon::create(2025, 2, 12, 20, 0, 0, 'CET')),
8591
],
8692
[
8793
'performer' => 'Billy Joel',
8894
'venue' => 'Madison Square Garden',
95+
'genres' => [ 'rock', 'soft rock', 'pop rock' ],
96+
'ticketsSold' => 12852,
8997
'performanceDate' => new UTCDateTime(Carbon::create(2025, 2, 12, 20, 0, 0, 'CET')),
9098
],
9199
];
@@ -97,4 +105,113 @@ public function testModelInsertMany(): void
97105

98106
$this->assertEquals(2, count($results));
99107
}
108+
109+
/**
110+
* @runInSeparateProcess
111+
* @preserveGlobalState disabled
112+
*/
113+
public function testModelUpdateSave(): void
114+
{
115+
require_once __DIR__ . '/Concert.php';
116+
Concert::truncate();
117+
118+
// insert the model
119+
Concert::create([
120+
'performer' => 'Brad Mehldau',
121+
'venue' => 'Philharmonie de Paris',
122+
'genres' => [ 'jazz', 'post-bop' ],
123+
'ticketsSold' => 5745,
124+
'performanceDate' => new UTCDateTime(Carbon::create(2025, 2, 12, 20, 0, 0, 'CET')),
125+
]);
126+
127+
// begin model update one save
128+
$concert = Concert::first();
129+
$concert->venue = 'Manchester Arena';
130+
$concert->ticketsSold = 9543;
131+
$concert->save();
132+
// end model update one save
133+
134+
$result = Concert::first();
135+
$this->assertInstanceOf(Concert::class, $result);
136+
137+
$this->assertNotNull($result);
138+
$this->assertEquals('Manchester Arena', $result->venue);
139+
$this->assertEquals('Brad Mehldau', $result->performer);
140+
$this->assertEquals(9543, $result->ticketsSold);
141+
}
142+
143+
/**
144+
* @runInSeparateProcess
145+
* @preserveGlobalState disabled
146+
*/
147+
public function testModelUpdateFluent(): void
148+
{
149+
require_once __DIR__ . '/Concert.php';
150+
Concert::truncate();
151+
152+
// insert the model
153+
Concert::create([
154+
'performer' => 'Brad Mehldau',
155+
'venue' => 'Philharmonie de Paris',
156+
'genres' => [ 'jazz', 'post-bop' ],
157+
'ticketsSold' => 5745,
158+
'performanceDate' => new UTCDateTime(Carbon::create(2025, 2, 12, 20, 0, 0, 'CET')),
159+
]);
160+
161+
// begin model update one fluent
162+
$concert = Concert::where(['performer' => 'Brad Mehldau'])
163+
->orderBy('_id')
164+
->first()
165+
->update(['venue' => 'Manchester Arena', 'ticketsSold' => 9543]);
166+
// end model update one fluent
167+
168+
$result = Concert::first();
169+
$this->assertInstanceOf(Concert::class, $result);
170+
171+
$this->assertNotNull($result);
172+
$this->assertEquals('Manchester Arena', $result->venue);
173+
$this->assertEquals('Brad Mehldau', $result->performer);
174+
$this->assertEquals(9543, $result->ticketsSold);
175+
}
176+
177+
/**
178+
* @runInSeparateProcess
179+
* @preserveGlobalState disabled
180+
*/
181+
public function testModelUpdateMultiple(): void
182+
{
183+
require_once __DIR__ . '/Concert.php';
184+
Concert::truncate();
185+
186+
// insert the model
187+
Concert::create([
188+
'performer' => 'Brad Mehldau',
189+
'venue' => 'Philharmonie de Paris',
190+
'genres' => [ 'jazz', 'post-bop' ],
191+
'ticketsSold' => 5745,
192+
'performanceDate' => new UTCDateTime(Carbon::create(2025, 2, 12, 20, 0, 0, 'CET')),
193+
]);
194+
195+
Concert::create([
196+
'performer' => 'The Rolling Stones',
197+
'venue' => 'Soldier Field',
198+
'genres' => [ 'rock', 'pop', 'blues' ],
199+
'ticketsSold' => 59527,
200+
'performanceDate' => Carbon::create(2024, 6, 30, 20, 0, 0, 'CDT'),
201+
]);
202+
// begin model update multiple
203+
Concert::whereIn('venue', ['Philharmonie de Paris', 'Soldier Field'])
204+
->update(['venue' => 'Concertgebouw', 'ticketsSold' => 0]);
205+
// end model update multiple
206+
207+
$results = Concert::get();
208+
209+
foreach ($results as $result) {
210+
$this->assertInstanceOf(Concert::class, $result);
211+
212+
$this->assertNotNull($result);
213+
$this->assertEquals('Concertgebouw', $result->venue);
214+
$this->assertEquals(0, $result->ticketsSold);
215+
}
216+
}
100217
}

0 commit comments

Comments
 (0)