22

For example i have algorithmic function, which calculates specific hash-code. Function itself is 300+ lines of code. I need to use that functions many times in many different controllers in my bundle. Where can i store my calculate_hash() to use it in my bundle ? Can i access it from other bundles ? Can i also write global calculate_hash() which have access to entity manager ?

Didn't find my answer here.

rjmunro
  • 27,203
  • 20
  • 110
  • 132
artyomboyko
  • 2,781
  • 5
  • 40
  • 54

2 Answers2

44

In the Symfony2 world, this is clearly belonging to a service. Services are in fact normal classes that are tied to the dependency injection container. You can inject them the dependencies you need. For example, say your class where the function calculate_hash is located is AlgorithmicHelper. The service holds "global" functions. You define your class something like this:

namespace Acme\AcmeBundle\Helper;

// Correct use statements here ...

class AlgorithmicHelper {

    private $entityManager;

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

    public function calculate_hash() {
        // Do what you need, $this->entityManager holds a reference to your entity manager
    }
}

This class then needs to be made aware to symfony dependecy container. For this, you define you service in the app/config/config.yml files by adding a service section like this:

services:
  acme.helper.algorithmic:
    class: Acme\AcmeBundle\Helper\AlgorithmicHelper
    arguments:
      entityManager: "@doctrine.orm.entity_manager"

Just below the service, is the service id. It is used to retrieve your service in the controllers for example. After, you specify the class of the service and then, the arguments to pass to the constructor of the class. The @ notation means pass a reference to the service with id doctrine.orm.entity_manager.

Then, in your controller, you do something like this to retrieve the service and used it:

$helper = $this->get('acme.helper.algorithmic');
$helper-> calculate_hash();

Note that the result of the call to $this->get('acme.helper.algorithmic') will always return the same instance of the helper. This means that, by default, service are unique. It is like having a singleton class.

For further details, I invite you to read the Symfony2 book. Check those links also

  1. The service container section from Symfony2 book.
  2. An answer I gave on accesing service outside controllers, here.

Hope it helps.

Regards,
Matt

Community
  • 1
  • 1
Matt
  • 10,633
  • 3
  • 46
  • 49
  • You've called the method `test_method()`. This makes me think it's somthing to do with unit testing, but as far as I can tell, it isn't. Can you either edit your answer and call it `example_method()` or something, or if this is about unit testing, where do you put the method you want to use/test? – rjmunro Jul 18 '12 at 16:14
  • I called it `test_function()` because the original poster did name his algorithmic method `test_function()`. It is not related to unit testing, but it could, if the algorithm is to be use in unit tests. If I change the function name, I would need to edit original question so it is in sync with the new naming. – Matt Jul 18 '12 at 16:28
  • Good point, I feel really stupid now :-). I'm going to take the liberty of just renaming everything to `calculate_hash()` – rjmunro Jul 19 '12 at 11:32
  • Hehe nothing stupid here, I often read the answer, and forgot to read the associated question :) Ok, no problem with the renaming. – Matt Jul 19 '12 at 18:11
  • 2
    how can we make this on symfony 3? – Braian Mellor Jul 07 '17 at 16:25
1

Braian in comment asked for Symfony 3 answer, so here is one Symfony 3.3 (released May 2017):

1. The original class remains the same

namespace Acme\AcmeBundle\Helper;

use Doctrine\ORM\EntityManager;

final class AlgorithmicHelper
{
    /**
     * @var EntityManager
     */
    private $entityManager;

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

    public function calculateHash()
    {
        // Do what you need, $this->entityManager holds a reference to your entity manager
    }
}

2. Service registration is much simpler

# app/config/services.yml
services:
    _defaults: autowire # this enabled constructor autowiring for all registered services

    Acme\AcmeBundle\Helper\AlgorithmicHelper: ~

3. Use constructor injection to get the service

use Acme\AcmeBundle\Helper\AlgorithmicHelper;

class SomeController
{
    /**
     * @var AlgorithmicHelper
     */
    private $algorithmicHelper;

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

    public function someAction()
    {
        // some code
        $hash = $this->algorithmicHelper->calculateHash();
        // some code
    }
}

You can read about Symfony 3.3 dependency injection (in this case registering services in config and using it in controller) news in these 2 posts:

Tomas Votruba
  • 23,240
  • 9
  • 79
  • 115
  • This should have been an answer to a separate question. You are allowed to ask and answer your own questions. In fact, since there are no votes on this answer, I would suggest making a new question and copying this answer to it, then deleting the answer here. Once this is done, you can leave a comment pointing the user to the new question and answer. – CJ Dennis Jul 10 '18 at 06:15
  • Why do you think so? – Tomas Votruba Jul 10 '18 at 12:59
  • You gave the reason yourself in the first sentence: "Braian in comment asked for Symfony 3 answer". So they asked a new question in a comment that you answered here, even though the question is specific to Symfony2. – CJ Dennis Jul 10 '18 at 13:36
  • I think it's trend and better to use 1 question over many version, rather than create a new own question + answer to that version for each version. For example, see: https://stackoverflow.com/questions/13901256/how-do-i-read-from-parameters-yml-in-a-controller-in-symfony2 The main goal is not about Symfony 2, even though it might seem to, but how to "get that working in Symfony of version that was new in time of asking that question". – Tomas Votruba Jul 10 '18 at 17:51