如何避免在不更改php.ini max_execution_time的情况下超过Laravel 60秒的最大执行时间

如何避免在不更改php.ini max_execution_time的情况下超过Laravel 60秒的最大执行时间,php,laravel,postgresql,Php,Laravel,Postgresql,我的代码有一个问题,我将导出到包含100000多个数据的CSV,在这里我使用了chunk2次,第一次是getData变量,其中该变量在另一个类中使用AssetRepository函数,另一次是我在foreach时的使用,如果使用限制加载1000个数据,则可以导出数据。是否可以在php.ini上加载数据而不更改max\u execute\u time,并且仅使用chunk? 如果可以,我如何优化我的代码 在本例中,我使用的是PostgreSQL 下面是AssetRepository.php cla

我的代码有一个问题,我将导出到包含100000多个数据的CSV,在这里我使用了
chunk
2次,第一次是
getData
变量,其中该变量在另一个类中使用
AssetRepository
函数,另一次是我在
foreach
时的使用,如果使用
限制加载1000个数据
,则可以导出数据。是否可以在
php.ini
上加载数据而不更改
max\u execute\u time
,并且仅使用
chunk
? 如果可以,我如何优化我的代码

在本例中,我使用的是PostgreSQL

下面是
AssetRepository.php

class AssetRepository
{
    public $query = null;
    private $trashed = false;

    public static function query()
    {
        $repo = new AssetRepository();
        $repo->query = DB::table('assets as a')
        ->select(
            DB::raw("distinct a.id"),
            "a.id",
            "a.duration as duration",
            DB::raw("COALESCE( NULLIF(a.qr_code,'') , 'QR Code Not Set' ) as qr_code"),
            "a.material_no",
            DB::raw("COALESCE( NULLIF(a.serial_no,'') , 'Serial No Not Set' ) as serial_no"),
            "a.sbu_id",
            "a.pop_id",
            "a.building_id",
            "a.type_id",
            "asset_to_sid.cust_id",
            "a.category_id",
            "a.brand_id",
            "a.model_id",
            "a.id as id",
            "b.name as model",
            "b2.name as brand",
            "p.name as pop",
            "p2.name as sbu",
            "q.name as building",
            "a.updated_at",
            "a.created_at",
            "a.deleted_at",
            'a.eos',
            'a.eol',
            "s.name as sts",
            "c.name as category",
            "a.app_code",
            "a.name",
            "a.status_approval as status_approval",
            "a.approval_notes",
            "a.approval_activities",
            "a.habis_masa_garansi as habis_masa_garansi",
            "permission_approval.action as action_approval",
            DB::raw("CONCAT(u.first_name, ' ', u.last_name) as username"),
            DB::raw("CONCAT(u2.first_name, ' ', u2.last_name) as username2"),
            DB::raw("CONCAT(u3.first_name, ' ', u3.last_name) as approved_by"),
            DB::raw("CASE WHEN q2.name is null THEN 'Not Set' ELSE q2.name END as room"),
            DB::raw("CASE WHEN cast(a.installation_year as text) is null THEN 'Not Set' ELSE cast(a.installation_year as text) END as installation_year"),
            DB::raw("CASE WHEN cast(b.mpls_hierarchy as text) is null THEN 'Not Set' ELSE cast(b.mpls_hierarchy as text) END as mpls_hierarchy"),
            DB::raw("CASE WHEN cast(a2.name as text) is null THEN 'Not Set' ELSE cast(a2.name as text) END as rack"),
            DB::raw("CASE WHEN cast(a.remark1 as text) is null THEN 'No Data' ELSE cast(a.remark1 as text) END as remark1"),
            DB::raw("CASE WHEN cast(a.remark2 as text) is null THEN 'No Data' ELSE cast(a.remark2 as text) END as remark2"),
            DB::raw("CASE WHEN cast(a.remark3 as text) is null THEN 'No Data' ELSE cast(a.remark3 as text) END as remark3"),
            DB::raw("CASE WHEN cast(a.remark4 as text) is null THEN 'No Data' ELSE cast(a.remark4 as text) END as remark4"),
            DB::raw("CASE WHEN cast(a.remark5 as text) is null THEN 'No Data' ELSE cast(a.remark5 as text) END as remark5"),
            DB::raw("CASE WHEN cast(a.desc as text) is null THEN 'No Data' ELSE cast(a.desc as text) END as notes"),
            DB::raw("CASE WHEN a.c_status = 1 THEN 'Complete' ELSE 'Not Complete' END AS complete"),
            DB::raw("CASE WHEN a.c_status = 1 THEN 'btn-primary' ELSE 'btn-warning' END AS btn"),
            DB::raw("CASE WHEN p.offline_sts = 1 THEN 'Offline' ELSE 'Online' END AS offline_sts"),
            DB::raw("CASE WHEN p.offline_sts = 1 THEN 'btn-default' ELSE 'btn-info' END AS offline_btn"),
            DB::raw("CASE WHEN p.offline_sts = 1 THEN 'disabled' ELSE 'enabled' END AS disableds")
        )
        ->leftJoin('assets as a2', 'a.rack', '=', 'a2.id')
        ->join('kategoris as c', 'a.asset_category', '=', 'c.id')
        ->join('users as u', 'a.updated_by', 'u.id')
        ->join('users as u2', 'a.created_by', 'u2.id')
        ->leftJoin('users as u3', 'a.role_approval', 'u3.id')
        ->join('sbus as p', 'p.id', '=', 'a.pop_id')
        ->join('sbus as p2', 'p2.id', '=', 'a.sbu_id')
        ->leftJoin('pops as q', 'a.building_id', '=', 'q.id')
        ->leftJoin('pops as q2', 'a.room_id', '=', 'q2.id')
        ->leftJoin('brands as b', 'a.model_id', '=', 'b.id')
        ->leftJoin('permission_approval', 'a.permission_approval_id', '=', 'permission_approval.id')
        ->leftJoin('asset_to_sid', 'a.id', '=', 'asset_to_sid.asset_id')
        ->join('brands as b2', 'a.brand_id', '=', 'b2.id')
        ->join('statuses as s', 's.id', '=', 'a.status')
        ->leftJoin('statuses as ss', 'p.type', '=', 'ss.id')
        ->orderBy('a.updated_at', 'desc');

        return $repo;
    }

