1

I have just developed a controller that consists of creating a subject with the ability to add one or more questions. It works, but I'm not really satisfied with the quality of my code:

Indeed when I want to create a new topic, I can not retrieve the last id of my table QUESTION in phpmyadmin. (I have for the moment two tables: SUBJECT, QUESTION)

The only solution I found, and it is very ugly, is to create the subject, and create a record in my QUESTION table to finally retrieve the last id via getid () by autoincrementation and delete this same question before Display the form for adding a question.

Does any of you have a better solution? :(

Thank you in advance for your return,

My code:

/**
* @Route("/add_sujet", name="add_sujet")
* @Method({"GET", "POST"})
*/
public function add_sujetAction(Request $request)
{

$sujet = new Sujet();

$form = $this->createForm(SujetType::class, $sujet)
    ->add('saveAndNext', SubmitType::class);
$form->handleRequest($request);


if ($form->isSubmitted() && $form->isValid()) {
    $sujet->setSlug($this->get('slugger')->slugify($sujet->getTitle()));
    $entityManager = $this->getDoctrine()->getManager();
    $entityManager->persist($sujet);
    $entityManager->flush();

    $this->addFlash('success', 'sujet.created_successfully');

    if ($form->get('saveAndNext')->isClicked()) {
        // On commence à créer les questions.

        $question = new question();
        $question->setContent('init');
        $question->setType('init');
        $question->setSujet($sujet);
        $entityManager = $this->getDoctrine()->getManager();
        $entityManager->persist($question);
        $entityManager->flush(); // Add factice question<br>
        $id = $question->getId()+1; // NOT OPTIMIZED.. <br>
        $entityManager->remove($question); 
<br>
        $entityManager->flush(); // JE SAIS C'EST TRES MOCHE.. <br>

        return $this->redirectToRoute('add_question', ['sujetSlug' => $sujet->getSlug(), 'id' => $id]);

    }
    // On annule la création de sujet.
    return $this->redirectToRoute('sujet');
}
// On présente le formulaire pour déclaration sujet.
return $this->render('default/add_sujet.html.twig', [
    'sujet' => $sujet,
    'form' => $form->createView(),
]);

}
David Fournier
  • 11
  • 1
  • 1
  • 2
  • First step is to go for a *custom method in a custom Repository.* something like `public function findLastQuestion()` You can then test it using unit tests, to deliver what you need....you can use queryBuilder if you prefer a simpler structure....and remove your workaround. – Confidence Apr 19 '17 at 08:28
  • Thank for your responce. Let me try this! :) – David Fournier Apr 19 '17 at 09:12
  • 2
    And what happens if another user creates a question while your app is waiting for a response from the first user. There should no need for the next available question id. Especially if you are using the Doctrine entity manager. – Cerad Apr 19 '17 at 13:15
  • Hello, Thank for your feedback. I tried to solved my problem with an another way with this: Cascade persiste looks me more apropriate. http://symfony.com/doc/current/form/form_collections.html It looks me better for one response. But if i want to integrate 3 or 4 responce i have an error 500 when I add "'allow_add' => true," on my questiontype form. – David Fournier Apr 26 '17 at 11:05

2 Answers2

3

You don't need to add a new record to get the last id. You may try this:

$lastQuestion = $em->getRepository('AppBundle:Question')->findOneBy([], ['id' => 'desc']);
$lastId = $lastQuestion->getId();

To get the last id after flush:

$em->persist($question); // Id not avalaible
$em->flush();
$lastId = $question->getId(); // we can now get the Id
2

Just select from your table and ORDER BY the id DESC, and LIMIT to 1 record. Creating a new record just to get the last insert id is crazy!

delboy1978uk
  • 12,118
  • 2
  • 21
  • 39
  • Yes I know... :( How can I do that. Directly from my controller? from entity? What's your advice? David – David Fournier Apr 19 '17 at 09:10
  • Personally, I use a service class for doing anything with my entities, and the service class has a repository class for any db calls. In your repository class, create a findLastRecord() method, put the query in there. In your controller, I would call $question = $service->getRepository()->findLastRecord(); – delboy1978uk Apr 19 '17 at 09:50
  • ok thank you. Are you agree with this? /** * @return Query */ public function queryLatest() { return $this->getEntityManager() ->createQuery(' SELECT q.id FROM AppBundle:Question q WHERE q.id=LAST_INSERT_ID(); ') ; } – David Fournier Apr 19 '17 at 11:01
  • No, you don't have the ID. Just SELECT q.id FROM AppBundle:Question q SORT BY q.id DESC LIMIT 1 – delboy1978uk Apr 19 '17 at 11:43