laravel 6 的服务容器通过路由分发或 app() 创建控制器实现依赖注入,构造函数注入为首选方式,接口需在服务提供者中显式绑定,方法注入适用于临时依赖。

Laravel 6 的服务容器是依赖注入(DI)的底层支撑,控制器中使用依赖注入的核心逻辑与后续版本一致,只是部分语法和默认配置略有差异。关键在于让容器接管控制器实例的创建,而不是手动 new。
控制器必须由路由系统或 app() 创建
Laravel 6 只对通过路由分发或 app() 获取的控制器执行自动依赖解析。如果你在事件、命令或测试中直接 new UserController(),类型提示会完全失效,报错如 Too few arguments to function。正确做法是:
- 访问对应路由(如
/users),由框架自动实例化并注入 - 或在需要时用
app(UserController::class)获取——它会递归解析全部构造函数参数
构造函数注入是最推荐的方式
把服务类作为参数写在控制器构造函数里,Laravel 会自动从容器取实例并赋值给属性:
use App\Services\UserService;
class UserController extends Controller
{
protected $userService;
public function __construct(UserService $userService)
{
$this->userService = $userService;
}
public function index()
{
$users = $this->userService->getAll();
return view('users.index', compact('users'));
}
}
只要 UserService 类本身没有无法解析的依赖(比如构造函数含未绑定的接口或原始值),容器就能顺利构建。
接口绑定需在服务提供者中显式声明
如果控制器依赖的是接口(如 UserRepositoryInterface),而该接口没有默认实现,必须在 AppServiceProvider@register() 中绑定:
use App\Contracts\UserRepositoryInterface;
use App\Repositories\EloquentUserRepository;
public function register()
{
$this->app->bind(UserRepositoryInterface::class, EloquentUserRepository::class);
}
注意:Laravel 6 不支持 PHP 8 的 ::class 常量简写(若用低版本 PHP),请确保命名空间字符串准确;绑定后可用 php artisan tinker 测试:app(UserRepositoryInterface::class) 应返回有效实例。
方法注入适合临时、条件性使用的依赖
某些服务只在某个动作中用到,且可能带运行时参数(如请求数据),可直接放在方法签名里:
public function store(Request $request, EmailService $emailService)
{
// $emailService 自动注入,$request 也是
$emailService->sendWelcome($request->email);
}
这种方式不占用整个控制器生命周期,也避免了构造函数过度臃肿。











