<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>PHP and Salesforce &#187; Getting Started</title>
	<atom:link href="http://phpandsalesforce.com/category/getting-started/feed/" rel="self" type="application/rss+xml" />
	<link>http://phpandsalesforce.com</link>
	<description>A CRM Reference For PHP Developers</description>
	<lastBuildDate>Wed, 26 May 2010 22:19:50 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Catching Salesforce Exceptions</title>
		<link>http://phpandsalesforce.com/2009/12/15/catching-salesforce-exceptions/</link>
		<comments>http://phpandsalesforce.com/2009/12/15/catching-salesforce-exceptions/#comments</comments>
		<pubDate>Wed, 16 Dec 2009 01:41:35 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Getting Started]]></category>
		<category><![CDATA[PHP Toolkit]]></category>
		<category><![CDATA[Salesforce API Development]]></category>

		<guid isPermaLink="false">http://phpandsalesforce.com/?p=319</guid>
		<description><![CDATA[Pretty simple, but for those new to PHP or to exception handling:

// instantiate a SOAP connection to Salesforce
// catch Salesforce exception if there is one
try {
  $crmHandle->createConnection(SALESFORCE_WSDL);
} catch (Exception $e) {
  // handle exception - did you set the WSDL path above?

  // print out the exception string
  echo $e->getMessage();
}

If an [...]]]></description>
			<content:encoded><![CDATA[<p>Pretty simple, but for those new to PHP or to exception handling:</p>
<pre>
// instantiate a SOAP connection to Salesforce
// catch Salesforce exception if there is one
try {
  $crmHandle->createConnection(SALESFORCE_WSDL);
} catch (Exception $e) {
  // handle exception - did you set the WSDL path above?

  // print out the exception string
  echo $e->getMessage();
}
</pre>
<p>If an exception occurs, and it&#8217;s not caught, it behaves more or less like a fatal error.  PHP&#8217;s set_exception_handler() function provides a nice fallback, allowing you to avoid try/catching every method call.  That&#8217;s pretty much all there is to it.</p>
<p align="left"><a class="tt" href="http://twitter.com/home/?status=Catching+Salesforce+Exceptions+http://is.gd/5pg8V" title="Post to Twitter"><img class="nothumb" src="http://phpandsalesforce.com/wp-content/plugins/tweet-this/icons/tt-twitter.png" alt="[Post to Twitter]" border="0" /></a> <a class="tt" href="http://twitter.com/home/?status=Catching+Salesforce+Exceptions+http://is.gd/5pg8V" title="Post to Twitter">Tweet This Post</a>&nbsp; </p>]]></content:encoded>
			<wfw:commentRss>http://phpandsalesforce.com/2009/12/15/catching-salesforce-exceptions/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Salesforce Gotchas and Undocumented &#8216;Features&#8217;</title>
		<link>http://phpandsalesforce.com/2009/06/29/salesforce-gotchas-and-undocumented-features/</link>
		<comments>http://phpandsalesforce.com/2009/06/29/salesforce-gotchas-and-undocumented-features/#comments</comments>
		<pubDate>Tue, 30 Jun 2009 05:27:35 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Getting Started]]></category>
		<category><![CDATA[Gotchas]]></category>
		<category><![CDATA[PHP Toolkit]]></category>
		<category><![CDATA[Salesforce API Development]]></category>
		<category><![CDATA[API]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Salesforce]]></category>

		<guid isPermaLink="false">http://phpandsalesforce.com/?p=62</guid>
		<description><![CDATA[Today we&#8217;re going to go through some things that I hope you find interesting and informative, things that hopefully will make your development process a lot easier.  With many of the following issues, I&#8217;ve found the documentation either sparse, obscured, or non-existent.
- Objects (such as individual leads or contacts) have either a 15-character or [...]]]></description>
			<content:encoded><![CDATA[<p>Today we&#8217;re going to go through some things that I hope you find interesting and informative, things that hopefully will make your development process a lot easier.  With many of the following issues, I&#8217;ve found the documentation either sparse, obscured, or non-existent.</p>
<p>- Objects (such as individual leads or contacts) have either a 15-character or an 18-character <b>case-sensitive</b> ID (e.g. 00Q6000000OaR87).  You should not count on one format or the other being returned.  The two formats can normally be used interchangeably (you can pass either version to an API call), but one notable exception to this rule is the Excel Connector, which integrates Salesforce and Excel.  <del datetime="2009-07-19T04:21:41+00:00">The 18-character version has some extra non-essential metadata about the object that&#8217;s not present in the earlier 15-character version.</del>  CORRECTION:  This is wrong.  The lesson here is that when your motivation for writing a blog is your horrible experience with your Salesforce integrators, you shouldn&#8217;t take what they say as gospel.  <a href="http://www.x2od.com/">David Schach</a> pointed out that the 15-character version is simply case-sensitive.  There is no metadata whatsoever.  I apologize again for failing to fact-check this.</p>
<p>- Object IDs have a three-character prefix, which will be consistent for standard objects and will differ between instances for custom objects.  This is not very well documented, and in fact, a Google search for &#8220;salesforce id prefix&#8221; returns no results (except this entry, after it gets indexed).  If you don&#8217;t yet have any objects of a particular type, but need the ID, you can get it from the URL after clicking on the tab (or the &#8216;&gt;&#8217; to the right of the tabs if you don&#8217;t see the object you&#8217;re looking for).  The URL will be something like &#8216;https://cs1.salesforce.com/00Q/o&#8217;, and the prefix is between the slashes (here, &#8216;00Q,&#8217; for leads).  Prefixes for common standard objects include:</p>
<ul>
<li>00Q (Leads)</li>
<li>003 (Contacts)</li>
<li>001 (Accounts)</li>
<li>006 (Opportunities)</li>
<li>701 (Campaigns)</li>
<li>500 (Cases)</li>
</ul>
<p>- Salesforce API logins (including logins from other third-party applications, like the Outlook tool) have the concept of a security token, which can be reset by going to Setup &gt; My Personal Information &gt; Reset My Security Token.</p>
<p>- Security tokens are appended to passwords when logging in via the API, so you might login with the username &#8216;joe&#8217; and the password &#8216;mypasswordmytoken&#8217;.</p>
<p>- Security tokens change automatically when a password changes &#8211; <b>watch out for this!</b></p>
<p>- There are no default administrator profiles whose passwords do not expire.  <b>This means that your API user&#8217;s password may expire, and your entire API integration will suddenly fail.</b>  I highly recommend making a new administrator profile called something like &#8216;Admins &#8211; Passwords Do Not Expire&#8217; and adding your API and other back-end users to it.  The original profile will not (currently) let you check the &#8216;Passwords do not expire&#8217; checkbox.</p>
<p>- Avoid using the logout() call.  As discussed before, all logins for a single user <b>share a session id</b>.  Calling logout() will log out all concurrent connections for that Salesforce user via the API.  Note also that this behavior is undocumented.  Not to worry, the PHP Toolkit gracefully cleans up the SOAP connection for you.</p>
<p>- Deleted and merged data (e.g. deleted leads) can wreak havoc if your application relies on valid Salesforce IDs.  Just because a lead exists today doesn&#8217;t mean Sales isn&#8217;t going to mass-delete those 10,000 &#8216;junk&#8217; leads tomorrow.</p>
<p>- Salesforce objects are always referred to in the API in the singular form, so &#8216;Lead&#8217; rather than &#8216;Leads.&#8217;</p>
<p>- Custom fields append __c to the field name, e.g. My_Custom_Field__c.</p>
<p>- There are a couple of Salesforce expressions that I&#8217;ll use here to be consistent, including &#8216;picklist&#8217; to mean an HTML select element, &#8216;dependent picklist&#8217; to mean a picklist whose appearance or values depend on another picklist, &#8216;auto number&#8217; to mean an auto-increment field, and &#8216;upsert&#8217; to mean a call that will update if a record with the specified ID exists, or else insert a new record.</p>
<p>Lastly, a quick aside about languages and operating systems.  The code examples presented here assume a POSIX-compliant OS, such as Linux, but Windows-specific considerations should pretty much non-existent.  PHP is fairly OS-agnostic for what we&#8217;re going to be doing, but inevitably there will be an OS-specific issue that will creep in.  As far as portable paths go, PHP lets you use &#8216;/&#8217; as a path separator in scripts on all OSes, but you could certainly instead use the native (and portable) DIRECTORY_SEPARATOR constant or &#8216;\\&#8217; in the paths if you prefer.  Lastly, in this blog, &#8216;native&#8217; is taken to mean &#8216;native to PHP, written in C&#8217; &#8211; an example of this is the native SOAP client (versus the much slower NuSOAP client written in PHP).</p>
<p align="left"><a class="tt" href="http://twitter.com/home/?status=Salesforce+Gotchas+and+Undocumented+%27%3BFeatures%27+http://is.gd/9Lk2O" title="Post to Twitter"><img class="nothumb" src="http://phpandsalesforce.com/wp-content/plugins/tweet-this/icons/tt-twitter.png" alt="[Post to Twitter]" border="0" /></a> <a class="tt" href="http://twitter.com/home/?status=Salesforce+Gotchas+and+Undocumented+%27%3BFeatures%27+http://is.gd/9Lk2O" title="Post to Twitter">Tweet This Post</a>&nbsp; </p>]]></content:encoded>
			<wfw:commentRss>http://phpandsalesforce.com/2009/06/29/salesforce-gotchas-and-undocumented-features/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>Creating a Lead via the Salesforce.com API</title>
		<link>http://phpandsalesforce.com/2009/06/23/creating-a-lead-via-the-salesforce-com-api/</link>
		<comments>http://phpandsalesforce.com/2009/06/23/creating-a-lead-via-the-salesforce-com-api/#comments</comments>
		<pubDate>Tue, 23 Jun 2009 16:20:00 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Getting Started]]></category>
		<category><![CDATA[Lead Generation]]></category>
		<category><![CDATA[PHP Toolkit]]></category>
		<category><![CDATA[Salesforce API Development]]></category>

		<guid isPermaLink="false">http://phpandsalesforce.com/?p=9</guid>
		<description><![CDATA[In our next installment, we&#8217;re going to take a closer look the lead generation code from the end the first post, as well as finish getting your SFDC development environment set up.  
Choosing the Right WSDL For You and Your Organization
Salesforce uses SOAP as its Web Services protocol, and SOAP uses an XML file [...]]]></description>
			<content:encoded><![CDATA[<p>In our next installment, we&#8217;re going to take a closer look the lead generation code from the end the first post, as well as finish getting your SFDC development environment set up.  </p>
<h3>Choosing the Right WSDL For You and Your Organization</h3>
<p>Salesforce uses SOAP as its Web Services protocol, and SOAP uses an XML file called a WSDL (Web Services Definition Language) file that defines how a client (our code) can interact with a server (Salesforce).  For our purposes, there are two different types of WSDL files, Enterprise and Partner.  Here are the specifics:</p>
<p>Enterprise WSDL</p>
<ul>
<li>Is strongly typed</li>
<li>Contains the metadata about all standard and custom fields and objects</li>
<li>Can only be used against your Salesforce instance</li>
</ul>
<p>Partner WSDL</p>
<ul>
<li>Is loosely typed</li>
<li>Takes an array of key-value pairs</li>
<li>Does not contain metadata about objects and fields</li>
<li>Can be used against many Salesforce.com organizations</li>
</ul>
<p>In our organization, we use the Enterprise WSDL, and the main reason why is that we like having a reference of all custom fields and objects readily available in the XML.  Having the type of every field right there next to the field name at hand is nice as well.  This being said, if we had a need to interact with many Salesforce.com instances, we might choose to use the Partner WSDL instead.</p>
<p>For the purposes of this blog, we&#8217;re generally going to be writing against the Enterprise WSDL, but our first example will be presented at the end in an &#8216;Enterprise&#8217; version and a &#8216;Partner&#8217; version.  Those of you who find you prefer the Partner WSDL should be able to take the Partner example and adapt it in the future very easily.  </p>
<h3>Generating the WSDL</h3>
<p>Each instance of Salesforce (each sandbox and production instance) will have their own corresponding WSDL file.  It can be generated by going to Setup &gt; Develop &gt; API &gt; Generate Enterprise WSDL (or Generate Partner WSDL) and downloading the generated XML.  I prefer to keep the default name and put each file in a dev/, staging/, and production/ folder, but you could just as easily call the files dev.enterprise.wsdl.xml, or something to that effect.</p>
<h3>Taking a Look at the Lead Generation Code</h3>
<p>Now that we&#8217;re set up with our WSDL, let&#8217;s take a look at the code at the bottom of the previous post.  I have removed the logout() call, after I read (and subsequently validated) <a href="http://eng.genius.com/blog/2009/05/06/salesforcecom-api-gotchas-1/">this absolutely terrific article</a> that pointed out that a user&#8217;s API connections <b>all get the same session ID</b>!  This means that logout() actually invalidates all of the concurrent connections for that user.  This is somewhat of an edge case for us, as page load times are generally very short, but all the same, we won&#8217;t be using the logout() call going forward.  If you&#8217;re wondering, logging out through the Salesforce API does not log the same user out of any API connections.  At any rate, here is the code, slightly modified, and this time with some comments:</p>
<p>Configuration passages:</p>
<pre>
define('SALESFORCE_USER', 'integration@example.com.sbox1');
define('SALESFORCE_PASS', '*password here*');
define('SALESFORCE_TOKEN', '*security token here*');
define('SALESFORCE_WSDL', '/path/to/enterprise.wsdl.xml');
</pre>
<p>Code:</p>
<pre>
require_once('SforceEnterpriseClient.php');

/**
 * explicitly turn off WSDL caching
 * there is a bug in PHP with this setting in php.ini
 * http://bugs.php.net/bug.php?id=41665
 * so it's safest to set it in the PHP source
 *
 * This param should take an int, not a string like most examples use
 * see http://us3.php.net/manual/en/soap.configuration.php
*/
ini_set('soap.wsdl_cache_enabled', 0);

// instantiate a new Salesforce Enterprise object
$crmHandle = new SforceEnterpriseClient();

// instantiate a SOAP connection to Salesforce
try {
  $crmHandle->createConnection(SALESFORCE_WSDL);
} catch (Exception $e) {
  // handle exception - did you set the WSDL path above?
  // we may also be in a Salesforce outage right now
}

// log in to Salesforce
try {
  $crmHandle->login(SALESFORCE_USER, SALESFORCE_PASS . SALESFORCE_TOKEN);
} catch (Exception $e) {
  // handle exception - did you modify the credentials above to your own?
}

// create our lead
$lead = array();
$lead['FirstName'] = 'Joe';
$lead['LastName'] = 'Moke';
$lead['Email'] = 'jmoke@example.com';
$lead['Title'] = 'CEO';

// create the lead
// $lead must be wrapped in an array, as create() can create
// many objects with a single API call
$result = $crmHandle->create(array($lead), 'Lead');
</pre>
<h3>But Wait, Where&#8217;s Our Lead?</h3>
<p>In this case, there was no exception thrown, but a var_dump() of the $result object will reveal what went wrong:</p>
<pre>
  ["errors"]=>
  object(stdClass)#8 (3) {
    ["fields"]=>
    string(7) "Company"
    ["message"]=>
    string(38) "Required fields are missing: [Company]"
    ["statusCode"]=>
    string(22) "REQUIRED_FIELD_MISSING"
  }
  ["id"]=>
  NULL
  ["success"]=>
  bool(false)
</pre>
<p>Salesforce will usually throw an exception when things go haywire, but not always, as in our example.  When there is an error, and no exception is thrown, $result->success will equal false, so always be prepared for both possibilities, and you can re-throw or create an exception as it applies to your situation.  </p>
<p>The REQUIRED_FIELD_MISSING error is actually fairly unusual to see in the API.  In nearly all cases, creating and updating via the API will exempt you from populating required fields, except where it would render the resulting object useless (omitting LastName from a lead, for instance).  So, let&#8217;s set the company, and take another look at var_dump($result):</p>
<pre>
$lead['Company'] = 'Bob\'s Country Bunker';

object(stdClass)#7 (2) {
  ["id"]=>
  string(18) "00QS00000034zU4MAI"
  ["success"]=>
  bool(true)
}
</pre>
<h3>Creating a Lead with the Partner WSDL</h3>
<p>As promised, the complete version that is compatible with the Partner WSDL is as follows:</p>
<pre>
define('SALESFORCE_USER', 'integration@example.com.sbox1');
define('SALESFORCE_PASS', '*password here*');
define('SALESFORCE_TOKEN', '*security token here*');
define('SALESFORCE_WSDL', '/path/to/partner.wsdl.xml');

