12

I'm trying to send an email from a CakePHP shell just as you would from the Controller.

Most of the code below was adapted from this dated article on the Bakery and it's comments. The email is sending, however the line $controller->set('result', $results[$i]); throws the following notices:

Notice: Undefined property: View::$webroot in /home/jmccreary/www/intranet.sazerac.com/cakephp/cake/libs/view/view.php on line 813

PHP Notice: Undefined variable: result in /home/jmccreary/www/intranet.sazerac.com/cakephp/app/views/elements/email/text/nea/task_reminder_it.ctp on line 2

So I'm not getting any of the variables passed to my email view.

How can I do this, ideally following the Cake conventions?

class NotificationShell extends Shell {
    var $uses = array('Employee', 'Task');

    function main() {
        // run if no action is passed
    }

    function nea_task_reminder() {
        // build Task to Employee relationship
        $this->Task->bindModel(array('belongsTo' => array('Employee' => array('className' => 'Employee', 'foreignKey' => 'object_id'))));
        $results = $this->Task->find('all', array('conditions' => array('application_id' => 1, 'completed_by_id' => 0), 'contain' => array('Employee' => array('Contact', 'Position'))));

        $count = count($results);
        if ($count) {
            App::import('Core', 'Controller');
            App::import('Component', 'Email');
            $controller =& new Controller();
            $email =& new EmailComponent();
            $email->startup($controller);

            // send email
            $email->from = Configure::read('Email.from');
            $email->to = 'jmccreary@whatever.com';
            $email->replyTo = 'no-reply@whatever.com';
            $email->template = 'nea/task_reminder_it';
            $email->sendAs = 'text';

            for ($i = 0; $i < $count; ++$i) {
                $email->subject = 'NEA Notification: Task Reminder for ' . $results[$i]['Employee']['Contact']['full_name'];
                $controller->set('result', $results[$i]);
                $email->send();
            }
        }
    }
}
Jason McCreary
  • 71,546
  • 23
  • 135
  • 174

4 Answers4

16

The problem is the way you're initializing the EmailComponent class. If you look at the source code, the startup() method doesn't actually have a body so it does nothing. Your controller isn't actually assigned to the EmailComponent. The problem isn't $controller->set('results', ...);. You need to use EmailComponent::initialize() instead of EmailComponent::startup().

$controller =& new Controller();
$email =& new EmailComponent(null);
$email->initialize($controller);

Sources:

  1. Comments section of http://bakery.cakephp.org/articles/Jippi/2007/12/02/emailcomponent-in-a-cake-shell
  2. EmailComponent::startup() Source
Francois Deschenes
  • 24,816
  • 4
  • 64
  • 61
13

If you're using CakePHP 2.x, you can ditch the EmailComponent entirely and use the CakeEmail class instead.

App::uses('CakeEmail', 'Network/Email');

class NotificationShell extends Shell {
    public function send() {
        $email = new CakeEmail();
    }
}

That entirely avoids all the thorny issues of loading components inside a shell. For email at least.

Brad Koch
  • 19,267
  • 19
  • 110
  • 137
1

If you're using CakePHP 2.x, try to use CakeEmail instead.

CakeEmail#viewVars() provides setting variables to template.

Here is example using CakeEmail from Shell. https://gist.github.com/tsmsogn/cee9cef2e851e7684021

tsmsogn
  • 11
  • 2
-1

Try this.

App::import('Core', 'Controller');
App::import('Component', 'Email');
$this->Controller =& new Controller();
$this->Email =& new EmailComponent(null);
$this->Email->initialize($this->Controller);    

//use set function as below  
$this->controller->set('result', $results[$i]);

for more reference click on below link:

http://ask.cakephp.org/questions/view/cron_shell_-_mail

Sanjeev Chauhan
  • 3,977
  • 3
  • 24
  • 30