无法将类实例传递给构造函数

Mar*_*ark 3 php autoload laravel composer-php laravel-4

我有一个User雄心勃勃的模型,该模型在其构造函数中包含UserMailer类的实例,但出现此错误

Argument 1 passed to User::__construct() must be an instance of TrainerCompare\Mailers\UserMailer, none given, called in /var/www/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Model.php on line 631 and defined
Run Code Online (Sandbox Code Playgroud)

我理解该错误,但无法弄清楚我做错了什么,但是我不太了解命名空间和composer类映射与psr0自动加载的关系。我记得使用过composer dump-autoload,所以不是

相关文件夹结构

composer.json
app/
  models/
    User.php
  TrainerCompare/
    Mailers/
      Mailer.php
      UserMailer.php
    Services/
      Validation/
Run Code Online (Sandbox Code Playgroud)

composer.json自动加载部分。psr-0部分是从我添加验证服务后开始的,您可以在TrainerCompare /中看到这些类,它们的工作效果很好。我按照我遵循的教程将app / TrainerCompare / Mailers添加到类映射中,以加载mailer类

"autoload": {
        "classmap": [
            "app/commands",
            "app/controllers",
            "app/models",
            "app/database/migrations",
            "app/database/seeds",
            "app/tests/TestCase.php",
            "app/tests/helpers",
            "app/TrainerCompare/Mailers"
        ],
        "psr-0":{
            "TrainerCompare": "app/"
        }
    }
Run Code Online (Sandbox Code Playgroud)

User.php

<?php

use Illuminate\Auth\UserInterface;
use Illuminate\Auth\Reminders\RemindableInterface;
use TrainerCompare\Mailers\UserMailer as Mailer;

class User extends BaseModel implements UserInterface, RemindableInterface
{
    protected $mailer;

    public function __construct(Mailer $mailer)
    {
        $this->mailer = $mailer;
    }
}
Run Code Online (Sandbox Code Playgroud)

Mailer.php

<?php namespace TrainerCompare\Mailers;

use Mail;

/**
* Email mailing class
*/
abstract class Mailer
{

    public function __construct()
    {
        # code...
    }

    public function sendTo($user, $subject, $view, $data = [])
    {
        Maill::send($view, $data, function ($message) use ($user, $subject) {
            $message->to($user->email)
                    ->subject($subject);
        });
    }
}
Run Code Online (Sandbox Code Playgroud)

UserMailer.php

<?php namespace TrainerCompare\Mailers;

use User;

/**
* User Mailer Class
*/
class UserMailer extends Mailer
{

    public function __construct()
    {
        # code...
    }

    public function welcome($user)
    {
        $view = 'emails.users.welcome';
        $data = [];
        $subject = 'Welcome to Laracsts';

        return $this->sendTo($user, $subject, $view, $data);
    }
}
Run Code Online (Sandbox Code Playgroud)

Ant*_*iro 5

雄辩的(重新)内部通过调用以下内容创建自己:

new static
Run Code Online (Sandbox Code Playgroud)

一个示例是创建一个新查询:

return with(new static)->newQuery();
Run Code Online (Sandbox Code Playgroud)

我不确定自动依赖项解析是否在这种情况下会起作用,它应该始终在laravel内部起作用,但是由于它也具有自己的构造函数方法,因此您至少必须转发对其的调用并支持该$attribute参数:

public function __construct(array $attributes = array(), Mailer $mailer)
{
    $this->mailer = $mailer;

    parent::__construct($attributes);
}
Run Code Online (Sandbox Code Playgroud)

编辑

打开一个问题来理解它:https : //github.com/laravel/framework/issues/3862

编辑2

就像我在评论中所说的那样,您最好自己创建服务,这是更好的应用程序设计。您不应该使用模型来发送电子邮件。接收用户模型(或仅名称和电子邮件)并将消息发送给该用户的服务将是更好的方法。

Taylor Otwell在此问题上给出的答案:

模型并不是真的要以这种方式将依赖项注入模型中。我猜想,这只是ActiveRecord样式ORM的一种。我建议将User传递给Mailer类或类似的类。或者,如果您对此感到满意,则可以使用App :: make从模型实例中获取Mail的实例,特别是如果您只需要单个方法的依赖项时。