2017-09-16 90 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自动加载,那个调用应该会触发一个错误。

又见

相关问题