1

Is it considered a bad practice to add fields to Symfony entity in controller? For example lets say that I have a simple entity:

/**
 * @ORM\Entity
 * @ORM\Table(name="user")
 */
class User extends BaseUser
{
    /**
     * @ORM\Id
     * @ORM\Column(type="integer")
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    protected $id;



    public function __construct()
    {
        parent::__construct();
    }

    public function getId()
    {
        return $this->id;
    }

    public function setId($id)
    {
        $this->id = $id;
    }
}

And then in UserController.php I want to do the following:

foreach($users as $user){
    $user->postsCount = someMethodThatWillCountPosts();
}

So later that postsCount can be displayed in Twig. Is it a bad practice?

Edit:

It's important to count posts on side of mysql database, there will be more than 50.000 elements to count for each user.

Edit2:

Please take a note that this questions is not about some particular problem but rather about good and bad practices in object oriented programming in Symfony.

  • will you not have have an association between the user class and the posts entity? If you do, you can simply do a count on the posts – Rooneyl Dec 05 '16 at 09:11
  • Counting posts is only a example. – Patryk Cysarz Dec 05 '16 at 09:26
  • 1
    "object oriented programming in Symfony" --- this makes very little sense. Symfony does not affect the design practices and common sense. – zerkms Dec 05 '16 at 09:39
  • 1
    It's okay as long as you don't get carried away with it. What you are basically doing is converting your User entity to a UserView entity by adding additional view only properties. If you have more then 2 or 3 special view properties then you should probably go ahead and create actual UserView entities with the original User as input. – Cerad Dec 05 '16 at 14:00
  • @Cerad That's the answer I needed :) Thanks for explaining this. – Patryk Cysarz Dec 05 '16 at 14:12

2 Answers2

3

As @Rooneyl explained that if you have relation between user and post then you can get count easily in your controller, refer this for the same. But if you are looking to constructing and using more complex queries from inside a controller. In order to isolate, reuse and test these queries, it's a good practice to create a custom repository class for your entity.Methods containing your query logic can then be stored in this class.

To do this, add the repository class name to your entity's mapping definition:

// src/AppBundle/Entity/Product.php
namespace AppBundle\Entity;

use Doctrine\ORM\Mapping as ORM;

/**
 * @ORM\Entity(repositoryClass="AppBundle\Repository\ProductRepository")
 */
class Product
{
    //...
}

Doctrine can generate empty repository classes for all the entities in your application via the same command used earlier to generate the missing getter and setter methods:

$ php bin/console doctrine:generate:entities AppBundle

If you opt to create the repository classes yourself, they must extend Doctrine\ORM\EntityRepository.

More Deatils

Updated Answer

In many cases associations between entities can get pretty large. Even in a simple scenario like a blog. where posts can be commented, you always have to assume that a post draws hundreds of comments. In Doctrine 2.0 if you accessed an association it would always get loaded completely into memory. This can lead to pretty serious performance problems, if your associations contain several hundreds or thousands of entities.

With Doctrine 2.1 a feature called Extra Lazy is introduced for associations. Associations are marked as Lazy by default, which means the whole collection object for an association is populated the first time its accessed. If you mark an association as extra lazy the following methods on collections can be called without triggering a full load of the collection: SOURCE

Community
  • 1
  • 1
TIGER
  • 2,864
  • 5
  • 35
  • 45
  • Check edit in my question. I don't want to count posts in PHP. – Patryk Cysarz Dec 05 '16 at 09:22
  • OK, but this still does not answer my question. Please don't take example of counting posts literally. – Patryk Cysarz Dec 05 '16 at 09:31
  • @NieUsune please ask a particular question then. This community is not about imaginary problems. – zerkms Dec 05 '16 at 09:33
  • @zerkms My question is not about some particular problem but rather about good and bad practices in object oriented programming. If this is not right place to ask that type of questions then sorry. – Patryk Cysarz Dec 05 '16 at 09:37
  • 2
    @NieUsune in OO programming you don't create properties dynamically. They form the type and must be known compile time. – zerkms Dec 05 '16 at 09:39
  • @zerkms That is the answer I was looking for :) Thanks. Sadly I can't upvote your comment. – Patryk Cysarz Dec 05 '16 at 09:43
2

"rather about good and bad practices in object oriented programming"

If that's the case then you really shouldn't have any business logic in controller, you should move this to services.

So if you need to do something with entities before passing them to twig template you might want to do that in specific service or have a custom repository class that does that (maybe using some other service class) before returning the results.

i.e. then your controller's action could look more like that:

public function someAction()
{
    //using custom repository
    $users = $this->usersRepo->getWithPostCount()

    //or using some other service
    //$users = $this->usersFormatter->getWithPostCount(x)

    return $this->render('SomeBundle:Default:index.html.twig', [
           users => $users
     ]);
}

It's really up to you how you're going to do it, the main point to take here is that best practices rather discourage from having any biz logic in controller. Just imagine you'll need to do the same thing in another controller, or yet some other service. If you don't encapsulate it in it's own service then you'll need to write it every single time.

btw. have a read there: http://symfony.com/doc/current/best_practices/index.html

Tom St
  • 908
  • 8
  • 15