    public function getQuery()
    {
        return $this->query ?? self::query();
    }

    public function get()
    {
        if (!$this->trashed) {
            return $this->getQuery()->whereNull('a.deleted_at')->get();
        }

        return $this->getQuery()->get();
    }
}
dan ini无法导出pada
AssetController.php

class AssetRepository
{
    public $query = null;
    private $trashed = false;

    public static function query()
    {
        $repo = new AssetRepository();
        $repo->query = DB::table('assets as a')
        ->select(
            DB::raw("distinct a.id"),
            "a.id",
            "a.duration as duration",
            DB::raw("COALESCE( NULLIF(a.qr_code,'') , 'QR Code Not Set' ) as qr_code"),
            "a.material_no",
            DB::raw("COALESCE( NULLIF(a.serial_no,'') , 'Serial No Not Set' ) as serial_no"),
            "a.sbu_id",
            "a.pop_id",
            "a.building_id",
            "a.type_id",
            "asset_to_sid.cust_id",
            "a.category_id",
            "a.brand_id",
            "a.model_id",
            "a.id as id",
            "b.name as model",
            "b2.name as brand",
            "p.name as pop",
            "p2.name as sbu",
            "q.name as building",
            "a.updated_at",
            "a.created_at",
            "a.deleted_at",
            'a.eos',
            'a.eol',
            "s.name as sts",
            "c.name as category",
            "a.app_code",
            "a.name",
            "a.status_approval as status_approval",
            "a.approval_notes",
            "a.approval_activities",
            "a.habis_masa_garansi as habis_masa_garansi",
            "permission_approval.action as action_approval",
            DB::raw("CONCAT(u.first_name, ' ', u.last_name) as username"),
            DB::raw("CONCAT(u2.first_name, ' ', u2.last_name) as username2"),
            DB::raw("CONCAT(u3.first_name, ' ', u3.last_name) as approved_by"),
            DB::raw("CASE WHEN q2.name is null THEN 'Not Set' ELSE q2.name END as room"),
            DB::raw("CASE WHEN cast(a.installation_year as text) is null THEN 'Not Set' ELSE cast(a.installation_year as text) END as installation_year"),
            DB::raw("CASE WHEN cast(b.mpls_hierarchy as text) is null THEN 'Not Set' ELSE cast(b.mpls_hierarchy as text) END as mpls_hierarchy"),
            DB::raw("CASE WHEN cast(a2.name as text) is null THEN 'Not Set' ELSE cast(a2.name as text) END as rack"),
            DB::raw("CASE WHEN cast(a.remark1 as text) is null THEN 'No Data' ELSE cast(a.remark1 as text) END as remark1"),
            DB::raw("CASE WHEN cast(a.remark2 as text) is null THEN 'No Data' ELSE cast(a.remark2 as text) END as remark2"),
            DB::raw("CASE WHEN cast(a.remark3 as text) is null THEN 'No Data' ELSE cast(a.remark3 as text) END as remark3"),
            DB::raw("CASE WHEN cast(a.remark4 as text) is null THEN 'No Data' ELSE cast(a.remark4 as text) END as remark4"),
            DB::raw("CASE WHEN cast(a.remark5 as text) is null THEN 'No Data' ELSE cast(a.remark5 as text) END as remark5"),
            DB::raw("CASE WHEN cast(a.desc as text) is null THEN 'No Data' ELSE cast(a.desc as text) END as notes"),
            DB::raw("CASE WHEN a.c_status = 1 THEN 'Complete' ELSE 'Not Complete' END AS complete"),
            DB::raw("CASE WHEN a.c_status = 1 THEN 'btn-primary' ELSE 'btn-warning' END AS btn"),
            DB::raw("CASE WHEN p.offline_sts = 1 THEN 'Offline' ELSE 'Online' END AS offline_sts"),
            DB::raw("CASE WHEN p.offline_sts = 1 THEN 'btn-default' ELSE 'btn-info' END AS offline_btn"),
            DB::raw("CASE WHEN p.offline_sts = 1 THEN 'disabled' ELSE 'enabled' END AS disableds")
        )
        ->leftJoin('assets as a2', 'a.rack', '=', 'a2.id')
        ->join('kategoris as c', 'a.asset_category', '=', 'c.id')
        ->join('users as u', 'a.updated_by', 'u.id')
        ->join('users as u2', 'a.created_by', 'u2.id')
        ->leftJoin('users as u3', 'a.role_approval', 'u3.id')
        ->join('sbus as p', 'p.id', '=', 'a.pop_id')
        ->join('sbus as p2', 'p2.id', '=', 'a.sbu_id')
        ->leftJoin('pops as q', 'a.building_id', '=', 'q.id')
        ->leftJoin('pops as q2', 'a.room_id', '=', 'q2.id')
        ->leftJoin('brands as b', 'a.model_id', '=', 'b.id')
        ->leftJoin('permission_approval', 'a.permission_approval_id', '=', 'permission_approval.id')
        ->leftJoin('asset_to_sid', 'a.id', '=', 'asset_to_sid.asset_id')
        ->join('brands as b2', 'a.brand_id', '=', 'b2.id')
        ->join('statuses as s', 's.id', '=', 'a.status')
        ->leftJoin('statuses as ss', 'p.type', '=', 'ss.id')
        ->orderBy('a.updated_at', 'desc');

        return $repo;
    }

