Improve MappingException message #6149

Open
opened 2026-01-22 15:27:45 +01:00 by admin · 6 comments
Owner

Originally created by @BonBonSlick on GitHub (Dec 29, 2018).

Feature Request

Q A
New Feature yes
RFC yes
BC Break no

Summary

I have spent some time to figure out why this exception was thrown because mapping files and calsses exist. Hard to track why and where(what mapping) exception was thrown.

  /**
    * @param string $className
    * @param string $fieldName
    *
    * @return MappingException
    */
   public static function mappingNotFound($className, $fieldName)
   {
       return new self("No mapping found for field '$fieldName' on class '$className'.");
   }

thrown in

    /**
     * Gets the mapping of a (regular) field that holds some data but not a
     * reference to another object.
     *
     * @param string $fieldName The field name.
     *
     * @return array The field mapping.
     *
     * @throws MappingException
     */
    public function getFieldMapping($fieldName)
    {
        if ( ! isset($this->fieldMappings[$fieldName])) {
       dump($this->fieldMappings);
        dump($fieldName);
        dump($this->name);
         dump($this->fieldMappings[$fieldName]);
         die;
            throw MappingException::mappingNotFound($this->name, $fieldName);
        }

        return $this->fieldMappings[$fieldName];
    }

dump output

bonbon@debian:/var/www/test$ mdif
array:5 [
  "id.uuid" => array:8 [
    "id" => true
    "fieldName" => "id.uuid"
    "type" => "guid"
    "length" => "55"
    "columnName" => "uuid"
    "originalClass" => "App\Domain\AnimePack\Episode\ValueObject\EpisodeId"
    "declaredField" => "id"
    "originalField" => "uuid"
  ]
  "name.name" => array:7 [
    "fieldName" => "name.name"
    "unique" => true
    "type" => "string"
    "columnName" => "name"
    "originalClass" => "App\Domain\AnimePack\Episode\ValueObject\EpisodeName"
    "declaredField" => "name"
    "originalField" => "name"
  ]
]
"id"
"App\Domain\AnimePack\Episode\Entity\Episode"

In ClassMetadataInfo.php line 1235:
                               
  Notice: Undefined index: id  

As you can see

<embedded name="id" class="App\Domain\AnimePack\Episode\ValueObject\EpisodeId" use-column-prefix="false" />

Is mapped, class loaded, it is ok, but where id comes from? Why?

It really took a while, error logged this message, not much useful info.
I tried to remove mapping files which we have a lot, and find out that problem was in realtions mappings where we miss join column

was

    <!-- One To One-->
    <one-to-one field="details" target-entity="App\Domain\AnimePack\EpisodeDetails\Entity\EpisodeDetails"
                inversed-by="episode">
    </one-to-one>

must be

    <!-- One To One-->
    <one-to-one field="details" target-entity="App\Domain\AnimePack\EpisodeDetails\Entity\EpisodeDetails"
                inversed-by="episode">
      <join-column name="details_uuid" referenced-column-name="uuid" /> // not ID but UUID
    </one-to-one>

As I figured out:
1 - join column was required
2 - because of embedded ids referenced-column-name must be uuid.

class EpisodeDetails{
  /**
   * @var EpisodeDetailsId
   */
  private $id; 
...
final class EpisodeDetailsId{
  /**
   * @var UuidInterface|string
   */
  protected $uuid;
}

It would be nice to throw exception with correct message that join column is missing for specified mapping.

EG

Join column is missing for OneToOne relations with entity App\Domain\AnimePack\EpisodeDetails\Entity\EpisodeDetails in mapping file App\Mapping\Episode.orm.xml

Error message and common, widespread used field ID confused a lot.

Thanks.

Originally created by @BonBonSlick on GitHub (Dec 29, 2018). ### Feature Request <!-- Fill in the relevant information below to help triage your issue. --> | Q | A |------------ | ------ | New Feature | yes | RFC | yes | BC Break | no #### Summary <!-- Provide a summary of the feature you would like to see implemented. --> I have spent some time to figure out why this exception was thrown because mapping files and calsses exist. Hard to track why and where(what mapping) exception was thrown. ``` /** * @param string $className * @param string $fieldName * * @return MappingException */ public static function mappingNotFound($className, $fieldName) { return new self("No mapping found for field '$fieldName' on class '$className'."); } ``` thrown in ``` /** * Gets the mapping of a (regular) field that holds some data but not a * reference to another object. * * @param string $fieldName The field name. * * @return array The field mapping. * * @throws MappingException */ public function getFieldMapping($fieldName) { if ( ! isset($this->fieldMappings[$fieldName])) { dump($this->fieldMappings); dump($fieldName); dump($this->name); dump($this->fieldMappings[$fieldName]); die; throw MappingException::mappingNotFound($this->name, $fieldName); } return $this->fieldMappings[$fieldName]; } ``` dump output ``` bonbon@debian:/var/www/test$ mdif array:5 [ "id.uuid" => array:8 [ "id" => true "fieldName" => "id.uuid" "type" => "guid" "length" => "55" "columnName" => "uuid" "originalClass" => "App\Domain\AnimePack\Episode\ValueObject\EpisodeId" "declaredField" => "id" "originalField" => "uuid" ] "name.name" => array:7 [ "fieldName" => "name.name" "unique" => true "type" => "string" "columnName" => "name" "originalClass" => "App\Domain\AnimePack\Episode\ValueObject\EpisodeName" "declaredField" => "name" "originalField" => "name" ] ] "id" "App\Domain\AnimePack\Episode\Entity\Episode" In ClassMetadataInfo.php line 1235: Notice: Undefined index: id ``` As you can see ` <embedded name="id" class="App\Domain\AnimePack\Episode\ValueObject\EpisodeId" use-column-prefix="false" />` Is mapped, class loaded, it is ok, but where id comes from? Why? It really took a while, error logged this message, not much useful info. I tried to remove mapping files which we have a lot, and find out that problem was in realtions mappings where we miss join column **was** ``` <!-- One To One--> <one-to-one field="details" target-entity="App\Domain\AnimePack\EpisodeDetails\Entity\EpisodeDetails" inversed-by="episode"> </one-to-one> ``` **must be** ``` <!-- One To One--> <one-to-one field="details" target-entity="App\Domain\AnimePack\EpisodeDetails\Entity\EpisodeDetails" inversed-by="episode"> <join-column name="details_uuid" referenced-column-name="uuid" /> // not ID but UUID </one-to-one> ``` As I figured out: 1 - join column was required 2 - because of embedded ids referenced-column-name must be uuid. ``` class EpisodeDetails{ /** * @var EpisodeDetailsId */ private $id; ... final class EpisodeDetailsId{ /** * @var UuidInterface|string */ protected $uuid; } ``` It would be nice to throw exception with correct message that join column is missing for specified mapping. EG > Join column is missing for OneToOne relations with entity App\Domain\AnimePack\EpisodeDetails\Entity\EpisodeDetails in mapping file App\Mapping\Episode.orm.xml Error message and common, widespread used field ID confused a lot. Thanks.
Author
Owner

@Ocramius commented on GitHub (Jan 2, 2019):

Could you make ab example of what is triggering the error? You've shown how it manifests, but not the userland code that leads to it.

If this is an attempt to use an @Embeddable as part of an @Id, I don't think that it ever worked before, not was implemented at all.

@Ocramius commented on GitHub (Jan 2, 2019): Could you make ab example of what is triggering the error? You've shown how it manifests, but not the userland code that leads to it. If this is an attempt to use an `@Embeddable` as part of an `@Id`, I don't think that it ever worked before, not was implemented at all.
Author
Owner

@BonBonSlick commented on GitHub (Jan 2, 2019):

Relation mapping triggering error. I should add join column, and UUID to reference not ID. UUID it is @Embeddable $id with parameter $uuid as you can see. But for other not relation @Embeddable fields we set name as it is $name and it is @Embeddable class.

@BonBonSlick commented on GitHub (Jan 2, 2019): Relation mapping triggering error. I should add join column, and UUID to reference not ID. UUID it is @Embeddable $id with parameter $uuid as you can see. But for other not relation @Embeddable fields we set name as it is $name and it is @Embeddable class.
Author
Owner

@Ocramius commented on GitHub (Jan 2, 2019):

@BonBonSlick that didn't come through very clear: can you please elaborate/rewrite that?

@Ocramius commented on GitHub (Jan 2, 2019): @BonBonSlick that didn't come through very clear: can you please elaborate/rewrite that?
Author
Owner

@BonBonSlick commented on GitHub (Jan 2, 2019):

2 entities, User and UserRole. xml mapping used.
Both of them has parameter $id which are @Embeddable.
This @Embeddable classes has own parameters $uuid.
Example UserId (@Embeddable points to User::$id)

class User{
/**
   * @var UserId
   */
private $id;
 ...

User @Embeddable $id

class UserId{
/**
   * @var string
   */
private $uuid;
...

Same has UserRole, UserRoleId.

Now, when we set up relation mapping with xml, by default referenced-column-name is ID
<join-column name="user_role"="uuid" /> // default reference column is UserRole::$id
To make it work we have to add
<join-column name="details_uuid" referenced-column-name="uuid" /> // not ID but UUID
We reference to @Embeddable class parameter, no original, related class. Referenced not UserRole::$id but to UserRoleId::$uuid parameter.

Exception says here that ID does not exists, which confusing.

@BonBonSlick commented on GitHub (Jan 2, 2019): 2 entities, User and UserRole. xml mapping used. Both of them has parameter $id which are `@Embeddable`. This `@Embeddable` classes has own parameters $uuid. Example UserId (`@Embeddable` points to `User::$id`) ``` class User{ /** * @var UserId */ private $id; ... ``` User @Embeddable $id ``` class UserId{ /** * @var string */ private $uuid; ... ``` Same has UserRole, UserRoleId. Now, when we set up relation mapping with xml, by default `referenced-column-name` is ID ```<join-column name="user_role"="uuid" /> // default reference column is UserRole::$id``` To make it work we have to add ```<join-column name="details_uuid" referenced-column-name="uuid" /> // not ID but UUID``` We reference to ```@Embeddable``` class parameter, no original, related class. Referenced not ```UserRole::$id``` but to ```UserRoleId::$uuid``` parameter. Exception says here that ID does not exists, which confusing.
Author
Owner

@Ocramius commented on GitHub (Jan 2, 2019):

All <join-column/> must reference identifiers though. Also, embeddable fields as identifiers are not really supported, as mentioned above.

@Ocramius commented on GitHub (Jan 2, 2019): All `<join-column/>` must reference identifiers though. Also, embeddable fields as identifiers are not really supported, as mentioned above.
Author
Owner

@BonBonSlick commented on GitHub (Jan 6, 2019):

But question is about improving exception message, I got it already

Also, embeddable fields as identifiers are not really supported, as mentioned above.

And made it work as it should be. Just letting you know that exception message was confusing. Someone else may run in the same situation. Maybe add or highlight such case in docs in relation mapping section would be nice.

@BonBonSlick commented on GitHub (Jan 6, 2019): But question is about improving exception message, I got it already > Also, embeddable fields as identifiers are not really supported, as mentioned above. And made it work as it should be. Just letting you know that exception message was confusing. Someone else may run in the same situation. Maybe add or highlight such case in docs in relation mapping section would be nice.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: doctrine/archived-orm#6149