如何使用Laravel通过复杂的未取代查询来发送电子邮件(〜1-2 mbytes)的批处理流程。
#php #laravel #howto

出于某种原因,在我当前的工作中,我需要从非最佳SQL查询中处理数据,然后将结果发送到CSV中。我只有一个PHP Laravel系统。

因此有一些局限性:

  1. 内存:使用Laravel的DB层,因为:
    1. SQL复杂性,我需要执行查询一旦分页提供了不使用
    2. resultset尺寸:我无法获取结果altodecter
  2. 电子邮件限制:CSV可能很大。即使被压缩,我也无法将其发送。

对于1.1和1.2,我们可以使用发送电子邮件的控制台命令。作业代表数据误解需要时间是没有时间的。

他们有以下选项:

  1. 使用&触发命令:

      shell_exec("php artisan data:crunch &");
    

    您可以看到,我们避免使用Artisan类,因为我们需要将命令运行到后台。为了做到这一点

  2. 使用cron:

    '
    
    
    In this case as you can see at `./app/Console/Kernel.php` we utilize the `runInBackground` method.
    

命令本身应直接使用PDO而不是Laravel的DB层。为此使用以下代码

namespace App\Console\Commands;

use Illuminate\Console\Command;
use Illuminate\Support\Facades\DB;

class MyCommand extends Command
{
   // COmmand Definitions are ommited

  public function handle()
  {
    // COmplex SQL
    $sql = "...";
    $pdo = DB::getPdo();

    $stmt = $pdo->prepare();

    while($item = $stmt->fetch(\PDO::FETCH_NUM)){
      // GEN CSV here
    }
  }
}

用于多个DB连接的使用(将my_connection替换为在./config/database.php上定义的合适的连接):

  DB::connection('my_connection')->getPdo();

对于CSV,您需要拥有足够的磁盘空间,需要遵循此算法:

  1. 使用php的file()fputcsv保存storage_path();
     $fp = fopen(storage_path('mycsv.csv','w');
     while($item = $stmt->fetch(\PDO::FETCH_NUM)){
        fputcsv($fp,$item);
        fflush($fp);
     }
     fclose($fp);

由于内存限制,我们需要逐行构建文件,而不是Laravel的API提供的一键。 fflush()确保在终止意外终止时编写线。

  1. 然后将其上传到:
    1. S3存储桶作为静态网站托管或通过CDN
    2. 提供
    3. Azure Blob存储
    4. 进入单独的FTP服务器。
    5. 任何可访问的存储 4.将电子邮件发送给接收器。在此电子邮件中,您需要将文件的URL放在其中。

这个想法是,我们需要一个URL,最终用户需要在其中下载文件。因此,我们需要将文件上传到能够提供公共可用URL的存储中。并发送此电子邮件。原因是因为邮箱无法处理大型文件。

另外,如果使用CDN,则如果可能的话,可以通过签名的URL提供文件。