Search code examples
swiftmailersilextraits

Silex traits for swiftmailer. Fatal error: Call to undefined method Silex\Application::mail()


I am trying to use traits in Silex for Swift mailer.

I have included:

use Silex\Application\SwiftmailerTrait;

I also checked that traits file were in the right Silex vendor directory.

Test traits:

$app->mail(\Swift_Message::newInstance()
    ->setSubject("title")
    ->setFrom(["www.domain.com"]])
    ->setTo(["[email protected]"])
    ->setReplyTo(["[email protected]"])
    ->setBody("TEST MESSAGE")
);

Then, I get this error message:

Fatal error: Call to undefined method Silex\Application::mail() in ...\app.php on line 88

Just to make it clear. I can, without any issue, use standard way of using swift in Silex and it works just fine.

This is the working bit without traits:

    // $message = \Swift_Message::newInstance()
    // ->setSubject('[YourSite] Feedback')
    // ->setFrom(array('[email protected]'))
    // ->setTo(array('[email protected]'))
    // ->setBody($request->get('message'));
    // $app['mailer']->send($message);

However I was wondering what was actually stopping Silex from running swift with traits. Any idea ?

I am using PHP Version 5.6.11 My composer file:

{
    "require": {
        "components/jquery": "^2.2",
        "components/css-reset": "^2.5",
        "silex/silex": "~1.2",
        "symfony/browser-kit": "~2.3",
        "symfony/console": "~2.3",
        "symfony/config": "~2.3",
        "symfony/css-selector": "~2.3",
        "symfony/dom-crawler": "~2.3",
        "symfony/filesystem": "~2.3",
        "symfony/finder": "~2.3",
        "symfony/form": "~2.3",
        "symfony/locale": "~2.3",
        "symfony/process": "~2.3",
        "symfony/security": "~2.3",
        "symfony/serializer": "~2.3",
        "symfony/translation": "~2.3",
        "symfony/validator": "~2.3",
        "symfony/monolog-bridge": "~2.3",
        "symfony/twig-bridge": "~2.3",
        "doctrine/dbal": ">=2.2.0,<2.4.0-dev",
        "swiftmailer/swiftmailer": "5.*",
        "twig/twig": "^1.24",
        "symfony/security-csrf": "~2.3",
        "symfony/yaml": "~2.3"
    },
    "autoload": {
        "psr-4": {
            "WL\\Form\\": "WL/Form/",
            "WL\\Email\\": "WL/Email/"
        },
        "classmap":[],
        "files":[]
    }
}

Solution

  • You need to create a custom Application class which extends \Silex\Application and uses that trait.

    Assuming a base project tree as:

    project/
      |
      |_app/
      |
      |_src/
      |
      |_vendor/
      |
      |_web/
    

    You need a class definition:

    // src/WL/App.php
    
    namespace WL;
    
    class App extends \Silex\Application
    {
        use \Silex\Application\SwiftmailerTrait;
    
        // add some other trait
        // even custom methods or traits
    }
    

    A bootstrap :

    // app/bootstrap.php
    
    $app = new \WL\App();
    
    // configure it, register controllers and services, ...
    
    // or import them
    foreach (glob(__DIR__ . "/../src/WL/Controller/*.php") as $controllers_provider) {
        include_once $controllers_provider;
    }
    
    return $app;
    

    So you can import a controller collection like :

    // src/Wl/Controller/blog.php
    
    use Symfony\Component\HttpFoundation\Request;
    
    /** @var \Silex\ControllerCollection $blog */
    $blog = $app['controllers_factory'];
    
    // define some routes
    
    $blog->post('/send-mail', function (Request $request, \WL\App $app)
    {
        // Now this application passed to your controller is an
        // instance of custom \App which has the trait you want
        // in contrary with the default \Silex\Application
    
        $app->mail(...
    
    }
    
    $app->mount('/blog', $blog);
    

    And a front controller :

    // web/index.php
    
    // define autoloading
    // customize debug and server parameters
    
    $app = require_once '../app/bootstrap.php';
    
    $app->run();