laravel / framework

The Laravel Framework.
https://laravel.com
MIT License
32.52k stars 11.02k forks source link

Morph type is integer #50691

Closed djlimix closed 7 months ago

djlimix commented 7 months ago

Laravel Version

10.48.3

PHP Version

8.2.16

Database Driver & Version

MySQL 8.2.0 on macOS Sonoma 14.3 (23E214) on M1 Mac 2020

Description

I'm using a package called asciisd/zoho-v3 to use Zoho CRM API. The issue is that morph type is sometimes an integer in some classes:

image

In order for it to be fixed, I had to change: vendor/laravel/framework/src/Illuminate/Database/Eloquent/Concerns/HasRelationships.php:771 from

return array_search(static::class, $morphMap, true);

to

return $morphMap[array_search(static::class, $morphMap, true)];

I can make an MR with this.

Steps To Reproduce

Honestly I don't know. I found it randomly with one specific model, which I can't show here publicly.

rojtjo commented 7 months ago

What does your MorphMap mapping look like?

driesvints commented 7 months ago

Please see https://github.com/laravel/framework/pull/50692

donnysim commented 7 months ago

Yeah, this seems more like a morph type is being registered incorrectly - most likely passed as an array - Relation::morphMap([MyClass::class]) instead of Relation::morphMap(['my-class' => MyClass::class])

edit: seems like without index it resolves to model table so this assumption is incorrect, which leads to something actually passing int as key withou 0 so it skips resolving model table names and just uses them as keys.

djlimix commented 7 months ago

@rojtjo

array:20 [▼ // vendor/laravel/framework/src/Illuminate/Database/Eloquent/Concerns/HasRelationships.php:769
  1 => "Redacted\Mod\Person\Model\Person"
  2 => "Redacted\Mod\Person\Model\Supplier"
  3 => "Redacted\Mod\Person\Model\Customer"
  4 => "Redacted\Mod\Person\Model\Company"
  5 => "Redacted\Mod\Orders\Model\Order"
  6 => "Redacted\Mod\Orders\Model\Orderitem"
  8 => "Redacted\Mod\Invoice\Model\Invoice"
  9 => "Redacted\Mod\Supplierinvoice\Model\Supplierinvoice"
  11 => "Redacted\Mod\Transaction\Model\Transaction"
  14 => "Redacted\Filesystem\Model\File"
  15 => "Redacted\Mod\Resource\Model\Resource"
  16 => "Redacted\Mod\Orders\Model\Supplieritem"
  17 => "Redacted\Comments\Model\Comment"
  18 => "Redacted\Mod\Device\Model\Device"
  19 => "Redacted\Mod\Device\Model\DeviceUser"
  20 => "Redacted\Mod\Employee\Model\Employee"
  21 => "Redacted\Mod\Contract\Model\Contract"
  22 => "Redacted\Mod\Orders\Model\Quote"
  23 => "Redacted\Mod\Invoice\Model\Taxconfirmation"
  24 => "Redacted\Authorization\Model\User"
]

and the relationship is registered this way:

public function zoho(): MorphOne
{
    return $this->morphOne(ZohoModel::class, 'zohoable');
}
donnysim commented 7 months ago

@djlimix it should look like:

[
  "user" => "App\User",
  "role" => "App\Role",
   // ...
]

I did not see asciisd/zoho-v3 registering any morph types so it should not be a culprit, which leads to your application or something else registering the types incorrectly.

rojtjo commented 7 months ago

Since the keys actually start at 1 it seems like the mapping is intentionally done with integers.

Looking at the screenshot and the morph map you posted it looks like the Contact model is just not registered in the morph map, that's why it returns the full class name there instead of the alias.

djlimix commented 7 months ago

jesus i'm dumb, overlooked part of code that registered MorphMap... Sorry for the inconvenience.