Unable to pass class instance to constructor

I have a user model that accepts an instance of the UserMailer class in its constructor, but I get this error

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 

I understand the error, but I can’t understand what I did wrong, but I am not very good at class names and class classes and vs psr0. I remember how to use the dump-autoload linker, so this is not the case.

folder structure

 composer.json app/ models/ User.php TrainerCompare/ Mailers/ Mailer.php UserMailer.php Services/ Validation/ 

startup section composer.json. The psr-0 section is when I added the validation service, which you can see in TrainerCompare /, and these classes work fine. I added the / TrainerCompare / Mailers application to classmap for the tutorial that I am following to load mailbox classes

 "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/" } } 

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; } } 

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); }); } } 

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); } } 
+2
source share
1 answer

The eloquent (re) creates himself internally, causing:

 new static 

An example is creating a new query:

 return with(new static)->newQuery(); 

I'm not sure that automatic dependency resolution will work in this case, it should always work inside laravel, but since it also has its own constructor method, you should at least redirect the call and support the $attribute parameter:

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

EDIT

Opened a problem to understand it: https://github.com/laravel/framework/issues/3862

EDIT 2

As I said in a comment, it’s better to create a service, as indicated by ourselves, is the best design of the application. You should not use your model to send email. A service will work best that receives a user model (or just a name and email address) and sends a message to that user.

The answer given by Taylor Otuel about this in the issue:

Models are not really designed to have dependencies introduced. I think this is just an ORM ActiveRecord style. I would suggest passing the user to the Mailer class or something similar. Or, if you like it, you can use App :: make to grab the Mail instance from the model instance, especially if you only need this dependency from one method.

+3
source

Source: https://habr.com/ru/post/1235633/


All Articles