    public function getQuery()
    {
        return $this->query ?? self::query();
    }

    public function get()
    {
        if (!$this->trashed) {
            return $this->getQuery()->whereNull('a.deleted_at')->get();
        }

        return $this->getQuery()->get();
    }
}
公共函数exportAll(请求$Request)
{
$data=AssetPository::query();//来自AssetPository函数
$headers=数组(
“内容类型”=>“文本/csv”,
“缓存控制”=>“必须重新验证,后检查=0,预检查=0”,
“内容处置”=>“附件;文件名=export.csv”,
“Expires”=>“0”,
“Pragma”=>“public”,
);
$response=新的流响应(函数()使用($data){
$handle=fopen($handle)php://output","w",;
$getData=$data->get();
$remark=remark::all(['id','label','type']);
$remarkAsset=remarkAsset::all(['asset\u id','value','remark\u id']);
$getHeader=数组_键((数组)$getData[0]);
$newArray=array();
$setHeader=array();
foreach($getHeader作为$header){
$setHeader[$header]=$header;
}
$remarkHeader=[];//结果
foreach(备注为$headerRemark){
$remarkHeader[]=数组(
'id'=>$headerRemark['id'],
'label'=>$headerRemark['label'],
'type'=>$headerRemark['type']
);
$setHeader[$headerRemark['type']]=$headerRemark['type'];
}
$remarkAssets=[];
foreach($AssetRemarkAsset作为$assetRemark){
$remarkAssets[]=(数组)数组(
'资产id'=>$AssetMark['资产id'],
'value'=>$assetRemark['value'],
'remark\u id'=>$assetRemark['remark\u id']
);
}
array_push($newArray,(object)$setHeader);
//$coountData=count($getData)/4;
$chunk=collect($getData);
$chunk->chunk(500);
foreach($chunk作为$data){
$theKey=array\u key(array\u组合(array\u key($remarkAssets),array\u列($remarkAssets,'asset\u id')),$data->id);
foreach($remarkHeader作为$head){
$countKey=count($theKey);
如果($countKey>0){
$valueRemark='';
foreach($key作为$key){
如果($remarkAssets[$key]['remark_id']==$head['id'])){
$valueRemark=$remarkAssets[$key]['value'];
}
}
$data=(数组)$data;
$data[$head['type']]=$valueRemark;
$data=(对象)$data;
}否则{
$data=(数组)$data;
$data[$head['type']]='';
$data=(对象)$data;
}
}
数组推送($newArray,$data);
}
$chunkArray=collect($newArray);
$chunkArray->chunk(500);
foreach($chunkArray作为$datas){
if(is_对象($datas))
$datas=(数组)$datas;
fputcsv($handle,$datas);
}
fclose($handle);
},200元,$;
返回$response->send();
}

