Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to get Doctrine to work inside a helper function on Symfony2

I need to get doctrine working inside my helper, im trying to use like i normaly do in a controller:

$giftRepository = $this->getDoctrine( )->getRepository( 'DonePunctisBundle:Gift' );

But this gave me:

FATAL ERROR: CALL TO UNDEFINED METHOD DONE\PUNCTISBUNDLE\HELPER\UTILITYHELPER::GETDOCTRINE() IN /VAR/WWW/VHOSTS/PUNCTIS.COM/HTTPDOCS/SRC/DONE/PUNCTISBUNDLE/HELPER/UTILITYHELPER.PH

What Im missing here?

EDIT:

services file

services:
    templating.helper.utility:
        class: Done\PunctisBundle\Helper\UtilityHelper
        arguments: [@service_container]
        tags:
            - { name: templating.helper, alias: utility }

Firts lines of helper file

<?php
namespace Done\PunctisBundle\Helper;

use Symfony\Component\Templating\Helper\Helper;
use Symfony\Component\Templating\EngineInterface;



class UtilityHelper extends Helper {

    /*
     * Dependency injection
     */

    private $container;

    public function __construct( $container )
    {
        $this->container = $container;
    }
like image 993
DomingoSL Avatar asked Dec 26 '22 07:12

DomingoSL


1 Answers

The problem here is that your Helper class is not container-aware; that is, it has no idea about all the services Symfony has loaded (monolog, twig, ...and doctrine).

You fix this by passing "doctrine" to it. This is called Dependency Injection, and is one of the core things that makes Symfony awesome. Here's how it works:

First, give your Helper class a place for the Doctrine service to live, and require it in the Helper's constructor:

class UtilityHelper
{
    private $doctrine;

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

    public function doSomething()
    {
        // Do something here
    }
}

Then, you use services.yml to define how Symfony should construct that instance of Helper:

services:
    helper:
        class: Done\PunctisBundle\Helper\UtilityHelper
        arguments: [@doctrine]

In this case, @doctrine is a placeholder that means "insert the Doctrine service here".

So now, in your Controller, or in anything else that is container-aware, you can get access to Doctrine through the Helper class like this:

class SomeController()
{
    public function someAction()
    {
        $this->get("helper")->doctrine->getRepository(...);
    }
}

EDIT

After looking at your edit, it appears that you're injecting the entire service container into the Helper class. That's not a best practice -- you should only inject what you need. However, you can still do it:

services.yml

services:
    helper:
        class: Done\PunctisBundle\Helper\UtilityHelper
        arguments: [@service_container]

UtilityHelper.php

class UtilityHelper
{
    private $container;

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

    public function doSomething()
    {
        // This won't work, because UtilityHelper doesn't have a getDoctrine() method:
        // $this->getDoctrine()->getRepository(...)

        // Instead, think about what you have access to...
        $container = $this->container;

        // Now, you need to get Doctrine

        // This won't work... getDoctrine() is a shortcut method, available only in a Controller
        // $container->getDoctrine()->getRepository(...)

        $container->get("doctrine")->getRepository(...)  
    }
}

I've included a few comments there that highlight some common pitfalls. Hope this helps.

like image 64
Thomas Kelley Avatar answered Jan 13 '23 15:01

Thomas Kelley