Toskan
Toskan

Reputation: 14931

What belongs into an entity class, what does not, why not and how to solve it?

So let's say I want to use

$this->generateUrl("SomeRouting_name") //this would return something like myApp/myCommentpage.html

in an entity. Why should I not do this?

What type of helper functions are fine to use in entity classes? Functions aside from something like

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

Many times in the controller I find that my functions look similar, and I hate that. E.g.:

class MyController extends Controller{
public function postCommentAction($cgid = null , $pid = null){
        $em = $this->getDoctrine()->getManager();
        $cg = $em->getRepository('MyBundle:CommentGroup')->findOneBy(array("id" => $cgid));
        $cgp = $em->getRepository('MyBundle:CommentGroupPerson')->findBy(array("comment_group_id" => $cgid, "person_id" => $pid));
        if ($cg === null) //redirect...
        if ($cgp === null) //redirect
       //rest left out since not important
}

Now for example, I want to know if this CommentGroupPerson can post a comment. Let's say the person can if the user is system admin or moderator or its id is 7 (why not). If the user does not meet these requirements I want to redirect to an error page errorwebpc.html.twig with the message "You shall not pass"

I don't like to put all this business logic into the controller all over the place. Since there can be different controllers, this would violate dry principle. What clean solution would there be?

Best would be as well, while reducing the number of lines. If we replace something here with something else, that needs more lines to write, the advantage is lost imho.

Further take into account that: We have as well a mobile application using the same entities, different error checks though and the page returned should be errormobile.html.twig with the error message "Sorry dear user, you cannot pass"

Upvotes: 0

Views: 129

Answers (2)

Syjin
Syjin

Reputation: 2810

Doctrine Entities should be plain old php objects and should only contain data as well as getter/setter. So you probably shouldn't implement your business logic inside them (although you probably can). The problem with your example

$this->generateUrl("SomeRouting_name");

is, that you need to inject the necessary objects into the entity or pass them from the controller. No one stops you from doing that, but your entities will be tightly coupled to the calling code. (I am not sure, if it is possible to use Symfony's Dependency Inection to inject something into an entity).

The "correct" solution (or at least one of them) is to use Services. If you google for "where to put business logic in symfony", most responses refer to the use of Services. You can create any number of services and inject everything you need (entity manager, routing service, etc.). With this approach you reduce the duplicated code in your controllers and have all your rules and logic inside your services.

See Symfony Service Container

Apart from that, Symfony and Doctrine provide the possiblity to create listeners and subscribers, which might be appropriate for some scenarios.

See Doctrine Event Listeners and Symfony Event Listener

Upvotes: 1

nicom974
nicom974

Reputation: 176

Use repositories for your business logic.

Also, in your Entity classes, are you actually writing all getters & setters? You might end up with a very long code.

My solution:

/**
 *  Constructor for the class.
 *
 */
public function __construct()
{
    // Initialise your variables, for example you can generate the UID, or the date
    //$this->createdAt = new \DateTime();
}

/**
 *  Get value for data '$name'
 *  @param string $name
 *  @return Type of data '$name'
 */
public function __get($name)
{
    return $this->$name;
}

/**
 *  Set value for data '$name'
 *  @param string $name
 *  @param generic $value
 *  @return Type of data '$name'
 */
public function __set($name, $value)
{
    $this->$name = $value;
    return $this;
}

public function offsetGet($name)
{
    return $this->$name;
}

Upvotes: 0

Related Questions