$job->setContentType("XML");
$job->setConcurrencyMode("Parallel");
//can also set to Serial
//$job->setExternalIdFieldName("My_Contact_External_Id");     //used with Upsert operations
//$job->setAssignmentRuleId("01Q60000000EPDU");               //optional for objects that support Assignment Rules
//send the job to the Bulk API and pass back returned JobInfo to the same variable
$job = $myBulkApiConnection->createJob($job);
// STEP 4. CREATE A NEW BATCH
//prep the data. normally this would be loaded from a file,
//but showing in plain text for demo purposes
$xmlData = "<sObjects xmlns=\"http://www.force.com/2009/06/asyncapi/dataload\">\n" . "    <sObject>\n" . "        <FirstName>Tom</FirstName>\n" . "        <LastName>Collins</LastName>\n" . "        <Email>tom@collins.com</Email>\n" . "    </sObject>\n" . "    <sObject>\n" . "        <FirstName>Mary</FirstName>\n" . "       <LastName>Martini</LastName>\n" . "        <Email nil=\"true\"/>\n" . "   </sObject>\n" . "</sObjects>";
$batch = $myBulkApiConnection->createBatch($job, $xmlData);
//add more and more batches.... (here, we will only do one)
// STEP 5. CLOSE THE JOB
$myBulkApiConnection->updateJobState($job->getId(), "Closed");
// STEP 6: MONITOR BATCH STATUS UNTIL DONE
while ($batch->getState() == "Queued" || $batch->getState() == "InProgress") {
    $batch = $myBulkApiConnection->getBatchInfo($job->getId(), $batch->getId());
    sleep(5);
    //wait for 5 seconds before polling again. in the real world, probably make this exponential as to not ping the server so much
}
// STEP 7: GET BATCH RESULTS
$batchResults = $myBulkApiConnection->getBatchResults($job->getId(), $batch->getId());
// PRINT EVERYTHING THAT HAPPENED ABOVE
print "<pre>" . "PHP BULK API CLIENT SAMPLE CODE OUTPUT\n" . "This is the output of the PHP Bulk API Client Sample Code. View the source code for step-by-step explanations.\n\n";
print "== XML DATA == \n" . htmlspecialchars($xmlData) . "\n\n";
print "== BATCH RESULTS == \n" . htmlspecialchars($batchResults) . "\n\n";
print "== CLIENT LOGS == \n" . $myBulkApiConnection->getLogs() . "\n\n";
$myBulkApiConnection->clearLogs();
//clear log buffer
print "</pre>";
 public function batchQuery($object, $fields, $startDate = null, $fh = null)
 {
     $this->initSession();
     $myBulkApiConnection = new BulkApiClient($this->session->serverUrl, $this->session->sessionId);
     $myBulkApiConnection->setLoggingEnabled(false);
     $myBulkApiConnection->setCompressionEnabled(true);
     // create in-memory representation of the job
     $job = new JobInfo();
     $job->setObject($object);
     $job->setOpertion('query');
     $job->setContentType('CSV');
     $job->setConcurrencyMode('Parallel');
     $soql = "SELECT " . implode(',', $fields) . " FROM {$object}";
     if ($startDate != null) {
         $soql .= " WHERE LastModifiedDate >= {$startDate}";
     }
     echo 'Creating job...';
     $job = $myBulkApiConnection->createJob($job);
     echo 'ok' . PHP_EOL;
     echo 'Creating batch...';
     $batch = $myBulkApiConnection->createBatch($job, $soql);
     echo 'ok' . PHP_EOL;
     echo 'Closing job...';
     $myBulkApiConnection->updateJobState($job->getId(), 'Closed');
     echo 'ok' . PHP_EOL;
     $sleepTime = 4;
     echo 'Waiting for job to complete...';
     while ($batch->getState() == 'Queued' || $batch->getState() == 'InProgress') {
         // poll Salesforce for the status of the batch
         sleep($sleepTime *= 1.1);
         echo ".";
         $batch = $myBulkApiConnection->getBatchInfo($job->getId(), $batch->getId());
     }
     echo 'ok' . PHP_EOL;
     // get status of batches
     echo "Retrieving results...";
     $resultList = $myBulkApiConnection->getBatchResultList($job->getId(), $batch->getId());
     // retrieve queried data
     foreach ($resultList as $resultId) {
         $myBulkApiConnection->getBatchResult($job->getId(), $batch->getId(), $resultId, $fh);
     }
     echo 'ok' . PHP_EOL;
     if (isset($fh)) {
         $preview = stream_get_contents($fh, 32, 0);
         rewind($fh);
         if (strcasecmp($preview, 'Records not found for this query') == 0 || trim($preview) == false) {
             // return false if no records returned
             return false;
         } else {
             return true;
         }
     }
 }