Avoid repeating the same query in controllers for

2019-07-11 05:44发布

I am trying to make a messaging system and I'm facing a small problem. I have a bigger template that displays my menu and my content. The menu includes the number of new messages, and the content can be any page(compose a new message, inbox, sent).

The problem is that I have to render each of the small templates by passing the number of new received messages to each of them, calling the doctrine each time and repeating code. Is there any way to send the number only to the parent template?

Here are my templates:

This is the parent containing the newmsg variable that gives me problems.

{% extends "::base.html.twig" %}

{% block body %}

    <a href="{{ path('private_message_inbox') }}">  inbox</a>  : {{ newmsg }}
    <a href="{{ path('private_message_sent') }}">sent</a>
    <a href="{{ path('private_message_new') }}">compose</a>

{% endblock body %}

Here is an example of child template:

{% block body %}
    {{ parent() }}

    {% if messageList %}
        {% for message in messageList %}
            <li><a href="{{ path('private_message_view',{'msg': message.id}) }}">title</a> = {{ message.title|e }}</li>
            <li>cont= {{ message.content|e }}</li>
            <li>data= {{ message.date|date('d-m-Y H:m:s') }}</li>
            <li>sender= {{ message.sender|e }}</li>
            <hr>
        {% endfor %}
    {% else %}
        <div>no messages</div>
    {% endif %}
{% endblock body %}

The problem is that each child template is asking me for the newmsg variable

$messages = $this->getDoctrine()->getRepository('MedAppCrudBundle:Message');
    $newMessagesNo = count($messages->findBy(array('seen' => '0', 'receiver' => $this->getUser())));
    return $this->render(
        'MedAppCrudBundle:UserBackend\Message:new.html.twig',
        array(
            'form' => $form->createView(),
            'newmsg' => $newMessagesNo,
        )
    );

And I have to write this in every single controller. Any way I can shorten this problem?

1条回答
【Aperson】
2楼-- · 2019-07-11 06:16

You could implement a service that gives back the newmsg value and call it on your parent template. Then it would not be necessary to pass the variable.

You can add a service in your bundle's services.yml with something like:

 services:
     newmessages:
         class: Full\Class\Name\NewMessagesService
         arguments: ["@doctrine.orm.entity_manager"]

Then, implement the Full\Class\Name\NewMessagesService class. Keep in mind that this class will need a constructor that receives an EntityManager argument. Something like:

  <?php
  namespace Full\Class\Name;
  class NewMessagesService{
     private $entityManager;

     public function __construct($entityManager){
         $this->entityManager = $entityManager;
     }

     public function methodToCalculate(){
          //Perform calculation and return result
     }
 }

Then, in your parent template, replace {{newmsg} with:

 {{ newmessages.methodToCalculate() }}
查看更多
登录 后发表回答