出于某种原因,在我当前的工作中,我需要从非最佳SQL查询中处理数据,然后将结果发送到CSV中。我只有一个PHP Laravel系统。
因此有一些局限性:
- 内存:使用Laravel的DB层,因为:
- SQL复杂性,我需要执行查询一旦分页提供了不使用
- resultset尺寸:我无法获取结果altodecter
- 电子邮件限制:CSV可能很大。即使被压缩,我也无法将其发送。
对于1.1和1.2,我们可以使用发送电子邮件的控制台命令。作业代表数据误解需要时间是没有时间的。
他们有以下选项:
-
使用
&
触发命令:
shell_exec("php artisan data:crunch &");
您可以看到,我们避免使用
Artisan
类,因为我们需要将命令运行到后台。为了做到这一点 -
使用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,您需要拥有足够的磁盘空间,需要遵循此算法:
- 使用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()
确保在终止意外终止时编写线。
- 然后将其上传到:
- S3存储桶作为静态网站托管或通过CDN 提供
- Azure Blob存储
- 进入单独的FTP服务器。
- 任何可访问的存储 4.将电子邮件发送给接收器。在此电子邮件中,您需要将文件的URL放在其中。
这个想法是,我们需要一个URL,最终用户需要在其中下载文件。因此,我们需要将文件上传到能够提供公共可用URL的存储中。并发送此电子邮件。原因是因为邮箱无法处理大型文件。
另外,如果使用CDN,则如果可能的话,可以通过签名的URL提供文件。