+ Reply to Thread
Page 1 of 3
1 2 3 LastLast
Results 1 to 10 of 21

Thread: PHP & Salesforce - Full Data Extract Process Tutorial

  1. #1
    Join Date
    May 2007
    Posts
    506
    Blog Entries
    3

    Talking PHP & Salesforce - Full Data Extract Process Tutorial

    I have successfully created an entire process that connects to Salesforce via the API using PHP to download each table that we backup in our database (Oracle 10g).

    This process connects to the API via PHP's built in SOAP using the partner.wsdl file and then using the ADOdb database abstraction php class to insert the records via a PL/SQL stored procedure.

    This new process replaces what I call the legacy system we had in place to download our marked tables using the DataLoader and storing the data into .CSV files. Then using SQL *Loader to truncate the tables and load the data fresh every time the process runs. This whole process could take up to 1 hour to download and load larger objects such as:
    • Product2 - which has 130,000 plus records
    • Opportunity - which has 60+ columns/fields and 64,000 records
    • and others
    The PL/SQL Procedure is relatively easy to run if you want to test it out for yourself. If you choose just the ID and Description fields to test on the Opportunity Object, you will need to do some manipulation because Salesforce set the size of the Description field to 32000 bytes, which can only be defined in Oracle as a CLOB:




    Code:
    CREATE OR REPLACE PROCEDURE sforce_opp_insert_test (
       pm_id            IN  VARCHAR2,
       pm_description   IN  CLOB DEFAULT EMPTY_CLOB()
    )
    IS
    BEGIN
          INSERT INTO php_opportunity
                      (ID, description)
    
               VALUES (pm_id, pm_description);
    COMMIT;
    END sforce_opp_insert_test;
    
    /
    If you are using ADOdb as your abstraction layer to connect to Oracle, you will need to utlize the OCI_B_CLOB so PHP knows how to deal with the CLOB when inserting the CLOB field into the database:



    PHP Code:
    $conn->InParameter($stmt$description,'pm_description', -1OCI_B_CLOB); 
    This is actually a <a href="http://bugs.php.net/?id=41711">bug</a> in PHP but there is a way around it. If any of the CLOB fields are NULL, meaning if any of the description fields do not have any data, then you have to populate the CLOB with some default text. Here is an example of what I did:

    PHP Code:
    if (strlen($r->fields->Description) == 0)
    {
      
    $description "No Description Posted";
    }
    else
    {
      
    $description =  $r->fields->Description;

    This checks to see if the string length is Zero and if it is, it populates a simple > "No Description Posted", so the field is not null and your PHP script will not render a FATAL error (as I found out in testing)

    I have tested this script and the real scripts that I have written and they work flawlessly. If anyone has any questions then feel free to contact me

    Here is a full example of a script that will work:

    PHP Code:
     ini_set("soap.wsdl_cache_enabled""0");

    require_once (
    '../includes/soapclient/SforcePartnerClient.php');
    require_once (
    '../includes/soapclient/SforceHeaderOptions.php');
    require_once (
    'adodb.inc.php');# load code common to ADOdb

    $conn ADONewConnection("oci8");
    $_ret $conn->Connect(''"database user""password""database");

    //TRUNCATEs the table each time the script is ran from Salesforce
    $sql "TRUNCATE TABLE PHP_OPPORTUNITY";

    if (
    $conn->Execute($sql))





    // Salesforce Login
    $wsdl '../includes/soapclient/partner.wsdl.xml';
    $userName "me@mymail.com";
    $password "password";

    $client = new SforcePartnerClient();
    $client->createConnection($wsdl);
    $loginResult $client->login($userName$password);
    $rows_loaded 0;

    //this processes the function get_accounts to perform your extract from your
    //instance of salesforce
    $accounts get_accounts($client);

    if (
    $accounts)
    {
      echo 
    'There are currently ' count($accounts) . ' opportunities:
    '
    ;
      foreach (
    $accounts as $r)
      {
            
    $r = new SObject($r);

            
    //set up PL/SQL Statement
            
    $strsql "begin sforce_opp_insert_test(";
            
    $strsql .= ":pm_id,";
            
    $strsql .= ":pm_description";
            
    $strsql .= "); end;";

            
    $id $r->Id;

            if (
    strlen($r->fields->Description) == 0)
            {
              
    $description "No Description Posted";
            }
            else
            {
              
    $description =  $r->fields->Description;
            }

            
    //Prepares PL/SQL Statement
            
    $stmt $conn->Prepare($strsql);
            
    $conn->InParameter($stmt$id'pm_id');
            
    $conn->InParameter($stmt$description,'pm_description', -1OCI_B_CLOB);

            
    $rconn $conn->Execute($stmt);

            if (!
    $rconn) {
                echo 
    $conn->ErrorMsg();
                echo 
    '' print_r($r->fieldstrue) . '';
                exit;
            }
      }
      echo 
    $rows_loaded;
    }



    //This is the function that performs the extract from salesforce
    //and loops through all your data until the last record is
    //returned
    function get_accounts($connection)
    {

      
    $query "Select Id, Description, Project_Comments__c FROM Opportunity";

      
    //lets set this to get 500 records each time
      
    $queryOptions = new QueryOptions(500);
      
    $response $connection->query(($query), $queryOptions);

        
    // Checks response records
        
    if ($response->size 0)
        {
            
    $accounts $response->records;
                
    // Cycles through additional responses if the number of records
                // exceeds the batch size
            
    while (!$response->done)
            {
                
    set_time_limit(100);
                
    $response $connection->queryMore($response->queryLocator);
                
    $accounts array_merge($accounts$response->records);
            }
        }

      return 
    $accounts;
    }

    ?> 

  2. #2
    Join Date
    May 2007
    Posts
    506
    Blog Entries
    3
    I have encountered some errors while doing this due to some tables/objects being so large that the php scripts are timing out and cannot finish their downloads from Salesforce.com. Each table download has its own script and, as I have stated before, some of data in these tables have large values.

    An example of the problem lies in the Opportunity object, which has over 50,000 records, with 40 plus columns. You can imagine the amount of data that is being downloaded. If the scripts are not written properly, your script will timeout

    I am going to continue to develop these scripts and see if I can get a clean run without a timeout over a weeks time. If the scripts can run for a week, multiple times a day (so the data in the locale Oracle database will remain fresh) and run without any such error or timeout that may occur

    Mike

  3. #3
    Join Date
    May 2007
    Posts
    506
    Blog Entries
    3

    increasing runtime of set_time_limit

    Since I stated in an earlier post about the scripts that were not finishing, I did some small changes within the main function to increase the run time of the loop while retrieving data from Salesforce.com.

    It has to do with increasing the time limit so the script will basically reset itself each time it retrieves 500 records. The built in function in php is:
    Code:
    set_time_limit(300);
    Here is an entire, working, function that can be modified to download the opportunity table and then do with it what you wish:


    PHP Code:
    function get_accounts($connection)
    {

      
    $query "Select Id, AccountId, Name, Description, StageName, Amount, Probability, ExpectedRevenue, TotalOpportunityQuantity, CloseDate,
                Type, NextStep, LeadSource, IsClosed, IsWon, ForecastCategory, CampaignId, HasOpportunityLineItem, Pricebook2Id,
                OwnerId, CreatedDate, CreatedById, LastModifiedDate, LastModifiedById, SystemModstamp FROM Opportunity"
    ;
      
    //Description,
      
    $queryOptions = new QueryOptions(500);
      
    $response $connection->query(($query), $queryOptions);

        
    // New code starts here
        
    if ($response->size 0)
        {
            
    $accounts $response->records;


                
    // Cycles through additional responses if the number of records
                // exceeds the batch size
            
    while (!$response->done)
            {
                
    set_time_limit(300);
                
    $response $connection->queryMore($response->queryLocator);
                
    $accounts array_merge($accounts$response->records);

            }
        }

      return 
    $accounts;

    With the array merge and returning the $accounts, you can then use that array to store the data into Oralce, MySQL, or even write it to a CSV file if that is what you wish

  4. #4
    Join Date
    May 2007
    Posts
    506
    Blog Entries
    3
    Just an update on this. I have successfully finished writing the Oracle DB replication scripts for the following Salesforce Objects / Tables:
    1. Account
    2. AccountShare
    3. AccountTeamMember
    4. Contact
    5. Opportunity
    6. OpportunityLineItem
    7. OpportunityTeamMember
    8. PriceBookEntry
    9. Product2
    10. User
    Someone once told me that this could not be accomplished in PHP, that it would not work. Well it does and like a charm. If you wish to see some of the working examples, they are posted on this site or Contact me!

  5. #5
    Hi Mike

    getting error this

    Fatal error
    : Uncaught SoapFault exception: [sf:REQUEST_LIMIT_EXCEEDED] REQUEST_LIMIT_EXCEEDED: TotalRequests Request Limit exceeded. in soapclient/SforceBaseClient.php:155 Stack trace: #0 [internal function]: SoapClient->__call('login', Array) #1 soapclient/SforceBaseClient.php(155): SoapClient->login(Array) #2 Testing1.php(27): SforceBaseClient->login('securenext@gmai...', 'sns4321Ap3Emtwn...') #3 {main} thrown in SforceBaseClient.php on line 155

    Please Advise me



  6. #6
    Join Date
    May 2007
    Posts
    506
    Blog Entries
    3
    That means that you hit your limit of queries against salesforce's API. I do not remember the allowed limit per day, but you will have to wait 24 hours. You will need to search the salesforce forums to find out that number or contact support

    ~Mike

  7. #7
    Hi Mike

    Thanks for reply

    I am used to get data from sales forces using query
    Select Id,MHC_Factor_Code__c from Account where Rating='Dodge'

    I am getting only the only Id value
    [records] => Array
    (
    [0] => stdClass Object
    (
    [Id] => 0014000000NWkDxAAL
    )

    [1] => stdClass Object
    (
    [Id] => 0014000000NWkDyAAL
    )

    [2] => stdClass Object
    (
    [Id] => 0014000000NWkDzAAL
    )

    [3] => stdClass Object
    (
    [Id] => 0014000000NWkE0AAL

    not getting the MHC_Factor_Code__c value any thoughts

    Please let me know

    thanks

  8. #8
    Join Date
    May 2007
    Posts
    506
    Blog Entries
    3
    Quote Originally Posted by Baburaj View Post
    Hi Mike

    Thanks for reply

    I am used to get data from sales forces using query
    Select Id,MHC_Factor_Code__c from Account where Rating='Dodge'



    not getting the MHC_Factor_Code__c value any thoughts

    Please let me know

    thanks
    Are you sure that those entries have the custom field populated? can you post your code that is pulling the records?

  9. #9

    PHP setup help

    Mike,

    I am new to PHP world. Could you pls help me setup PHP. I have all the downloads you mentioned in the threads.

    -cpwr1

  10. #10
    Join Date
    May 2007
    Posts
    506
    Blog Entries
    3
    @cpwr1

    I surely could help you with this, if you have not done this by now, but I will not be able to unless you catch me in the evening this week or during the day starting next week


    Hope that helps and sorry for the delayed response


    ~Mike

+ Reply to Thread
Page 1 of 3
1 2 3 LastLast

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts

SEO by vBSEO 3.5.0 RC1 PL1