0

Currently working with Symfony 5.2

I am trying to create a dynamic route for multiple enties which have mostly same properties (some still have other fields too, but all have the same default properties).

Example (minified)

Entity News:
- id, title, author

Entity Event:
- id, title, author

I am now trying to create a dynamic route to fetch News or Events from my the repository.

class ContentController extends AbstractController {
    
    /**
     * @Route("/{type}", name="get_content")
     */
    public function get(string $type) {  //type is the name of the entity e.g.   'news'   or   'event'
        //fetch from repo
        $results = $this->getDoctrine()->getRepository(/* entity class */)->findAll();
    }
}

I already came up with some ideas, but not sure if they are good practise.

1) use full namespace for the entity (how do I check if the class exists? error handling?)
$results = $this->getDoctrine()->getRepository('App\\Entity\\News')->findAll();
$results = $this->getDoctrine()->getRepository('App\\Entity\\' . ucfirst($type))->findAll();



2) provide a route for each entity and call a generic function (not exactly what I want because I have like 10+ entities for this)

class ContentController extends AbstractController {
    
    /**
     * @Route("/news", name="get_news")
     */
    public function get_news() {
        $results = getContent(News::class);
    }

    /**
     * @Route("/event", name="get_event")
     */
    public function get_event() { 
        $results = getContent(Event::class);
    }


    public function getContent($class) {
        return $this->getDoctrine()->getRepository($class)->findAll();
    }
}

Mabye some of you have better ideas/improvements and can help me out a bit.

Syllz
  • 290
  • 6
  • 22
  • 1
    For your first case, see how to [test if a class exists](https://stackoverflow.com/questions/37971997/in-php-how-can-i-check-if-class-exists). Also, don't manually build the full namespace, use the [`::class`](https://stackoverflow.com/questions/30770148/what-is-class-in-php) feature. With these tools, that case seems viable. All that is left is for you to decide what you want to display to the user when the parameter doesn't match an existing class. – El_Vanja Mar 04 '21 at 10:35
  • @El_Vanja ty for your quick anwser. How exactly can I use `::class` without using the full namespace? Do I have to add a `use` statement for every entity? Also I tried doing `$type::class` (since my entity name is inside the string) - but that seems not to be valid. I'll have a look in your links for validation tho. Thanks again :) – Syllz Mar 04 '21 at 10:49
  • 1
    Yes, add all of them through `use` statements. Don't avoid doing such things just because you may have many of them. A `use` statement signals that this code makes use of that class. – El_Vanja Mar 04 '21 at 10:52
  • 1
    I think you maybe over complicating things. Go with option 2 until you encounter a reason not to. And no need for getContent unless there is a lot more going on in there. Just inject the repository. And if you do decide to go with option 1 then just make a simple array mapping type to classname. – Cerad Mar 04 '21 at 12:55
  • thanks for all answers. @Cerad the code was just simplified to understand what I want. My getContent function is quite big and would be just duplicated code in every route - therefore the function :) The array mapping is a good idea - thanks! – Syllz Mar 05 '21 at 06:54

1 Answers1

1

You can define available for fetching entities manually.

class ContentController extends AbstractController
{
    /**
     * @Route("/{type}", name="get_content")
     */
    public function get(string $type)
    {  //type is the name of the entity e.g.   'news'   or   'event'
        //fetch from repo
        $results = $this->getDoctrine()->getRepository($this->getEntityClassFromType($type))->findAll();
    }

    private function getEntityClassFromType(string $type): string
    {
        //define your entities manually
        foreach ([News::class, Event::class] as $class) {
            $parts = explode('\\', $class);
            $entity = array_pop($parts);

            if ($type === lcfirst($entity)) {
                return $class;
            }
        }

        throw new NotFoundHttpException();
    }
}

Or check your entities dynamically using $entityManager->getMetadataFactory()->hasMetadataFor($className);

  • Thanks for your answer! That looks quite promising. I'll try to implement this one later :) – Syllz Mar 05 '21 at 06:58