best-practices.rst 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127
  1. Best Practices
  2. ==============
  3. The best practices mentioned here that affect database
  4. design generally refer to best practices when working with Doctrine
  5. and do not necessarily reflect best practices for database design
  6. in general.
  7. Don't use public properties on entities
  8. ---------------------------------------
  9. It is very important that you don't map public properties on
  10. entities, but only protected or private ones. The reason for this
  11. is simple, whenever you access a public property of a proxy object
  12. that hasn't been initialized yet the return value will be null.
  13. Doctrine cannot hook into this process and magically make the
  14. entity lazy load.
  15. This can create situations where it is very hard to debug the
  16. current failure. We therefore urge you to map only private and
  17. protected properties on entities and use getter methods or magic
  18. \_\_get() to access them.
  19. Constrain relationships as much as possible
  20. -------------------------------------------
  21. It is important to constrain relationships as much as possible.
  22. This means:
  23. - Impose a traversal direction (avoid bidirectional associations
  24. if possible)
  25. - Eliminate nonessential associations
  26. This has several benefits:
  27. - Reduced coupling in your domain model
  28. - Simpler code in your domain model (no need to maintain
  29. bidirectionality properly)
  30. - Less work for Doctrine
  31. Avoid composite keys
  32. --------------------
  33. Even though Doctrine fully supports composite keys it is best not
  34. to use them if possible. Composite keys require additional work by
  35. Doctrine and thus have a higher probability of errors.
  36. Use events judiciously
  37. ----------------------
  38. The event system of Doctrine is great and fast. Even though making
  39. heavy use of events, especially lifecycle events, can have a
  40. negative impact on the performance of your application. Thus you
  41. should use events judiciously.
  42. Use cascades judiciously
  43. ------------------------
  44. Automatic cascades of the persist/remove/merge/etc. operations are
  45. very handy but should be used wisely. Do NOT simply add all
  46. cascades to all associations. Think about which cascades actually
  47. do make sense for you for a particular association, given the
  48. scenarios it is most likely used in.
  49. Don't use special characters
  50. ----------------------------
  51. Avoid using any non-ASCII characters in class, field, table or
  52. column names. Doctrine itself is not unicode-safe in many places
  53. and will not be until PHP itself is fully unicode-aware (PHP6).
  54. Don't use identifier quoting
  55. ----------------------------
  56. Identifier quoting is a workaround for using reserved words that
  57. often causes problems in edge cases. Do not use identifier quoting
  58. and avoid using reserved words as table or column names.
  59. Initialize collections in the constructor
  60. -----------------------------------------
  61. It is recommended best practice to initialize any business
  62. collections in entities in the constructor. Example:
  63. .. code-block:: php
  64. <?php
  65. namespace MyProject\Model;
  66. use Doctrine\Common\Collections\ArrayCollection;
  67. class User {
  68. private $addresses;
  69. private $articles;
  70. public function __construct() {
  71. $this->addresses = new ArrayCollection;
  72. $this->articles = new ArrayCollection;
  73. }
  74. }
  75. Don't map foreign keys to fields in an entity
  76. ---------------------------------------------
  77. Foreign keys have no meaning whatsoever in an object model. Foreign
  78. keys are how a relational database establishes relationships. Your
  79. object model establishes relationships through object references.
  80. Thus mapping foreign keys to object fields heavily leaks details of
  81. the relational model into the object model, something you really
  82. should not do.
  83. Use explicit transaction demarcation
  84. ------------------------------------
  85. While Doctrine will automatically wrap all DML operations in a
  86. transaction on flush(), it is considered best practice to
  87. explicitly set the transaction boundaries yourself. Otherwise every
  88. single query is wrapped in a small transaction (Yes, SELECT
  89. queries, too) since you can not talk to your database outside of a
  90. transaction. While such short transactions for read-only (SELECT)
  91. queries generally don't have any noticeable performance impact, it
  92. is still preferable to use fewer, well-defined transactions that
  93. are established through explicit transaction boundaries.