laravel module 接口不能实例化解决办法

背景

laravel 项目在测试服务器报错

Target [Modules\Chip\Repository\ChipServiceInterface] is not instantiable while building [App\Http\Controllers\Api\Service\ChipController].

前提是已经在对应 module 的 ServiceProvider 中绑定了该接口实例化的类

namespace Modules\Chip\Providers;

use Illuminate\Support\ServiceProvider;
use Illuminate\Database\Eloquent\Factory;
use Modules\Chip\Repository\ChipService;
use Modules\Chip\Repository\ChipServiceInterface;

class ChipServiceProvider extends ServiceProvider
{
    ...
    /**
     * Register the service provider.
     *
     * @return void
     */
    public function register()
    {
        $this->app->register(RouteServiceProvider::class);
        $this->app->bind(ChipServiceInterface::class,ChipService::class);
    }    
}

解决办法

从报错反推来看,是ServiceProvider没有被正确加载的问题,所以在 config/app.php 里添加上 \Modules\Chip\Providers\ChipServiceProvider::class, 即可解决

    /*
    |--------------------------------------------------------------------------
    | Autoloaded Service Providers
    |--------------------------------------------------------------------------
    |
    | The service providers listed here will be automatically loaded on the
    | request to your application. Feel free to add your own services to
    | this array to grant expanded functionality to your applications.
    |
    */

    'providers' => [
        ...
        \Modules\Chip\Providers\ChipServiceProvider::class,
    ]

由于本地没有出现这个问题,而代码传到测试服就会报这个错,从而代码比对本地与测试服的区别找问题。
排查出来的结果是测试服上缺少了 storageappmodules_statuses.json 这个文件,文件的内容如下:

{
    "User": true,
    "Game": true,
    "Activity": true,
    "Article": true,
    "Chip":true
}

从项目中全局找文件被引用的代码,即可发现在 vendornwidartlaravel-modulesconfig 有引用到:

    /*
    |--------------------------------------------------------------------------
    | Activators
    |--------------------------------------------------------------------------
    |
    | You can define new types of activators here, file, database etc. The only
    | required parameter is 'class'.
    | The file activator will store the activation status in storage/installed_modules
    */
    'activators' => [
        'file' => [
            'class' => FileActivator::class,
            'statuses-file' => storage_path('app/modules_statuses.json'),
            'cache-key' => 'activator.installed',
            'cache-lifetime' => 604800,
        ],
    ],

出现问题的原因是 storage/ 作为缓存目录,已经被忽略添加到git版本控制中了。
而使用 php artisan module:make Chip 创建 module 的时候则会在 storageappmodules_statuses.json 这个文件中生成一行 "Chip":true

所以解决方法只需要把 storageappmodules_statuses.json 这个文件传到服务器或者加入到版本控制中即可。

Responses