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

Call to an undefined method Sylius\Component\Core\Repository\*::findOneBy*() and other magic methods #576

Open
vasilvestre opened this issue Jun 17, 2024 · 4 comments

Comments

@vasilvestre
Copy link

vasilvestre commented Jun 17, 2024

On any released version of Sylius-Standard, I couldn't get phpstan-doctrine to work.

Full error :

Call to an undefined method Sylius\Component\Core\Repository\OrderRepositoryInterface::findOneByThing().  

Here's a minimal reproducer :

<?php

namespace App\Controller;

use Sylius\Component\Core\Repository\OrderRepositoryInterface;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Attribute\Route;

class GrumpyGnomeController extends AbstractController
{
    public function __construct(
        private readonly OrderRepositoryInterface $orderRepository,
    )
    {
    }

    #[Route('/grumpy/gnome', name: 'app_grumpy_gnome')]
    public function index(): Response
    {
        $a = $this->orderRepository->findOneByThing();
        return $this->render('grumpy_gnome/index.html.twig', [
            'controller_name' => 'GrumpyGnomeController',
        ]);
    }
}


use Sylius\Component\Order\Repository\OrderRepositoryInterface as BaseOrderRepositoryInterface;
/**
 * @template T of OrderInterface
 *
 * @extends BaseOrderRepositoryInterface<T>
 */
interface OrderRepositoryInterface extends BaseOrderRepositoryInterface


use Sylius\Component\Resource\Repository\RepositoryInterface;
/**
 * @template T of OrderInterface
 *
 * @extends RepositoryInterface<T>
 */
interface OrderRepositoryInterface extends RepositoryInterface


use Doctrine\Persistence\ObjectRepository;
/**
 * @template T of ResourceInterface
 *
 * @extends ObjectRepository<T>
 */
interface RepositoryInterface extends ObjectRepository

/**
 * Contract for a Doctrine persistence layer ObjectRepository class to implement.
 *
 * @template-covariant T of object
 */
interface ObjectRepository

phpstan.neon

includes:
    - vendor/phpstan/phpstan-doctrine/extension.neon

parameters:
    level: 4
    paths:
        - src
    doctrine:
        ormRepositoryClass: Sylius\Component\Resource\Repository\RepositoryInterface
        objectManagerLoader: tests/object-manager.php

I've configured an object-manager.php test just in case and it doesn't improve the detection.

Sylius do not use ServerEntityManager

@vasilvestre vasilvestre changed the title Call to an undefined method Sylius\Component\Core\Repository\OrderRepositoryInterface::findOneByThing(). Call to an undefined method Sylius\Component\Core\Repository\*::findOneByThing(). Jun 17, 2024
@vasilvestre vasilvestre changed the title Call to an undefined method Sylius\Component\Core\Repository\*::findOneByThing(). Call to an undefined method Sylius\Component\Core\Repository\*::findOneBy*() and other magic methods Jun 17, 2024
@ondrejmirtes
Copy link
Member

You can check this by running PHPStan with Xdebug and seeing where it ends in EntityRepositoryClassReflectionExtension but in my opinion this can only work if OrderInterface is an entity and has a field named $thing. Which it probably isn't because interfaces can't declare properties.

@vasilvestre
Copy link
Author

vasilvestre commented Jun 19, 2024

foreach ($entityClassNames as $entityClassName) {

In this line, entityClassNames is empty.

Here's the value of $templateTypeMap :

PHPStan\Type\Generic\TemplateTypeMap {#22787                                                                              
-types: array:1 [
"TEntityClass" => PHPStan\Type\ObjectWithoutClassType {#13595                                                         
-subtractedType: null                                                                                               
}                                                                                                                     
]                                                                                                                       
-lowerBoundTypes: []
-resolvedToBounds: null                                                                                                 
}

$entityClassType :

PHPStan\Type\ObjectWithoutClassType {#13595                                                                               
	-subtractedType: null                                                                                                   
 }     

$entityClassNames is an empty array and field name is fine. (I've changed to "name" because name exists on the order entity).

I've changed the repository to use my entity instead of the interface, the error and data previously shared is the same.

/**
 * @template T of Order
 *
 * @extends BaseOrderRepositoryInterface<T>
 */
interface OrderRepositoryInterface extends BaseOrderRepositoryInterface

@vasilvestre
Copy link
Author

I got it to work by modifying these.

Whatever I change in phpdoc of Sylius\Component\Core\Repository\OrderRepositoryInterface has no effect.

/**
 * @template T of OrderInterface
 *
 * @extends BaseOrderRepositoryInterface<T>
 */
interface OrderRepositoryInterface extends BaseOrderRepositoryInterface

Modifying type in @template had no effect
Sylius\Component\Order\Repository\OrderRepositoryInterface

/**
 * @template T of Order
 *
 * @extends RepositoryInterface<T>
 */
interface OrderRepositoryInterface extends RepositoryInterface

Dropping @template and using my own entity works here
Sylius\Component\Order\Repository\OrderRepositoryInterface

use App\Entity\Order\Order;

/**
 * @extends RepositoryInterface<Order>
 */
interface OrderRepositoryInterface extends RepositoryInterface

@vasilvestre
Copy link
Author

vasilvestre commented Jun 19, 2024

And finally for a clean solution :

Following this tutorial : https://docs.sylius.com/en/1.12/customization/repository.html

App\Repository\OrderRepositoryInterface

<?php

declare(strict_types=1);

namespace App\Repository;

use App\Entity\Order\Order;
use Sylius\Component\Core\Repository\OrderRepositoryInterface as BaseOrderRepositoryInterface;

/**
 * @extends BaseOrderRepositoryInterface<Order>
 */
interface OrderRepositoryInterface extends \Sylius\Component\Core\Repository\OrderRepositoryInterface
{
}

The doctrine configuration is required :

parameters:
    doctrine:
        objectManagerLoader: tests/object-manager.php

This only work for Sylius 1.13+. There was no template phpdoc before. Maybe the @extends with ObjectManager would work

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

2 participants