skip to Main Content

I have a polymorphic relationship between an Article model and 3 models (Company, Group & User) that sometimes returns null.

90% of the time, the articleable relation is perfectly OK and looks like this:

#relations: array:1 [▼
    "articleable" => AppModelsUser {#1443 ▼
      #connection: "mysql"
      #table: "users"
      #primaryKey: "id"
      #keyType: "int"
      +incrementing: false
      #with: array:2 [▶]
      #withCount: []
      +preventsLazyLoading: false
      #perPage: 15
      +exists: true
      +wasRecentlyCreated: false
      #escapeWhenCastingToString: false
      #attributes: array:7 [▶]
      #original: array:7 [▶]
      #changes: []
      #casts: []
      #classCastCache: []
      #attributeCastCache: []
      #dates: array:1 [▶]
      #dateFormat: null
      #appends: array:1 [▶]
      #dispatchesEvents: []
      #observables: []
      #relations: array:2 [▶]
      #touches: []
      +timestamps: true
      #hidden: array:2 [▶]
      #visible: []
      #fillable: []
      #guarded: array:1 [▶]
      #rememberTokenName: "remember_token"
    }
  ]

But sometimes (1 / 10 ~), the relation is null:

#relations: array:1 [▼
    "articleable" => null
  ]

However, my model’s attribute seems perfectly fine:

  #attributes: array:8 [▼
    "id" => "e5db380f-9516-491f-bf5d-c13eb2978eac"
    "articleable_type" => "AppModelsUser" ←
    "articleable_id" => "20e00040-477b-44c5-800f-629a2380afe3" ←
    "title" => "Between yourself and me.' 'That's the most."
    "content" => "Alice. 'And ever since that,' the Hatter went on, spreading out the verses the White Rabbit interrupted: 'UNimportant, your Majesty means, of course,' the Mock  ▶"
    "image_url" => "https://via.placeholder.com/640x480.png/005511?text=non"
    "created_at" => "2022-07-27 11:51:01"
    "updated_at" => "2022-07-27 11:51:01"
  ]

And my DB does have the record (JSON export from my users table):

[
  {
    "id": "20e00040-477b-44c5-800f-629a2380afe3",
    "email": "[email protected]",
    "email_verified_at": "2022-07-27 11:51:01",
    "password": "$2y$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi",
    "remember_token": "3gRso464ST",
    "created_at": "2022-07-27 11:51:01",
    "updated_at": "2022-07-27 11:51:01"
  }
]

My models look like this:

User:

  AppModelsUser ..........................................
  Database ........................................... mysql
  Table .............................................. users

  Attributes ................................... type / cast
  id unique ..................................... string(36)
  email unique, fillable ....................... string(255)
  email_verified_at nullable, fillable . datetime / datetime
  password fillable, hidden .................... string(255)
  remember_token nullable, fillable, hidden .... string(100)
  created_at nullable, fillable ........ datetime / datetime
  updated_at nullable, fillable ........ datetime / datetime
  type appended .................................. attribute

  Relations ................................................
  profile HasOne .................... AppModelsUserProfile
  companies BelongsToMany ............... AppModelsCompany
  groups BelongsToMany .................... AppModelsGroup
  page MorphOne ............................ AppModelsPage
  articles MorphMany .................... AppModelsArticle
  notifications MorphMany  IlluminateNotificationsDatabaseNotification

Company:

  AppModelsCompany .......................................
  Database ........................................... mysql
  Table .......................................... companies

  Attributes ................................... type / cast
  id unique ..................................... string(36)
  name fillable ................................. string(60)
  description nullable, fillable ............... text(65535)
  created_at nullable, fillable ........ datetime / datetime
  updated_at nullable, fillable ........ datetime / datetime
  type appended .................................. attribute

  Relations ................................................
  page MorphOne ............................ AppModelsPage
  articles MorphMany .................... AppModelsArticle

Group:

  AppModelsGroup .........................................
  Database ........................................... mysql
  Table ............................................. groups

  Attributes ................................... type / cast
  id unique ..................................... string(36)
  name fillable ................................. string(60)
  description nullable, fillable ............... text(65535)
  created_at nullable, fillable ........ datetime / datetime
  updated_at nullable, fillable ........ datetime / datetime
  type appended .................................. attribute

  Relations ................................................
  page MorphOne ............................ AppModelsPage
  articles MorphMany .................... AppModelsArticle

These models use the following HasArticles Trait:

<?php

namespace AppModelsTraits;

use AppModelsArticle;
use IlluminateDatabaseEloquentRelationsMorphMany;

trait HasArticles
{
    /**
     * Return model's articles.
     *
     * @return MorphMany
     */
    public function articles(): MorphMany
    {
        return $this->morphMany(Article::class, 'articleable');
    }
}

Article

  AppModelsArticle .......................................
  Database ........................................... mysql
  Table ........................................... articles

  Attributes ................................... type / cast
  id unique ..................................... string(36)
  articleable_type fillable .................... string(255)
  articleable_id fillable ....................... string(36)
  title fillable ................................ string(70)
  content fillable .................................... text
  image_url nullable, fillable ................. string(255)
  created_at nullable, fillable ........ datetime / datetime
  updated_at nullable, fillable ........ datetime / datetime

  Relations ................................................

The Article model has the following MorphTo relationship:

public function articleable(): MorphTo
{
    return $this->morphTo(__FUNCTION__, 'articleable_type', 'articleable_id');
}

My create_articles_table migration (up Schema):

Schema::create('articles', function (Blueprint $table) {
    $table->uuid('id')->primary();
    $table->uuidMorphs('articleable');
    $table->string('title', '70');
    $table->longText('content');
    $table->string('image_url')->nullable();
    $table->timestamps();
});

I am debugging in a Controller using the following:

$articles = Article::query()
    ->with('articleable')
    ->inRandomOrder()
    ->first();

dd($articles, $articles->articleable?->toArray());

Am I missing something? Thanks for your help.

Env:

PHP: 8.1
Laravel: 9.22
Nginx
MariaDB 10.7.4

2

Answers


  1. Chosen as BEST ANSWER

    Turns out the solution was to not use Str::uuid() (which uses RamseyUuidUuid::uuid4()) to create my models' UUID, but to use RamseyUuidUuid::uuid6() instead. No more issues, everything works fine now.


  2. The problem is that you need to separate the first() method from the with(‘articleable’), i have chek up and it looks like modify the query in some way. Instead of with() use the load after that you have the result.

    $articles = Article::query()
        ->inRandomOrder()
        ->first();
    $articles->load('articleable');// try to add a check if $articles return null
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search