U8DatabaseServerService.php 2.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192
  1. <?php
  2. namespace App\Service;
  3. use Illuminate\Support\Facades\Config;
  4. use Illuminate\Support\Facades\DB;
  5. class U8DatabaseServerService
  6. {
  7. public $db = null;
  8. public $error = null; // 错误信息存储
  9. private $database = "";
  10. private $connName = "";
  11. public function __construct($loginUser = [])
  12. {
  13. $this->database = $loginUser['zt_database'] ?? "";
  14. if (empty($this->database)) {
  15. $this->error = "账套数据库名称不能为空";
  16. return;
  17. }
  18. $this->connName = 'sqlsrv_dynamic_' . md5($this->database);
  19. $this->createConnection();
  20. }
  21. /**
  22. * 创建 SQL Server 连接
  23. */
  24. private function createConnection()
  25. {
  26. $mainConnName = $this->connName;
  27. $mainConfig = [
  28. 'driver' => 'sqlsrv',
  29. 'host' => env('SQLSRV_HOST'),
  30. 'port' => env('SQLSRV_PORT'),
  31. 'database' => $this->database,
  32. 'username' => env('SQLSRV_USERNAME'),
  33. 'password' => env('SQLSRV_PASSWORD'),
  34. 'options' => [
  35. \PDO::SQLSRV_ATTR_QUERY_TIMEOUT => 15, // 查询超时
  36. \PDO::ATTR_ERRMODE => \PDO::ERRMODE_EXCEPTION,
  37. ],
  38. 'charset' => 'utf8',
  39. 'prefix' => '',
  40. ];
  41. try {
  42. // 1. 动态注入配置
  43. Config::set("database.connections.{$mainConnName}", $mainConfig);
  44. // 2. 获取连接句柄
  45. $this->db = DB::connection($mainConnName);
  46. // 3. 验证连接(执行一次 SELECT 1)
  47. // 注意:SQLServer 有时候会因为防火墙或网络伪连,这里必须 try 才能抓到错误
  48. $this->db->getPdo();
  49. } catch (\Throwable $e) {
  50. $this->error = "SQLServer连接验证失败: " . $e->getMessage();
  51. // 如果连接失败,清理掉无效配置
  52. $this->close();
  53. }
  54. }
  55. /**
  56. * 手动关闭并清理连接 (非常关键)
  57. * 特别是在 Command 脚本中,不调用这个会导致数据库句柄残留
  58. */
  59. public function close()
  60. {
  61. try {
  62. if ($this->connName) {
  63. // 1. 断开物理连接
  64. DB::disconnect($this->connName);
  65. // 2. 从 Laravel 的连接池中彻底清除
  66. DB::purge($this->connName);
  67. // 3. 移除动态注入的 Config
  68. Config::offsetUnset("database.connections.{$this->connName}");
  69. }
  70. } catch (\Throwable $e) {
  71. // 忽略清理时的异常
  72. } finally {
  73. $this->db = null;
  74. }
  75. }
  76. }