Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Related Objects not Hydrated at all despite fetch:EAGER #11203

Closed
craigh opened this issue Jan 31, 2024 · 4 comments
Closed

Related Objects not Hydrated at all despite fetch:EAGER #11203

craigh opened this issue Jan 31, 2024 · 4 comments

Comments

@craigh
Copy link

craigh commented Jan 31, 2024

Bug Report

Q A
BC Break maybe
Version 2.17.4

Summary

No matter how "EAGER" the query, I keep getting a proxy object.

Current behavior

I have a query like

        $qb = $this->createQueryBuilder('record')
            ->innerJoin('record.assignment', 'assignment')
            ->innerJoin('assignment.certification', 'certification')
            ->innerJoin('record.boardMember', 'board_member')
            ->select('record', 'assignment', 'certification', 'board_member');

        return $qb
            ->andWhere('certification.client = :client')
            ->setParameter('client', $client)
            ->orderBy('record.createdAt', 'DESC')
            ->addOrderBy('record.boardMember')
            ->getQuery()
            ->getResult();

The record object (obviously) has relations

    #[ORM\ManyToOne(fetch: 'EAGER')]
    #[ORM\JoinColumn(nullable: false)]
    private ?BoardMember $boardMember = null;

    #[ORM\ManyToOne(fetch: 'EAGER', inversedBy: 'records')]
    private ?CertificationAssignment $assignment = null;

If I run the query and dump the results

        $records = $recordRepository->findAllByClient($filterRequest);
        dd($records);

The BoardMember object in each Record object is a Proxy and that Proxy has NO VALUES. Additionally, the proxy doesn't fetch the values when they are called. The values are all simply unset.

Screenshot 2024-01-31 at 4 50 52 PM

I am using this via Symfony 6.4.3 and I have configured Symfony doctrine/doctrine-bundle 2.11.1 like so:

    orm:
        auto_generate_proxy_classes: true
        enable_lazy_ghost_objects: true
        report_fields_where_declared: true
        # other stuff...

I also tried

            ->setFetchMode(BoardMember::class, 'board_member', ClassMetadataInfo::FETCH_EAGER)

in the query, but that made no change.

I also tried

            ->getArrayResult();

instead of getResult and the arrays are fully hydrated correctly but I would prefer the objects...

This worked previously, with Symfony 5 ( I know you're not Symfony) but the enable_lazy_ghost_objects value changed for that from false to true so may be related. Changing this back to false does seem to fix my problem (Object is still a proxy but has needed values in it). But then I have the depreciation warnings again. So I'd like to fix the other problem...

Expected behavior

I expect the object to by fully hydrated since the fetch:EAGER property is set. I would also expect the Proxy to fetch the value if I called it.

@wmouwen
Copy link

wmouwen commented Feb 26, 2024

Loosely relates to #11185

@stof
Copy link
Member

stof commented Mar 6, 2024

If a proxy object already exists in the identity map of the ORM, you will still get it (even though it might be an initialized proxy at some point) because the identity map must only manage one object instance for each database id (by design), and it cannot replace it by a different one (as it does not have any way to replace the other references to that object in other entities already instantiated). That's why you might still get a proxy object

@craigh
Copy link
Author

craigh commented Mar 6, 2024

@stof are you saying that if I have two fetch actions for that entity, I might be creating a proxy in the first and then on the second fetch getting that same proxy instead of the fully hydrated object? (and thank you for answering, I still have not solved this)

@stof
Copy link
Member

stof commented Mar 7, 2024

@craigh the second fetch will indeed get the same object instance (whether it gets hydrated or no during the second fetch depends on the case).

@craigh craigh closed this as completed Mar 11, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants