+ Start a Discussion
CwestonrCwestonr 

CakePHP example Data source for Enterprise

I have built a sample way to integrate the Salesforce API  with CakePHP.

 

The zip package is at http://www.contangoadvisors.com/work/SalesforceCakePHPdatasource.zip

 

This Datasource is for a Salesforce Enterprise implementation
to use the other types you will have to modify the code.

 

 This Package requires you to have the Salesforce PHP Toolkit 13.0  or greater.
(http://wiki.developerforce.com/index.php/PHP_Toolkit)
I wrote this as a simple implementation of the Salesforce enterprise API for read and login

!!!!THIS PACKAGE IS NOT COMPLETE USE AS A STARTING POINT!!!!

 

 

 

You will want to extend the salesforce_source.php file with other methods for "upsert", "delete", etc.
(SEE NEXT MESSAGE: I have updated the code to support all of the WSDL functions including any that will be changed or added it is now included in the zip)

How to install this package:

1. Bake a CakePHP app ( see CakePHP.org) "app" refers your newly baked application's directory
2. Place the following files in your App.
    models/datasources/salesforce_source.php     in app/models/datasources/ (replace with salesforce_source.php in next message it is now included in the zip)
    config/database.php                                        in app/config/


    models/account.php                                        in app/models/ (use below if using new salesforce_source.php in next message now included in the zip)


<?php
class Account extends AppModel {

var $useDbConfig='sftest';
var $useTable = false;

function first10account() {
$SOQL = "SELECT
a.AccountNumber,
a.AnnualRevenue,
a.BillingCity,
a.BillingCountry,
a.BillingPostalCode,
a.BillingState,
a.BillingStreet,
a.CreatedById,
a.CreatedDate,
a.Description,
a.Fax,
a.FirstName,
a.Id,
a.Industry,
a.IsDeleted,
a.IsPersonAccount,
a.LastActivityDate,
a.LastModifiedById,
a.LastModifiedDate,
a.LastName,
a.MasterRecordId,
a.Name,
a.NumberOfEmployees,
a.OwnerId,
a.Ownership,
a.ParentId,
a.Phone,
a.Rating,
a.RecordTypeId,
a.Salutation,
a.Type,
a.Website
FROM Account a
WHERE IsDeleted = Null
Limit 10";
return $this->query(array('query',$SOQL)); // changed to support new datasource
}

}
?>



 

    controllers/mytest_controller.php                    in app/controllers/
    views/mytest directory                                    in app/views/

   Your copy of the Salesforce PHP Toolkit "soapclient/" directory is placed in app/models/datasources/
   
3. Download your enterprise.wsdl.xml from your Production salesforce instance
4. Download your enterprise.wsdl.xml from your Sandbox salesforce instance and name it test.enterprise.wsdl.xml
5. copy your enterprise.wsdl.xml and test.enterprise.wsdl.xml to  app/models/datasources/soapclient
6. Edit your app/config/database.php add your usernames and passwords for BOOTH Instances.
   (change sflive to default if needed.)

You can then test your connection by going to your new cake app in a web browser:

http://URL_OF_YOUR_CAKE_INSTANCE/mytest
you should see the first 10 accounts on your test instance of salesforce.

The Model for account SOBJ (app/models/account.php) contains a SOQL query.
The controller (app/controllers/mytest_controller.php) gets the result of the query method in the model and passes it to the view.
The View (app/views/mytest/index.ctp) iterates through the query result and displays the data in a table.

Message Edited by Cwestonr on 01-04-2010 10:08 AM
CwestonrCwestonr

The Data source "salesforce_source.php" has been updated to support ALL wsdl methods  using Query function.



The following is an example call to this from a Model using the test connector in the database.conf:


<?php
class Opportunityt extends AppModel {
var $useDbConfig='sftest';
var $useTable = false;
function OpportunityIdByAccountNumber($account_number = null) {
$SOQL = "SELECT
Id
FROM Opportunity
WHERE Account_Number__c = '".$account_number."'";
return $this->query(array('query',$SOQL));
}
}
?>

 Note the  $this->query(array('methodname', data1, data2, data 3);


Here is a call using the Upsert method from a controller:



<snip>
$sObjects = array();

for (...) {
$sObject = new stdClass();
$sObject->Id = '12345678OOOABC';
$sObject->Amount = '10001.00';
array_push($sObjects, $sObject);
}
$success = $this->Opportunityt->query(array('upsert', $sObjects, 'Opportunity'));

if ($success->success == 1) {
print_r("<br><b>UPSERT SUCCESS</b><br>");
} else {
print_r( "<br><font color=\"#FF0000\"><b>UPSERT ERROR</b></font><br><pre>");
print_r($success->errors);
echo "</pre>";
}
</snip>

 


The above uses a modified version of the SforceEnterpriseClient.php that changes upsert method to be more PHP rational.

mod to upsert follows:


/**
* Creates new objects and updates existing objects; uses a custom field to
* determine the presence of existing objects. In most cases, we recommend
* that you use upsert instead of create because upsert is idempotent.
* Available in the API version 7.0 and later.
*
* @param array $sObjects Array of sObjects
* @param string $objectType Name of Sf object to upsert to
* @param string $ext_Id Field the id matching is set to ID by default
* @return UpsertResult stdClass Object
*/
public function upsert($sObjects, $objectType = "Contact", $ext_Id ='ID' ) {
$arg = new stdClass;
$arg->externalIDFieldName = new SoapVar($ext_Id, XSD_STRING, 'string', 'http://www.w3.org/2001/XMLSchema');
foreach ($sObjects as &$sObject) {
$sObject = new SoapVar($sObject, SOAP_ENC_OBJECT, $objectType, $this->namespace);
}
$arg->sObjects = $sObjects;
return parent::_upsert($arg);
}

 Here is the new salesforce_source.php


<?php
require_once ('models/datasources/soapclient/SforceEnterpriseClient.php');
/**
* SalesForceSource
*
* A Slaesforce SOAP Client Datasource
* Connects to a Salesforce enterprise SOAP server using the configured wsdl file
*
* PHP Version 5
* Copyright 2009 Chris Roberts Ph.D, www.osxgnu.org
* This library is free software: you can redistribute it and/or modify
* it.
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*/
class SalesforceSource extends DataSource {

/**
* Description for this DataSource
*
* @var string
*/
public $description = 'Salesforce Enterprise SOAP Client DataSource';

/**
* The SoapClient instance
*
* @var object
*/
public $client = null;

/**
* The current connection status
*
* @var boolean
*/
public $connected = false;

/**
* The default configuration
*
* @var array
*/
public $_baseConfig = array(
'wsdl' => '',
'username' => '',
'password' => ''
);

/**
* Constructor
*
* @param array $config An array defining the configuration settings
*/
public function __construct($config) {
parent::__construct($config);
$this->connect();
}

public function isConnected(){
return true;
}

/**
* Connects to the SOAP server using the wsdl in the configuration
* passes the salesforce credentals for login
* @param array $config An array defining the new configuration settings
* @return boolean True on success, false on failure
*/
public function connect() {
if (empty($this->config['username']) || empty($this->config['password']) || empty($this->config['wsdl'])) {
$this->error = "Your username-password-wsdl must all be set";
$this->showError();
return false;
}
$wsdl = APP.'models/datasources/soapclient/'.$this->config['wsdl'];
$mySforceConnection = new SforceEnterpriseClient();
$mySforceConnection->createConnection($wsdl);
$mySoapClient = $mySforceConnection->createConnection($wsdl);
$mylogin = $mySforceConnection->login($this->config['username'], $this->config['password']);
$this->client = $mySforceConnection;

return $mySforceConnection;
}

/**
* Sets the SoapClient instance to null
*
* @return boolean True
*/
public function close() {
$this->client = null;
$this->connected = false;
return true;
}

/**
* Returns the available SOAP methods
*
* @return array List of SOAP methods
*/
public function listSources() {
$this->client = $this->connect();
return $this->client->__getFunctions();
}

/**
* Query the SOAP server with the given method and parameters
* pass the SOQL query as the only pram
* @return mixed Returns the soql object array result on success, false on failure
*/
public function query() {
$this->error = false;
$this->client = $this->connect();
$args = array();
$arg = func_get_args();
$args = $arg[0];
$method = null;
$queryData = null;
$type =null;
if(count($args) >1) {
$method = $args[0];
$queryData = $args[1];
} else {
$queryData = $args[0];
}
try {
if(count($args) > 1){
if (isset($args[2]) ){
$result = $this->client->$method($queryData, $args[2]);
} else {
$result = $this->client->$method($queryData);
}
} else {
$result = $this->query($arg);
}
} catch (SoapFault $fault) {
$this->error = $fault->faultstring;
}

if($this->error) {
$this->showError();
return false;
} else {
return $result;
}
}


/**
* Returns the last SOAP response
*
* @return string The last SOAP response
*/
public function getResponse() {
return $this->client->__getLastResponse();
}

/**
* Returns the last SOAP request
*
* @return string The last SOAP request
*/
public function getRequest() {
return $this->client->__getLastRequest();
}

/**
* Shows an error message and outputs the SOAP result if passed
*
* @param string $result A SOAP result
* @return string The last SOAP response
*/
public function showError($result = null) {
if(Configure::read() > 0) {
if($this->error) {
trigger_error('<span style = "color:Red;text-align:left"><b>SalesForce Error:</b> <pre>' . print_r($this->error) . '</pre></span>', E_USER_WARNING);
}
if($result) {
e(sprintf("<p><b>Result:</b> %s </p>", $result));
}
}
}

}

?>
Message Edited by Cwestonr on 01-04-2010 09:24 AM
Test TestTest Test

Hii Cwestonr,

 

Can you plz post the modified code also for create methos ad you posted for upsert method as soon as possible??,,,