quick icon indicating copy to clipboard operation
quick copied to clipboard

[Quick 7.2.0] Calling Getter Method on Relationship Throws Exception

Open homestar9 opened this issue 1 year ago • 1 comments

I encountered an issue when calling a getter method on a Quick entity relationship that throws the following exception: Value must be initialized before use.

How to replicate:

  1. Create a simple entity with a relationship that joins to the same table (simple hierarchy)
component
    extends="quick.models.BaseEntity"
    accessors="true"
    table="category"
{

    proprety name="id";
    property name="parentId";


    // RELATIONSHIPS

    function parent() {
        return belongsTo( "Category", "parentId", "id" ).withDefault();  // Return a new entity if no match found.
    }
	
}
  1. Now execute the following code in your handler of choice:
// Works!
prc.category = getInstance( "CategoryQ@cms" ).findOrFail( rc.id );
writeDump( var=prc.category.getParent().isLoaded() );

// Works!
prc.category = getInstance( "CategoryQ@cms" )
    .with( "parent" )
    .findOrFail( rc.id );

writeDump( var=prc.category.parent().get().isLoaded() );

// Throws Exception!
prc.category = getInstance( "CategoryQ@cms" )
    .with( "parent" )
    .findOrFail( rc.id );

writeDump( var=prc.category.getParent().isLoaded() ); // Value must be initialized before use.

If you initialize the Quick entity and eager load the relationship using the with() statement. If the relationship returns null (or a new entity because of withDefault() and then get the relationship using the get[relationship]() method, you will get an exception. However, calling the relationship using [relationship]().get() still works as expected.

Additional Info:

I opened up FusionReactor to see if I could figure out what was going on. What's interesting is that if the entity has a null/empty value for parentId, the with( "parent" ) statement never attempts a query. However, I suspect that it still caches the result somewhere so that the getter attempts to retrieve a null from the entity cache.

If you call parent().get(), Quick executes a query and then returns a new instance of the object.

I suspect the problem has to do with the eagerLoadRelation() method in QuickBuilder, but I'm not sure how to fix it. I believe it should respect the withDefault() property and cache the new entity.

homestar9 avatar Dec 15 '23 22:12 homestar9