How can I complete this process using the command line?

I've got a script that I've been asked to alter by initiating a command line dynamic so as to avoid a situation where things are otherwise timing out.

What's happening is that the user will click a button that's grabbing a series of files and converting them to pdf documents. At the end of the script, it then takes the directory that has all of these new files and zips it up and makes it available to the user as a downloadable entity. It works great right up until the point where you're having to process 600+ docs, now you're looking at 20 minutes plus and it's a mess.

At the risk of providing too much info, here's the "machine" as it exists right now.

User clicks the button and you get "  function init_genPSM($empID_sel=NULL,$hID_sel=NULL,$item_sel=NULL,$cpID_sel=NULL, $orderID=NULL, $quantity=500) {"

That's the method that initiates the merry go round. Here it is in its entirety:

function init_genPSM($empID_sel=NULL,$hID_sel=NULL,$item_sel=NULL,$cpID_sel=NULL, $orderID=NULL, $quantity=500) {
        global $S;
        global $A;
        $R = new xajaxResponse();
        $R->appendResponse(Application::InitializeClass());


        if (strpos($item_sel, 'prime') !== false) {
            //ini_set('max_execution_time', $quantity > 120 ? $quantity : 120);
			//I set the max_execution_time to 500 to accommodate larger files that were showing up as empty zip files because of the system timing out (Bruce Gust 4/20/2018)
			ini_set('max_execution_time', 120);
            $out = array();
            $T = new Blitz(WEBROOT.'templates/pap/primePrintOrder.tpl');
            $stmt = $this->cn->prepare('SELECT rhID FROM Orders_hraResponseHeaders WHERE orderID = ?');
            $stmt->execute(array($orderID));
            $table = $stmt->fetchall(PDO::FETCH_ASSOC);


            $userTable = array();

            foreach($table as $value) {
                $rhID = $value['rhID'];
                $stmt = $this->cn->prepare('SELECT cp.cpID, RIGHT(u.usrSSN, 4) as usrSSN_L4, u.*, r.rhID,  e.empName, h.hPID, h.hID, h.hName, c.cmpLogoLrg, c.cmpLogoMed, c.cmpSignatureImg, c.cmpSignatoryName, c.cmpSignatoryTitle, c.cmpPHRLetter, c.cmpPostSurveyTxt, c.cmpSurveyLegalTxt, c.cmpBioSurveyLegalTxt, c.cmpSurveyLetter_sp, c.cmpSignatoryTitle_sp, c.cmpSurveyLetter
                                            FROM hraResponseHeaders r INNER JOIN
                                            hraUsers u ON r.usrID = u.usrID INNER JOIN
                                            Employers e ON u.empID = e.empID INNER JOIN
                                            ChannelPartners cp ON e.cpID = cp.cpID INNER JOIN
                                            hraHeaders h ON r.hID = h.hID INNER JOIN
                                            Components c ON cp.cmpID=c.cmpID
                                            WHERE (r.rhID= ?)');
                $stmt->execute(array($rhID));
                $userTable[]= $stmt->fetchall(PDO::FETCH_ASSOC);
            }
            //Date for PDF Folder
            $pDate = date('m_d_Y');
            
            // Loop through Prime Users and Generate a report.
            //Determine the number of orders
            $orderCount = sizeof($userTable);
            
            //get the character count for the number of orders so we can use it in padding
            $orderCountCharCount = strlen($orderCount);
            
            for ($i=0; $i < $orderCount; $i++) {
                $incrFileName = $orderID.'_'.str_pad($i, $orderCountCharCount, '0', STR_PAD_LEFT).'_';
                
                $pdfPath = $this->exe_primeGenPSM($item_sel, $userTable[$i][0], $incrFileName, $orderID, $pDate);
                //$R->append('d4', 'innerHTML', '<iframe style="display: none" name="iframe" name="iframe" src="'.$fpath[$i].'"></iframe>');
            }


            $out = array('zipLink' => $pdfPath);

            $R->appendResponse($A->populateFltDiv('Download Prime Order '.$orderID,$T->parse($out),$T->fetch('/btns'),450));
        } else {
            $T = new Blitz(WEBROOT.'templates/pap/init_genPSM.tpl');
            $out = array('hID_sel'=>$hID_sel,'empList'=>'','engSurvey'=>'','spSurvey'=>'','bioLegal'=>'','bioLegalNCR'=>'');
            $splitList = true;
            $stmt = $this->cn->query('SELECT cpID,cpName,cptID FROM ChannelPartners ORDER BY cptID,cpName ASC');
            while(($row = $stmt->fetch()) != null) {
                if ($row['cptID'] == 2 && $splitList){
                    $out['cpList'].= '<option value="" disabled="disabled">------------------</option>';
                    $splitList = false;
                }
                $out['cpList'].= '<option value="'.$row['cpID'].'" '.(($cpID_sel == $row['cpID'])?'SELECTED':'').'>'.$row['cpName'].' ('.$row['cpID'].')</option>';
            }

            $stmt = $this->cn->query('SELECT empID,empName FROM Employers ORDER BY empName ASC');
            while (($row = $stmt->fetch()) != null)
                $out['empList'].= '<option value="'.$row['empID'].'" '.(($empID_sel == $row['empID'])?'SELECTED':'').'>'.$row['empName'].' ('.$row['empID'].')</option>';

            $out['itemSel'] = '';
            $productArr = array('English Survey / Sales - English Survey','Spanish Survey','Biometric Survey','Biometric Survey 2-Part','Biometric Survey 3-Part','|','Sales - Personal Health Report','Sales - 10 Steps');
            $valueArr = array('engSurvey','spSurvey','bioSurvey','bioSurvey2','bioSurvey3','|','sales-phr','sales-10steps');
            for ($i=0; $i < count($productArr); $i++){
                if ($productArr[$i] == '|')
                    $out['itemSel'].= '<option value="disabled" disabled="disabled">------------------</option>';
                else if ($item_sel == $valueArr[$i])
                    $out['itemSel'].= '<option value="'.$valueArr[$i].'" SELECTED>'.$productArr[$i].'</option>';
                else
                    $out['itemSel'].= '<option value="'.$valueArr[$i].'">'.$productArr[$i].'</option>';
            }

            // set location and name for image upload
            $out['folder'] = 'temp';
            $out['fileID'] = '9999';

            $S->Set(array('pap_pageLastVisited'=>'init_genPSM'));
            $R->assign('d1', 'innerHTML', $T->parse($out));

            if (!empty($empID_sel) && !empty($hID_sel))
                $R->script("$('#empHeaderDiv').css('display','inline');$('#cpDiv').css('display','none');");
            else if (!empty($cpID_sel))
                $R->script("$('#empHeaderDiv').css('display','none');$('#cpDiv').css('display','inline');");


            if (!empty($empID_sel))
                $R->script('xajax_Production.genPSM_listHeaderGroups(xajax.getFormValues(\'genPSMForm\'));');
            // Generate PDF(s)
            if ((!empty($empID_sel) && !empty($hID_sel) && !empty($item_sel)) || !empty($cpID_sel) && !empty($item_sel))
                $R->script('xajax_Production.exe_genPSM(xajax.getFormValues(\'genPSMForm\'),\'true\');');

            $R->script('$.fancybox.close()');
        }
        return $R;
    }

Open in new window


On line #47, you have this: $pdfPath = $this->exe_primeGenPSM($item_sel, $userTable[$i][0], $incrFileName, $orderID, $pDate);

exe_primeGenPSM is what's hogging all of the systemic capital. It's here where things start to drag.

Here's that method:

 function exe_primeGenPSM($ordItem, $usrTable, $increment, $orderID, $pDate){
        require_once(WEBROOT.'lib/functions.php');
        require_once(WEBROOT.'lib/fpdf/multicelltag/class.multicelltag.php');
        require_once(WEBROOT.'lib/fpdf/fpdi/fpdi.php');

        if (!empty($usrTable['cmpLogoLrg']))
            $usrTable['cmpLogoLrg'] = WEBROOT . $usrTable['cmpLogoLrg'];
        if (!empty($usrTable['cmpLogoMed']))
            $usrTable['cmpLogoMed'] = WEBROOT . $usrTable['cmpLogoMed'];
        if (!empty($usrTable['cmpSignatureImg']))
            $usrTable['cmpSignatureImg'] = WEBROOT . $usrTable['cmpSignatureImg'];

        // Bio decision here
        if (stristr($ordItem, 'bio')) {
            $pdf =& new FPDI('P', 'mm', 'Legal');
            $templateFile = WEBROOT . 'pdf/bioLegal.pdf';
        } else {
            $pdf =& new FPDI('P', 'mm', 'Letter');

            if (stristr($ordItem, 'survey'))
                if (stristr($ordItem, 'eng'))
                    $templateFile = WEBROOT . 'pdf/engSurvey.pdf';
                else
                    $templateFile = WEBROOT . 'pdf/spSurvey.pdf';
            else if ($ordItem == 'sales-phs')
                $templateFile = WEBROOT . 'pdf/engSurvey.pdf';
        }

        $pdf->SetMargins(0, 0);
        $pdf->SetAutoPageBreak(false);
        $pdf->AddFont('Barcode1', '', 'barcode1.php');

        $iterations = 1; // for bioLegal
        $pagecount = $pdf->setSourceFile($templateFile);
        for ($i = 1; $i <= $pagecount; $i++) {
            $tplidx = $pdf->ImportPage($i);
            $s = $pdf->getTemplatesize($tplidx);
            $pdf->AddPage('P', array($s['w'], $s['h']));
            $pdf->useTemplate($tplidx);

            if (stristr($ordItem, 'survey') && !stristr($ordItem, 'bio')) {
                if ($i == 1) {
                    if (!empty($usrTable['hName'])) {
                        $pdf->SetFont('Arial','',22);
                        $pdf->SetXY(14,66);
                        $pdf->MultiCell(189, 9, $usrTable['empName'] . ' / ' . $usrTable['hName'], 0, 'C', 0);
                    }

                    if (!empty($usrTable['cmpLogoLrg']) && is_file($usrTable['cmpLogoLrg'])) {
                        $img = getimagesize($usrTable['cmpLogoLrg']);
                        if ($img[0] * (18 / $img[1]) > 110) // IMAGE IS TOO WIDE SHRINK BY WIDTH, and vertically center
                            $pdf->Image($usrTable['cmpLogoLrg'], 107 - 110 / 2, 217 + 27 / 2 - ($img[1] * 110 / $img[0]) / 2, 110, 0);
                        else // IMAGE IS TOO TALL, SHRINK BY HEIGHT
                            $pdf->Image($usrTable['cmpLogoLrg'], 107 - ($img[0] * 18 / $img[1]) / 2, 217 + 27 / 2 - 18 / 2, 0, 18);
                    }
                    $pdf->SetFont('Arial', '', 18);
                    $pdf->SetXY(10, 25);
                    $pdf->Cell(180, 20, $usrTable['usrFN'] . ' ' . $usrTable['usrLN'], 0, 0, 'R');
                } else if ($i == 2) {
                    $sigHeight = 8;
                    $textLeading = 4.5;
                    $pdf->SetFont('Times', '', 10);
                    $pdf->SetXY(36, 65);

                    // For some reason the PHR is in here? The PHR reads nothing like the Survey Letter does. It reads like you have taken the survey already.
                    // Why is it present here? I have taken it out for now. ~ allen
                    //$pdf->SetXY(29,65);
                    //$usrTable['cmpPHRLetter'] = str_replace('$Recipient', $usrTable['usrFN'], $usrTable['cmpPHRLetter']);
                    //$pdf->MultiCell(138, $textLeading, $usrTable['cmpPHRLetter'], 0, 'L', false);

                    $cmpLogoLrg = $usrTable['cmpLogoLrg'];
                    // Set Logo Pos
                    if (!empty($cmpLogoLrg) && is_file($cmpLogoLrg)) {
                        $img = getimagesize($cmpLogoLrg);
                        if ($img[0]*(10/$img[1]) > 50) // IMAGE IS TOO WIDE SHRINK BY WIDTH
                            $pdf->Image($cmpLogoLrg,35,50.5,50,0);
                        else // IMAGE IS TOO TALL, SHRINK BY HEIGHT
                            $pdf->Image($cmpLogoLrg,35,50.5,0,10);
                    }


                    if ((stristr($ordItem, 'eng')) || empty($usrTable['cmpSurveyLetter_sp']))
                        $cmpLetter = $usrTable['cmpSurveyLetter'];
                    else
                        $cmpLetter = $usrTable['cmpSurveyLetter_sp'];

                    // body text pos
                    $pdf->SetXY(36,65);
                    $pdf->MultiCell(138,4.5,((stristr($ordItem, "eng") || empty($usrTable['cmpSurveyLetter_sp'])) ? $usrTable['cmpSurveyLetter'] : $usrTable['cmpSurveyLetter_sp']),0,'L',false);
                    $sigY = $pdf->GetY() + ($textLeading/2);

                    //SIGNATURE if else block

                    $cmpSignatureImg = $usrTable['cmpSignatureImg'];
                    if (!empty($cmpSignatureImg) && is_file($cmpSignatureImg)){
                        list($originalW, $originalH) = getimagesize($cmpSignatureImg);
                        $newW = $newH = 0;
                        $targetW = 80;
                        $targetH = ($originalW/$originalH > 2) ? 10 /*aspect ratio is wide and rectangular*/ : 15 /*aspect ratio is near square*/;
                        // changing target height to 8.  10 - 15 seemed way too large and unrealistic.  sticking with default height
                        $targetH = 8;
                        while ($originalW > $targetW || $originalH > $targetH){
                            if ($originalW > $targetW){
                                $diff = $originalW-$targetW;
                                $percnt_reduced = (($diff/$originalW)*100);
                                $newH = $originalH-(($percnt_reduced*$originalH)/100);
                                $newW = $originalW-$diff;
                            }
                            if ($originalH > $targetH){
                                $diff = $originalH-$targetH;
                                $percnt_reduced = (($diff/$originalH)*100);
                                $newW = $originalW-(($percnt_reduced*$originalW)/100);
                                $newH = $originalH-$diff;
                            }

                            $originalW = $newW;
                            $originalH = $sigHeight = $newH;
                        }
                        $pdf->Image($cmpSignatureImg,36,$sigY,$newW,$newH);
                    } else {
                        $pdf->AddFont('RageItalic', '', 'RageItalic.php');
                        $pdf->SetFont('RageItalic', '', 26);
                        $pdf->Text(29, $sigY + $textLeading * 1.5, $usrTable['cmpSignatoryName']);
                    }
                    $pdf->SetFont('Times', '', 10);
                    $pdf->SetXY(36, $sigY + $sigHeight + 2);
                    $pdf->MultiCell(100, $textLeading, $usrTable['cmpSignatoryName'] . "\n" . ((stristr($ordItem, "eng") || empty($usrTable['cmpSignatoryTitle_sp'])) ? $usrTable['cmpSignatoryTitle'] : $usrTable['cmpSignatoryTitle_sp']), 0, 'L', false);

                } else if ($i == 3) {
                    //Distance of the blocks for placement of letters
                    $block = 6;

                    //firstname
                    $pdf->SetFont('Arial', '', 12);
                    $fnArray = array();
                    $fnArray = str_split(strtoupper($usrTable['usrFN']));
                    // If it is not a spanish
                    if ($templateFile != WEBROOT . 'pdf/spSurvey.pdf') {
                        $pdf->SetXY(41, 43);
                        $x = $pdf->GetX();
                        for ($j = 0; $j != 19; $j++) {
                            $pdf->MultiCell(3, 2, $fnArray[$j], 0, 0);
                            $x = $x + $block;
                            $pdf->SetXY($x, 43);
                        }
                    } else {
                        $pdf->SetXY(47, 46);
                        $x = $pdf->GetX();
                        for ($j = 0; $j != 19; $j++) {
                            $pdf->MultiCell(3, 2, $fnArray[$j], 0, 0);
                            $x = $x + $block;
                            $pdf->SetXY($x, 46);
                        }
                    }

                    //lastname
                    $lnArray = array();
                    $lnArray = str_split(strtoupper($usrTable['usrLN']));
                    // If it is not a spanish
                    if ($templateFile != WEBROOT . 'pdf/spSurvey.pdf') {
                        $pdf->SetXY(41, 51);
                        $x = $pdf->GetX();
                        for ($j = 0; $j != 19; $j++) {
                            $pdf->MultiCell(3, 2, $lnArray[$j], 0, 0);
                            $x = $x + $block;
                            $pdf->SetXY($x, 51);
                        }
                    } else {
                        $pdf->SetXY(48, 54);
                        $x = $pdf->GetX();
                        for ($j = 0; $j != 19; $j++) {
                            $pdf->MultiCell(3, 2, $lnArray[$j], 0, 0);
                            $x = $x + $block;
                            $pdf->SetXY($x, 54);
                        }
                    }

                    //middleInitial
                    if (!empty($usrTable['usrMI'])) {
                        //IF not Spanish
                        if ($templateFile != WEBROOT . 'pdf/spSurvey.pdf') {
                        $pdf->SetXY(193, 44);
                        $pdf->MultiCell(3, 2, strtoupper($usrTable['usrMI']), 0, 0);
                        }
                    }

                    //Employee ID
                    if (!empty($usrTable['usrEEID'])){
                        $EEIDArray = array();
                        $EEIDArray = str_split($usrTable['usrEEID']);
                        // IF Spanish
                        if ($templateFile != WEBROOT . 'pdf/spSurvey.pdf') {
                            $pdf->SetXY(132, 35);
                            $x = $pdf->GetX();
                            for ($j = 0; $j != 12; $j++) {
                                $pdf->MultiCell(3, 2, $EEIDArray[$j], 0, 0);
                                $x = $x + $block;
                                $pdf->SetXY($x, 35);
                            }
                        } else {
                            $pdf->SetXY(124, 37);
                            $x = $pdf->GetX();
                            for ($j = 0; $j != 12; $j++) {
                                $pdf->MultiCell(3, 2, $EEIDArray[$j], 0, 0);
                                $x = $x + $block;
                                $pdf->SetXY($x, 37);
                            }
                        }
                    }

                    //Home Address
                    if (!empty($usrTable['usrAddr'])){
                        $addrArray = array();
                        $addrArray = str_split(strtoupper($usrTable['usrAddr']));
                        // If it is not a spanish
                        if ($templateFile != WEBROOT . 'pdf/spSurvey.pdf') {
                            $pdf->SetXY(42, 59);
                            $x = $pdf->GetX();
                            for ($j = 0; $j != 27; $j++) {
                                $pdf->MultiCell(3, 2, $addrArray[$j], 0, 0);
                                $x = $x + $block;
                                $pdf->SetXY($x, 59);
                            }
                        } else {
                            $pdf->SetXY(48, 62);
                            $x = $pdf->GetX();
                            for ($j = 0; $j != 25; $j++) {
                                $pdf->MultiCell(3, 2, $addrArray[$j], 0, 0);
                                $x = $x + $block;
                                $pdf->SetXY($x, 62);
                            }
                        }
                    }

                    //Apt/Suite
                    if (!empty($usrTable['usrAddr2'])){
                        $addrArray = array();
                        $addrArray = str_split(strtoupper($usrTable['usrAddr2']));
                        // If it is not a spanish
                        if ($templateFile != WEBROOT . 'pdf/spSurvey.pdf') {
                            $pdf->SetXY(42, 67);
                            $x = $pdf->GetX();
                            for ($j = 0; $j != 19; $j++) {
                                $pdf->MultiCell(3, 2, $addrArray[$j], 0, 0);
                                $x = $x + $block;
                                $pdf->SetXY($x, 67);
                            }
                        } else {
                            $pdf->SetXY(48, 70);
                            $x = $pdf->GetX();
                            for ($j = 0; $j != 19; $j++) {
                                $pdf->MultiCell(3, 2, $addrArray[$j], 0, 0);
                                $x = $x + $block;
                                $pdf->SetXY($x, 70);
                            }
                        }
                    }

                    //City
                    if (!empty($usrTable['usrCity'])){
                        $cityArray = array();
                        $cityArray = str_split(strtoupper($usrTable['usrCity']));
                        //If it is not a spanish
                        if ($templateFile != WEBROOT . 'pdf/spSurvey.pdf') {
                            $pdf->SetXY(41, 74);
                            $x = $pdf->GetX();
                            for ($j = 0; $j != 19; $j++) {
                                $pdf->MultiCell(3, 2, $cityArray[$j], 0, 0);
                                $x = $x + $block;
                                $pdf->SetXY($x, 74);
                            }
                        } else {
                            $pdf->SetXY(48, 77);
                            $x = $pdf->GetX();
                            for ($j = 0; $j != 19; $j++) {
                                $pdf->MultiCell(3, 2, $cityArray[$j], 0, 0);
                                $x = $x + $block;
                                $pdf->SetXY($x, 77);
                            }
                        }
                    }

                    //State
                    if (!empty($usrTable['usrState'])){
                        $stateArray = array();
                        $stateArray = str_split(strtoupper($usrTable['usrState']));
                        //If it is not a spanish
                        if ($templateFile != WEBROOT . 'pdf/spSurvey.pdf') {
                            $pdf->SetXY(41, 82);
                            $x = $pdf->GetX();
                            for($j=0; $j != 2; $j++){
                                $pdf->MultiCell(3, 2, $stateArray[$j], 0, 0);
                                $x = $x + $block;
                                $pdf->SetXY($x, 82);
                            }
                        } else {
                            $pdf->SetXY(48, 85);
                            $x = $pdf->GetX();
                            for($j=0; $j != 2; $j++){
                                $pdf->MultiCell(3, 2, $stateArray[$j], 0, 0);
                                $x = $x + $block;
                                $pdf->SetXY($x, 85);
                            }
                        }
                    }

                    //Zip
                    if (!empty($usrTable['usrZip'])){
                        $zipArray = array();
                        $zipArray = str_split(strtoupper($usrTable['usrZip']));
                        //If it is not a spanish
                        if ($templateFile != WEBROOT . 'pdf/spSurvey.pdf') {
                            $pdf->SetXY(83, 82);
                            $x = $pdf->GetX();
                            for($j=0; $j != 5; $j++){
                                $pdf->MultiCell(3, 2, $zipArray[$j], 0, 0);
                                $x = $x + $block;
                                $pdf->SetXY($x, 82);
                            }
                        } else {
                            $pdf->SetXY(90, 85);
                            $x = $pdf->GetX();
                            for($j=0; $j != 5; $j++){
                                $pdf->MultiCell(3, 2, $zipArray[$j], 0, 0);
                                $x = $x + $block;
                                $pdf->SetXY($x, 85);
                            }
                        }
                    }

                    //Email Address
                    if (!empty($usrTable['usrEmail'])) {
                        $emailArray = array();
                        $emailArray = str_split(strtoupper($usrTable['usrEmail']));
                        // If it is not a spanish
                        if ($templateFile != WEBROOT . 'pdf/spSurvey.pdf') {
                            $pdf->SetXY(18, 97);
                            $x = $pdf->GetX();
                            for($j=0; $j !=31; $j++){
                                $pdf->MultiCell(3, 2, $emailArray[$j], 0, 0);
                                $x = $x + $block;
                                $pdf->SetXY($x, 97);
                            }
                        } else {
                            $pdf->SetXY(18, 100);
                            $x = $pdf->GetX();
                            for($j=0; $j != 31; $j++){
                                $pdf->MultiCell(3, 2, $emailArray[$j], 0, 0);
                                $x = $x + $block;
                                $pdf->SetXY($x, 100);
                            }
                        }
                    }

                    //DoB
                    if (!empty($usrTable['usrDOB'])) {
                        $dobArray = array();
                        $monthArray = array();
                        $dayArray = array();
                        $yearArray = array();
                        $usrTable['usrDOB'] = date('m-d-Y', strtotime($usrTable['usrDOB']));
                        $dobArray = explode('-', $usrTable['usrDOB']);
                        $monthArray = str_split($dobArray[0]);
                        $dayArray = str_split($dobArray[1]);
                        $yearArray = str_split($dobArray[2]);
                        // If it is not a spanish
                        if ($templateFile != WEBROOT . 'pdf/spSurvey.pdf') {
                            $pdf->SetXY(65, 106);
                            $x = $pdf->GetX();
                            foreach ($monthArray as $month) {
                                $pdf->MultiCell(3, 2, $month, 0, 0);
                                $x = $x + $block;
                                $pdf->SetXY($x, 106);
                            }
                            $pdf->SetXY(83, 106);
                            $x = $pdf->GetX();
                            foreach ($dayArray as $day) {
                                $pdf->MultiCell(3, 2, $day, 0, 0);
                                $x = $x + $block;
                                $pdf->SetXY($x, 106);
                            }
                            $pdf->SetXY(101, 106);
                            $x = $pdf->GetX();
                            foreach ($yearArray as $year) {
                                $pdf->MultiCell(3, 2, $year, 0, 0);
                                $x = $x + $block;
                                $pdf->SetXY($x, 106);
                            }
                        } else {
                            $pdf->SetXY(72, 109);
                            $x = $pdf->GetX();
                            foreach ($monthArray as $month) {
                                $pdf->MultiCell(3, 2, $month, 0, 0);
                                $x = $x + $block;
                                $pdf->SetXY($x, 109);
                            }
                            $pdf->SetXY(90, 109);
                            $x = $pdf->GetX();
                            foreach ($dayArray as $day) {
                                $pdf->MultiCell(3, 2, $day, 0, 0);
                                $x = $x + $block;
                                $pdf->SetXY($x, 109);
                            }
                            $pdf->SetXY(108, 109);
                            $x = $pdf->GetX();
                            foreach ($yearArray as $year) {
                                $pdf->MultiCell(3, 2, $year, 0, 0);
                                $x = $x + $block;
                                $pdf->SetXY($x, 109);
                            }
                        }
                    }

                    //SSN
                    if (!empty($usrTable['usrSSN_L4'])) {
                        $ssnArray = array();
                        if (strpos($usrTable['usrSSN_L4'], '-')) {
                            $ssnArray = explode('-', $usrTable['usrSSN_L4']);
                            $ssnArray = $ssnArray[2];
                            $ssnArray = str_split(strval($ssnArray));
                        } else {
                            $ssnArray = str_split(strval($usrTable['usrSSN_L4']));
                        }

                        // If it is not a spanish
                        if ($templateFile != WEBROOT . 'pdf/spSurvey.pdf') {
                            // If the ssn was all digits with no dash and exceeded size of last 4 ex(123465789)
                            if (sizeof($ssnArray) > 4) {
                                $pdf->SetXY(102, 113);
                                $x = $pdf->GetX();
                                for ($j = 5; $j < sizeof($ssnArray); $j++) {
                                    $pdf->MultiCell(3, 2, $ssnArray[$j], 0, 0);
                                    $x = $x + $block;
                                    $pdf->SetXY($x, 113);
                                }
                            } else {
                                //else the array going to treat it as last 4 of ssn
                                $pdf->SetXY(102, 113);
                                $x = $pdf->GetX();
                                foreach ($ssnArray as $ssn) {
                                    $pdf->MultiCell(3, 2, $ssn, 0, 0);
                                    $x = $x + $block;
                                    $pdf->SetXY($x, 113);
                                }
                            }
                        } else {
                            // else it is spanish we are working with
                            if (sizeof($ssnArray) > 4) {
                                $pdf->SetXY(108, 116);
                                $x = $pdf->GetX();
                                for ($j = 5; $j < sizeof($ssnArray); $j++) {
                                    $pdf->MultiCell(3, 2, $ssnArray[$j], 0, 0);
                                    $x = $x + $block;
                                    $pdf->SetXY($x, 116);
                                }
                            } else {
                                //else the array is just the size of 4/5
                                $pdf->SetXY(108, 116);
                                $x = $pdf->GetX();
                                foreach ($ssnArray as $ssn) {
                                    $pdf->MultiCell(3, 2, $ssn, 0, 0);
                                    $x = $x + $block;
                                    $pdf->SetXY($x, 116);
                                }
                            }
                        }
                    }

                    //Phone Number
                    if (!empty($usrTable['usrBestPhone'])) {
                        $phoneArray = array();
                        // Phone is not stored in any consistant fashion other than always 10 digits. So I am
                        // going to take it back to only digits then do my strsplit stuff.
                        $usrTable['usrBestPhone'] = str_replace('(', '', $usrTable['usrBestPhone']);
                        $usrTable['usrBestPhone'] = str_replace(')', '', $usrTable['usrBestPhone']);
                        $usrTable['usrBestPhone'] = str_replace(' ', '', $usrTable['usrBestPhone']);
                        $usrTable['usrBestPhone'] = str_replace('-', '', $usrTable['usrBestPhone']);
                        $phoneArray = str_split($usrTable['usrBestPhone']);
                        // If Not Spanish
                        if ($templateFile != WEBROOT . 'pdf/spSurvey.pdf') {
                            $pdf->SetXY(102, 121);
                            $x = $pdf->GetX();
                            for($j=0; $j < sizeof($phoneArray); $j++) {
                                $pdf->MultiCell(3, 2, $phoneArray[$j], 0, 0);
                                $x = $x + $block + $dash = ($j==2 || $j==5) ? $block : 0;
                                $pdf->SetXY($x, 121);
                            }
                        } else {
                            $pdf->SetXY(108, 124);
                            $x = $pdf->GetX();
                            for($j=0; $j < sizeof($phoneArray); $j++) {
                                $pdf->MultiCell(3, 2, $phoneArray[$j], 0, 0);
                                $x = $x + $block + $dash = ($j==2 || $j==5) ? $block : 0;
                                $pdf->SetXY($x, 124);
                            }
                        }
                    }

                    //Health Insurance Provider
                    if (!empty($usrTable['usrInsurer'])) {
                        $insuranceArray = array();
                        $insuranceArray = str_split(strtoupper($usrTable['usrInsurer']));
                        // If it is not a spanish
                        if ($templateFile != WEBROOT . 'pdf/spSurvey.pdf') {
                            $pdf->SetXY(18, 136);
                            $x = $pdf->GetX();
                            for($j=0; $j != 31; $j++){
                                $pdf->MultiCell(3, 2, $insuranceArray[$j], 0, 0);
                                $x = $x + $block;
                                $pdf->SetXY($x, 136);
                            }
                        } else {
                            $pdf->SetXY(18, 140);
                            $x = $pdf->GetX();
                            for($j=0; $j != 31; $j++){
                                $pdf->MultiCell(3, 2, $insuranceArray[$j], 0, 0);
                                $x = $x + $block;
                                $pdf->SetXY($x, 140);
                            }
                        }
                    }

                    //User Has Doctor
                    if (!empty($usrTable['usrHasDoc'])) {
                        if ($templateFile != WEBROOT . 'pdf/spSurvey.pdf') {
                            $pdf->Image(WEBROOT.'images/layout/img_fullDot.png', 168, 160, 5, 5, '');
                        } else {
                            $pdf->Image(WEBROOT.'images/layout/img_fullDot.png', 165, 165, 5, 5, '');
                        }
                    }

                    //User Doc Name
                    if (!empty($usrTable['usrDocName'])){
                        $docArray = array();
                        $docArray = str_split(strtoupper($usrTable['usrDocName']));
                        // If it is not a spanish
                        if ($templateFile != WEBROOT . 'pdf/spSurvey.pdf') {
                            $pdf->SetXY(16, 176);
                            $x = $pdf->GetX();
                            for($j=0; $j != 21; $j++){
                                $pdf->MultiCell(3, 2, $docArray[$j], 0, 0);
                                $x = $x + $block;
                                $pdf->SetXY($x, 176);
                            }
                        } else {
                            $pdf->SetXY(16, 182);
                            $x = $pdf->GetX();
                            for($j=0; $j != 21; $j++){
                                $pdf->MultiCell(3, 2, $docArray[$j], 0, 0);
                                $x = $x + $block;
                                $pdf->SetXY($x, 182);
                            }
                        }
                    }

                    //User Doc City
                    if (!empty($usrTable['usrDocLoc'])){
                        $docLocArray = array();
                        $docLocArray = str_split(strtoupper($usrTable['usrDocLoc']));
                        // If it is not a spanish
                        if ($templateFile != WEBROOT . 'pdf/spSurvey.pdf') {
                            $pdf->SetXY(16, 192);
                            $x = $pdf->GetX();
                            for($j=0; $j != 20; $j++){
                                $pdf->MultiCell(3, 2, $docLocArray[$j], 0, 0);
                                $x = $x + $block;
                                $pdf->SetXY($x, 192);
                            }
                        } else {
                            $pdf->SetXY(16, 197);
                            $x = $pdf->GetX();
                            for($j=0; $j != 20; $j++){
                                $pdf->MultiCell(3, 2, $docLocArray[$j], 0, 0);
                                $x = $x + $block;
                                $pdf->SetXY($x, 197);
                            }
                        }
                    }
                } else if ($i == 15) {
                    //MULTI CELL MORE THAN ONE LINE -- CMP POSTSURVEY TEXT
                    $staticLegalTxt = "This Personal Health Survey is intended to help you understand health risks you may face and offer suggestions on how best to minimize or eliminate these risks.  The information you provide WILL BE KEPT STRICTLY CONFIDENTIAL and WILL NOT BE SHARED WITH YOUR INSURANCE CARRIER.  Any information shared with your employer WILL NOT IDENTIFY ANY SINGLE INDIVIDUAL and will only be presented to represent the workforce as a whole.
                    \r\nThis assessment is not intended to establish a patient-health professional relationship nor replace any advice provided by your physician.  Information you provide may be made available to health resource experts whose product or services may be appropriate to help you reduce health risks you may face.  Your participation in these initiatives is strictly voluntary.
                    \r\nYou hereby consent to the performance of your health screening, which may include the drawing of blood samples.  You agree to release all organizations associated with this screening, their affiliates, directors, officers, employees, successors, and assigns, from any and all liabilities arising from or in any way connected with this health survey or blood drawing.  You understand that the data derived from these tests is considered preliminary and does not constitute a diagnosis.  You also understand that the data collected from these tests may be used to generate statistical information.  WE ARE REQUIRED BY LAW TO MAINTAIN THE PRIVACY OF YOUR HEALTH INFORMATION.  The responsibility for initiating a follow-up examination to confirm the results of these screenings and obtain professional medical assistance is yours alone and not that of any organization associated with this screening.";

                    $pdf->SetFont('Arial', '', 10);
                    $pdf->SetXY(10, 10);
                    $pdf->MultiCell(195, 4, (!empty($usrTable['cmpSurveyLegalTxt']) ? $usrTable['cmpSurveyLegalTxt'] : $staticLegalTxt) . (!empty($usrTable['cmpPostSurveyTxt']) ? "\r\n\r\n\r\n\r\n\r\n" . $usrTable['cmpPostSurveyTxt'] : ""), 0, 'L', false);
                } else if ($i == $pagecount) {
                    $pdf->SetFont('Barcode1', '', 20);
                    $pdf->SetY(247);
                    $pdf->SetX(23);
                    // negative usrID for prime
                    $negUsrID = $usrTable['usrID'] * -1;
                    $pdf->Cell(65, 0, "*" . $negUsrID . "*", 0, 0, 'L', 0, 0, 0);
                    $pdf->SetX(128);
                    $pdf->Cell(65, 0, "*" . $usrTable['hID'] . "*", 0, 0, 'R', 0, 0, 0);
                }
            } else if (stristr($ordItem, 'bio')) {
                $pdf->SetTextColor(0, 0, 0);
                $pdf->SetFont('Arial', '', 8);
                if (($ordItem == 'bioSurvey2' || $ordItem == 'primeBio2' || $ordItem == 'bioSurvey3' || $ordItem == 'primeBio3') && $i == 1) {
                    $pdf->SetXY(10, 19);
                    $pdf->Cell(105, 0, 'Please send white copy to Applied Health Analytics, the other may be kept for your records.', 0, 0, 'L', 0, 0, 0);
                }
                if ($i == 1) {
                    if (!empty($usrTable['cmpLogoLrg']) && is_file($usrTable['cmpLogoLrg'])) {
                        $img = getimagesize($usrTable['cmpLogoLrg']);
                        if ($img[0] * (10 / $img[1]) > 70) { // IMAGE IS TOO WIDE SHRINK BY WIDTH, and vertically center
                            $lFix = (70 - 10 * $img[0] / $img[1] > 70) ? floor(70 - 10 * $img[0] / $img[1]) : 0;
                            $vCenterFix = (70 * $img[1] / $img[0] < 10) ? floor(10 - 70 * $img[1] / $img[0]) : 0;
                            $pdf->Image($usrTable['cmpLogoLrg'], 132 + $lFix, 10 + $vCenterFix, 70, 0);
                        } else { // IMAGE IS TOO TALL, SHRINK BY HEIGHT
                            $lFix = floor(70 - 10 * $img[0] / $img[1]);
                            $pdf->Image($usrTable['cmpLogoLrg'], 132 + $lFix, 10, 0, 10);
                        }
                    }

                    $pdf->SetFont('Arial', '', 12);

                    // BEGIN PRIME USER INFO
                    $block = 6;

                    //firstname
                    $fnArray = array();
                    $fnArray = str_split(strtoupper($usrTable['usrFN']));
                    $pdf->SetXY(39, 39);
                    $x = $pdf->GetX();
                    for ($j = 0; $j != 20; $j++) {
                        $pdf->MultiCell(3, 2, $fnArray[$j], 0, 0);
                        $x = $x + $block;
                        $pdf->SetXY($x, 39);
                    }

                    //middleInitial
                    if (!empty($usrTable['usrMI'])) {
                        $pdf->SetXY(196, 39);
                        $pdf->MultiCell(3, 2, strtoupper($usrTable['usrMI']), 0, 0);
                    }

                    //lastname
                    $lnArray = array();
                    $lnArray = str_split(strtoupper($usrTable['usrLN']));
                    $pdf->SetXY(39, 46);
                    $x = $pdf->GetX();
                    for ($j = 0; $j != 20; $j++) {
                        $pdf->MultiCell(3, 2, $lnArray[$j], 0, 0);
                        $x = $x + $block;
                        $pdf->SetXY($x, 46);
                    }

                    //home address
                    $addrArray = array();
                    $addrArray = str_split(strtoupper($usrTable['usrAddr']));
                    $pdf->SetXY(39, 54);
                    $x = $pdf->GetX();
                    for ($j=0; $j != 27; $j++){
                        $pdf->MultiCell(3, 2, $addrArray[$j], 0, 0);
                        $x = $x + $block;
                        $pdf->SetXY($x, 54);
                    }

                    //address 2
                    $addrArray = array();
                    $addrArray = str_split(strtoupper($usrTable['usrAddr2']));
                    $pdf->SetXY(39, 62);
                    $x = $pdf->GetX();
                    for ($j=0; $j != 20; $j++){
                        $pdf->MultiCell(3, 2, $addrArray[$j], 0, 0);
                        $x = $x + $block;
                        $pdf->SetXY($x, 62);
                    }

                    //city
                    $cityArray = array();
                    $cityArray = str_split(strtoupper($usrTable['usrCity']));
                    $pdf->SetXY(39, 70);
                    $x = $pdf->GetX();
                    for ($j=0; $j != 20; $j++){
                        $pdf->MultiCell(3, 2, $cityArray[$j], 0, 0);
                        $x = $x + $block;
                        $pdf->SetXY($x, 70);
                    }

                    //state
                    $stateArray = array();
                    $stateArray = str_split(strtoupper($usrTable['usrState']));
                    $pdf->SetXY(39, 77);
                    $x = $pdf->GetX();
                    for ($j=0; $j != 2; $j++){
                        $pdf->MultiCell(3, 2, $stateArray[$j], 0, 0);
                        $x = $x + $block;
                        $pdf->SetXY($x, 77);
                    }

                    //ZipCode
                    $zipArray = array();
                    $zipArray = str_split($usrTable['usrZip']);
                    $pdf->SetXY(81, 77);
                    $x = $pdf->GetX();
                    for ($j=0; $j != 5; $j++){
                        $pdf->MultiCell(3, 2, $zipArray[$j], 0, 0);
                        $x = $x + $block;
                        $pdf->SetXY($x, 77);
                    }

                    //EEID
                    $EEIDArray = array();
                    $EEIDArray = str_split($usrTable['usrEEID']);
                    $pdf->SetXY(135, 77);
                    $x = $pdf->GetX();
                    for ($j=0; $j != 12; $j++){
                        $pdf->MultiCell(3, 2, $EEIDArray[$j], 0, 0);
                        $x = $x + $block;
                        $pdf->SetXY($x, 77);
                    }


                    //SSN
                    if (!empty($usrTable['usrSSN_L4'])) {
                        $ssnArray = array();
                        if (strpos($usrTable['usrSSN_L4'], '-')) {
                            $usrTable['usrSSN_L4'] = str_replace('-', '', $usrTable['usrSSN_L4']);
                            $ssnArray = str_split(strval($usrTable['usrSSN_L4']));
                        } else
                            $ssnArray = str_split(strval($usrTable['usrSSN_L4']));

                        if (sizeof($ssnArray) > 5) {
                            $pdf->SetXY(38, 86);
                            $x = $pdf->GetX();
                            foreach ($ssnArray as $k => $ssn) {
                                $pdf->MultiCell(3, 2, $ssn, 0, 0);
                                if ($k == 2 || $k == 4)
                                    $x = $x + 6;
                                $x = $x + $block;
                                $pdf->SetXY($x, 86);
                            }
                        } else {
                            if (sizeof($ssnArray) == 4) {
                                $pdf->SetXY(80, 86);
                                $x = $pdf->GetX();
                                foreach ($ssnArray as $k => $ssn) {
                                    $pdf->MultiCell(3, 2, $ssn, 0, 0);
                                    $x = $x + $block;
                                    $pdf->SetXY($x, 86);
                                }
                            } else if (sizeof($ssnArray) == 5) {
                                $pdf->SetXY(68, 86);
                                $x = $pdf->GetX();
                                $counter = 1;
                                foreach ($ssnArray as $k => $ssn) {
                                    if ($counter == 1) {
                                        $x = $x + $block;
                                    }
                                    $pdf->MultiCell(3, 2, $ssn, 0, 0);
                                    $x = $x + $block;
                                    $pdf->SetXY($x, 86);
                                    $counter ++;
                                }
                            }
                        }
                    }

                    //DoB
                    if (!empty($usrTable['usrDOB'])) {
                        $dobArray = array();
                        $monthArray = array();
                        $dayArray = array();
                        $yearArray = array();
                        $date = date('m-d-Y', strtotime($usrTable['usrDOB']));
                        $dobArray = explode('-', $date);
                        $monthArray = str_split($dobArray[0]);
                        $dayArray = str_split($dobArray[1]);
                        $yearArray = str_split($dobArray[2]);
                        $pdf->SetXY(62, 94);
                        $x = $pdf->GetX();

                        foreach ($monthArray as $month) {
                            $pdf->MultiCell(3, 2, $month, 0, 0);
                            $x = $x + $block;
                            $pdf->SetXY($x, 94);
                        }
                        $pdf->SetXY(81, 94);
                        $x = $pdf->GetX();
                        foreach ($dayArray as $day) {
                            $pdf->MultiCell(3, 2, $day, 0, 0);
                            $x = $x + $block;
                            $pdf->SetXY($x, 94);
                        }
                        $pdf->SetXY(98, 94);
                        $x = $pdf->GetX();
                        foreach ($yearArray as $year) {
                            $pdf->MultiCell(3, 2, $year, 0, 0);
                            $x = $x + $block;
                            $pdf->SetXY($x, 94);
                        }
                    }

                    //Gender
                    if (!empty($usrTable['usrGender'])) {
                        $usrTable['usrGender'] = strtolower($usrTable['usrGender']);
                        if ($usrTable['usrGender'] == 'female') {
                            $pdf->Image(WEBROOT.'images/layout/img_fullDot.png', 163, 91, 5, 5, '');
                        } else if ($usrTable['usrGender']) {
                            $pdf->Image(WEBROOT.'images/layout/img_fullDot.png', 186, 91, 5, 5, '');
                        }
                    }

                    // Phone
                    $phoneArray = array();
                    // Phone is not stored in any consistant fashion other than always 10 digits. So I am
                    // going to take it back to only digits then do my strsplit stuff.
                    $usrTable['usrBestPhone'] = str_replace('(', '', $usrTable['usrBestPhone']);
                    $usrTable['usrBestPhone'] = str_replace(')', '', $usrTable['usrBestPhone']);
                    $usrTable['usrBestPhone'] = str_replace(' ', '', $usrTable['usrBestPhone']);
                    $usrTable['usrBestPhone'] = str_replace('-', '', $usrTable['usrBestPhone']);
                    $phoneArray = str_split($usrTable['usrBestPhone']);
                    $pdf->SetXY(99, 101);
                    $x = $pdf->GetX();
                    for ($j=0; $j < sizeof($phoneArray) && $j != 20; $j++){
                        $pdf->MultiCell(3, 2, $phoneArray[$j], 0, 0);
                        $x = $x + $block + $dash = ($j==2 || $j==5) ? $block : 0;
                        $pdf->SetXY($x, 101);
                    }

                    // Email
                    $emailArray = array();
                    // Phone is not stored in any consistant fashion other than always 10 digits. So I am
                    // going to take it back to only digits then do my strsplit stuff.
                    $emailArary = str_split(strtoupper($usrTable['usrEmail']));
                    $pdf->SetXY(39, 108);
                    $x = $pdf->GetX();
                    for ($j=0; $j < sizeof($emailArary) && $j != 27; $j++){
                        $pdf->MultiCell(3, 2, $emailArary[$j], 0, 0);
                        $x = $x + $block;
                        $pdf->SetXY($x, 108);
                    }

                    //Insurance
                    $insuranceArray = array();
                    $insuranceArray = str_split(strtoupper($usrTable['usrInsurer']));
                    $pdf->SetXY(15, 123);
                    $x = $pdf->GetX();
                    for ($j=0; $j < sizeof($insuranceArray) && $j != 31; $j++){
                        $pdf->MultiCell(3, 2, $insuranceArray[$j], 0, 0);
                        $x = $x + $block;
                        $pdf->SetXY($x, 123);
                    }
                    // END PRIME USER INFO

                    $pdf->SetXY(103, 22);
                    $pdf->MultiCell(100, 4, $usrTable['empName'] . ' / ' . $usrTable['hName'], 0, 'R', 0);

                    $pdf->SetFont('Barcode1', '', 20);
                    $pdf->SetY(343);
                    $pdf->SetX(15);
                    $negUsrID = $usrTable['usrID'] * -1;
                    $pdf->Cell(65, 0, "*" . $negUsrID . "*", 0, 0, 'L', 0, 0, 0);
                    $pdf->SetX(134);
                    $pdf->Cell(65, 0, "*" . $usrTable['hID'] . "*", 0, 0, 'R', 0, 0, 0);
                }

                if ($i == 2) {
                    $pdf->SetFont('Arial', '', 10);
                    $pdf->SetXY(10, 10);
                    //$pdf->MultiCell(195,4,$usrTable['cmpBioSurveyLegalTxt'].(!empty($usrTable['cmpPostSurveyTxt']) ? "\r\n\r\n\r\n\r\n\r\n".$usrTable['cmpPostSurveyTxt']:""),0,'L',false);
                    $pdf->MultiCell(195, 4, $usrTable['cmpBioSurveyLegalTxt'], 0, 'L', false);
                }

                if (($ordItem == 'bioSurvey2' || $ordItem == 'primeBio2') && $i == 2 && $iterations < 2) {
                    $iterations++;
                    $i = 0;
                }

                if (($ordItem == 'bioSurvey3' || $ordItem == 'primeBio3') && $i == 2 && $iterations < 3) {
                    $iterations++;
                    $i = 0;
                }

            }
        }
        $fPath = SECUREROOT . 'internal/production/' . $pDate . '/primed/' . $orderID . '/' . $increment . 'productionOutput.pdf';
        $pdfPath = rtrim($fPath, $increment . 'productionOutput.pdf');
        //\\192.168.1.100\d$\secure\internal\production\04_01_2013
        //$linkPath = '/SecureFileZipper.php?zipLoc=internal/production/' . $pDate . '/primed/' . $orderID;
		$linkPath=$fPath;
        if (!is_dir($pdfPath))
            mkdir($pdfPath, 0755, true);

        $pdf->Output($fPath, 'F');
        return $linkPath;
    }

Open in new window


I know, right?

If you look at the end of the aforementioned method, you'll see this:

  $fPath = SECUREROOT . 'internal/production/' . $pDate . '/primed/' . $orderID . '/' . $increment . 'productionOutput.pdf';
        $pdfPath = rtrim($fPath, $increment . 'productionOutput.pdf');
        //\\192.168.1.100\d$\secure\internal\production\04_01_2013
        //$linkPath = '/SecureFileZipper.php?zipLoc=internal/production/' . $pDate . '/primed/' . $orderID;
            $linkPath=$fPath;
        if (!is_dir($pdfPath))
            mkdir($pdfPath, 0755, true);

        $pdf->Output($fPath, 'F');
        return $linkPath;

This is what's happening after every pdf has been generated and what's happening is that after 20 minutes or more, you'll finally get the prompt that says your file is ready to download, but when the zip file shows up in your download directory, it's empty.  Hence, my being here among the ninjas.

My supervisor who is very sharp, suggested I assert a command line dynamic that triggers the necessary PDF production and engages in something called, "polling," which I'm not familiar with. Basically, it does exactly what the browser / system would normally do, but it's happening at the server level, so you're not having to contend with timeouts or extravagant consumption of memory.

How?

Or, if there's another solution, talk to me!

What do you think?
Bruce GustPHP DeveloperAsked:
Who is Participating?

[Product update] Infrastructure Analysis Tool is now available with Business Accounts.Learn More

x
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

gr8gonzoConsultantCommented:
First, I'd suggest doing a code profile of your script, particularly that heavy function, so you can check to see why it's taking so long to generate the PDFs. PDF generation isn't exactly the speediest thing, but 1200 seconds for 600 PDFs (2 seconds per PDF) seems a little heavier than I would expect.

https://www.experts-exchange.com/articles/12179/PHP-Code-Profiling-and-Analyzing-Performance.html

The good news is that whenever you deal with scripts that repeat the same thing hundreds of times, every millisecond saved off of each iteration means hundreds of milliseconds saved, so ALL optimization, even the little things, counts extra.

You had a commented path at the end:

//\\192.168.1.100\d$\secure\internal\production\04_01_2013

...which suggests that maybe you're saving the generated files onto a network share. If so, that could be a bottleneck, but again, run the code profiling and see what it says. I would normally expect FPDF/FPDI to generate documents in milliseconds, not seconds.

Getting back to the whole idea of polling - basically the idea is that you would create a database table somewhere that looked like this:
Job | Details                                                                      | Status
----+------------------------------------------------------------------------------+--------
1   | The contents of $ordItem, $usrTable, etc... for the 1st PDF for the 1st user | Running
1   | The contents of $ordItem, $usrTable, etc... for the 2nd PDF for the 1st user | Waiting
1   | The contents of $ordItem, $usrTable, etc... for the 3rd PDF for the 1st user | Waiting
2   | The contents of $ordItem, $usrTable, etc... for the 1st PDF for the 2nd User | Running
2   | The contents of $ordItem, $usrTable, etc... for the 2nd PDF for the 2nd User | Waiting
...etc...

Open in new window


Your initial code would simply populate this table and kick off a separate PHP process that would act as a "worker" that would try to go through and process the Waiting records.

The user wouldn't really be waiting for an AJAX response to come back - the worker would be executed independently, and would keep updating processing all of the waiting jobs, and every time that all the records for a job all reached "Completed" status, you could then copy them into the right position and let the user download them.

Meanwhile, the user's browser would just sent over AJAX requests occasionally to "check" on the status of the Jobs ("are they all done yet?"). Again, the request wouldn't do the work - it would just be checking to see if the work was done, so it could take the user to the final results.

Does that make sense?
0
Bruce GustPHP DeveloperAuthor Commented:
Gonzo, this looks great! Thanks so much!

Question: My supervisor was pretty specific in mentioning a Command Line approach. The logic being, by doing that, you're not using memory the say way you would if your webpage was just sitting there, "spinning."

I've done something similar to what you're suggesting and I might go that route depending on your recommendation. I created the table like you suggested and then I just did a loop. I incorporated some JQuery so that the loop would go through 10 records and then advance to another page that I called a "breather," where the process was intentionally interrupted to avoid a timeout and then with JQuery, it would circle back and start the process all over again, this time working on a different set of 10 records and it would continue until it was done.

That I can do.

It's the command line / server level commands that have me stumped.

How would I do that?
0
gr8gonzoConsultantCommented:
Well, command line is just another way to START a PHP script. Suggesting a "command line approach" doesn't really provide a lot of insight on what he expects you to do. There are a few possible implications, but they'd just be guesses.

My best guess is that he wants you to kick off asynchronous child processes as workers by using popen() or proc_open() to start the process, like:

$php_executable = "/path/to/php";
$php_script = "/path/to/the/worker_script.php";
$parameters = "abc";

popen($php_executable . " " . $php_script . " " . $parameters, "r");

When your main script executes those lines, it will launch a new instance of the PHP engine on the command line to run the worker_script.php file, which could then process some work for you in another thread (so the main script continues to execute - it doesn't wait for the child process / worker script to finish).

The catch to that is that you can't just kick off one worker for every PDF, because kicking off 600+ PHP processes is going to hit your system HARD. The PDF processing code (worker_script.php) might be lightweight but each process will have to load the PHP engine, which can take up several megabytes (depends on your configuration) of memory and a chunk of I/O and CPU, so multiply that times 600 and suddenly you're going to exhaust your system resources almost right away.

So if you do this kind of asynchronous / popen logic, then you need to limit the number of workers that run at one time, which can be complicated to do correctly (if each main script kicks off 10 workers but you have 20 people that are all starting jobs around the same timeframe, then you might end up with hundreds of processes).

You'll also have to ensure you don't run into race conditions (two workers trying to process the same job), which can also be complicated (the simplest thing for a 1-server setup is to add a column to the jobs table I mentioned to store the Process ID that "owns" the job, then use getmypid() to get the current process ID, and run an UPDATE query like this: UPDATE jobs SET pid=[results of getmypid()] WHERE pid=NULL LIMIT 1. Then turn around and query SELECT * FROM jobs where pid=[results of getmypid()] AND status='Waiting'. If anything is returned, then that particular PHP process has acquired a lock on a particular job (so no other PHP process has it), and can safely process it.

It's this kind of stuff that makes the overall process a little complicated, so I would make sure that this is a necessary solution before you go down the road too far. Ideally, if the # of PDFs isn't growing steadily, if you can figure out how to reduce the processing time of your script so that it only takes 100-200 milliseconds (or less) per PDF instead of 2 seconds, then you might not need a separate job scheduling process like this (which would be good, because it would save on valuable system resources).
0
JavaScript Best Practices

Save hours in development time and avoid common mistakes by learning the best practices to use for JavaScript.

Bruce GustPHP DeveloperAuthor Commented:
gonzo, for the sake of ensuring that I'm learning something and not just "copying and pasting," I want to explain back to you what it is that you've suggested / recommended.

First off, "asynchronous" means the opposite of "synchronous," which means "in sequence." In other words, when you're operating in the context of an asynchronous dynamic, rather than being bound by a process that happens sequentially,  you can now circumvent the normal flow of things and have something like a form being submitted with data returned to you without having to refresh the page. That would be an AJAX form (Asynchronous Javascript, XML).

A PHP Worker is an instance of the PHP infrastructure that is assigned to a request coming from the browser. It's like a ticket cashier at a stadium. They're capable and they're fast, but they can help only one person at a time.  If that one person tends to be a difficult / involved customer, that PHP worker is going to be tied up for a while which means that other workers have to be available and if they're not, you get 504 errors which means that too many people are lined up behind that one ticket counter and things are timing out.

What I hear you saying is that even with an asynchronous, command line dynamic in place, while it's happening in the background, you're still having to employ a PHP worker. And if you've got 600 plus PDFs to process, you're launching a new instance of the PHP engine with every PDF which is going to be a huge drain on the system. That process may not timeout, but other users who are needing PHP Workers may be affected and that's where you need to exercise some caution before you head down this road.

Correct?
0
gr8gonzoConsultantCommented:
Hi bruce,

Correct, although async isn't JUST implemented in AJAX. Rather, AJAX is just one example of async programming.

So here's an example. Let's say you have these MySQL tables:
CREATE TABLE `job_sets` (
	`job_set_id` INT(11) NOT NULL AUTO_INCREMENT,
	`created` DATETIME NULL DEFAULT CURRENT_TIMESTAMP,
	`completed` DATETIME NULL DEFAULT NULL,
	PRIMARY KEY (`job_set_id`)
) COLLATE='utf8_general_ci' ENGINE=InnoDB;

CREATE TABLE `jobs` (
	`job_id` INT(11) NOT NULL AUTO_INCREMENT,
	`job_set_id` INT(11) NOT NULL DEFAULT '0',
	`data` TEXT NULL COLLATE 'latin1_swedish_ci',
	`created` DATETIME NULL DEFAULT CURRENT_TIMESTAMP,
	`started` DATETIME NULL DEFAULT NULL,
	`completed` DATETIME NULL DEFAULT NULL,
	`worker_id` INT(10) UNSIGNED NULL DEFAULT NULL,
	PRIMARY KEY (`job_id`),
	INDEX `started` (`started`),
	INDEX `worker_id` (`worker_id`),
	INDEX `job_set_id` (`job_set_id`)
) COLLATE='utf8_general_ci' ENGINE=InnoDB;

CREATE TABLE `job_workers` (
	`worker_id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
        `process_id` INT(10) UNSIGNED NOT NULL DEFAULT '0',
	`created` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
	`completed` DATETIME NULL DEFAULT NULL,
	PRIMARY KEY (`worker_id`),
	INDEX `completed` (`completed`)
) ENGINE=InnoDB;

Open in new window


So a job_set represents one request that might have many PDF-creation jobs. Then job_workers just helps us to keep track of our workers.

Now let's say you had the following PHP script that takes the incoming request, figures out that it needs 600 PDFs, and generates a job set and adds 600 PDF jobs to it, then kicks off a handful of workers to process the jobs.
<?php
// create_request.php
// @author: Jonathan Hilgeman (gr8gonzo @ Experts Exchange)
// @date: 2018-04-23

// #############################################################################
// INITIALIZATION
// #############################################################################

// How many workers to kick off at the end
$numWorkers = 5; 

// The path to our PHP executable / binary
$phpExe = "D:\\php\\7\\php.exe"; 

// The path to our worker script
$workerScript = "D:\\scripts\\job_worker.php"; 

// Connect to the database
$db = new mysqli("localhost","root","","experts_exchange_demos");

// #############################################################################
// PREPARE THE DATA NEEDED FOR EACH JOB 
// #############################################################################

// Define the details for 600 jobs
$jobs = array();
for($i = 0; $i < 600; $i++)
{
  // This is where the per-PDF-job details would go
  $jobs[] = array("blah" => "blah blah", "foo" => "bar", "hello" => "world");
}

// #############################################################################
// CREATE A JOB SET
// #############################################################################

// Now create the job set record to get the next ID
if(!$db->query("INSERT INTO job_sets () VALUES ()"))
{
  throw new Exception("There was an error while initializing the job set: " . $db->error);
}

// If successful, get the new job set ID
$job_set_id = $db->insert_id;

// #############################################################################
// CREATE THE JOBS
// #############################################################################

// And use it to create our jobs
$insert_sql = "INSERT INTO jobs (job_set_id, data) VALUES ";
foreach($jobs as $job)
{
  // Use JSON to stuff all of our job's data into a string that a worker can later extract in order to perform the job
  $insert_sql .= "({$job_set_id}, '" . $db->real_escape_string(json_encode($job)) . "'),\n";
}

// Trim off the final comma and newline
$insert_sql = rtrim($insert_sql, ",\n");

// Perform the bulk insert
if(!$db->query($insert_sql))
{
  throw new Exception("There was an error while initializing the jobs: " . $db->error);
}

// #############################################################################
// START THE WORKERS
// #############################################################################

// Kick off 5 workers (or however many is defined by $numWorkers, but don't overdo this - each worker takes up system resources)
for($i = 0; $i < $numWorkers; $i++)
{
  execInBackground($phpExe . " " . $workerScript);
}

// Original Author: Arno van den Brink in the comments on http://php.net/manual/en/function.exec.php
function execInBackground($cmd) { 
    if (substr(php_uname(), 0, 7) == "Windows"){ 
        pclose(popen("start /B ". $cmd, "r"));  
    } 
    else { 
        exec($cmd . " > /dev/null &");   
    } 
} 

Open in new window


And then finally job_worker.php:
<?php
// job_worker.php
// @author: Jonathan Hilgeman (gr8gonzo @ Experts Exchange)
// @date: 2018-04-23

// #############################################################################
// INITIALIZATION
// #############################################################################

// The maximum number of active workers that can be running at any given time
$maxWorkers = 10;

// Turn off the script's time limit
set_time_limit(0);

// Connect to the database
$db = new mysqli("localhost","root","","experts_exchange_demos");

// #############################################################################
// ALLOW THIS WORKER TO CONTINUE WE'RE UNDER THE MAX WORKERS LIMIT 
// #############################################################################

// Lock the table to prevent race conditions
if(!$db->query("LOCK TABLES job_workers WRITE"))
{
  throw new Exception("There was an error while trying to lock job_workers: " . $db->error);
}

// Get the active # of workers
$rs = $db->query("SELECT COUNT(*) FROM job_workers WHERE completed IS NULL");
if($rs === false)
{
  throw new Exception("There was an error while trying to get the count of active workers: " . $db->error);
}
$row = $rs->fetch_row();

// Is there room for another worker to start?
$allowNewWorker = ($row[0] < $maxWorkers);

if($allowNewWorker)
{
  // Yes! Insert our new worker and get its new ID
  $db->query("INSERT INTO job_workers (process_id) VALUES (".getmypid().")");
  $worker_id = $db->insert_id;
}

// Unlock the table so other processes can go on with their lives
if(!$db->query("UNLOCK TABLES"))
{
  throw new Exception("There was an error while trying to unlock job_workers: " . $db->error);
}

// Abort early if we're already running the max # of workers
if(!$allowNewWorker)
{
  exit();
}

// #############################################################################
// START PROCESSING UNWORKED JOBS
// #############################################################################

while(true)
{
  // Try to grab the next available job
  $db->query("UPDATE jobs SET worker_id={$worker_id} WHERE worker_id IS NULL LIMIT 1");
  if($db->affected_rows > 0)
  {
    // We successfully volunteered for a job, so let's go find out what it is and mark it as started
    $rs = $db->query("SELECT * FROM jobs WHERE worker_id={$worker_id} AND started IS NULL");
    $job_row = $rs->fetch_assoc();
    
    // Mark the job as started
    $db->query("UPDATE jobs SET started=NOW() WHERE job_id=" . $job_row["job_id"]);
    
    try
    {
      // Extract the data
      $data = json_decode($job_row["data"],true);
      if($data === null)
      {
        // Make sure we don't proceed if we can't extract the original data for some reason
        throw new Exception("Unable to decode the data!");
      }
      
      // Perform the job (just for the sake of clean code, move this to a separate performJob() function below
      performJob($data);

      // If no error is thrown, just mark it as completed
      $db->query("UPDATE jobs SET completed=NOW() WHERE job_id=" . $job_row["job_id"]);
    }
    catch(Exception $ex)
    {
      // Mark the job as completed with an error
      $db->query("UPDATE jobs SET completed=NOW() WHERE job_id=" . $job_row["job_id"] . ", error='".$db->real_escape_string($ex->getMessage())."'");
    }
    
    // Check to see we just completed the last job in a job set. Start by locking jobs to prevent a race condition.
    if(!$db->query("LOCK TABLES jobs WRITE"))
    {
      throw new Exception("There was an error while trying to lock jobs: " . $db->error);
    }
    
    // Look for any incomplete jobs 
    $rs = $db->query("SELECT COUNT(*) FROM jobs WHERE job_set_id=".$job_row["job_set_id"]." AND completed IS NULL");
    $row = $rs->fetch_row();
    if($row[0] == 0)
    {
      // We just completed a job set, mark it as completed (a separate process will check occasionally to see if the job set is completed)
      $db->query("LOCK TABLES job_sets WRITE");
      $db->query("UPDATE job_sets SET completed=NOW() WHERE completed is NULL AND job_set_id=" . $job_row["job_set_id"]);
    }

    if(!$db->query("UNLOCK TABLES"))
    {
      throw new Exception("There was an error while trying to unlock jobs: " . $db->error);
    }
  }
  else
  {
    // No jobs were acquired by this worker, so let's break out of our while(true) loop
    break;
  }
}

// #############################################################################
// FINISH THE WORKER
// #############################################################################

// Mark this worker as completed before we exit
$db->query("UPDATE job_workers SET completed=NOW() WHERE worker_id=" . $worker_id);



// #############################################################################
// CODE FOR DOING THE ACTUAL JOB WORK
// #############################################################################

function performJob($data)
{
  // Simulate some work being done by sleeping for a random # of microseconds 
  // between 0.1 and 2 seconds. The real PDF work would be done in here.
  usleep(rand(100000, 2000000));
}

Open in new window


So obviously, you'll have to update this code to match your DB connection info and also populate the job data correctly and perform it correctly, but it's otherwise a working model.

So when create_request.php, it doesn't do any of the work itself. It simply sets up all the jobs and tries to kick off the workers asynchronously. So this create_request.php script might set up 600 jobs, kick off the workers, and then finish in about 1-2 seconds.

Each worker is a separate PHP process that is executing job_worker.php.

The job_worker.php script does a little MySQL to ensure that you only have up to 10 active workers at any given time (which you can adjust by changing $maxWorkers in job_worker.php). If a worker starts and discovers that there are already 10, it aborts early. Otherwise, if it's among the 10 allowed workers, it starts an infinite loop that keeps pulling the next available job for itself, and then works that job, and repeats until it can't find any more available jobs (at which point it exits the loop and marks itself as completed).

For demo purposes, I just made performJob() wait a random number of milliseconds, but that's basically where you'd have all your "heavy" code that takes a long time to run.

If a job worker completes a specific job, then after it finishes that job, it checks to see if it was the last open job for a job set. If so, then it it marks the job set as completed, too.

It would be then up to you to have an AJAX call to some other script that simply checks to see if the desired request / job set is completed. Once the job set is completed, then you know all of the 600 PDFs or whatever are done and ready, and you can have your AJAX script handle that appropriately (e.g. prompt the user to download a ZIP file of them or display the PDFs in a list or something).
0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
gr8gonzoConsultantCommented:
Also I should note that I haven't fully tested this out yet - there may be a few quirks or glitches that need to be addressed, but you get the general idea.
0
Bruce GustPHP DeveloperAuthor Commented:
Thank you, sir!
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
PHP

From novice to tech pro — start learning today.