2015-06-02 3 views
2

В CakePHP 2.X для одного из моих действий с контроллером я пытаюсь отправить электронное письмо всем пользователям каждый раз, когда создается новая запись.Cakephp не перенаправляется после отправки электронной почты через CakeEmail

Обновлено с предложениями drmonkeyninja по:

// NewslettersContoller.php 

public function add() { 
    if($this->request->is('post')) { 
    $this->Newsletter->create(); 

    if($this->Newsletter->save($this->request->data)) { 
     $this->Session->setFlash(__('Your newsletter has been submited.')); 
     $this->redirect(array('action' => 'view', $this->Newsletter->id)); 
    } 
    else { 
     $this->Session->setFlash(__('Unable to add your post.')); 
     return $this->redirect(array('action' => 'add')); 
    } 
} 
} 

// Newsletter.php 
public function afterSave($created, $options = []) { 
    parent::afterSave($created, $options); 
    if ($created === true) { 
    $newsletter = $this->findById($this->id); 

    // Get all users with an email address. 
    $emails = ClassRegistry::init('User')->find(
     'list', 
     array(
      'fields' => array(
       'User.id', 
       'User.email' 
      ), 
      'conditions' => array(
       'User.email <>' => null 
      ) 
     ) 
    ); 

    $Email = new CakeEmail('gmail'); 
    $Email->from(array('[email protected]' => 'Caprock Portal')); 
    $Email->to($emails); 
    $Email->subject($newsletter['Newsletter']['title']); 
    $Email->message($newsletter['Newsletter']['content']); 
    try { 
     $Email->send(); 
    } catch (Exception $exception) { 
     $this->log($exception); 
    } 
    } 
} 

Как вы можете видеть из фрагмента кода, я использую CakeEmail отправить каждому пользователю письмо, содержащее бюллетень, созданный в действии. К сожалению, по какой-то причине каждый раз, когда CakeEmail заканчивает отправку электронной почты, CakePHP игнорирует мой запрос на перенаправление и переходит к визуализации пустого представления (маршрут все еще добавляется). Я проверил, что это функция CakeEmail, комментируя ее и проверяя, что перенаправление начинает работать снова. Ничего не поймано в блоке try-catch.

Одно из моих предположений о причине этой проблемы состоит в том, что заголовки электронной почты вмешиваются в заголовки переадресации для моего действия. Я проверил сетевые запросы через мой браузер, но ничего не отправляется, кроме как из исходного запроса на отправку в функцию добавления.

+0

удалите 'return' и проверьте. –

+0

Пожалуйста, проверьте и сообщите, что произойдет? –

+0

nop, ничего. Сохраняет пустой вид –

ответ

0

Вы также можете попробовать указать контроллер в массиве URL:

if($Email->send()) { 
    return $this->redirect(
      array('controller' => 'controller_name', 'action' => 'view', $id) 
     ); 
} else { 
    return $this->redirect(
      array('controller' => 'controller_name', 'action' => 'add') 
     ); 
}   
+0

Я пробовал это сначала, но CakePHP по-прежнему не перенаправляет. –

+0

Перейдите в 'app/tmp/logs/error.log' Посмотрите, что дает системная ошибка – Supravat

+0

Просто проверил журналы, ничего. Я вижу другие ошибки, но при отправке писем ничего не регистрируется. –

0

Снимите var_dump. Он прерывает HTTP-протокол, если вы пытаетесь отправить информацию заголовка (для перенаправления) после. Содержимое было отправлено.

+0

Я забыл удалить var_dump перед отправкой вопроса. Проблема сохраняется и без var_dump. Я просто поставил как средство для проверки заголовков, созданных функцией отправки. –

+0

Вы получаете * любой * вывод, когда сбой перенаправления? – Populus

+0

, когда я использую var_dump, я могу видеть заголовки для функции отправки. Представление полностью пустое, если я удалю var_dump. –

2

Было бы лучше, чтобы отправить по электронной почте от модели Информационного бюллетеня в afterSave() обратного вызова: -

// app/Model/Newsletter.php 

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

public function afterSave($created, $options = []) { 
    parent::afterSave($created, $options); 
    if ($created === true) { 
     $newsletter = $this->findById($this->id); 

     // Get all users with an email address. 
     $emails = ClassRegistry::init('User')->find(
      'list', 
      array(
       'fields' => array(
        'User.id', 
        'User.email' 
       ), 
       'conditions' => array(
        'User.email <>' => null 
       ) 
      ) 
     ); 

     $Email = new CakeEmail('gmail'); 
     $Email->from(array('[email protected]' => 'Caprock Portal')); 
     $Email->to($emails); 
     $Email->subject($newsletter['Newsletter']['title']); 
     $Email->message($newsletter['Newsletter']['content']); 
     try { 
      $Email->send(); 
     } catch (Exception $exception) { 
      $this->log($exception); 
     } 
    } 
} 

