Audiophile
Audiophile

Reputation: 1060

How to inherit parent methods with annotation routing?

Using Symfony 3.4. Want to keep all functionality in parent abstract class, and just set the route prefixes in childs:

namespace AppBundle\Controller;

use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;

abstract class TaskAbstractController extends Controller
{

    /**
     * Lists all Task entities.
     *
     * @Route("/", name="tasks_index")
     * @Method("GET")
     */
    public function indexAction()
    {
        $em = $this->getDoctrine()->getManager();

        $tasks = $em->getRepository($this->getTargetClassName())->findAll();
        return $this->render('@App/' . $this->getPrefix() . '/index.html.twig', array(
            'tasks' => $tasks,
            'delete_forms' => $this->generateDeleteFormsViews($tasks)
        ));
    }

child:

/**
 * Daily task controller.
 *
 * @Route("daily_tasks")
 */
class DailyTaskController extends TaskAbstractController
{

   protected function getPrefix(): string
   {
       return 'daily_task';
   }

    protected function getTargetClassName(): string
    {
        return 'AppBundle:DailyTask';
    }
}

But I get "No route found for "GET /daily_tasks/"" . What's the problem? How to implement my idea? Don't want to duplicate every action with annotations in every child controller.

Upvotes: 3

Views: 1672

Answers (1)

colburton
colburton

Reputation: 4715

OK, since I have only this one example to go on, this looks like what your are trying to achieve:

class TaskAbstractController extends Controller
{
    /**
     * Lists all Task entities.
     *
     * @Route("/{prefix}", name="tasks_index", requirements={"prefix":"daily_task|add_some_more"})
     * @Method("GET")
     */
    public function indexAction($prefix)
    {
        $em = $this->getDoctrine()->getManager();

        /** @var TaskFactory $taskFactory */
        $taskFactory = $this->container->get('task_factory');
        $task        = $taskFactory->get($prefix);

        $tasks = $em->getRepository($task->getTargetClassName())->findAll();

        return $this->render('@App/'.$prefix.'/index.html.twig',
            [
                'tasks'        => $tasks,
                'delete_forms' => $this->generateDeleteFormsViews($tasks),
            ]);
    }
}

class TaskFactory
{
    public function get(string $prefix): TaskInterface
    {
        $map = [
            'daily_task' => DailyTask::class,
        ];

        if (isset($map[$prefix])) {
            return new $map[$prefix];
        }

        throw new \RuntimeException('task not found');
    }
}

interface TaskInterface
{
    public function getTargetClassName(): string;
}

Make the route dynamically and define all possible values as requirements. You had to do something similar anyway in your @Route() approach.

TaskFactory then decides what the child would be, based on that $prefix.

Upvotes: 3

Related Questions