03.05 实体

在SF的术语中,实体(Entity)是一个对象,有自己的属性和方法。我们都知道,根据面向对象的编程理念,一个所谓的对象是一个封装的实体。这么来回说似乎有点循环定义的味道。但是,确实我们只能这样来理解。

在实际应用中个,我们通常可以将一个实体理解为数据库中某个表格中记录的PHP中的类实现。

我们可以简单地说:有一个user表格,保存了诸如用户名,密码,主页等用户信息,那么通过某种方式将这个表格映射到一个User实体,这个实体有着诸如username, password, hompage这样的属性,也有类似setusername这样的方法来设置某个属性。

或者,更SF的想法是,我有一个User实体,其中定义了诸如username,password,homepage这样的属性和一些方法来操作属性,我们可以要求SF和Doctrine根据我们这个实体的结构来创建相应的数据库表格以存续(persist)这样的用户信息。

这是一个很巨大的变动。对我们如何编程,先定义什么后定义什么的顺序以及这个顺序内涵的意义有着不寻常的影响。

以往我们总是先定义一个数据库结构,定义各个表格以及之间的关系,然后才是通过ORM将数据库结构映射回一个类。而现在,SF的推荐方式是先不要管底层数据库会怎样,我们先要关心的是我们的应用需要哪些实体的支持,这些实体怎样互相操作,又各自提供怎样的一些属性和方法。这些工作做完之后,才是数据库结构的映射和将来对象得以存续。

现有数据库再有对象是传统的思路;而先有对象再有数据库是SF提倡的思路。

在本书所讲述的应用开发过程中,我们会用到这两种不同的方式。

在最开始的时候,我们用传统的方法:先定义数据库然后导出,并映射到一个个实体。这是因为我们的应用定义很明确,要处理的对象也非常明确。

在开发过程中,我们会采用SF提倡的方法,对我们的实体进行一些微调,这些微调可能是会影响到数据库表格结构的。我们将会发现,这个反向(或者更应该说是正向?)的操作室无损的,不会影响数据库中现有数据。

也许,在我们的开发中,这样两个方向的调整还是需要进行若干次的。这样的循环没有一个固定的模式,我们要根据实际的需要和自己的经验来确定此时此地用哪个方向的映射最合适。

讲述了这么多实体的理论,我们来看一个典型的实体的代码。这是一个书籍表格的映射,文件位于:src/AppBundle/Entity/Book.php

  1. <?php
  2. namespace tr\rsywxBundle\Entity;
  3. use Doctrine\ORM\Mapping as ORM;
  4. /**
  5. * BookBook
  6. */
  7. class BookBook
  8. {
  9. /**
  10. * @var integer
  11. */
  12. private $id;
  13. /**
  14. * @var string
  15. */
  16. private $bookid;
  17. ... ...
  18. /**
  19. * Get id
  20. *
  21. * @return integer
  22. */
  23. public function getId()
  24. {
  25. return $this->id;
  26. }
  27. /**
  28. * Set bookid
  29. *
  30. * @param string $bookid
  31. * @return BookBook
  32. */
  33. public function setBookid($bookid)
  34. {
  35. $this->bookid = $bookid;
  36. return $this;
  37. }
  38. /**
  39. * Get bookid
  40. *
  41. * @return string
  42. */
  43. public function getBookid()
  44. {
  45. return $this->bookid;
  46. }
  47. ... ...
  48. }

以上列出的只是该实体很小的一部分。一般而言,一个实体中将包含所有属性(全部是private成员)和针对该属性的R/W操作(对于某些只读或者只写参数,R/W操作会只有一个,但无论如何,都是public函数)。

对于实体的更多讨论,我们在后续章节会结合编程的过程加以进一步的介绍。