Ваше действие контроллера будет тогда просто: -

// app/Controller/NewslettersController.php 
public function add() { 
    if ($this->request->is('post')) { 
     $this->Newsletter->create(); 
     if ($this->Newsletter->save($this->request->data)) { 
      return $this->redirect(array('action' => 'view', $this->Newsletter->id)); 
     } else { 
      $this->Session->setFlash(__('Unable to add your post.')); 
      return $this->redirect(array('action' => 'add')); 
     } 
    } 
} 

Если посмотреть еще не рендеринг, а затем временно отключить обратный вызов afterSave(), чтобы проверить, что часть контроллера работает должным образом при сохранении вашего бюллетеня.

Обратите внимание, что вы можете отфильтровывать пользователей без адреса электронной почты при извлечении пользователей из базы данных. Используя find('list'), вам не нужно связываться с циклом foreach.

Вам также не нужно использовать $this->Newsletter->getLastInsertId();, так как $this->Newsletter->id должен был быть установлен на это во время сохранения.

Метод debug() Cake лучше использовать при отладке переменных, чем var_dump(), который, кстати, не будет работать в вашем примере, поскольку вы перенаправляете после его выхода!

+0

Это похоже на хорошую альтернативу. Я попробую его и отчитаюсь, если это сработает. Кстати, спасибо за подсказку функции debug(), я понятия не имел. Хотя, var_dump работает, как я его устанавливаю, так как моя функция не перенаправляется. Пустая страница, которая отображается, отображает var_dump, который в этом случае является заголовками электронной почты. –

+0

Я просто попробовал, и он все еще останавливает перенаправление. Я отключил обратный вызов, чтобы убедиться, что это не проблема контроллера. Контроллер работает без обратного вызова и перестает работать, как только я включу его снова. –

+0

Помните, что вы включили библиотеку CakeEmail, используя 'App :: uses ('CakeEmail', 'Network/Email');'? Я только что обновил свой примерный код, чтобы показать это в модели. – drmonkeyninja

0

Другой альтернативой является отправка электронной почты в виде консоли/консоли с помощью Cronjob.

Это ссылка на книгу, где вы можете найти кучу информации о создании оболочек.

CakePHP 3.x http://book.cakephp.org/3.0/en/console-and-shells.html

CakePHP 2.x http://book.cakephp.org/2.0/en/console-and-shells.html

Это исключает блокирует обработку.Если вы отправляете электронные письма в контроллере или модели, ваше приложение все еще ожидает отправки писем до того, как страница будет отображена или перенаправлена. Поэтому, перейдя на cronjob, у пользователя будет такой же лучший опыт, потому что они не ждут отправки писем.

Так как вы знаете, что отправить через оболочку ??? Хорошо, что зависит от вашего варианта использования, но я записываю флажки, которые нужно отправить с помощью столбца базы данных для этой цели, найти все те, которые не были отправлены, пометить найденные записи другим флагом как обработанные, второй флаг в базе данных предотвращает чтение двух заданий cron и отправку тех же записей, пока первая cronjob все еще обрабатывает. Мне нравится устанавливать мои cronjob для рассылки как можно меньше для писем типа транзакций, однако это может зависеть от хостинг-провайдера и их настроек.

+0

Это хорошее предложение, хотя оно не доходит до сути проблемы с описанием приложения. Я лично использую плагин Queue (ht tps: //github.com/dereuromark/cakephp-queue/tree/2.x), чтобы удалить необходимость отправки электронных писем с кодом. Это очень гибкий подход, чтобы избежать блокировки критических процессов. – drmonkeyninja

+0

Прохладный, я проверю этот плагин, спасибо за обмен.Я думаю, что удаление электронной почты с контроллера и/или модели и использование оболочек или плагин cakephp-queue имеет больше смысла, поскольку в противном случае перенаправление или рендеринг не произойдет до тех пор, пока сообщения не будут отправлены. Если есть ошибки SMTP или проблема с таймаутом, тогда встряхивание начинается с обновления пользователя, что может добавить к проблеме и навлечь людей нежелательными сообщениями электронной почты. Иногда я использую столбец для хранения количества неудачных попыток, отправляющих сообщение. Это удобно, если SMTP-сервер не работает, и вы знаете, что позже ваш cronjob попытается снова. – darensipes

Смежные вопросы