PageRenderTime 38ms CodeModel.GetById 10ms RepoModel.GetById 0ms app.codeStats 0ms

/vendor/gedmo/doctrine-extensions/doc/blameable.md

https://bitbucket.org/hanutimes/hanutimes
Markdown | 592 lines | 470 code | 122 blank | 0 comment | 0 complexity | 5d013e9129945d52e58ed82221269edf MD5 | raw file
  1. # Blameable behavior extension for Doctrine 2
  2. **Blameable** behavior will automate the update of username or user reference fields
  3. on your Entities or Documents. It works through annotations and can update
  4. fields on creation, update or even on specific property value change.
  5. This is very similar to Timestampable but sets a string or user object for a user association.
  6. If you map the blame onto a string field, this extension will try to assign the user name.
  7. If you map the blame onto a association field, this extension will try to assign the user
  8. object to it.
  9. Note that you need to set the user on the BlameableListener (unless you use the
  10. Symfony2 extension which does automatically assign the current security context
  11. user).
  12. Features:
  13. - Automatic predifined user field update on creation, update and even on record property changes
  14. - ORM and ODM support using same listener
  15. - Specific annotations for properties, and no interface required
  16. - Can react to specific property or relation changes to specific value
  17. - Can be nested with other behaviors
  18. - Annotation, Yaml and Xml mapping support for extensions
  19. **Symfony:**
  20. - **Blameable** is available as [Bundle](http://github.com/stof/StofDoctrineExtensionsBundle)
  21. for **Symfony2**, together with all other extensions
  22. This article will cover the basic installation and functionality of **Blameable** behavior
  23. Content:
  24. - [Including](#including-extension) the extension
  25. - Entity [example](#entity-mapping)
  26. - Document [example](#document-mapping)
  27. - [Yaml](#yaml-mapping) mapping example
  28. - [Xml](#xml-mapping) mapping example
  29. - Advanced usage [examples](#advanced-examples)
  30. - Using [Traits](#traits)
  31. <a name="including-extension"></a>
  32. ## Setup and autoloading
  33. Read the [documentation](http://github.com/l3pp4rd/DoctrineExtensions/blob/master/doc/annotations.md#em-setup)
  34. or check the [example code](http://github.com/l3pp4rd/DoctrineExtensions/tree/master/example)
  35. on how to setup and use the extensions in most optimized way.
  36. <a name="entity-mapping"></a>
  37. ## Blameable Entity example:
  38. ### Blameable annotations:
  39. - **@Gedmo\Mapping\Annotation\Blameable** this annotation tells that this column is blameable
  40. by default it updates this column on update. If column is not a string field or an association
  41. it will trigger an exception.
  42. Available configuration options:
  43. - **on** - is main option and can be **create, update, change** this tells when it
  44. should be updated
  45. - **field** - only valid if **on="change"** is specified, tracks property for changes
  46. - **value** - only valid if **on="change"** is specified, if tracked field has this **value**
  47. then it updates the blame
  48. **Note:** that Blameable interface is not necessary, except in cases there
  49. you need to identify entity as being Blameable. The metadata is loaded only once then
  50. cache is activated
  51. Column is a string field:
  52. ``` php
  53. <?php
  54. namespace Entity;
  55. use Gedmo\Mapping\Annotation as Gedmo;
  56. use Doctrine\ORM\Mapping as ORM;
  57. /**
  58. * @ORM\Entity
  59. */
  60. class Article
  61. {
  62. /** @ORM\Id @ORM\GeneratedValue @ORM\Column(type="integer") */
  63. private $id;
  64. /**
  65. * @ORM\Column(type="string", length=128)
  66. */
  67. private $title;
  68. /**
  69. * @var string $createdBy
  70. *
  71. * @Gedmo\Blameable(on="create")
  72. * @ORM\Column(type="string")
  73. */
  74. private $createdBy;
  75. /**
  76. * @var string $updatedBy
  77. *
  78. * @Gedmo\Blameable(on="update")
  79. * @ORM\Column(type="string")
  80. */
  81. private $updatedBy;
  82. public function getId()
  83. {
  84. return $this->id;
  85. }
  86. public function setTitle($title)
  87. {
  88. $this->title = $title;
  89. }
  90. public function getTitle()
  91. {
  92. return $this->title;
  93. }
  94. public function getCreated()
  95. {
  96. return $this->created;
  97. }
  98. public function getUpdated()
  99. {
  100. return $this->updated;
  101. }
  102. }
  103. ```
  104. Column is an association:
  105. ``` php
  106. <?php
  107. namespace Entity;
  108. use Gedmo\Mapping\Annotation as Gedmo;
  109. use Doctrine\ORM\Mapping as ORM;
  110. /**
  111. * @ORM\Entity
  112. */
  113. class Article
  114. {
  115. /** @ORM\Id @ORM\GeneratedValue @ORM\Column(type="integer") */
  116. private $id;
  117. /**
  118. * @ORM\Column(type="string", length=128)
  119. */
  120. private $title;
  121. /**
  122. * @var string $createdBy
  123. *
  124. * @Gedmo\Blameable(on="create")
  125. * @ORM\ManyToOne(targetEntity="Path\To\Entity\User")
  126. * @ORM\JoinColumn(name="created_by", referencedColumnName="id")
  127. */
  128. private $createdBy;
  129. /**
  130. * @var string $updatedBy
  131. *
  132. * @Gedmo\Blameable(on="update")
  133. * @ORM\ManyToOne(targetEntity="Path\To\Entity\User")
  134. * @ORM\JoinColumn(name="updated_by", referencedColumnName="id")
  135. */
  136. private $updatedBy;
  137. public function getId()
  138. {
  139. return $this->id;
  140. }
  141. public function setTitle($title)
  142. {
  143. $this->title = $title;
  144. }
  145. public function getTitle()
  146. {
  147. return $this->title;
  148. }
  149. public function getCreated()
  150. {
  151. return $this->created;
  152. }
  153. public function getUpdated()
  154. {
  155. return $this->updated;
  156. }
  157. }
  158. ```
  159. <a name="document-mapping"></a>
  160. ## Blameable Document example:
  161. ``` php
  162. <?php
  163. namespace Document;
  164. use Gedmo\Mapping\Annotation as Gedmo;
  165. use Doctrine\ODM\MongoDB\Mapping\Annotations as ODM;
  166. /**
  167. * @ODM\Document(collection="articles")
  168. */
  169. class Article
  170. {
  171. /** @ODM\Id */
  172. private $id;
  173. /**
  174. * @ODM\String
  175. */
  176. private $title;
  177. /**
  178. * @var string $createdBy
  179. *
  180. * @ODM\String
  181. * @Gedmo\Blameable(on="create")
  182. */
  183. private $createdBy;
  184. /**
  185. * @var string $updatedBy
  186. *
  187. * @ODM\String
  188. * @Gedmo\Blameable
  189. */
  190. private $updatedBy;
  191. public function getId()
  192. {
  193. return $this->id;
  194. }
  195. public function setTitle($title)
  196. {
  197. $this->title = $title;
  198. }
  199. public function getTitle()
  200. {
  201. return $this->title;
  202. }
  203. public function getCreatedBy()
  204. {
  205. return $this->createdBy;
  206. }
  207. public function getUpdatedBy()
  208. {
  209. return $this->updatedBy;
  210. }
  211. }
  212. ```
  213. Now on update and creation these annotated fields will be automatically updated
  214. <a name="yaml-mapping"></a>
  215. ## Yaml mapping example:
  216. Yaml mapped Article: **/mapping/yaml/Entity.Article.dcm.yml**
  217. ```
  218. ---
  219. Entity\Article:
  220. type: entity
  221. table: articles
  222. id:
  223. id:
  224. type: integer
  225. generator:
  226. strategy: AUTO
  227. fields:
  228. title:
  229. type: string
  230. length: 64
  231. createdBy:
  232. type: string
  233. gedmo:
  234. blameable:
  235. on: create
  236. updatedBy:
  237. type: string
  238. gedmo:
  239. blameable:
  240. on: update
  241. ```
  242. <a name="xml-mapping"></a>
  243. ## Xml mapping example
  244. ``` xml
  245. <?xml version="1.0" encoding="UTF-8"?>
  246. <doctrine-mapping xmlns="http://doctrine-project.org/schemas/orm/doctrine-mapping"
  247. xmlns:gedmo="http://gediminasm.org/schemas/orm/doctrine-extensions-mapping">
  248. <entity name="Mapping\Fixture\Xml\Blameable" table="blameables">
  249. <id name="id" type="integer" column="id">
  250. <generator strategy="AUTO"/>
  251. </id>
  252. <field name="createdBy" type="string">
  253. <gedmo:blameable on="create"/>
  254. </field>
  255. <field name="updatedBy" type="string">
  256. <gedmo:blameable on="update"/>
  257. </field>
  258. <field name="publishedBy" type="string" nullable="true">
  259. <gedmo:blameable on="change" field="status.title" value="Published"/>
  260. </field>
  261. <many-to-one field="status" target-entity="Status">
  262. <join-column name="status_id" referenced-column-name="id"/>
  263. </many-to-one>
  264. </entity>
  265. </doctrine-mapping>
  266. ```
  267. <a name="advanced-examples"></a>
  268. ## Advanced examples:
  269. ### Using dependency of property changes
  270. Add another entity which would represent Article Type:
  271. ``` php
  272. <?php
  273. namespace Entity;
  274. use Doctrine\ORM\Mapping as ORM;
  275. /**
  276. * @ORM\Entity
  277. */
  278. class Type
  279. {
  280. /** @ORM\Id @ORM\GeneratedValue @ORM\Column(type="integer") */
  281. private $id;
  282. /**
  283. * @ORM\Column(type="string", length=128)
  284. */
  285. private $title;
  286. /**
  287. * @ORM\OneToMany(targetEntity="Article", mappedBy="type")
  288. */
  289. private $articles;
  290. public function getId()
  291. {
  292. return $this->id;
  293. }
  294. public function setTitle($title)
  295. {
  296. $this->title = $title;
  297. }
  298. public function getTitle()
  299. {
  300. return $this->title;
  301. }
  302. }
  303. ```
  304. Now update the Article Entity to reflect publishedBy on Type change:
  305. ``` php
  306. <?php
  307. namespace Entity;
  308. use Gedmo\Mapping\Annotation as Gedmo;
  309. use Doctrine\ORM\Mapping as ORM;
  310. /**
  311. * @ORM\Entity
  312. */
  313. class Article
  314. {
  315. /** @ORM\Id @ORM\GeneratedValue @ORM\Column(type="integer") */
  316. private $id;
  317. /**
  318. * @ORM\Column(type="string", length=128)
  319. */
  320. private $title;
  321. /**
  322. * @var string $createdBy
  323. *
  324. * @Gedmo\Blameable(on="create")
  325. * @ORM\Column(type="string")
  326. */
  327. private $createdBy;
  328. /**
  329. * @var string $updatedBy
  330. *
  331. * @Gedmo\Blameable(on="update")
  332. * @ORM\Column(type="string")
  333. */
  334. private $updatedBy;
  335. /**
  336. * @ORM\ManyToOne(targetEntity="Type", inversedBy="articles")
  337. */
  338. private $type;
  339. /**
  340. * @var string $publishedBy
  341. *
  342. * @ORM\Column(type="string", nullable=true)
  343. * @Gedmo\Blameable(on="change", field="type.title", value="Published")
  344. */
  345. private $publishedBy;
  346. public function setType($type)
  347. {
  348. $this->type = $type;
  349. }
  350. public function getId()
  351. {
  352. return $this->id;
  353. }
  354. public function setTitle($title)
  355. {
  356. $this->title = $title;
  357. }
  358. public function getTitle()
  359. {
  360. return $this->title;
  361. }
  362. public function getCreatedBy()
  363. {
  364. return $this->createdBy;
  365. }
  366. public function getUpdatedBy()
  367. {
  368. return $this->updatedBy;
  369. }
  370. public function getPublishedBy()
  371. {
  372. return $this->publishedBy;
  373. }
  374. }
  375. ```
  376. Yaml mapped Article: **/mapping/yaml/Entity.Article.dcm.yml**
  377. ```
  378. ---
  379. Entity\Article:
  380. type: entity
  381. table: articles
  382. id:
  383. id:
  384. type: integer
  385. generator:
  386. strategy: AUTO
  387. fields:
  388. title:
  389. type: string
  390. length: 64
  391. createdBy:
  392. type: string
  393. gedmo:
  394. blameable:
  395. on: create
  396. updatedBy:
  397. type: string
  398. gedmo:
  399. blameable:
  400. on: update
  401. publishedBy:
  402. type: string
  403. gedmo:
  404. blameable:
  405. on: change
  406. field: type.title
  407. value: Published
  408. manyToOne:
  409. type:
  410. targetEntity: Entity\Type
  411. inversedBy: articles
  412. ```
  413. Now few operations to get it all done:
  414. ``` php
  415. <?php
  416. $article = new Article;
  417. $article->setTitle('My Article');
  418. $em->persist($article);
  419. $em->flush();
  420. // article: $createdBy, $updatedBy were set
  421. $type = new Type;
  422. $type->setTitle('Published');
  423. $article = $em->getRepository('Entity\Article')->findByTitle('My Article');
  424. $article->setType($type);
  425. $em->persist($article);
  426. $em->persist($type);
  427. $em->flush();
  428. // article: $publishedBy, $updatedBy were set
  429. $article->getPublishedBy(); // the user that published this article
  430. ```
  431. Easy like that, any suggestions on improvements are very welcome
  432. <a name="traits"></a>
  433. ## Traits
  434. You can use blameable traits for quick **createdBy** **updatedBy** string definitions
  435. when using annotation mapping.
  436. **Note:** this feature is only available since php **5.4.0**. And you are not required
  437. to use the Traits provided by extensions.
  438. ``` php
  439. <?php
  440. namespace Blameable\Fixture;
  441. use Gedmo\Blameable\Traits\BlameableEntity;
  442. use Gedmo\Mapping\Annotation as Gedmo;
  443. use Doctrine\ORM\Mapping as ORM;
  444. /**
  445. * @ORM\Entity
  446. */
  447. class UsingTrait
  448. {
  449. /**
  450. * Hook blameable behavior
  451. * updates createdBy, updatedBy fields
  452. */
  453. use BlameableEntity;
  454. /**
  455. * @ORM\Id
  456. * @ORM\GeneratedValue
  457. * @ORM\Column(type="integer")
  458. */
  459. private $id;
  460. /**
  461. * @ORM\Column(length=128)
  462. */
  463. private $title;
  464. }
  465. ```
  466. **Note:** you must import **Gedmo\Mapping\Annotation as Gedmo** and **Doctrine\ORM\Mapping as ORM**
  467. annotations. If you use mongodb ODM import **Doctrine\ODM\MongoDB\Mapping\Annotations as ODM** and
  468. **BlameableDocument** instead.
  469. Traits are very simple and if you use different field names I recomment to simply create your
  470. own ones based per project. These ones are standing as an example.