You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Laravel项目Github Action执行失败:key生成时数据库连接拒绝

问题描述

我在Laravel项目中配置了如下GitHub Action工作流文件:

name: Laravel

on:
  push:
      branches: [ "main" ]
  pull_request:
      branches: [ "main" ]

jobs:
  laravel-tests:

  runs-on: ubuntu-latest

  steps:
  - uses: shivammathur/setup-php@15c43e89cdef867065b0213be354c2841860869e
    with:
      php-version: '8.1'
  - uses: actions/checkout@v3
  - name: Copy .env
    run: php -r "file_exists('.env') || copy('.env.example', '.env');"
  - name: Install Dependencies
    run: composer install -q --no-ansi --no-interaction --no-scripts --no-progress --prefer-dist
- name: Generate key
  run: php artisan key:generate
- name: Directory Permissions
  run: chmod -R 777 storage bootstrap/cache
- name: Create Database
  run: |
    mkdir -p database
    touch database/database.sqlite
- name: Execute tests (Unit and Feature tests) via PHPUnit
  env:
    DB_CONNECTION: sqlite
    DB_DATABASE: database/database.sqlite
  run: vendor/bin/phpunit

同时我使用了GenreServiceProvider,代码如下:

$allGenres = Genre::where('isActive', 1)->orderBy('name')->get();
View::share([
    'allGenres' => $allGenres,
]);

在执行php artisan key:generate步骤时出现如下错误:

SQLSTATE[HY000] [2002] Connection refused (Connection: mysql, SQL: select * from `genres` where `isActive` = 1 and `genres`.`deleted_at` is null order by `name` asc)

注释GenreServiceProvider中的代码后项目可正常运行,但我希望它在GitHub Action中也能正常工作,请问该如何解决?

问题原因

Laravel服务提供者的boot方法会在应用启动阶段执行,而php artisan key:generate命令会触发完整的应用启动流程。此时GitHub Action环境中还未完成数据库配置:

  1. 执行key:generate时,.env是从.env.example复制的默认配置,数据库连接为mysql,但Action环境没有启动MySQL服务
  2. SQLite数据库文件尚未创建,连接配置也未切换到SQLite

因此服务提供者启动时执行的数据库查询会因无法连接数据库而报错。

解决方案

方案1:延迟执行数据库查询(推荐)

不在服务提供者的boot方法中直接执行查询,改用视图合成器或懒加载,仅在实际使用数据时才执行查询:

// GenreServiceProvider.php
public function boot()
{
    // 视图合成器:仅当指定视图被渲染时才查询数据
    View::composer(['layouts.app', 'your.target.views'], function ($view) {
        $view->with('allGenres', Genre::where('isActive', 1)->orderBy('name')->get());
    });

    // 或者全局懒加载:仅当视图调用$allGenres时才执行查询
    // View::share('allGenres', function () {
    //     return Genre::where('isActive', 1)->orderBy('name')->get();
    // });
}

这种方式下,key:generate这类不涉及视图渲染的命令不会触发数据库查询,自然不会报错。

方案2:提前配置数据库环境变量

调整GitHub Action步骤顺序,在执行key:generate前就设置好SQLite连接配置,让应用启动时使用SQLite而非默认的MySQL:

# ... 原有步骤 ...
- name: Copy .env
  run: php -r "file_exists('.env') || copy('.env.example', '.env');"
# 添加此步骤,写入SQLite配置到.env
- name: Set SQLite Database Config
  run: |
    echo "DB_CONNECTION=sqlite" >> .env
    echo "DB_DATABASE=database/database.sqlite" >> .env
- name: Generate key
  run: php artisan key:generate
# ... 后续步骤 ...

或者直接在Generate key步骤中注入环境变量:

- name: Generate key
  env:
    DB_CONNECTION: sqlite
    DB_DATABASE: database/database.sqlite
  run: php artisan key:generate

SQLite会自动创建不存在的数据库文件,不会出现连接拒绝的问题。

方案3:在服务提供者中判断执行环境

在服务提供者中判断当前是否为命令行环境,且不是测试相关命令,若是则跳过数据库查询:

// GenreServiceProvider.php
use Illuminate\Support\Str;

public function boot()
{
    // 跳过命令行下的非测试命令
    if (app()->runningInConsole() && !Str::contains(request()->server('argv')[0] ?? '', ['phpunit', 'test'])) {
        return;
    }

    $allGenres = Genre::where('isActive', 1)->orderBy('name')->get();
    View::share([
        'allGenres' => $allGenres,
    ]);
}

内容的提问来源于stack exchange,提问作者Taleh Orujov

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.07 10:22:47