Note that there are some explanatory texts on larger screens.

plurals
  1. POHow should I handle BusinessLogic-related data definitions (like status types) in Doctrine 2?
    text
    copied!<p>Let's assume I have a <code>Booking</code> entity and it has a <code>state</code> field which may be set to one of a few values - let's make it: <code>NEW</code>, <code>ACCEPTED</code>, and <code>REJECTED</code></p> <p>I am looking for the "right" way to implement this. So far I used an approach like this:</p> <pre><code>class Booking { const STATUS_NEW = 0; const STATUS_ACCEPTED = 1; const STATUS_REJECTED = 2; protected $status = self::STATUS_ACTIVE; } </code></pre> <p>And it works ok, but I am really curious of the "proper" way of doing, also I have a few problems with this approach:</p> <ol> <li><p>It looks awfully lot like a business logic hidden in the entity class - if entity is supposed to be a <code>POJO</code>, then why would it care what the status may be? So I could put it in a manager class like:</p> <pre><code>class BookingManager { const STATUS_NEW = 0; const STATUS_ACCEPTED = 1; const STATUS_REJECTED = 2; public function setBookingStatus(Booking $b, $status) { } } </code></pre> <p>but it still does not help with the second issue:</p></li> <li><p>It is hard to re-use that data in the view, let's take a twig for example - I would have to create a Twig Extension in order to convert a number into an actual name:</p> <pre><code>Status type: {{ booking.status }} Status name: {{ booking.status|statusName }}{# I don't like this approach #} Status name: {{ booking.getStatusName() }} {# This seems even worse #} </code></pre> <p>So I could add <code>getStatusName</code> method to the <code>BookingManager</code> but I believe it does not belong there. I could add the same method to the <code>Booking</code> class and it would work just fine, but then again - business logic AND now also presentation logic is hidden in the entity. </p></li> <li><p>If some of my code depends on <code>MyVendor\MyBundle\Entity\Booking::STATUS_NEW</code> then could it become a problem when unit-testing the code? With static method calls the problem is obvious - I cannot mock the dependency. Is there any use case where depending on static constants may be a problem?</p></li> </ol> <p>All I could think of would be moving all this logic to the service layer and create a service like <code>BookingStatusManager</code> (let's ignore the fact that it could be mistakenly took for an EntityManager subclass) - it could look like this:</p> <pre><code>class BookingStatusManager { const STATUS_NEW = 0; const STATUS_ACCEPTED = 1; const STATUS_REJECTED = 2; public function getStatusName($code) { ... } } </code></pre> <p>but now I need an extra class for each <code>enum</code>-like property for each entity and it's a pain, also it still does not seem right - I need to reference static values from this class whenever I want to deal with <code>Booking</code>'s status.</p> <p>Note that this is a general question, not one specific to presented <code>Booking</code> example - it could be for example <code>BorderLength</code> entity with <code>lengthUnit</code> field with possible values of <code>MILES</code> or <code>KILOMETERS</code>; also, status transitions are not restricted to those caused by users, it must be possible to perform these from the code.</p> <p>What in your experience is "the right way" to solve this?</p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload