Получение данных через пользовательский репозиторий в расширении Twig

Я хотел бы отображать новые уведомления на каждой странице своего веб-приложения symfony 2. Мне было рекомендовано использовать расширение Twig для этого. Я создал функцию getFriendRequests в этом расширении, но я не знаю, насколько хорошей практикой является получение данных через мой пользовательский репозиторий в расширении ветки: прямо сейчас он дает мне ошибку, что он не может найти метод getDoctrine,

<?php

namespace Tennisconnect\DashboardBundle\Extension;

class NotificationTwigExtension extends \Twig_Extension
{
    public function getFriendRequests($user)
    {
        $users = $this->getDoctrine()
            ->getRepository('TennisconnectUserBundle:User')
            ->getFriendRequests();
        return count($users);
    }

    public function getName()
    {
        return 'notification';
    }

    public function getFunctions()
    {
        return array(
            'getFriendRequests' => new \Twig_Function_Method($this, 'getFriendRequests'));
    }
}

Ответ 1

Я не думаю, что это так плохо, чтобы получать ваши данные непосредственно из вашего расширения ветки. В конце концов, если вы этого не сделаете, вам нужно будет забрать эти записи до этого, а затем передать их в расширение для отображения в любом случае.

Важным моментом является использование данных DQL/SQL в репозитории, как вы уже делали. Это важно, чтобы отделить заявления базы данных от другой части вашего проекта.

У вас проблема в том, что метод getDoctrine не существует в этом классе. Насколько я понимаю, вы взяли этот код из контроллера, который расширяет базовый контроллер FrameworkBundle. Базовый контроллер FrameworkBundle определяет этот метод.

Чтобы решить эту проблему, вам нужно будет ввести правильную услугу в расширение. Это основано на контейнере инъекции зависимостей. Вы определенно определили службу для расширения ветки, что-то вроде этого определения:

services:
  acme.twig.extension.notification:
    class: Acme\WebsiteBundle\Twig\Extension\NotificationExtension
    tags:
      - { name: twig.extension }

Теперь вам нужно ввести нужные вам зависимости:

services:
  acme.twig.extension.notification:
    class: Acme\WebsiteBundle\Twig\Extension\NotificationExtension
    arguments:
      doctrine: "@doctrine"
    tags:
      - { name: twig.extension }

И затем в расширении вы определяете конструктор, который получает зависимость доктрины:

    use Symfony\Bridge\Doctrine\RegistryInterface;

    class NotificationTwigExtension extends \Twig_Extension
    {
        protected $doctrine;

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

        // Now you can do $this->doctrine->getRepository('TennisconnectUserBundle:User')

        // Rest of twig extension
    }

Это концепция инъекции зависимостей. Вы можете увидеть еще один вопрос, который я когда-то отвечал о доступе к службам вне контроллера: здесь

Надеюсь, что это поможет.

С уважением,
Matt

Ответ 2

То же самое, но с монго:

в config.yml

services:
    user.twig.extension:
        class: MiProject\CoreBundle\Twig\Extension\MiFileExtension
        arguments:
          doctrine: "@doctrine.odm.mongodb.document_manager"
        tags:
          -  { name: twig.extension }

и в вашем Twig\Extensions\MiFile.php

<?php

namespace MiProject\CoreBundle\Twig\Extension;

use Symfony\Component\HttpKernel\KernelInterface;

class MiFileExtension extends \Twig_Extension
{
    protected $doctrine;

    public function __construct( $doctrine){
        $this->doctrine = $doctrine;
    }
    public function getTransactionsAmount($user_id){
    return $results = $this->doctrine
    ->createQueryBuilder('MiProjectCoreBundle:Transaction')             
    ->hydrate(false)
    ->getQuery()            
    ->count();
    }

    Rest of mi code ... 

}