Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit a4ac5fd

Browse files
Merge 4.6 into 4.7 (#3056)
2 parents 926aa7e + 4943bcc commit a4ac5fd

File tree

4 files changed

+190
-1
lines changed

4 files changed

+190
-1
lines changed

‎docs/eloquent-models/model-class.txt

Lines changed: 100 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,8 @@ to {+odm-short+} models:
3333
- :ref:`laravel-model-customize` explains several model class customizations.
3434
- :ref:`laravel-model-pruning` shows how to periodically remove models that
3535
you no longer need.
36+
- :ref:`laravel-schema-versioning` shows how to implement model schema
37+
versioning.
3638

3739
.. _laravel-model-define:
3840

@@ -67,7 +69,6 @@ This model is stored in the ``planets`` MongoDB collection.
6769
To learn how to specify the database name that your Laravel application uses,
6870
:ref:`laravel-quick-start-connect-to-mongodb`.
6971

70-
7172
.. _laravel-authenticatable-model:
7273

7374
Extend the Authenticatable Model
@@ -333,3 +334,101 @@ models that the prune action deletes:
333334
:emphasize-lines: 5,10,12
334335
:dedent:
335336

337+
.. _laravel-schema-versioning:
338+
339+
Create a Versioned Model Schema
340+
-------------------------------
341+
342+
You can implement a schema versioning pattern into your application by
343+
using the ``HasSchemaVersion`` trait on an Eloquent model. You might
344+
choose to implement a schema version to organize or standardize a
345+
collection that contains data with different schemas.
346+
347+
.. tip::
348+
349+
To learn more about schema versioning, see the :manual:`Model Data for
350+
Schema Versioning </tutorial/model-data-for-schema-versioning/>`
351+
tutorial in the {+server-docs-name+}.
352+
353+
To use this feature with models that use MongoDB as a database, add the
354+
``MongoDB\Laravel\Eloquent\HasSchemaVersion`` import to your model.
355+
Then, set the ``SCHEMA_VERSION`` constant to ``1`` to set the first
356+
schema version on your collection. If your collection evolves to contain
357+
multiple schemas, you can update the value of the ``SCHEMA_VERSION``
358+
constant in subsequent model classes.
359+
360+
When creating your model, you can define the ``migrateSchema()`` method
361+
to specify a migration to the current schema version upon retrieving a
362+
model. In this method, you can specify the changes to make to an older
363+
model to update it to match the current schema version.
364+
365+
When you save a model that does not have a schema version
366+
specified, the ``HasSchemaVersion`` trait assumes that it follows the
367+
latest schema version. When you retrieve a model that does not contain
368+
the ``schema_version`` field, the trait assumes that its schema version
369+
is ``0`` and performs the migration.
370+
371+
Schema Versioning Example
372+
~~~~~~~~~~~~~~~~~~~~~~~~~
373+
374+
In this sample situation, you are working with a collection that was
375+
first modeled by the following class:
376+
377+
.. literalinclude:: /includes/eloquent-models/PlanetSchemaVersion1.php
378+
:language: php
379+
:dedent:
380+
381+
Now, you want to implement a new schema version on the collection.
382+
You can define the new model class with the following behavior:
383+
384+
- Implements the ``HasSchemaVersion`` trait and sets the current
385+
``SCHEMA_VERSION`` to ``2``
386+
387+
- Defines the ``migrateSchema()`` method to migrate models in which the
388+
schema version is less than ``2`` to have a ``galaxy`` field that has a value
389+
of ``'Milky Way'``
390+
391+
.. literalinclude:: /includes/eloquent-models/PlanetSchemaVersion2.php
392+
:language: php
393+
:emphasize-lines: 10,12,20
394+
:dedent:
395+
396+
In the ``"WASP-39 b"`` document in the following code, the
397+
``schema_version`` field value is less than ``2``. When you retrieve the
398+
document, {+odm-short+} adds the ``galaxy`` field and updates the schema
399+
version to the current version, ``2``.
400+
401+
The ``"Saturn"`` document does not contain the ``schema_version`` field,
402+
so {+odm-short+} assigns it the current schema version upon saving.
403+
404+
Finally, the code retrieves the models from the collection to
405+
demonstrate the changes:
406+
407+
.. io-code-block::
408+
:copyable: true
409+
410+
.. input:: /includes/eloquent-models/SchemaVersionTest.php
411+
:language: php
412+
:dedent:
413+
:start-after: begin-schema-version
414+
:end-before: end-schema-version
415+
416+
.. output::
417+
:language: none
418+
:visible: false
419+
420+
[
421+
{
422+
"_id": ...,
423+
"name": "WASP-39 b",
424+
"type": "gas",
425+
"galaxy": "Milky Way",
426+
"schema_version": 2,
427+
},
428+
{
429+
"_id": ...,
430+
"name": "Saturn",
431+
"type": "gas",
432+
"schema_version": 2,
433+
}
434+
]
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
<?php
2+
3+
namespace App\Models;
4+
5+
use MongoDB\Laravel\Eloquent\Model;
6+
7+
class Planet extends Model
8+
{
9+
protected $fillable = ['name', 'type'];
10+
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
<?php
2+
3+
namespace App\Models;
4+
5+
use MongoDB\Laravel\Eloquent\HasSchemaVersion;
6+
use MongoDB\Laravel\Eloquent\Model;
7+
8+
class Planet extends Model
9+
{
10+
use HasSchemaVersion;
11+
12+
public const SCHEMA_VERSION = 2;
13+
14+
protected $fillable = ['name', 'type', 'galaxy'];
15+
16+
/**
17+
* Migrate documents with a lower schema version to the most current
18+
* schema when inserting new data or retrieving from the database.
19+
*/
20+
public function migrateSchema(int $fromVersion): void
21+
{
22+
if ($fromVersion < 2) {
23+
$this->galaxy = 'Milky Way';
24+
}
25+
}
26+
}
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace App\Tests;
6+
7+
use App\Models\Planet;
8+
use MongoDB\Laravel\Tests\TestCase;
9+
10+
class SchemaVersionTest extends TestCase
11+
{
12+
/**
13+
* @runInSeparateProcess
14+
* @preserveGlobalState disabled
15+
*/
16+
public function testSchemaVersion(): void
17+
{
18+
require_once __DIR__ . '/PlanetSchemaVersion2.php';
19+
20+
Planet::truncate();
21+
22+
// begin-schema-version
23+
// Simulates a document in the collection with schema version 1
24+
Planet::insert([
25+
[
26+
'name' => 'WASP-39 b',
27+
'type' => 'gas',
28+
'schema_version' => 1,
29+
],
30+
]);
31+
32+
// Saves a document with no specified schema version
33+
$saturn = Planet::create([
34+
'name' => 'Saturn',
35+
'type' => 'gas',
36+
]);
37+
38+
// Retrieves both models from the collection
39+
$planets = Planet::where('type', 'gas')
40+
->get();
41+
// end-schema-version
42+
43+
$this->assertCount(2, $planets);
44+
45+
$p1 = Planet::where('name', 'Saturn')->first();
46+
47+
$this->assertEquals(2, $p1->schema_version);
48+
49+
$p2 = Planet::where('name', 'WASP-39 b')->first();
50+
51+
$this->assertEquals(2, $p2->schema_version);
52+
$this->assertEquals('Milky Way', $p2->galaxy);
53+
}
54+
}

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /