Null-object error in spl_object_hash() when loading associations with association-keys #6811

Open
opened 2026-01-22 15:39:13 +01:00 by admin · 5 comments
Owner

Originally created by @AlexanderDahmen on GitHub (Aug 18, 2021).

Bug Report

Q A
BC Break (?)
Version 2.9.2

Summary

In an entity with foreign identity (using association-key="true"), having a many-to-many association with fetch="EAGER" results in the following error message:

spl_object_hash(): Argument # 1 ($object) must be of type object, null given

Current behavior

When using lazy many-to-one association mappings with Entity classes that contain eager many-to-many associations, loading these entities will cause an internal error with the EntityManager trying to hash an object.

A screenshot of the partial stack-trace is attached:
grafik

How to reproduce

Given a table schema like:

create table "first" (
  "id" uuid,
  primary key ("id")
);

create table "second" (
  "first_id" uuid references "first" ("id") on delete cascade,
  primary key ("first_id")
);

create table "third" (
  "id" uuid,
  primary key ("id")
);

create table "second_third" (
  "second_id" uuid references "second" ("first_id") on delete cascade,
  "third_id" uuid references "third" ("id") on delete cascade,
  primary key ("second_id", "third_id"),
  unique ("third_id")
);

Entity classes are defined as:

<?php
use Doctrine\Common\Collections\Collection;

class First {
  private string $id;
  private Collection $second;
}

class Second {
  private First $first;
  private Collection $third;
}

class Third {
  private string $id;
}

With an ORM XML mapping like:

<doctrine-mapping>
  <entity name="First" table="first">
    <id name="id" column="id" type="guid"/>
    <one-to-many field="second" target-entity="Second" mapped-by="first" fetch="EXTRA_LAZY" orphan-removal="true">
      <cascade><cascade-all/></cascade>
    </one-to-many>
  </entity>

  <entity name="Second" table="second">
    <id name="first" association-key="true"/>
    <many-to-one field="first" target-entity="First" inversed-by="second" fetch="EAGER">
      <join-column name="first_id" referenced-column-name="id" unique="true" nullable="false" on-delete="CASCADE"/>
    </many-to-one>
    <many-to-many field="third" target-entity="Third" fetch="EAGER">
      <join-table name="second_third">
        <join-columns>
          <join-column name="second_id" referenced-column-name="first_id" unique="false" nullable="false" on-delete="CASCADE"/>
        </join-columns>
        <inverse-join-columns>
          <join-column name="third_id" referenced-column-name="id" unique="true" nullable="false" on-delete="CASCADE"/>
        </inverse-join-columns>
      </join-table>
    </many-to-many>
  </entity>

  <entity name="Third" table="third">
    <id name="id" column="id" type="guid"/>
  </entity>
</doctrine-mapping>

Trying to initialize the collection First::$second by accessing elements will result in the above mentioned error.
As far as I can tell, this is caused by the EntityManager trying to hash the key of Second, which is $first, but the association is not yet loaded when initializing the $third Collection.

(This is an anonymized transcript of the production code causing the issue, if the reproduction does not work, please tell and I will revise the example.)

Expected behavior

The expectation is for the foreign collection to be loaded correctly.

Currently, only fetch="LAZY" works for loading the associations.

Originally created by @AlexanderDahmen on GitHub (Aug 18, 2021). ### Bug Report <!-- Fill in the relevant information below to help triage your issue. --> | Q | A |------------ | ------ | BC Break | (?) | Version | 2.9.2 #### Summary <!-- Provide a summary describing the problem you are experiencing. --> In an entity with foreign identity (using `association-key="true"`), having a many-to-many association with `fetch="EAGER"` results in the following error message: > spl_object_hash(): Argument # 1 ($object) must be of type object, null given #### Current behavior <!-- What is the current (buggy) behavior? --> When using lazy many-to-one association mappings with Entity classes that contain eager many-to-many associations, loading these entities will cause an internal error with the EntityManager trying to hash an object. A screenshot of the partial stack-trace is attached: ![grafik](https://user-images.githubusercontent.com/35454906/129912052-09730891-6936-48f2-a6d7-77c08f86d0c3.png) #### How to reproduce <!-- Provide steps to reproduce the bug. If possible, also add a code snippet with relevant configuration, entity mappings, DQL etc. Adding a failing Unit or Functional Test would help us a lot - you can submit one in a Pull Request separately, referencing this bug report. --> Given a table schema like: ```sql create table "first" ( "id" uuid, primary key ("id") ); create table "second" ( "first_id" uuid references "first" ("id") on delete cascade, primary key ("first_id") ); create table "third" ( "id" uuid, primary key ("id") ); create table "second_third" ( "second_id" uuid references "second" ("first_id") on delete cascade, "third_id" uuid references "third" ("id") on delete cascade, primary key ("second_id", "third_id"), unique ("third_id") ); ``` Entity classes are defined as: ```php <?php use Doctrine\Common\Collections\Collection; class First { private string $id; private Collection $second; } class Second { private First $first; private Collection $third; } class Third { private string $id; } ``` With an ORM XML mapping like: ```xml <doctrine-mapping> <entity name="First" table="first"> <id name="id" column="id" type="guid"/> <one-to-many field="second" target-entity="Second" mapped-by="first" fetch="EXTRA_LAZY" orphan-removal="true"> <cascade><cascade-all/></cascade> </one-to-many> </entity> <entity name="Second" table="second"> <id name="first" association-key="true"/> <many-to-one field="first" target-entity="First" inversed-by="second" fetch="EAGER"> <join-column name="first_id" referenced-column-name="id" unique="true" nullable="false" on-delete="CASCADE"/> </many-to-one> <many-to-many field="third" target-entity="Third" fetch="EAGER"> <join-table name="second_third"> <join-columns> <join-column name="second_id" referenced-column-name="first_id" unique="false" nullable="false" on-delete="CASCADE"/> </join-columns> <inverse-join-columns> <join-column name="third_id" referenced-column-name="id" unique="true" nullable="false" on-delete="CASCADE"/> </inverse-join-columns> </join-table> </many-to-many> </entity> <entity name="Third" table="third"> <id name="id" column="id" type="guid"/> </entity> </doctrine-mapping> ``` Trying to initialize the collection `First::$second` by accessing elements will result in the above mentioned error. As far as I can tell, this is caused by the EntityManager trying to hash the key of `Second`, which is `$first`, but the association is not yet loaded when initializing the `$third` Collection. (This is an anonymized transcript of the production code causing the issue, if the reproduction does not work, please tell and I will revise the example.) #### Expected behavior <!-- What was the expected (correct) behavior? --> The expectation is for the foreign collection to be loaded correctly. Currently, only `fetch="LAZY"` works for loading the associations.
Author
Owner

@greg0ire commented on GitHub (Aug 18, 2021):

Possible next steps:

  • check if this still exists in 2.9.4
  • create a failing test case from the example above
  • find out the value of $field in BasicEntityPersister on line 1011
@greg0ire commented on GitHub (Aug 18, 2021): Possible next steps: - [x] check if this still exists in 2.9.4 - [x] create a failing test case from the example above - [x] find out the value of `$field` in `BasicEntityPersister` on line 1011
Author
Owner

@greg0ire commented on GitHub (Aug 18, 2021):

@AlexanderDahmen what piece of code should I write inside testIssue to reproduce the issue: e6976436b3 ? Please send a PR to my fork.

@greg0ire commented on GitHub (Aug 18, 2021): @AlexanderDahmen what piece of code should I write inside `testIssue` to reproduce the issue: https://github.com/greg0ire/doctrine-orm/commit/e6976436b35b75bf8c90c10e3936096282e50289 ? Please send a PR to my fork.
Author
Owner

@AlexanderDahmen commented on GitHub (Aug 18, 2021):

@greg0ire Created a fork and pull request with a test case reproducing the error: https://github.com/greg0ire/doctrine-orm/pull/4
Thank you for looking into this.

@AlexanderDahmen commented on GitHub (Aug 18, 2021): @greg0ire Created a fork and pull request with a test case reproducing the error: https://github.com/greg0ire/doctrine-orm/pull/4 Thank you for looking into this.
Author
Owner

@greg0ire commented on GitHub (Aug 19, 2021):

I pushed another commit with a better error handling. It reveals that the field with an issue is Second::$first. I think this happens because there is an attempt to load $third while assuming that $first was loaded, well, first.

@greg0ire commented on GitHub (Aug 19, 2021): I pushed another commit with a better error handling. It reveals that the field with an issue is `Second::$first`. I think this happens because there is an attempt to load `$third` while assuming that `$first` was loaded, well, first.
Author
Owner

@Feolius commented on GitHub (Apr 27, 2022):

I have created a pull request https://github.com/doctrine/orm/pull/9680 to solve this issue.

@Feolius commented on GitHub (Apr 27, 2022): I have created a pull request https://github.com/doctrine/orm/pull/9680 to solve this issue.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: doctrine/archived-orm#6811