I have what must be a really minor problem that I just can't get my head around. I have a new blog with an index page (showing all articles), category pages, and the article page. It's all on Symfony 5.2.14, with twig etc.
I want to implement a simple 'subscribe now' sign up form (just capturing the visitors email address), which can be re-used on each page - the kind of "Subscribe now to get regular newsletters direct to your inbox" thing. Simple, right?
From a UX viewpoint I don't want to direct the user to complete this form on another stand-alone page, and I want to avoid using any popup modal etc.
I've tried following a few similar questions/answers on here and I cannot get it to work.
I've tried adding a POST method to the same controller/route as the index page - splitting the index page that fetches the articles into a GET method for display and a POST method for the form. It's not working, and comes back with an error that says the 'form' variable isn't valid when I try to 'include' the twig template for the form in the index page template - which suggests to me that basically the POST function/method isn't being called.
I've tried creating a separate controller + form + twig fragment template for the form, and then embedding it into the index page with: {{ render(controller('App\Controller\InsiderSubscribeController::subscribe')) }} it successfully displays the form on the page, but clicking the Subscribe button throws a "No route found for "POST /insider/": Method Not Allowed (Allow: GET)" error. In any case this seems like it wasn't going to work (I just got desperate and threw mud to the wall to see if anything would stick)
I tried following Thomas' approach How to create 2 actions with same path but different http methods Symfony2, but it doesn't work for me (yes, I know that's an old version of Symfony, but I coded it up for s5)
I tried xurshid29's answer here: Multiple Symfony Forms Added Accross Many Pages - and tried to create a twig extension, and still no joy
So here goes on what I have - at this point I have pulled everything back out into separate Controllers/Classes so I can sit back and try to review:
My Index Controller
/**
* @Route("/insider/news", name="insider_article_index", methods={"GET"})
*/
public function index(EntityManagerInterface $em, Request $request): Response
{
$insiderArticles = $this->getDoctrine()->getManager()
->getRepository(InsiderArticle::class)
->findAll();
// Get some repository of data, in our case we have an Insider entity
$insiderRepository = $em->getRepository(InsiderArticle::class);
// Find all the data on the Insider table, filter our query as we need
$allInsiderQuery = $insiderRepository->createQueryBuilder('i')
->where('i.featured = false')
->andWhere('i.promoted = false')
->andWhere("i.status LIKE '%Published%'")
->leftJoin('i.userpublished', 'au')
->getQuery();
/* @var $paginator \Knp\Component\Pager\Paginator */
$paginator = $this->paginator;
// Paginate the results of the query
$pagination = $paginator->paginate(
// Doctrine Query, not results
$allInsiderQuery,
// Define the page parameter
$request->query->getInt('page', 1),
// set the number of items per page
5
);
//dd($pagination);
// Render the twig view
return $this->render('insider_article/index.html.twig', [
'insider_articles' => $insiderArticles,
'pagination' => $pagination,
]);
}
My Subscribe controller
/**
* @Route("/", name="insider_article_subscribe", methods={"POST"})
*/
public function subscribe(Request $request): Response
{
$insidersubscriber = new InsiderSubscriber();
$form = $this->createForm(InsiderSubscribeType::class, $insidersubscriber);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$entityManager = $this->getDoctrine()->getManager();
$insidersubscriber->setActive(true);
$insidersubscriber->setDatecreated(new \DateTime());
$insidersubscriber->setEmailweekly(true);
$entityManager->persist($insidersubscriber);
$entityManager->flush();
return $this->redirectToRoute('insider_article_index'); //doing this for now until I get it working and return the result with Ajax or push a success message to the page
}
return $this->render('fragments/insider_public/_subscriber_form.html.twig',
[
'insider_subscriber' => $insidersubscriber,
'form' => $form->createView(),
]
);
}
My Form
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('email', EmailType::class, [
'required' => true,
'label' => false,
'attr' => [
'placeholder' => 'Enter your email address',
],
])
;
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults([
'data_class' => InsiderSubscriber::class,
]);
}
My Index page snippet
<div class="p-4">
{{ render(controller('App\\Controller\\InsiderSubscribeController::subscribe')) }}
</div>
My twig template for the form render
{{ form_start(form) }}
<h4>Subscribe to Insider</h4>
<p class="mb-4">Get the latest news and updates directly to your inbox with Insider</p>
{{ form_widget(form) }}
<button class="btn btn-wcm">{{ button_label|default('Subscribe') }}</button> {{ form_end(form) }}
There are 2 entities at play here;
- The news articles rendered into a list by the Index controller
- the subscriber entity where we store our subscribers plus some data about them (preferences, unsubscribe tag, etc)
I haven't implemented sending the subscriber a welcome email yet (I know how to do that) and I suppose I could use Ajax to keep the subscriber on the same page and serve them with a "thanks for signing up" message - but I want to actually get the basic thing working first.
I'm sure the answer must be staring me in the face, but for the life of me right now I cannot get it working.
What am I doing wrong?