require_once('SforcePartnerClient.php');

/**
 * explicitly turn off WSDL caching
 * there is a bug in PHP with this setting in php.ini
 * http://bugs.php.net/bug.php?id=41665
 * so it's safest to set it in the PHP source
 *
 * This param should take an int, not a string like most examples use
 * see http://us3.php.net/manual/en/soap.configuration.php
*/
ini_set('soap.wsdl_cache_enabled', 0);

// instantiate a new Salesforce Partner object
$crmHandle = new SforcePartnerClient();

// instantiate a SOAP connection to Salesforce
try {
  $crmHandle->createConnection(SALESFORCE_WSDL);
} catch (Exception $e) {
  // handle exception - did you set the WSDL path above?
  // we may also be in a Salesforce outage right now
}

// log in to Salesforce
try {
  $crmHandle->login(SALESFORCE_USER, SALESFORCE_PASS . SALESFORCE_TOKEN);
} catch (Exception $e) {
  // handle exception - did you modify the credentials above to your own?
}

// create our lead
$lead = new sObject();
$lead->type = 'Lead';
$lead->fields = array('FirstName' => 'Joe',
                      'LastName' => 'Moke',
                      'Email' => 'jmoke@example.com',
                      'Title' => 'CEO',
                      'Company' => 'Bob\'s Country Bunker');

