kodeine / laravel-meta

Fluent Meta Data for Eloquent Models, as if it is a property on your model
MIT License
398 stars 89 forks source link

Meta exists in database but getMeta() returns an empty collection #100

Closed f4llenz closed 2 years ago

f4llenz commented 2 years ago

I'm having a weird issue where I set meta for my model inside a job so I can retrieve it from another job. It gets saved in the database, but it's not retrieved when using getMeta().

I set the meta inside a job like so:

$bot->setMeta('needapproval', (array) $needApproval);
$bot->save();

The meta exists:

❯ tinker
Psy Shell v0.11.8 (PHP 8.1.10 — cli) by Justin Hileman
>>> $b = Bot::with(['metas'])->get()->first();
[!] Aliasing 'Bot' to 'App\Models\Bot' for this Tinker session.
=> App\Models\Bot {#5814
     id: 1,
     name: "USDCWETH",
     user_id: 1,
     wallet_id: 1,
     current_side: "out",
     created_at: "2022-09-08 22:49:55",
     updated_at: "2022-09-08 22:49:55",
     metas: Illuminate\Database\Eloquent\Collection {#5839
       all: [
         Kodeine\Metable\MetaData {#5828
           id: 3,
           bot_id: 1,
           type: "array",
           key: "needapproval",
           value: "["0x07865c6E87B9F70255377e024ace6630C1Eaa37F","0xB4FBF271143F4FBf7B91A5ded31805e42b2208d6"]",
           created_at: "2022-09-08 22:54:03",
           updated_at: "2022-09-08 22:54:03",
         },
       ],
     },
   }

However the package doesn't retrieve it with getMeta():

>>> $b->getMeta()
=> Illuminate\Support\Collection {#5841
     all: [],
   }

>>> $b->getMeta('needapproval');
=> null

My bots_meta schema:

Schema::create('bots_meta', function (Blueprint $table) {
    $table->bigIncrements('id');

    $table->bigInteger('bot_id')->unsigned();
    $table->foreign('bot_id')->references('id')->on('bots')->onDelete('cascade');

    $table->string('type')->default('null');

    $table->string('key')->index();
    $table->text('value')->nullable();

    $table->timestamps();
});

The Bot model has the Metable trait.

Weirdly enough, if I do the same inside Tinker rather than inside an async job, it works fine. This only happens when I set the meta from an async job.

I'm using Postgres and Laravel Horizon. Any clues on how I can fix or debug this?

f4llenz commented 2 years ago

Update: It works as expected after I disabled fluency by adding protected bool $disableFluentMeta = true; to my model.

siamak2 commented 2 years ago

protected bool $disableFluentMeta = true; only affects fluent access like $bot->needapproval which you don't use it in this case. perhaps problem was from Postgres. I never worked with Postgres so I don't know how it works. this package includes tests with sqlite and this scenario: https://github.com/kodeine/laravel-meta/blob/ceeeb56c13d5e36ff89a9c8bd09894af0b5c1d08/tests/MetableTest.php#L223-L235 and all the test are passed.

bfiessinger commented 1 year ago

I currently struggle with a similar problem. As @f4llenz says getMeta returns an empty Collection unless disableFluentMeta is turned off. I can't really tell how turning this property off is making getMeta work again..

In my case the problem lies in the package spatie/laravel-model-states https://github.com/spatie/laravel-model-states/blob/main/src/HasStates.php#L24-L27 where it calls initializeHasStates. I did not find out yet how to keep this functionality and making getMeta work as expected.

siamak2 commented 1 year ago

@bfiessinger Please send laravel version, casts, mutators, accessors, the traits you're using on the model and all of laravel-meta related properties or methods. Also tell me how you set and get metas step by step, so I can reproduce this bug and hopefully find it.

bfiessinger commented 1 year ago

Hi @siamak2,

I've just created a PR with a working solution.