0

I have a function that I need a few controllers. Can i call it in some other way than to extend the class in which the function is? Question:

class CategoryController extends Controller
{
    public function getCategoriesAction()
    {
        $categories = $this->getDoctrine()->getRepository('ModelBundle:Category')->findAll();
        return $categories;
    }
}

How call this function in PostController?

5
  • In Symfony Controller's actions returns Response Object, not arrays. But in PostController you still can do $this->getDoctrine()->getRepository('ModelBundle:Category')->findAll(); Commented May 21, 2015 at 15:33
  • @Med Yes, I can do so , but the duplication of code - it's bad . I need call this function 7 times ( Commented May 21, 2015 at 15:35
  • That's the way to do it, and the reason why services and container are usefull. By the way, you can't call controller's methods in others controllers, you have to declare them as service first... So why not use the doctrine service as intended to be used ? Commented May 21, 2015 at 15:39
  • @Med can you write example? I would be very grateful Commented May 21, 2015 at 15:43
  • It's not code duplication. That's the correct way to get the categories. You need it 7 times? Call it 7 times. Commented May 21, 2015 at 15:52

4 Answers 4

1

You can define a service and inject entity manager in it, for retrieving data:

dummy.manager:
    class: AppBundle\Model\DummyManager
    arguments:
        entityManager: "@doctrine.orm.entity_manager"

In your service, call findAll() method:

class DummyManager {

   /** @var EntityManager */
   protected $entityManager;

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

   public function getCategories(){ 
      return $this->entityManager->getRepository('ModelBundle:Category')->findAll();
   }
}

And last step, in your controller:

class CategoryController extends Controller
{
    public function getCategoriesAction()
    {
        $categories = $this->container->get('dummy.manager')->getCategories();
        //...
    }
}

I hope this helps.

Sign up to request clarification or add additional context in comments.

5 Comments

Explain me what's difference between $categories = $this->container->get('dummy.manager')->getCategories(); and $categories = $this->getDoctrine()->getRepository('ModelBundle:Category')->findAll(); ? Your answer is far more complicated than just getting categories from doctrine.
Your case is simple because findAll() can be called from any controller. But... if you have a custom method (findAllActiveCategories etc.) and you want to be shared by different controllers, add it to a service, and that service can be called anywhere.
In a complex case, service is the way to solve it, but in that case you can get it easily from doctrine why create another service? Keep It Simple.
@Med Creating services should not be avoided as a KISS principle. If you use a manager to hide the "find" implementation, then you've achieved good abstraction. What happens if you put CategoryRepository::findAll() in 8 different places but then one day your business requirements change and findAll() is no longer appropriate? Would you rather change that in 8 places or just one because you used a manager to define business-related methods and now you just have to change it in one place?
That's a good point, sure it's better to change only one place. You understood better the problem of OP. Was too much focused on the action returning an array...
1

You can also use pure PHP with traits

trait CategoryProvider {
   public function getCategoriesAction() {
    $categories = $this->container->get('dummy.manager')>getCategories();
    //...
   }
}

After that you can use this trait in your controllers

class Controller1 {

   use CategoryProvider;

   public function indexAction(){
      //...
      $this->getCategoriesAction();
      //...
   }
}

class Controller2 {

   use CategoryProvider;

   public function anotherAction(){
      //...
      $this->getCategoriesAction();
      //...
   }
}

Comments

0

You should not define model-style getters on a controller. The notion of a "getCategoriesAction" method for a controller should be vacated from your brain.

What you want to do is define this fetching behavior in the model layer. This can be done a bunch of different ways. Cristian just posted one way so I'll offer another.

You can define the Entity Repository itself as a service.

app/config/services.yml

services:
    model.repository.category:
        class:   ModelBundle\Entity\CategoryRepository
        factory: ["@doctrine.orm.entity_manager", getRepository]
        arguments: ['ModelBundle:Category']

Then in your controller (assuming it's a container-aware controller) you can do this

$categories = $this->get('model.repository.category')->findAll();

2 Comments

if I do not have a repository class, I must create it empty?
No, you can change the class to Doctrine\ORM\EntityRepository
0

Another approach, how @Med mentioned, is to declare your controller as service:

services:
    categoryController:
        class: AppBundle\Controller\CategoryController
        arguments:
            entityManager: @entityManager

2 Comments

Question If my class hsa other methods, it noncontradiction to the rules or correct programming or i must create a separate class for the method call all categories?
Well, the best way is to create a separate class to accomplish this, that's why explained you the method below, with a service.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.