-1

I am new to symfony, i was reading through the best practices guide here https://symfony.com/doc/3.4/best_practices/business-logic.html

I have a controller called Category and i have this action method to list down categories.

public function listCategory(Request $request, CategoryLogic $categoryLogic)
{
    $categories = $categoryLogic->getAllCategory($this->getDoctrine());

    return $this->render('listCategory.html.twig', ['categories' => $categories]);
}

As you can see all my business logic for controller goes to -> AppBundle\Utils\CategoryLogic

There i have this method to handle the logic and return the categories

use AppBundle\Entity\Category; 

/**
 * @param Registry $doctrine
 * @return array
 */
public function getAllCategory(Registry $doctrine)
{
    $repositoryCategory = $doctrine->getRepository(Category::class);
    $category = $repositoryCategory->findAll();

    return $category;
}

The purpose is to keep the controller clean. is this the best way to do it? i have a little concern about naming the logic class as CategoryLogic instead i would like to name it as Category but then i have another problem because i am already importing use AppBundle\Entity\Category in CategoryLogic class so there cant be two Category classes

dev1234
  • 5,376
  • 15
  • 56
  • 115
  • 3
    There are a great many ways of handling business logic in Symfony and the "best way" is dependant on your preference. You could write it as a service, controller event, in your model, as a separate model, or as a Entity Repository method. Ultimately it would be what you deem as the best approach to satisfy your needs. For this however, doctrine is satisfying the Business logic for you with `$categories = $em->getRepository(Category::class)->findAll();` and would be more optimal. If however you had conditions such as `return $a + $b`, I would use a service, model, or repository. – Will B. Aug 21 '18 at 04:24
  • @fyrye can you give an example of service, model, or repository ? is using Utils considered as Service ? – dev1234 Aug 21 '18 at 05:44
  • @dev1234 The “best practices” page you linked should be taken with a grain of salt. There are a couple of good ideas there, but don’t take everything literally. Use common sense and common software development best practices. – lxg Aug 21 '18 at 08:10
  • @dev1234 As you are new to Symfony, I strongly urge you to walk through some tutorials, such as those on [KnpUniversity](https://knpuniversity.com/tracks/symfony3) and study the [Doctrine best-practices by Ocramius](https://ocramius.github.io/doctrine-best-practices/). FInd out what works best for *YOU* and your application needs. Your question will only provide you with opinionated answers with no singular correct answer, without writing an essay on each method, which is more a tutorial than an answer. For example the current answer I highly discourage due to it causing unnecessary bloating – Will B. Aug 21 '18 at 14:19

1 Answers1

2

For your specific example, its useless to use a Util class when you can inject Repository in controller.

public function listCategory(Request $request, CategoryRepository $categoryRepository)
{
    $categories = $categoryRepository->findAll();

    return $this->render('listCategory.html.twig', ['categories' => $categories]);
}

Since symfony 3.3, it has dependency injection that means you can inject services into other services. If you want to handle it with some services e.g. Utils, you can make it like this.

//CategoryController.php

public function listCategory(Request $request, CategoryService $categoryService)
{
    $categories = $categoryService->getAllCategories();

    return $this->render('listCategory.html.twig', ['categories' => $categories]);
}

//CategoryService.php

namespace App\Service;

use App\Repository\CategoryRepository ;

class CategoryService 
{
    private $categoryRepository;

    // We need to inject these variables for later use.
    public function __construct(CategoryRepository $categoryRepository)
    {
        $this->categoryRepository = $categoryRepository;
    }

    public function getAllCategories()
    {
        $categories = $this->categoryRepository->findAll();

        return $categories;
    }
}

Always use singular and plural names to rule out confusions e.g. $category will have a Category object and $categories will be an array of Category objects or at least Iteratable (Collection) object of Category objects. It will make your life easy when you try to debug code later and help others to understand your code better.

Appendix:

https://symfony.com/doc/current/doctrine.html#querying-for-objects-the-repository https://symfony.com/doc/current/service_container/3.3-di-changes.html https://symfony.com/doc/current/service_container/injection_types.html

hanish singla
  • 782
  • 8
  • 21
  • using repositories how do we save a record ? this is how i am saving records $em = $doctrine->getManager(); $em->persist($category); $em->flush(); – dev1234 Aug 21 '18 at 07:19
  • this is the error i get when i tried with your way "Controller "AppBundle\Controller\CategoryController::listCategory()" requires that you provide a value for the "$categoryRepository" argument – dev1234 Aug 21 '18 at 07:26
  • Your method to save object is fine. Don't overthink about it. For your error regarding entity and repository, I will suggest to follow https://symfony.com/doc/current/doctrine.html#querying-for-objects-the-repository, https://symfony.com/doc/current/service_container/3.3-di-changes.html, https://symfony.com/doc/current/service_container/injection_types.html – hanish singla Aug 21 '18 at 07:43
  • Tnx for these links. tell me one purpose of having services? – dev1234 Aug 21 '18 at 08:02
  • 1
    After Controllers and Entities. everything you create a service. e.g. You use repositories to fetch data for entities, Repo is a service. You create a lib class for sending emails or pdf, it will be a service. You can inject these services in controllers or in other services. – hanish singla Aug 21 '18 at 08:08
  • @dev1234 Just to reinforce what Hanish is say, understanding services, dependency injection and when to use them is the key to effectively using the Symfony framework. More than worth your time to read through the service container docs. The hard part is recognizing and ignoring older legacy code. – Cerad Aug 21 '18 at 12:24
  • @dev1234 Keep in mind that by default both the [Entity and Repository directories are excluded](https://github.com/symfony/symfony-standard/blob/3.4/app/config/services.yml#L23) by Symfony for the auto-wire and auto-configure service detection. If you want repositories to be automatically created as services, put them in your `AppBundle\Repository` directory and remove the `Repository` exclusion from your services.yml – Will B. Aug 21 '18 at 14:44
  • 1
    @dev1234 However you should/do not need to turn Entities into services, instead use the [SensiFrameworkExtraBundle ParamConverter](https://symfony.com/doc/current/bundles/SensioFrameworkExtraBundle/annotations/converters.html), which provides a DI behavior for doctrine entities. – Will B. Aug 21 '18 at 14:45
  • @fyrye Repository directories are no longer excluded by default. The assumption is that the repositories extend the fairly new ServiceEntityRepository which in turn allows the repositories to be autowired with no additional effort on the part of the developer. – Cerad Aug 21 '18 at 18:16
  • 1
    @Cerad while you are correct for Symfony 4+, this question is regarding Symfony 3.4, where the Repository directory is excluded by default in Symfony Standard, as referenced in the link I posted. I did fail to mention extending [`ServiceEntityRepository`](https://stackoverflow.com/a/49168332/1144627) instead of `EntityRepository` which is also available in Symfony 3.4 using `DoctrineBundle 1.8+` which should be installed during a composer update due to the composer rules for Symfony Standard. None-the-less you can prototype repositories as services in 3.4, but not by default. – Will B. Aug 22 '18 at 00:16
  • @fyrye I suppose that it is mildly interesting to note that Repository is not excluded by default when installing 3.4 using flex. So we are both right. Yea. Of course it only takes a moment to remove Repository from the standard edition install but I suspect we are getting a bit off topic. – Cerad Aug 22 '18 at 12:19