Search code examples
phpslimswiftmailerfortrabbit

Slim - Swift Mailer on the route is work but if after moved on controller get errors


I add libraries slimcontroller and swift mailer in my slim project, when in route goes well:

Route::get('/send', function() use ($app, $mailer) {

$message = Swift_Message::newInstance('Activation Code')
                ->setFrom(array('xxx@gmail.com' => 'xxx'))
                ->setTo(array('xxxs@gmail.com' => 'xxxs'))
                ->setBody('Test');

// Send the message
$results = $mailer->send($message);

// Print the results, 1 = message sent!
print($results);
});

but after a run on the controller there is an error

class MyController extends \SlimController\SlimController
{

    public function getRegisters()
    {
        $data = (empty(\Session::flash())) ? array(
            'token' => \Token::getToken()
        ) : array_merge(\Session::flash(), array(
            'token' => \Token::getToken()
        ));

        return $this->render('auth/register.html', $data);
    }
    public function postRegisters()
    {
        $message = Swift_Message::newInstance('Activation Code')->setFrom(array(
            'xxx@gmail.com' => 'xxx'
        ))->setTo(array(
            'xxxs@gmail.com' => 'xxxs'
        ))->setBody('Test');

        // Send the message
        $results = $this->app->mailer->send($message);
    }
}

Fatal error: Call to a member function send() on a non-object in.
I reference from fortrabbit/slimcontroller


Solution

  • I'm just guessing here (since I don' have your full Controller code) that your controller's $this->app is empty. Slim won't inject the $app object in your controllers.

    There are several ways to inject dependencies with Slim. I'm not entirely sure what's the best practice here. But I'd start looking here.

    Also, you can do some nasty hack in your controllers __construct. Although I don't recommend it, it would look something like:

    class Controller {
        protected $app;
        public function __construct()
        {
             $this->app = \Slim\Slim::getInstance();
        }
    }
    

    If you are sure that your controller have the $app property, then the problem is how you inject your $mailer instance. As I see from your routes, you're passing both the $app and the $mailer to the closure.

    You can inject that mailer object into your app as a singleton. The code should be something like:

    $app->mailer = function() {
       $mailer = new WhateverMailerYouAreUsing();
       // ...config stuff...
    
       return $mailer;
    };