如果需要,请忽略
AssetController.php
这是我的代码中使用的查询

最好异步执行这些长时间运行的任务。在拉威尔,你可以用它。当队列在CLI上运行时,您可以为此配置不同的
max\u execution\u time
。如果希望保持执行时间不变,则应尝试将正在执行的任务拆分为多个部分。如果这些部分中的每一部分都不超过1分钟,那么您就可以开始了。

您可以调用
set\u time\u limit(0)
从其余的执行中删除时间限制,或者在循环的每次迭代(例如)中调用
set\u time\u limit(n)
将计时器重置n秒以上


也许这个查询返回的元素太多了,PHP大部分时间都只是在它们周围包装一个
集合
对象。如果您想查看查询本身花费了多少时间,可以直接在
PostgreSQL Server
、控制台(
php artisan tinker
)上运行它,或者在代码中使用
DB::listen

公共函数exportAll(请求$Request)
{
//PHP>=7.4.0
DB::listen(fn($query)=>dump($query->sql,$query->bindings,$query->time));
//PHP<7.4.0
DB::listen(函数($query){dump($query->sql,$query->bindings,$query->time);});
...
}
如果出现
集合
包装问题,请尝试使用
懒散集合
。它从Laravel 6.0开始提供。您可以通过调用
$data->cursor()
而不是
$data->get()
来使用它

LazyCollection
基本上是一个对象,您可以在其上迭代并使用一些
Collection
方法。它们允许您处理数据,而无需为X行构建一个大的
集合

我将重新发布您的
exportAll
函数,其中包含一些我认为会对性能产生积极影响的更改

公共函数exportAll(请求$Request)
{
$data=AssetPository::query();//来自AssetPository F