DbTarget.php 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100
  1. <?php
  2. /**
  3. * @link http://www.yiiframework.com/
  4. * @copyright Copyright (c) 2008 Yii Software LLC
  5. * @license http://www.yiiframework.com/license/
  6. */
  7. namespace yii\log;
  8. use Yii;
  9. use yii\base\InvalidConfigException;
  10. use yii\db\Connection;
  11. use yii\db\Exception;
  12. use yii\di\Instance;
  13. use yii\helpers\VarDumper;
  14. /**
  15. * DbTarget stores log messages in a database table.
  16. *
  17. * The database connection is specified by [[db]]. Database schema could be initialized by applying migration:
  18. *
  19. * ```
  20. * yii migrate --migrationPath=@yii/log/migrations/
  21. * ```
  22. *
  23. * If you don't want to use migration and need SQL instead, files for all databases are in migrations directory.
  24. *
  25. * You may change the name of the table used to store the data by setting [[logTable]].
  26. *
  27. * @author Qiang Xue <qiang.xue@gmail.com>
  28. * @since 2.0
  29. */
  30. class DbTarget extends Target
  31. {
  32. /**
  33. * @var Connection|array|string the DB connection object or the application component ID of the DB connection.
  34. * After the DbTarget object is created, if you want to change this property, you should only assign it
  35. * with a DB connection object.
  36. * Starting from version 2.0.2, this can also be a configuration array for creating the object.
  37. */
  38. public $db = 'db';
  39. /**
  40. * @var string name of the DB table to store cache content. Defaults to "log".
  41. */
  42. public $logTable = '{{%log}}';
  43. /**
  44. * Initializes the DbTarget component.
  45. * This method will initialize the [[db]] property to make sure it refers to a valid DB connection.
  46. * @throws InvalidConfigException if [[db]] is invalid.
  47. */
  48. public function init()
  49. {
  50. parent::init();
  51. $this->db = Instance::ensure($this->db, Connection::className());
  52. }
  53. /**
  54. * Stores log messages to DB.
  55. * Starting from version 2.0.14, this method throws LogRuntimeException in case the log can not be exported.
  56. * @throws Exception
  57. * @throws LogRuntimeException
  58. */
  59. public function export()
  60. {
  61. if ($this->db->getTransaction()) {
  62. // create new database connection, if there is an open transaction
  63. // to ensure insert statement is not affected by a rollback
  64. $this->db = clone $this->db;
  65. }
  66. $tableName = $this->db->quoteTableName($this->logTable);
  67. $sql = "INSERT INTO $tableName ([[level]], [[category]], [[log_time]], [[prefix]], [[message]])
  68. VALUES (:level, :category, :log_time, :prefix, :message)";
  69. $command = $this->db->createCommand($sql);
  70. foreach ($this->messages as $message) {
  71. list($text, $level, $category, $timestamp) = $message;
  72. if (!is_string($text)) {
  73. // exceptions may not be serializable if in the call stack somewhere is a Closure
  74. if ($text instanceof \Throwable || $text instanceof \Exception) {
  75. $text = (string) $text;
  76. } else {
  77. $text = VarDumper::export($text);
  78. }
  79. }
  80. if ($command->bindValues([
  81. ':level' => $level,
  82. ':category' => $category,
  83. ':log_time' => $timestamp,
  84. ':prefix' => $this->getMessagePrefix($message),
  85. ':message' => $text,
  86. ])->execute() > 0) {
  87. continue;
  88. }
  89. throw new LogRuntimeException('Unable to export log through database!');
  90. }
  91. }
  92. }