Jaap Joop
Jaap Joop

Reputation: 23

Entity expected object returned symfony

I'm trying to get an item from the database and pass it to a new item to push to the database.

$post = $entityManager->getRepository('App:Post')
            ->find($id);

$comment->setPost($post)

the setPost looks like the following:

public function setPost(Post $post): self
    {
        $this->post = $post;

        return $this;
    }

and the $post variable:

 /**
     * @ORM\ManyToOne(targetEntity="App\Entity\Post", inversedBy="comments")
     * @ORM\JoinColumn(nullable=false)
     */
    private $post;

But when i try to set the post like setPost($post) it gives me the following error:

Expected parameter of type '\App\Entity\Post', 'object' provided

Upvotes: 1

Views: 1318

Answers (1)

Jakumi
Jakumi

Reputation: 8374

I assume, that the error you see is from your integrated developent environment (IDE), for example eclipse, vs code, phpstorm, and others. But the code - when actually executed - should work.

Now, the error most likely stems from a static code analysis running in the background of said IDE, which will look at the statement and trying to analyze according to the called methods, accessed properties etc. of which type your variables are.

So, let's do this slowly (and you can probably hover over the $vars and ->methods() do verify. The line I'm interested in is

$post = $entityManager->getRepository('App:Post')
            ->find($id);

so $entityManager is of type EntityManagerInterface, which has a getRepository method with one required parameter of type string ('App:Post' in your case), and it will return an object of type ObjectRepository, which has a method find which requires one parameter (mixed, don't ask), and returns ?object which means, an object or null. So, $post is of type object (best case, or null, in which case it would fail!). Now, the next line obviously expects a parameter of type Post and not of type object, thus the warning/notice/error.

Now, static code analysis is quite helpful up to a certain level, but it isn't infallible because it has limitations. It doesn't know what runtime will actually return, it just assumes that the type hints found in the code (of doctrine) are sufficiently specific - which they aren't in your case.

the easy fix

add a doc string to tell static code analysis what the variable $post's type actually is:

/** @var Post $post */
$post = $entityManager->getRepository('App:Post')
            ->find($id);

this explicitly tells the static analysis tool, that $post is of type Post, maybe you have to write App\Entity\Post or even \App\Entity\Post.

the hard fix

Alternatively, you could implement your own PostRepository (doctrine provides some help) and define a function like function findById($id) :Post - which would explicitly tell static code analysis, what the return type is when you call it in your code (injected in your function via dependency injection: PostRepostory $postRepository):

$post = $postRepository->findById($id);

If you're using lots and lots of different entities, this is a very verbose solution but depending on your project it might be worth it, since you explicitly name the dependencies instead of injecting the very unspecific (as we have seen) EntityManagerInterface. Using the EntityManagerInterface might make testing HELL (imho!).

Upvotes: 3

Related Questions