// create the lead
// $lead must be wrapped in an array, as create() can create
// many objects with a single API call
$result = $crmHandle->create(array($lead), 'Lead');
</pre>
<h3>WSDL Type Mismatches</h3>
<p>Specifying the wrong WSDL such as pointing Salesforce to the Enterprise WSDL when you&#8217;re instantiating the SalesforcePartnerClient or vice-versa can give some obscure exception messages, such as this one:</p>
<pre>
Fatal error: Uncaught SoapFault exception: [soapenv:Client] Element {}item invalid
    at this location in /var/www...
</pre>
<p>Hopefully, if you see this message, this post will jog your memory.</p>
<h3>API Coding Style</h3>
<p>I always use the variable $crmHandle as the handle to my CRM object, and names like $lead or $contact as references to individual objects.  From now on, we will leave the error/exception handling to you, as the different approaches vary widely.  As Salesforce does routinely undergo maintenance, and does on occasion throw exceptions itself (Java socket exceptions, etc&#8230;) I would strongly recommend that you try/catch essential calls (e.g. createConnection()), and that you handle these exceptions in a way that doesn&#8217;t bring down your site if they occur.  Registering a global exception handler with set_exception_handler() and re-throwing exceptions as CrmException($e->getMessage) or CrmCreateException&#8230; is certainly a good start.</p>
<h3>User Input Considerations</h3>
<p>There are a couple of simple things you can check user-supplied data for to avoid throwing exceptions left, right, and center.  </p>
<ul>
<li>Validate email addresses.  An extremely thorough, yet untested (by me) script can be found <a href="http://snipplr.com/view/11616/rfccompliant-email-address-validator/">here</a>.  Salesforce will throw an exception if the email address is not RFC-compliant.</li>
<li>Enforce field length limits.  Have a look at Setup &gt; Customize &gt; {Object Name} &gt; Fields for lengths.  Data exceeding field lengths will throw an exception.  Salesforce will trim whitespace for you, so factor that into your length calculations.</li>
</ul>
<h3>Documentation and References</h3>
<p>Apart from the lack of PHP code examples, you&#8217;ll find that the <a href="http://www.salesforce.com/us/developer/docs/api/index.htm">API Developer&#8217;s Guide</a> is an invaluable resource throughout your Salesforce PHP development.</p>
<p>A handy (and extensive) reference regarding the differences in capabilities and thresholds between the different Salesforce editions can be found <a href="http://www.salesforce.com/assets/pdf/datasheets/DS_RightSFDC.pdf">here</a>.  This PDF is quite useful to keep at hand in order to understand exactly the limitations of your particular instance.</p>
<h3>Wrapping Up</h3>
<p>I realize this was lengthy, but to paraphrase Albert Einstein, I tried to make things as simple as possible, but not simpler.  Coming up, we&#8217;ll take a look at some examples involving converting leads with the API, and creating and updating Contact and Account objects in Salesforce.</p>
<p align="left"><a class="tt" href="http://twitter.com/home/?status=Creating+a+Lead+via+the+Salesforce.com+API+http://is.gd/5EHEK" title="Post to Twitter"><img class="nothumb" src="http://phpandsalesforce.com/wp-content/plugins/tweet-this/icons/tt-twitter.png" alt="[Post to Twitter]" border="0" /></a> <a class="tt" href="http://twitter.com/home/?status=Creating+a+Lead+via+the+Salesforce.com+API+http://is.gd/5EHEK" title="Post to Twitter">Tweet This Post</a>&nbsp; </p>]]></content:encoded>
			<wfw:commentRss>http://phpandsalesforce.com/2009/06/23/creating-a-lead-via-the-salesforce-com-api/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Welcome to PHP and Salesforce!</title>
		<link>http://phpandsalesforce.com/2009/06/16/welcome-to-php-and-salesforce/</link>
		<comments>http://phpandsalesforce.com/2009/06/16/welcome-to-php-and-salesforce/#comments</comments>
		<pubDate>Tue, 16 Jun 2009 23:57:51 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Getting Started]]></category>
		<category><![CDATA[API]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Salesforce]]></category>
		<category><![CDATA[Sandbox]]></category>
		<category><![CDATA[Toolkit]]></category>

		<guid isPermaLink="false">http://phpandsalesforce.com/?p=3</guid>
		<description><![CDATA[PHP and Salesforce is a new blog dedicated to helping web developers take control over their CRM integration.  Most of the early entries will focus on building a reference of Salesforce PHP examples, followed by discussions on topics including performance, concurrency, CRM framework architecture (and whether you should consider building one), and strategies for [...]]]></description>
			<content:encoded><![CDATA[<p>PHP and Salesforce is a new blog dedicated to helping web developers take control over their CRM integration.  Most of the early entries will focus on building a reference of Salesforce PHP examples, followed by discussions on topics including performance, concurrency, CRM framework architecture (and whether you should consider building one), and strategies for handling scheduled and unscheduled outages.</p>
<p>Before we go any further, <b>you must have either the Enterprise Edition or the Unlimited Edition</b> to access the API with your production Salesforce.com instance.  Those of you who are using the Group Edition or the Professional Edition can test your API code against the Developer Edition, by signing up <a href="http://www.developerforce.com/events/regular/registration.php">here</a>.  However, there is currently a limit of 5,000 API calls per 24 hour period in the Developer Edition.  </p>
<h3>Downloading The Toolkit</h3>
<p>Today, we&#8217;re going to walk through getting the PHP Toolkit set up and a sandbox copied off.  Let&#8217;s start by downloading the Toolkit:</p>
<ul>
<li><a href="http://wiki.developerforce.com/index.php/PHP_Toolkit">Toolkit for PHP 5.2+</a></li>
<li><a href="http://wiki.developerforce.com/index.php/PHP_Toolkit_11.0">Toolkit for PHP 5.1.2+</a></li>
<li><a href="http://wiki.developerforce.com/index.php/PHP_Toolkit_1.1">Toolkit for PHP 5.0+</a> (free DeveloperForce login required)</li>
</ul>
<p>All versions of the Toolkit require the curl, openssl, and soap extensions, the installation status of which can be determined by issuing `php -m` at the command line.</p>
<h3>Unpacking the Toolkit</h3>
<p>To set up the toolkit, simply unpack it.  I normally unpack it to lib/crm/salesforce, but the only thing that&#8217;s really important is to keep the Toolkit in its own directory so it can easily be upgraded.</p>
<h3>Sandboxes</h3>
<p>If you have sandbox access, I highly recommend testing your code there before running it against your production instance.  One reason for this (aside from inadvertently creating or deleting thousands of records, of course) is that the number of API calls per 24-hour period is metered, and once you&#8217;re out, you&#8217;re out.  This means that if your site relies on Salesforce being available via the API to function correctly, the results could be very damaging to your business.  If you have sandbox access, you can view your entitlement under Setup &gt; Data Management &gt; Sandbox.  The current API limits can be found <a href="http://www.salesforce.com/us/developer/docs/api/Content/implementation_considerations.htm#topic-title_request_metering">here</a>.</p>
<p>If you don&#8217;t have a sandbox already, go ahead and clone one off by going to Setup &gt; Data Management &gt; Sandbox.  The three types of sandboxes are:</p>
<ul>
<li>Configuration Only &#8211; Production configuration without the data.  Holds 500 MB.</li>
<li>Developer &#8211; The same as Configuration Only, but holds only 10 MB.</li>
<li>Full &#8211; A full copy of your production instance.</li>
</ul>
<p>A Configuration or Developer sandbox will be probably be fine, and if you do need a Full sandbox, keep in mind that it can take upwards of several hours to create.  Also, <b>sandboxes can only be refreshed every 30 days</b>, and you can typically only have one full copy at a time.  Another gotcha with sandboxes is that labels cannot currently be edited after the sandbox is created or refreshed, so go ahead and label yours now.  You don&#8217;t want to have to worry about someone refreshing your critical sandbox instance because they didn&#8217;t realize it was in use.  I tend to name my sandboxes &#8217;sbox1&#8242;, &#8217;sbox2&#8242;, etc., and to log into a sandbox called &#8217;sbox1&#8242;, &#8216;user@example.com&#8217; would log into SFDC at https://test.salesforce.com with the username &#8216;user@example.com.sbox1&#8242; and the same password they use on production.</p>
<p>Yet another thing to bear in mind when cloning off a sandbox is that the process will copy over your existing workflow rules from production, <b>and leave them active</b>.  This can cause a variety of issues, particularly if you have rules that trigger emails to mailing lists.  Depending on your IT infrastructure, mail loops can inadvertently be created because of this.  So, now would be a good time to disable any unnecessary workflow rules (under Setup &gt; Create &gt; Workflow &#038; Approvals &gt; Workflow Rules).</p>
<h3>Finally, Some Code</h3>
<p>We&#8217;ll go over this code in detail in the next entry, but I wanted to give you at least an idea of how straightforward it can be to develop against the API and integrate Salesforce and PHP.  The following snippet will declare some configuration constants, log in, create a lead, and log out.</p>
<p>Configuration passages:</p>
<pre>
define('SALESFORCE_USER', 'integration@example.com.sbox1');
define('SALESFORCE_PASS', '*password here*');
define('SALESFORCE_TOKEN', '*security token here*');
define('SALESFORCE_WSDL', '/path/to/enterprise.wsdl.xml');
</pre>
<p>Code:</p>
<pre>
$crmHandle = new SforceEnterpriseClient();
$crmHandle->createConnection(SALESFORCE_WSDL);
$crmHandle->login(SALESFORCE_USER, SALESFORCE_PASS . SALESFORCE_TOKEN);

// create our lead
$lead = array();
$lead['FirstName'] = 'Joe';
$lead['LastName'] = 'Moke';
$lead['Email'] = 'jmoke@example.com';
$lead['Title'] = 'CEO';
$lead['Company'] = 'Acme Widget Corporation';
$result = $crmHandle->create(array($lead), 'Lead');

$crmHandle->logout();
</pre>
<h3>Final Thoughts</h3>
<p>I hope you enjoyed my first entry, and I hope it was helpful.  I&#8217;ll generally be posting one or two entries a week, and next time, we&#8217;ll walk through getting your PHP environment configured to make the above snippet go, and start looking at some SFDC development considerations, gotchas, and quirks.  See you again shortly!</p>
<p align="left"><a class="tt" href="http://twitter.com/home/?status=Welcome+to+PHP+and+Salesforce%21+http://is.gd/9LKEL" title="Post to Twitter"><img class="nothumb" src="http://phpandsalesforce.com/wp-content/plugins/tweet-this/icons/tt-twitter.png" alt="[Post to Twitter]" border="0" /></a> <a class="tt" href="http://twitter.com/home/?status=Welcome+to+PHP+and+Salesforce%21+http://is.gd/9LKEL" title="Post to Twitter">Tweet This Post</a>&nbsp; </p>]]></content:encoded>
			<wfw:commentRss>http://phpandsalesforce.com/2009/06/16/welcome-to-php-and-salesforce/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
	</channel>
</rss>
