laravel-mongodb - Issue #3549: In-memory model hydration bug masks id after Model::create()

XMLWordPrintableJSON

    • Type: Question
    • Resolution: Unresolved
    • Priority: Unknown
    • None
    • Affects Version/s: None
    • None
    • None
    • None
    • None
    • None
    • None

      ahmdadl has created Issue #3549: In-memory model hydration bug masks id after Model::create() in laravel-mongodb. This Jira ticket was filed by GromNaN

      Issue Text:

      • Laravel-mongodb Version: 5.8.2
      • PHP Version: 8.3 / 8.4
      • Database Driver & Version: MongoDB (Custom Connection Extension)

      Description:

      The integer `id` manually generated and assigned inside the `creating` model event works perfectly upon database insertion and subsequent retrieval via queries (e.g., `::find()`, `::first()`). However, *immediately following a `Model::create()` operation*, the returned in-memory model instance drops the custom integer `id` value when serialized via `toArray()`, replacing it with the auto-generated MongoDB hexadecimal `_id` string instead.

      Steps to reproduce

      1. Extend the database connection to map a custom Mongo connection handling integer primary keys in `AppServiceProvider`:
      ```php
      use Illuminate\Support\Facades\DB;

      DB::extend("mongodb", function ($config, $name) {
      $config["name"] = $name;
      return new CustomMongoConnection($config);
      });
      DB::purge("mongodb");
      ```

      2. Define the model targeting the custom primary key and hooks:
      ```php
      use MongoDB\Laravel\Eloquent\Model;

      class Request extends Model
      {
      protected $connection = 'mongodb';
      protected $primaryKey = 'id';
      protected $keyType = 'int';

      protected static function booted(): void
      {
      static::creating(function ($model) {
      $generateId = fn() => random_int(100000000, 999999999);
      $modelId = $generateId();

      if (!$model->id)

      { $model->id = $modelId; }

      $model->cid = $modelId;
      });
      }
      }
      ```

      3. Execute a `create()` command and compare the inline model output with a freshly queried document model instance:
      ```php
      $request = Request::create([]);
      dump($request->toArray());

      $fetchedRequest = Request::latest()->first();
      dd($fetchedRequest->toArray());
      ```

      Expected behaviour

      Both `toArray()` outputs should yield identical structures, retaining the assigned integer `id` attribute without mutating it post-save.

      ```php
      array:5 [
      "_id" => "6a5e0a40a3c1417750053505"
      "id" => 285028729
      "cid" => 285028729
      "updated_at" => "2026-07-20T11:45:04.368000Z"
      "created_at" => "2026-07-20T11:45:04.368000Z"
      ]
      ```

      Actual behaviour

      The model returned directly from `Request::create()` masks the integer `id` with the MongoDB `_id` string, while the fetched model displays the correct attributes:

      *Output 1: Freshly created instance (`dump($request->toArray());`)*
      ```php
      array:4 [
      "id" => "6a5e0a40a3c1417750053505" // BUG: Overwritten by MongoDB string _id, integer value lost in memory
      "cid" => 285028729
      "updated_at" => "2026-07-20T11:45:04.368000Z"
      "created_at" => "2026-07-20T11:45:04.368000Z"
      ]
      ```

      *Output 2: Freshly fetched from DB (`dd($fetchedRequest->toArray());`)*
      ```php
      array:5 [
      "_id" => "6a5e0a40a3c1417750053505"
      "id" => 285028729 // Works perfectly here!
      "cid" => 285028729
      "updated_at" => "2026-07-20T11:45:04.368000Z"
      "created_at" => "2026-07-20T11:45:04.368000Z"
      ]
      ```

      <details><summary><b>Logs</b>:</summary>
      No exception is thrown. The bug is limited to an inconsistent internal state mapping on the `Eloquent\Model` attribute dictionary immediately following a `save()` pipeline operation.
      </details>

              Assignee:
              Unassigned
              Reporter:
              TPM Jira Automations Bot
              Votes:
              0 Vote for this issue
              Watchers:
              1 Start watching this issue

                Created:
                Updated: