0

I have one entity Photo and another PhotoNote ( 0 to 10 ) A photo can have note but can’t too

When I request a photo entity I get the following error

Entity of type 'App\Entity\PhotoNote' for IDs idPhoto(1737) was not found

Using this in my controller

$photo = $photoRepository->findOneBy(['idPhoto' => $idPhoto]);

// check if there is a note
$note = (null !== $photo->getPhotoNote() ? $photo->getPhotoNote()->getNotePhoto() : 0);

// Also tried following
//$note = (null !== $photo->getPhotoNote()->getNotePhoto() ? $photo->getPhotoNote()->getNotePhoto() : null);

/**
 * --> this throws the error : $photo->getPhotoNote()->getNotePhoto()
 */

And here is the dumping of $photo->getPhotoNote() in App\Entity\Photo :

Photo.php on line 443:
Proxies\__CG__\App\Entity\PhotoNote {#5710 ▼
  +__isInitialized__: false
  -idPhoto: 1737
  -notePhoto: null
   …2
}

Actually $photo->getPhotoNote() is not null, and photoNote is populated with the photoId. When using $photo->getPhotoNote()->getNotePhoto() doctrine generates the query to get the associated note, but that photo doesn’t have a note. Note is not mandatory.

What I want is ‘getPhotoNote’ returns null or even 0 but seems that one to one relation requires an existing id.

How to say to doctrine returns null ?

Class Photo {
    /**
     * @var int
     *
     * @ORM\Column(name="id_photo", type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    private $idPhoto.

    // some fields

    /**
     * @ORM\OneToOne(targetEntity=“App\Entity\PhotoNote”)
     * @ORM\JoinColumn(name="id_photo", referencedColumnName="id_photo", nullable=true)
     */
    private $photoNote;

    public function setPhotoNote(PhotoNote $photoNote = null)
    {
        $this->photoNote = $photoNote;

        return $this;
    }

    public function getPhotoNote()
    {
        return $this->photoNote;
    } 
}

Class PhotoNote {
    /**
     * @ORM\Id()     
     * @ORM\Column(name="id_photo", type="integer")
     */
    private $idPhoto;

    /**
     * @ORM\Column(name="note_photo", type="smallint")
     */
    private $notePhoto;

    public function getNotePhoto(): ?int
    {
        return $this->notePhoto;
    }

    public function setNotePhoto(int $notePhoto): self
    {
        $this->notePhoto = $notePhoto;

        return $this;
    }
}

Generated query :

SELECT
    t0.id_photo AS id_photo_1, 
    t0.note_photo AS note_photo_2
FROM 
    photo_note t0 
WHERE
    t0.id_photo = 1737;
akio
  • 851
  • 9
  • 29
  • Does your `PhotoNote` class really have just those properties or is this a simplified example? – El_Vanja Dec 04 '20 at 18:06
  • @El_Vanja only two fields on table so two properties. For legacy reasons I can’t change anything on the MySQL structure – akio Dec 04 '20 at 18:08
  • I see. Really unfortunate, because there is no reason for that to be a separate table. Have you tried adding the `referencedColumnName` explicitly (in the `JoinColumn` annotation)? – El_Vanja Dec 04 '20 at 18:17
  • Yes I did but I wrote the question on mobile that’s why snippet is as simplest as possible – akio Dec 04 '20 at 18:24
  • And I agree with that there is no reason that to be a separate table. Legacy projects are really nightmares – akio Dec 04 '20 at 18:26
  • Is `@ORM\OneToOne` only defined in `Photo`, not `PhotoNote`? – El_Vanja Dec 04 '20 at 18:29
  • Actually only on Photo but I tried an one to one bidirectional without success. Maybe I didn’t set it correctly – akio Dec 04 '20 at 18:37
  • See if [this](https://stackoverflow.com/a/43657190/4205384) helps clear out the issue. – El_Vanja Dec 04 '20 at 18:51
  • I will check this out ASAP and come back with feedback – akio Dec 04 '20 at 19:07
  • @El_Vanja [this](https://stackoverflow.com/questions/43654996/doctrine-one-to-one-unidirectional/43657190#43657190) involve that I need to add foreign key into Photo table but I can't or so I missunderstood the given solution.I also tried to set the generation strategy to NONE into PhotoNote. – akio Dec 05 '20 at 08:13
  • Yeah, I forgot you couldn't change the structure. I have no more ideas on how to make it work. You could instead make every photo have a note, by using an empty string note where no actual note was added (if you have control over display, where you can tell the app not to show the note if it's empty). – El_Vanja Dec 05 '20 at 10:39
  • I tried, see the updated question :) – akio Dec 05 '20 at 15:26
  • Of course, if you tried that, then you'd have to populate the database with the missing entries (add a row in photo note table for any photo that didn't have a note thus far). – El_Vanja Dec 05 '20 at 16:09
  • Can’t believe that something so easy to implement with pure sql is so hard to do using doctrine – akio Dec 05 '20 at 20:32
  • It's not hard with Doctrine. It's hard with legacy you can't change. – El_Vanja Dec 05 '20 at 20:33
  • I’m continuing to search a way there is necessarily a solution – akio Dec 05 '20 at 20:37

1 Answers1

0

For now the only way that I found is to not use a relationship between these two entities.

I get the photo’s note using the associated repository with something like

$note = $photoNoteRepo->findOneBy([
    'idPhoto' => $idPhoto
]);

if ( empty($note))
    $note = null;

I think it’s should be better with relation but I’m stuck with this issue.

This is a working workaround but it’s not answering the issue. Maybe someone here will give me a way to use the relationship.

EDIT

I found a way based on this

public function getPhotoNote()
{
    if ($this->photoNote instanceof \Doctrine\ORM\Proxy\Proxy) {
        try {
            $this->photoNote->__load();
        } catch (\Doctrine\ORM\EntityNotFoundException $e) {
            return null;
        }
    }

    return $this->photoNote;
}

I have read something about doctrine's events especially postLoad event which seems cleaner but I did not implement it with success yet

akio
  • 851
  • 9
  • 29