+ Start a Discussion
ClimbatizeClimbatize 

upsert problem with php toolkit 13

Hi,

I've got an exception trying to upsert on a custom object with php toolkit 13:

Code:
SoapFault exception: [sf:INVALID_FIELD] INVALID_FIELD: No such column 'Comment__c' on entity 'contact'. in C:\Dev\Workspace\CnV\phptoolkit-13_0\soapclient\SforceBaseClient.php:419

Stack trace:

#0 [internal function]: SoapClient->__call('upsert', Array)

#1 C:\Dev\Workspace\CnV\phptoolkit-13_0\soapclient\SforceBaseClient.php(419): SoapClient->upsert(Object(stdClass))

#2 C:\Dev\Workspace\CnV\phptoolkit-13_0\soapclient\SforceEnterpriseClient.php(93): SforceBaseClient->_upsert(Object(stdClass))

#3 C:\Dev\Workspace\CnV\post.php(34): SforceEnterpriseClient->upsert('Comment__c', Array)

#4 {main}

 
I usually use update function, but now I'd like to upsert. There is my code:

My connexion functions:
Code:
define("SOAP_CLIENT_BASEDIR", "phptoolkit-13_0/soapclient");


require_once (SOAP_CLIENT_BASEDIR.'/SforceEnterpriseClient.php');
require_once (SOAP_CLIENT_BASEDIR.'/SforceHeaderOptions.php');
require_once ('phptoolkit-13_0/userAuth.php');

function ConnectSession($USERNAME,$PASSWORD)
{


    try 
    {
        $mySforceConnection = new SforceEnterpriseClient();
        $mySoapClient = $mySforceConnection->createConnection(SOAP_CLIENT_BASEDIR.'/enterprise.wsdl.xml');
        $mylogin = $mySforceConnection->login($USERNAME, $PASSWORD);
        $_SESSION['connexion'] = $mySforceConnection;

        $_SESSION['location'] = $mySforceConnection->getLocation();
        $_SESSION['sessionId'] = $mySforceConnection->getSessionId();
        $_SESSION['wsdl'] = SOAP_CLIENT_BASEDIR.'/enterprise.wsdl.xml';

    }
    catch (Exception $e)
    {
        echo $mySforceConnection->getLastRequest();
        echo $e->faultstring;
    }

}

function reconnect()
{
    $location = $_SESSION['location'];
    $sessionId = $_SESSION['sessionId'];
    $wsdl = $_SESSION['wsdl'];

    $mySforceConnection = new SforceEnterpriseClient();
    $sforceSoapClient = $mySforceConnection->createConnection($wsdl);
    $mySforceConnection->setEndpoint($location);
    $mySforceConnection->setSessionHeader($sessionId);

    $_SESSION['connexion'] = $mySforceConnection;
}

 


My upsert code on a 'Test_Case__c' custom object:

Code:
reconnect();

$sObject1 = new stdClass();
$sObject1->Comment__c = $_GET['comments'];
$sObject1->Id = $_GET['id'];


try
{

    $response = $_SESSION['connexion']->upsert('Comment__c',array ($sObject1));

}
catch(Exception $e)
{
    echo "Update FAILED";
    echo "erreur! ".str_replace("\n","<br>",$e);

}

 



and the response:


erreur! SoapFault exception: [sf:INVALID_FIELD] INVALID_FIELD: No such column 'Comment__c' on entity 'contact'. in C:\Dev\Workspace\CnV\phptoolkit-13_0\soapclient\SforceBaseClient.php:419

Stack trace:

#0 [internal function]: SoapClient->__call('upsert', Array)

#1 C:\Dev\Workspace\CnV\phptoolkit-13_0\soapclient\SforceBaseClient.php(419): SoapClient->upsert(Object(stdClass))

#2 C:\Dev\Workspace\CnV\phptoolkit-13_0\soapclient\SforceEnterpriseClient.php(93): SforceBaseClient->_upsert(Object(stdClass))

#3 C:\Dev\Workspace\CnV\post.php(34): SforceEnterpriseClient->upsert('Comment__c', Array)

#4 {main}


Why does uspert tries to update the contact object instead of my custom one?
Best Answer chosen by Admin (Salesforce Developers) 
Park Walker (TAGL)Park Walker (TAGL)

 That does look like the problem. Have you tried modifying the Enterprise client function like this:

 

  public function upsert($ext_Id, $sObjects, $type) {

    $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, $type, $this->namespace);

    }

    $arg->sObjects = $sObjects;

    return parent::_upsert($arg);

  }

 

I haven't tested this, but it should solve the problem.

 

Park 

All Answers

SuperfellSuperfell
What does the SOAP request look like?
ClaiborneClaiborne
It is not clear that you are using the upsert command correctly.

First, in order to use the upsert command, you have to establish one field in theobject as an external ID.

Second, the syntax for the upsert command is upsert(string ExternalFieldName, sObject ObjectBeingUpdate).

So, in your code, it looks like Comment__c is a custom field, not a custom object, on the Contact object. It looks like it does not exist.
ClimbatizeClimbatize
Yes you're right, my custom object is Test_Case__c, and Comment__c one of its fields.

So in order to upsert Test_case__c, I have to define an external ID? I'm invistaging in this way, thanks both for the answer. I'll be back if it's too difficult :)
CWDCWD

has any one resolved this?

I'm using the enterprise client and I'm having issues with upsert as well. I think it's because of line 90 in the client:

$sObject = new SoapVar($sObject, SOAP_ENC_OBJECT, 'Contact', $this->namespace);

 

that seems to specify the Contact object as the Type for the data being sent. all other calls specify a "type" param.

 

-CWD

 

Park Walker (TAGL)Park Walker (TAGL)

 That does look like the problem. Have you tried modifying the Enterprise client function like this:

 

  public function upsert($ext_Id, $sObjects, $type) {

    $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, $type, $this->namespace);

    }

    $arg->sObjects = $sObjects;

    return parent::_upsert($arg);

  }

 

I haven't tested this, but it should solve the problem.

 

Park 

This was selected as the best answer
CWDCWD

yup. I did exactly that yesterday evening. everything works like a charm for me.

 

=)

 

-CWD

EricRenfroEricRenfro

This is not at all a true solve. The part that this code change in the core PHP API is the fact that upsert allows the use of multiple different sObject types, this code solve provided, only allows it to work with one at a time which almost completely defeats the purpose and point of good OOP.

 

A more proper way to handle it would be to extract the $type from each sObject, respectively. The question being, what is the best way to construct this and during the process of encapsulation, destruct it, pull the type out, reconstruct it and apply it?

Am I wrong in my thoughts that upsert allows for multiple objects to be used, so long as they share a similar External ID's, such as the actual ID field itself?

 

--

Eric

 

SuperfellSuperfell
all sobjects passed in a single upsert call need to be of the same type.