2017-09-16 99 views
0

我想在我的應用程序中做後臺電子郵件發送。CakePHP 3.x在Shell中使用控制器方法

我正在製作一個shell,我最終將安排通過crontask來運行。

我試圖跑在我的EmailShell下面的代碼:

<?php 
namespace App\Shell; 

use Cake\Console\Shell; 
use Cake\Core\App; 

App::import('Controller', 'Messages'); 

class EmailShell extends Shell{ 
    public function main(){ 
     //Check for unsent emails 
     $messagesCont = new MessagesController; 
     $messages = $messagesCont->findAllUnsent(); 

     //Send all unsent emails 
     foreach ($messages as $message){ 
     $email = new Email(); 

     $email->to($messages->receiver) 
      ->subject($message->subject) 
      ->send($message->body); 
     } 
     //Update the table to be marked as sent 
    } 
} 
?> 

,我從MessagesController需要的代碼是這樣的:

public function findAllUnsent(){ 
    $messages = $this->paginate($this->Messages); 

    foreach ($messages as $message){ 
     if ($message->sent == false){ 
     //If message is unsent then add it to the array 
     $messagesFound[] = $message; 
     } 
    } 
    //Return the array of unsent messages 
    return $messagesFound; 
    } 
} 

然而,當我通過運行shell命令行終端使用bin/cake email

我收到以下錯誤:

Exception: Call to undefined method Cake\Core\App::import() in [/home/cabox/workspace/src/Shell/EmailShell.php, line 7]

+1

https://stackoverflow.com/questions/28511023/how-to-load-a-component-in-console-shell取代組件與控制器和答案是完全一樣的。可以標記爲它的副本。 – burzum

+0

@burzum那麼你會如何建議在後臺做電子郵件?沒有任何資源可以做到這一點,我正努力爲CakePHP 3.x找到詳細的最新指南。 –

回答

0

正如在the answer中指出的那樣,在註釋中鏈接的問題中,根本不應該在shell中使用控制器。該代碼應該放在你的模型中,例如在查找器中,或者只是一個普通的類方法。

還應該注意的是,paginator的使用與方法名稱相矛盾,方法名稱爲「find all」,但paginator默認只會查找最多20條記錄。此外,我建議過濾SQL級別的記錄,以便您只接收實際需要的記錄,之後減少它們將打破分頁,因爲它使用爲原始結果計算的數字進行操作。

所以在你MessagesTable類添加例如自定義查找,如:

public function findUnsent(\Cake\ORM\Query $query, array $options) 
{ 
    return $query->where([ 
     $this->aliasField('sent') => false 
    ]); 
} 

而在你的shell中使用的模型,如:

class EmailShell extends Shell 
{ 
    use Cake\ORM\Locator\LocatorAwareTrait; 

    public function main() 
    { 
     // tableLocator() before CakePHP 3.5 
     $MessagesTable = $this->getTableLocator()->get('Messages'); 
     $unsentMessages = $MessagesTable->find('unsent'); 

     foreach ($unsentMessages as $message) { 
      // ... 
     } 
    } 
} 
相若方式

你會使用取景器中,然後您的控制器也是這樣,並將查詢傳遞給paginate()方法。

順便說一句,沒有App::import()了,CakePHP 3.x現在使用Composer自動加載,那個調用應該會觸發一個錯誤。

又見