Updates
2012-12-06
Added support for Salesforce.com API Version 26.0 (beta) features Now supports GEOLOCATION(), DISTANCE() SOQL functions No supports conditional SELECT fieldlist statements (SELECT [...] TYPEOF sobjectName WHEN type THEN [fieldlist] END) Additional unit tests for the underlying Force.com Toolkit For PHP 5.3 libraryIntroduction
CodemitteForceToolkitBundle is a Symfony 2 bundle to integrate Force.com Toolkit for PHP 5.3 into your Symfony 2 project. Simply enable the bundle, configure SOAP access to your salesforce organisation and start working.
THIS BUNDLE AND IT'S LIBRARY DEPENDENCIES ARE STILL SUBJECT OF HEAVY DEVELOPMENT AND SHOULD NOT BE CONSIDERED STABLE! DONT USE IT IN PRODUCTION UNTIL YOU REALLY NOW WHAT YOU'RE DOING (though i don't in every circumstances.)
This bundle is part of a multi-tenant self service portal application currently developed by the company i work for and will recieve updates/backports from time-to-time, but there is no "official release schedule".
In the meanwhile, some other, rather popular libraries arised, perhaps you want to take a look at these ones:
SalesforceClientBundle SalesforceMapperBundleFeatures
SOAP client abstraction layer through CodemitteSoap library SOAP API: partner.wsdl.xml, enterprise.wsdl.xml Metadata API: Use .describeX()-Methods to fetch metadata information Basis soap interface for custom webservices (APEX-Webservice classes) SOQL query abstraction layer through CodemitteForceToolkit Build queries "by hand" Build queries by using the fluent API of a SOQL query builder Chain both string queries and API-built queries Use limit(), offset(), orderBy(), where() methods to easily implement filters Symfony 2 form component integration Validators and form types/widgets for each relevant salesforce datatype is provided, e.g. picklists. Easily handle i18n and l10n by simply changing the locale of the underlying Force.com API user. Handle picklist entry display by modifying your API user's profile, or object record types. Handle currency or date fields only dependent on Force.com settings API user factory Use different API users dependent on the current webuser's localeInstallation
By composer/packagist (recommended)
Add the following line to your composer.json file into the "require"-section:
require { [...] "codemitte/ForceToolkitBundle" : "dev-master" [...] }
After that run the composer update command:
$ php ./composer.phar update
If you face problems, refer to the official composer documentation. Remark the required whitelist entry when using .phar-files with a php executable that has ext/suhosin enabled!
Enable the freshly downloaded bundle in your Kernel PHP file (usually located in app/AppKernel.php):
class AppKernel extends Kernel { public function registerBundles() { return array( [...] new CodemitteBundleForceToolkitBundleCodemitteForceToolkitBundle() ); } }
Clear all caches
Manual installation
Download/clone the bundle sources into your project (recommended: Define the github repository as a git submodule) The bundle should reside in an updateable vendor directory, the location should reflect the full namespaced path, e.g.
vendor/codemitte/codemitte-force-toolkit-bundle/Codemitte/Bundle/ForceToolkit/{repository root, the dir where the .git directory resides}
Download/clone the bundle's dependencies as well
CodemitteSoap CodemitteForceToolkit CodemitteCommonAdd the classpaths of the bundle and all dependencies to your autoload.php file. The mapping is
'CodemitteBundleForceToolkitBundle' => 'path/to/cloned/repository/'
for instance:
'CodemitteBundleForceToolkitBundle' => 'vendor/codemitte/codemitte-force-toolkit-bundle', 'CodemitteForceToolkit' => 'vendor/codemitte/codemitte-force-toolkit', 'CodemitteSoap' => 'vendor/codemitte/codemitte-soap', 'CodemitteCommon' => 'vendor/codemitte/codemitte-common'
Enable the freshly downloaded bundle to your Kernel PHP file (usually to find in app/AppKernel.php):
class AppKernel extends Kernel { public function registerBundles() { return array( [...] new CodemitteBundleForceToolkitBundleCodemitteForceToolkitBundle() ); } }
5. Clear all caches
Configuration
=============
The bundle provides a Configuration class which defines the schema of all config keys you may use in your config.yml (xml|php) files, as usual. The full schema is:
app/config/config.yml
```yaml
codemitte_force_toolkit:
soap_api_client:
classname: "CodemitteForceToolkitSoapClientPartnerClient"
connection_ttl: 28800
service_location: ~
wsdl_location: "%kernel.root_dir%/config/wsdl/prod/partner.wsdl.xml"
api_users:
default: { username: "user1@myorg.tld", password: "********" }
locales:
en: { username: "user1@myorg.co.uk", password: "********" }
de: { username: "user1@myorg.de", password: "********" }
de_AT: { username: "user1@myorg.at", password: "********" }
metadata:
cache_service_id: "codemitte_forcetk.metadata.file_cache"
cache_location: "%kernel.root_dir%/cache/forcetk"
cache_ttl: -1
A minimal configuration may look like this:
app/config/config.yml
codemitte_force_toolkit: soap_api_client: wsdl_location: "%kernel.root_dir%/config/wsdl/prod/partner.wsdl.xml" api_users: default: { username: "user1@myorg.co.uk", password: "********" } locales: en: { username: "user1@myorg.co.uk", password: "********" } metadata: cache_service_id: "codemitte_forcetk.metadata.array_cache"
Configuration options explained
soap_api_client.classname: The classname of the client PHP class, usually "CodemitteForceToolkitSoapClientPartnerClient" "CodemitteForceToolkitSoapClientEnterpriseClient" Future plans tend to implemend a factory that is able to auto-detect the correct client class from the given WSDL information. soap_api_client.connection_ttl: The time-to-live of an API user, stored in memory (APC, for instance, is the only adapter for connection storage at the moment). Since a API connection is reset each 24 h, the ttl should reflect this value. If an unexpected connection error occurs, an symfony 2 exception event handler will re-bootstrap the API connection gracefully. soap_api_client.service_location: Use this flag to override the service location endpoint defined in the underlying WSDL file. This is useful when e.g. using a single WSDL file in different development environments (A production WSDL against a Quality Assurance sandbox, for instance). Though, best practice seems to maintain dedicated .wsdl-files for each organisation to avoid strange "could not connect to host" issues. soap_api_client.api_users: Array to define one or more API users for different frontend user locales. See example above. Each user must have API usage permission within salesforce. metadata.cache_service_id: The cache service id for the metadata cache (metadata are cleaned-up results from describeSobject()/describeLayout() calls.) Available values are: "codemitte_forcetk.metadata.file_cache": for production "codemitte_forcetk.metadata.array_cache": for development metadata.cache_location: The cache location (currently in file system only) -- refactoring candidate!! metadata.cache_ttl: The lifetime of the metadata cache until it is about to invalidate. -1 means the cache does never expire.For using the Force.com symfony form types in your twig templates, consider enabling the following global form template extension:
twig: form: resources: - 'CodemitteForceToolkitBundle:Form:fields.html.twig'
Documentation
Basic usage of the client/query builder
src/AcmeBundle/Controller/DefaultController.php
/** @var $client CodemitteForceToolkitSoapClientPartnerClient */ $client = $this->get('codemitte_forcetk.client'); /** @var $response CodemitteSoapMappingGenericResult */ $response = $client->query('SELECT Id, Name FROM Account LIMIT 10'); foreach($response['result']['records'] AS $account) { print_r($account); }
$response is Instanceof CodemitteSoapMappingGenericResult. You may access each property by array notation, object notation of method notation:
$response['result'] $response->result $response->get('result')
$response->get('result')->get('records'); is instanceof CodemitteSoapMappingGenericResultCollection which adds methods for easy traversal.
foreach($response['result']['records'] AS $account) { print_r($account); }
(Please refer to the client interface (CodemitteForceToolkitSoapClientAPIInterface) for a list of all available service call methods.)
$client->query() is a low-level API method for fireing SOQL queries against the platform. A more convinient way is to utilize the QueryBuilder:
src/AcmeBundle/Controller/AccountController.php
public function accountShowAction($id) { /** @var $queryBuilder CodemitteForceToolkitSoqlBuilderQueryBuilder */ $queryBuilder = $this->get('codemitte_forcetk.query_builder'); /** @var $account CodemitteSoapMappingGenericResult */ $account = $queryBuilder->prepareStatement('SELECT Id, Name FROM Account WHERE Id = :id')->bind(array( 'id' => $id ))->fetchOne(); if(null === $account) { throw new NotFoundHttpException(sprintf('The account with Id "%s" could not be found', $id)); } return $this->render('AcmeBundle:Account:show.html.twig', array( 'account' => $account ); }
Analogously, the account list view:
src/AcmeBundle/Controller/AccountController.php
public function accountListAction($limit = 20, $offset = 0, $orderBy = 'Name') { /** @var $queryBuilder CodemitteForceToolkitSoqlBuilderQueryBuilder */ $queryBuilder = $this->get('codemitte_forcetk.query_builder'); // MAXIMUM OFFSET IS 2000!!! /** @var $accounts CodemitteSoapMappingGenericResultCollection */ $accounts = $queryBuilder->prepareStatement('SELECT Id, Name FROM Account')->orderBy($orderBy)->limit($limit)->offset($offset)->fetch(); return $this->render('AcmeBundle:Account:list.html.twig', array( 'accounts' => $accounts ); }
QueryBuilder Reference
Basic query to select a collection of sobjects:
$queryBuilder ->select('Id, AccountNumber, Email') ->from('Account') ->fetch() ;
Basic query to select a single sobject instance:
$queryBuilder ->select('Id, AccountNumber, Name') ->from('Account') ->where('Id = :id', array('id' => $id)) ->fetchOne(); ;
Query with compound WHERE clause (useful for building filters, for instance):
$builder ->select('Id, AccountNumber, Name') ->from('Account') ->where( $builder ->whereExpr() ->xpr('Id', '=', ':id') ->andXpr ( $builder ->whereExpr() ->xpr('Name', '=', "'Supercompany'") ->orXpr('AccountNumber', '=', "'12345'") ), array('id' => $id) ) ->getSoql();
This query should result in an output like:
SELECT Id, AccountNumber, Name FROM Account WHERE Id = 'xxxxxxxxxxxxxxxxxx' AND (Name = 'Supercompany' OR AccountNumber = '12345')
Please refer to the query builder interface for further information.
The form component
You may register salesforce types as usual, but instead of using the standard symfony 2 form types, you can utilize special Force.com types. These types take only a few mandatory parameters, namely
sobject type the field name an optional record type idOther well-known options like "required", "choices", etc. are also available, because each Force.com form type extend standard symfony 2 types!
NOTE: For using the force_tk widgets you have to enable a global custom form template in your config.yml twig section:
twig: form: resources: - 'CodemitteForceToolkitBundle:Form:fields.html.twig'
Example for building a Force.com enabled form type:
src/AcmeBundle/Type/AccountEditType.php
<?php namespace AcmeBundleTypeEditAccountType; use SymfonyComponentFormAbstractType; use SymfonyComponentFormFormBuilderInterface; use SymfonyComponentOptionsResolverOptionsResolverInterface; /** * Contact type for rendering a registration form. */ class EditAccountType extends AbstractType { /** * @param SymfonyComponentFormFormBuilderInterface $builder * @param array $options * @return void */ public function buildForm(FormBuilderInterface $builder, array $options) { parent::buildForm($builder, $options); $builder->add('billingCountry', 'forcetk_picklist', array( 'sobject_type' => 'Account', 'fieldname' => 'AccountSource', 'recordtype_id' => $options['accountRecordTypeId'] )); } /** * Returns the name of this type. * * @return string The name of this type */ function getName() { return 'edit_account'; } public function setDefaultOptions(OptionsResolverInterface $resolver) { parent::setDefaultOptions($resolver); $resolver ->setRequired(array('accountRecordTypeId')) ->setAllowedTypes(array('accountRecordTypeId' => array('null', 'string'))) ->setDefaults(array( 'data_class' => 'CodemitteBundleUserBundleValidatorEditAccountValidator', 'accountRecordTypeId' => null )); } }
For Force.com form types, the bundle comes with some built-in validators you may use in your validation models. For example, consider this account represenation:
<?php namespace CodemitteBundleUserBundleValidator; use SymfonyComponentValidatorConstraints AS Assert, CodemitteForceToolkitValidatorConstraints AS AssertForce ; class EditAccountValidator { /** * @var string * @AssertNotBlank * @AssertForcePicklist(sObjectType="Account", fieldname="AccountSource") */ public $billingCountry; [...]
There is yet no full documentation about Force.com validators + form types available, so please refer to the validator's sourcecode and/or services.xml of the bundle (Resources/config/services.xml), there you will find the full list of available form types including their aliases (the alias is the token which enables the "short address" in form builders, namely for instance "forcetk_picklist", "forcetk_date" and so on.
版权声明:
1、该文章(资料)来源于互联网公开信息,我方只是对该内容做点评,所分享的下载地址为原作者公开地址。2、网站不提供资料下载,如需下载请到原作者页面进行下载。
3、本站所有内容均由合作方或网友上传,本站不对文档的完整性、权威性及其观点立场正确性做任何保证或承诺!文档内容仅供研究参考学习用!
4、如文档内容存在违规,或者侵犯商业秘密、侵犯著作权等,请点击“违规举报”。