mongodb / laravel-mongodb

A MongoDB based Eloquent model and Query builder for Laravel (Moloquent)

Home Page:https://www.mongodb.com/compatibility/mongodb-laravel-integration

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

`createOrFirst` is not triggering `creating` nor `created` model events

prwnr opened this issue · comments

  • Laravel-mongodb Version: 4.3.0
  • Laravel version: 11.6.0
  • PHP Version: 8.2.2

Description:

There seem to be a problem, where using the createOrFirst builder method, that it does not trigger the creating or created model events when the model is being created (not retrieved, as there is no matching model found).

This seems to be caused by the fact that the createOrFirst method is overwritten in MongoDB package, but it is not calling the $model->save() method after an attempt to find the model, which would trigger those two events.

This is how it behaved in the past (I just upgraded from v3 to v4) and it is how it behaves in Laravel without MongoDB.

Steps to reproduce

  1. set up a simple Model class
  2. call Model::query()->createOrFirst() on it
  3. see that it won't trigger the creating and created event if it recently created the model (there was no matching model for the attributes)

This will however trigger the retrieving event instead - even if the model was recently created, but not actually "retrieved"

Expected behaviour

When a model is being created as a new one with use of createOrFirst method, it should trigger the creating and created model events.

Actual behaviour

When a model is being created as a new one with use of createOrFirst method, there is no creating nor created events dispatched.

Workaround

At the moment the only workaround I could think of is to manually try to fetch the model first with use of find/where query, and if its not found, create it with use of Model::query()->create() method, or $model->save() - which both will dispatch the creating and created events.

Hello, thanks for the feedback. I'm tracking it in Jira PHPORM-180

You are right that this events are not triggered because newModelInstance is used. It might be possible to explicitly trigger this events in MongoDB\Laravel\Eloquent::createOrFirst.

I'm curious, what do you do with these events?

Thank you @prwnr for putting this into better words than I was preparing until I saw your post 😅

I'm facing the same issue when using models that use another field than _id as primary key, like so:

<?php

declare(strict_types=1);

namespace App\Models;

use Illuminate\Database\Eloquent\Concerns\HasUuids;
use MongoDB\Laravel\Eloquent\Model as MongoDBModel;

abstract class UuidModel extends MongoDBModel
{
    use HasUuids;

    protected $primaryKey = 'id';

    public function uniqueIds()
    {
        return ['id'];
    }
}

or when using a trait

<?php

declare(strict_types=1);

namespace App\Models\Traits;

use Ramsey\Uuid\Uuid;

trait HasUuid
{
    public static function bootHasUuid(): void
    {
        static::creating(static function (self $model): void {
            // Automatically generate a UUID if using them, and not provided.
            if (empty($model->{$model->getKeyName()})) {
                $model->{$model->getKeyName()} = Uuid::uuid4()->toString();
            }
        });
    }
}

This stopped working with release 4.2, my current workaround is staying with release 4.1.3

@GromNaN We are using the creating event to set our tenancy fields, as we need them always set upon creation to prevent any model from being created without them. The creating event
appeared to be the best fit for this purpose in the lifecycle of a model when we wrote this code several years ago.

We also use it in a similar manner as @jeromegamez suggested, setting a UUID on the id field during creation.

I've also run some additional tests and I can see that saving and saved events are also not being triggered when using firstOrCreate method that was overwritten by MongoDB - however they are both being dispatched when using the regular create method.

This itself will also be causing problems with Sluggable package that we are using in our application, that relies on those two events.

Could you check this PR that should fix your issue: #2980

@GromNaN I'm sorry, but I'm failing to install your fork's branch, not sure why, but probably I am doing something wrong as Im installing fork for the first time.

Added your repo to repositories list as VCS and set package version to your branch "dev-PHPORM-180 as 4.3.0" and it can't find it Your requirements could not be resolved to an installable set of packages - tried some other variation of the branch name, or master branch, or changing repository type from VCS to git, but nothing works for me. Most likely some dumb thing I am missing.

I would have gone through the same process as you did. Alternatively, you can install from source

composer reinstall --prefer-source mongodb/laravel-mongodb

Add the remote:

cd vendor/mongodb/laravel-mongodb
git remote add gromnan https://github.com/GromNaN/laravel-mongodb-fork.git

And checkout the branch

git fetch gromnan
git checkout PHPORM-180

Fixed by #2984 in an other way.

Thank you @GromNaN! 🙏🏻