0

I need an advice for my Symfony 3.4 project (yes I know there is Symfony 6), I have an entity Product and I created a method that calculates the completion percentage of a Product sheet. It checks many properties of the entity and some other entities related to it (collections).

For now, I placed that method inside my Product entity and it works well. But for a specific thing, I need to do a complex query to the database and I can't use the query builder in the Entity class. So I'm wondering if I should place that code in the ProductController or maybe in the ProductRepository ?

Is it possible to use the entity object in the repository ? I don't need to build queries for each check, I simply use entity getters for the most of the checks.

Then, I will show the result in several pages of my project.

My function is someting like this (simplified) :

public function checkSetup()
{
    $setup = array(
        'active'    => $this->isActive(),
        'ref'       => !empty($this->ref) ? true : false,
        'tags'      => $this->tags->isEmpty() ? false : true,
    );

    // I want to add the following part :
    $qb = $em->getRepository(Product::class)->createQueryBuilder('p');
    // build complex query...
    $records = $qb->getQuery()->getResult();

    $setup['records'] = !empty($records) ? false : true;

    // Completion level
    $score = 0;
    foreach ($setup as $s) {
        if ($s) $score++;
    }

    $num = $score / count($setup) * 100;
    $setup['completion'] = round($num);

    return $setup;
}
5
  • 1
    You definitely do not want this sort of stuff in a controller. Repository is the easy choice. Write a repository method that returns your records and then pass the records where needed. You might consider moving the check code into it's own ProductCheck class. You would inject the repository and then pass the entity as an argument to the check method. Commented Sep 28, 2022 at 11:26
  • @Cerad Interesting, thank you! Maybe create a class at /src/Checker/ProductChecker.php and register it as a service ? Then inject EntityManager and do all the stuff. I'll just have to call the service in my Controller to render the result in a view. I'm gonna try that. Commented Sep 28, 2022 at 12:35
  • You can make a trait class , you call EntityManager there and create your own functions in this trait, you can create the queries there or in the repository and call them in this trait. When you add "use trait" in Product entity, you will have an access to public functions of Product like getters and setters from this trait and from entity Product you can acces to the functions inside the trail this wil work but I'm not sure if it's the best solution Commented Sep 28, 2022 at 13:58
  • @hous Thank you for your answer, what is a trait class ? A service ? Commented Sep 30, 2022 at 6:44
  • Trait is a class and can't be instantiated. A class can inherit from just one class, so the trait comes to solve this problem. For example you have Order class and to keep it clean , you can make a trait and put in the calculation functions and others Commented Sep 30, 2022 at 14:01

1 Answer 1

0

Based on the comment of @Cerad :

Create a specific class for the checker.

<?php
// src/Checker/ProductChecker.php

namespace AppBundle\Checker;

use AppBundle\Entity\Product\Product;
use Doctrine\ORM\EntityManager;

class ProductChecker
{
    private $em;

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

    public function check(Product $p)
    {
        // code...

        $result = $this->em->getRepository(Product::class)->customQuery($p->getId());

        // code...
    }
}

Register ProductChecker as a service and inject EntityManager for using ProductRepository in ProductChecker.

# app/config/services.yml

app.product_checker:
   public: true
   class:      AppBundle\Checker\ProductChecker
   arguments:  ["@doctrine.orm.entity_manager"]

Write the complex query in ProductRepository.

Then, call the checker in the Controller :

$checker = $this->get("app.product_checker");
$report = $checker->check($product);
Sign up to request clarification or add additional context in comments.

Comments

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.