HasTimestamps.php 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224
  1. <?php
  2. namespace Illuminate\Database\Eloquent\Concerns;
  3. use Illuminate\Support\Facades\Date;
  4. trait HasTimestamps
  5. {
  6. /**
  7. * Indicates if the model should be timestamped.
  8. *
  9. * @var bool
  10. */
  11. public $timestamps = true;
  12. /**
  13. * The list of models classes that have timestamps temporarily disabled.
  14. *
  15. * @var array
  16. */
  17. protected static $ignoreTimestampsOn = [];
  18. /**
  19. * Update the model's update timestamp.
  20. *
  21. * @param string|null $attribute
  22. * @return bool
  23. */
  24. public function touch($attribute = null)
  25. {
  26. if ($attribute) {
  27. $this->$attribute = $this->freshTimestamp();
  28. return $this->save();
  29. }
  30. if (! $this->usesTimestamps()) {
  31. return false;
  32. }
  33. $this->updateTimestamps();
  34. return $this->save();
  35. }
  36. /**
  37. * Update the model's update timestamp without raising any events.
  38. *
  39. * @param string|null $attribute
  40. * @return bool
  41. */
  42. public function touchQuietly($attribute = null)
  43. {
  44. return static::withoutEvents(fn () => $this->touch($attribute));
  45. }
  46. /**
  47. * Update the creation and update timestamps.
  48. *
  49. * @return $this
  50. */
  51. public function updateTimestamps()
  52. {
  53. $time = $this->freshTimestamp();
  54. $updatedAtColumn = $this->getUpdatedAtColumn();
  55. if (! is_null($updatedAtColumn) && ! $this->isDirty($updatedAtColumn)) {
  56. $this->setUpdatedAt($time);
  57. }
  58. $createdAtColumn = $this->getCreatedAtColumn();
  59. if (! $this->exists && ! is_null($createdAtColumn) && ! $this->isDirty($createdAtColumn)) {
  60. $this->setCreatedAt($time);
  61. }
  62. return $this;
  63. }
  64. /**
  65. * Set the value of the "created at" attribute.
  66. *
  67. * @param mixed $value
  68. * @return $this
  69. */
  70. public function setCreatedAt($value)
  71. {
  72. $this->{$this->getCreatedAtColumn()} = $value;
  73. return $this;
  74. }
  75. /**
  76. * Set the value of the "updated at" attribute.
  77. *
  78. * @param mixed $value
  79. * @return $this
  80. */
  81. public function setUpdatedAt($value)
  82. {
  83. $this->{$this->getUpdatedAtColumn()} = $value;
  84. return $this;
  85. }
  86. /**
  87. * Get a fresh timestamp for the model.
  88. *
  89. * @return \Illuminate\Support\Carbon
  90. */
  91. public function freshTimestamp()
  92. {
  93. return Date::now();
  94. }
  95. /**
  96. * Get a fresh timestamp for the model.
  97. *
  98. * @return string
  99. */
  100. public function freshTimestampString()
  101. {
  102. return $this->fromDateTime($this->freshTimestamp());
  103. }
  104. /**
  105. * Determine if the model uses timestamps.
  106. *
  107. * @return bool
  108. */
  109. public function usesTimestamps()
  110. {
  111. return $this->timestamps && ! static::isIgnoringTimestamps($this::class);
  112. }
  113. /**
  114. * Get the name of the "created at" column.
  115. *
  116. * @return string|null
  117. */
  118. public function getCreatedAtColumn()
  119. {
  120. return static::CREATED_AT;
  121. }
  122. /**
  123. * Get the name of the "updated at" column.
  124. *
  125. * @return string|null
  126. */
  127. public function getUpdatedAtColumn()
  128. {
  129. return static::UPDATED_AT;
  130. }
  131. /**
  132. * Get the fully qualified "created at" column.
  133. *
  134. * @return string|null
  135. */
  136. public function getQualifiedCreatedAtColumn()
  137. {
  138. return $this->qualifyColumn($this->getCreatedAtColumn());
  139. }
  140. /**
  141. * Get the fully qualified "updated at" column.
  142. *
  143. * @return string|null
  144. */
  145. public function getQualifiedUpdatedAtColumn()
  146. {
  147. return $this->qualifyColumn($this->getUpdatedAtColumn());
  148. }
  149. /**
  150. * Disable timestamps for the current class during the given callback scope.
  151. *
  152. * @param callable $callback
  153. * @return mixed
  154. */
  155. public static function withoutTimestamps(callable $callback)
  156. {
  157. return static::withoutTimestampsOn([static::class], $callback);
  158. }
  159. /**
  160. * Disable timestamps for the given model classes during the given callback scope.
  161. *
  162. * @param array $models
  163. * @param callable $callback
  164. * @return mixed
  165. */
  166. public static function withoutTimestampsOn($models, $callback)
  167. {
  168. static::$ignoreTimestampsOn = array_values(array_merge(static::$ignoreTimestampsOn, $models));
  169. try {
  170. return $callback();
  171. } finally {
  172. static::$ignoreTimestampsOn = array_values(array_diff(static::$ignoreTimestampsOn, $models));
  173. }
  174. }
  175. /**
  176. * Determine if the given model is ignoring timestamps / touches.
  177. *
  178. * @param string|null $class
  179. * @return bool
  180. */
  181. public static function isIgnoringTimestamps($class = null)
  182. {
  183. $class ??= static::class;
  184. foreach (static::$ignoreTimestampsOn as $ignoredClass) {
  185. if ($class === $ignoredClass || is_subclass_of($class, $ignoredClass)) {
  186. return true;
  187. }
  188. }
  189. return false;
  190. }
  191. }