【问题标题】:CakePHP 3.x Using Controller Methods in ShellCakePHP 3.x 在 Shell 中使用控制器方法
【发布时间】:2017-09-16 08:11:01
【问题描述】:

我正在尝试在我的应用程序中发送后台电子邮件。

我正在制作一个 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;
  }
}

但是,当我使用 bin/cake email 通过命令行终端运行 shell 时

我收到以下错误:

异常:调用未定义的方法 Cake\Core\App::import() in [/home/cabox/workspace/src/Shell/EmailShell.php,第 7 行]

【问题讨论】:

  • stackoverflow.com/questions/28511023/…用控制器替换组件,答案完全一样。可能被标记为它的副本。
  • @burzum 那么您还建议如何在后台发送电子邮件?没有任何在线资源可以做到这一点,我正在努力寻找 CakePHP 3.x 的详细和最新指南

标签: php shell cakephp cron


【解决方案1】:

正如the answer 中针对 cme​​ts 中链接的问题所指出的,您根本不应该在外壳中使用控制器。该代码应该在您的模型中,例如在查找器中,或者只是一个常规的类方法。

还应该注意,分页器的使用与方法名称相矛盾,即“查找所有”,但默认情况下,分页器最多只能找到 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 自动加载,那里的调用应该会触发错误。

另见

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-11-09
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多