codemitte/force-toolkit-bundle

轻松将Force.com Toolkit for PHP 5.3集成到您的symfony 2.1项目中

dev-master 2015-10-29 08:04 UTC

This package is not auto-updated.

Last update: 2024-09-28 14:44:11 UTC


README

2012-12-06

  • 支持Salesforce.com API版本26.0(beta)功能
    • 现在支持GEOLOCATION(),DISTANCE() SOQL函数
    • 不支持条件SELECT字段列表语句(SELECT [...] TYPEOF sobjectName WHEN type THEN [fieldlist] END)
  • 为底层的Force.com Toolkit for PHP 5.3库提供额外的单元测试

简介

CodemitteForceToolkitBundle是一个将Force.com Toolkit for PHP 5.3集成到您的symfony 2.1项目的Symfony 2组件。只需启用组件,配置SOAP访问您的Salesforce组织,即可开始工作。

此组件及其库依赖项仍在积极开发中,不应被视为稳定!除非您确实了解自己在做什么,否则请勿在生产环境中使用(尽管在所有情况下都未必如此。)

此组件是我所在公司目前开发的多租户自助门户应用程序的一部分,将不时接收更新/回溯,但没有“官方发布计划”。

同时,出现了一些其他相当流行的库,也许您想看看这些库

特性

  • 通过CodemitteSoap库提供的SOAP客户端抽象层
    • SOAP API:partner.wsdl.xml,enterprise.wsdl.xml
    • 元数据API:使用.describeX()方法获取元数据信息
    • 为自定义Web服务(APEX-Webservice类)提供基本的SOAP接口
  • 通过CodemitteForceToolkit提供的SOQL查询抽象层
    • 手动构建查询
    • 使用SOQL查询构建器的流畅API构建查询
    • 链式使用字符串查询和API构建的查询
    • 使用limit(),offset(),orderBy(),where()方法轻松实现筛选
  • 集成Symfony 2表单组件
    • 为每个相关的Salesforce数据类型提供验证器和表单类型/小部件,例如选择列表。
      • 通过简单地更改底层的Force.com API用户的区域设置,轻松处理i18n和l10n。
      • 通过修改您的API用户的配置文件或对象记录类型来处理选择列表条目显示。
      • 仅根据Force.com设置处理货币或日期字段
  • API用户工厂
    • 根据当前Web用户的区域设置使用不同的API用户

安装

通过composer/packagist(推荐)

  1. 将以下行添加到您的composer.json文件中的"require"部分

    require {
      [...]
      "codemitte/ForceToolkitBundle" : "dev-master"
      [...]
    }
  2. 之后运行composer update命令

    $ php ./composer.phar update

    如果您遇到问题,请参阅官方composer文档。注意,当使用具有ext/suhosin启用的php可执行文件的.phar文件时,需要所需的whitelist条目!

  3. 在您的Kernel PHP文件中启用新下载的组件(通常位于app/AppKernel.php中)

    class AppKernel extends Kernel
    {
      public function registerBundles()
      {
        return array(
          [...]
          new \Codemitte\Bundle\ForceToolkitBundle\CodemitteForceToolkitBundle()
        );
      }
    }
  4. 清除所有缓存

手动安装

  1. 将捆绑源代码下载/克隆到您的项目中(推荐:将GitHub仓库定义为git子模块)捆绑应该位于可更新的供应商目录中,位置应反映完整的命名空间路径,例如:

    vendor/codemitte/codemitte-force-toolkit-bundle/Codemitte/Bundle/ForceToolkit/{repository root, the dir where the .git directory resides}
    
  2. 同时下载/克隆捆绑的依赖项

  3. 将捆绑及其所有依赖项的类路径添加到您的autoload.php文件中。映射如下:

       'Codemitte\\Bundle\\ForceToolkitBundle' => 'path/to/cloned/repository/'
    

    例如

       'Codemitte\\Bundle\\ForceToolkitBundle' => 'vendor/codemitte/codemitte-force-toolkit-bundle',
       'Codemitte\\ForceToolkit' => 'vendor/codemitte/codemitte-force-toolkit',
       'Codemitte\\Soap' => 'vendor/codemitte/codemitte-soap',
       'Codemitte\\Common' => 'vendor/codemitte/codemitte-common'
  4. 在Kernel PHP文件中启用新鲜下载的捆绑(通常在app/AppKernel.php中找到)

    class AppKernel extends Kernel
    {
      public function registerBundles()
      {
        return array(
          [...]
          new \Codemitte\Bundle\ForceToolkitBundle\CodemitteForceToolkitBundle()
        );
      }
    }

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: "Codemitte\\ForceToolkit\\Soap\\Client\\PartnerClient"
  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

最小配置可能如下所示

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"

配置选项说明

  • soap_api_client.classname: 客户端PHP类的类名,通常是
    • "Codemitte\ForceToolkit\Soap\Client\PartnerClient"
    • "Codemitte\ForceToolkit\Soap\Client\EnterpriseClient" 将来计划实现一个工厂,能够从给定的WSDL信息中自动检测正确的客户端类。
  • soap_api_client.connection_ttl: API用户的存活时间,存储在内存中(例如,APC是目前唯一的连接存储适配器)。由于API连接每24小时重置一次,因此ttl应反映此值。如果发生意外的连接错误,symfony 2异常事件处理器将优雅地重新启动API连接。
  • soap_api_client.service_location: 使用此标志来覆盖底层WSDL文件中定义的服务位置端点。当例如使用单个WSDL文件在不同的开发环境中时,这很有用(例如,针对质量保证沙盒的生产WSDL)。尽管如此,最佳实践似乎是维护为每个组织保留的专用.wsdl文件,以避免出现“无法连接到主机”的奇怪问题。
  • soap_api_client.api_users: 数组,用于定义针对不同前端用户区域的一个或多个API用户。请参阅上面的示例。每个用户都必须在salesforce中具有API使用权限。
  • metadata.cache_service_id: 元数据缓存的缓存服务ID(元数据是从describeSobject()/describeLayout()调用中清理后的结果)。可用值包括:
    • "codemitte_forcetk.metadata.file_cache": 用于生产
    • "codemitte_forcetk.metadata.array_cache": 用于开发
  • metadata.cache_location: 缓存位置(目前仅在文件系统中)-- 重构候选人!!
  • metadata.cache_ttl: 元数据缓存直到即将失效的生命周期。-1表示缓存永远不会过期。

要在您的twig模板中使用Force.com symfony表单类型,请考虑启用以下全局表单模板扩展

twig:
    form:
        resources:
            - 'CodemitteForceToolkitBundle:Form:fields.html.twig'

文档

客户端/查询构建器的基本用法

src/AcmeBundle/Controller/DefaultController.php

/** @var $client Codemitte\ForceToolkit\Soap\Client\PartnerClient */
$client = $this->get('codemitte_forcetk.client');
/** @var $response Codemitte\Soap\Mapping\GenericResult */
$response = $client->query('SELECT Id, Name FROM Account LIMIT 10');
foreach($response['result']['records'] AS $account)
{
    print_r($account);
}

$response是Instanceof \Codemitte\Soap\Mapping\GenericResult。您可以通过数组表示法、对象表示法或方法表示法访问每个属性

$response['result']
$response->result
$response->get('result')

$response->get('result')->get('records');是Instanceof Codemitte\Soap\Mapping\GenericResultCollection,它添加了用于轻松遍历的方法。

foreach($response['result']['records'] AS $account)
{
    print_r($account);
}

(请参阅客户端接口(Codemitte\ForceToolkit\Soap\Client\APIInterface)以获取所有可用服务调用方法的列表。)

$client->query()是一个低级API方法,用于对平台执行SOQL查询。更方便的方法是利用QueryBuilder

src/AcmeBundle/Controller/AccountController.php

public function accountShowAction($id)
{
  /** @var $queryBuilder Codemitte\ForceToolkit\Soql\Builder\QueryBuilder */
  $queryBuilder = $this->get('codemitte_forcetk.query_builder');
  /** @var $account Codemitte\Soap\Mapping\GenericResult */
  $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
  );
}

类似地,帐户列表视图

src/AcmeBundle/Controller/AccountController.php

public function accountListAction($limit = 20, $offset = 0, $orderBy = 'Name')
{
  /** @var $queryBuilder Codemitte\ForceToolkit\Soql\Builder\QueryBuilder */
  $queryBuilder = $this->get('codemitte_forcetk.query_builder');
  // MAXIMUM OFFSET IS 2000!!!
  /** @var $accounts Codemitte\Soap\Mapping\GenericResultCollection */
  $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参考

选择一组sobjects的基本查询

$queryBuilder
    ->select('Id, AccountNumber, Email')
    ->from('Account')
    ->fetch()
;

选择单个sobject实例的基本查询

$queryBuilder
    ->select('Id, AccountNumber, Name')
    ->from('Account')
    ->where('Id = :id', array('id' => $id))
    ->fetchOne();
;

具有复合WHERE子句的查询(用于构建过滤器等很有用)

$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();
    

此查询应产生以下输出

SELECT Id, AccountNumber, Name FROM Account WHERE Id = 'xxxxxxxxxxxxxxxxxx' AND (Name = 'Supercompany' OR AccountNumber = '12345')

请参阅查询构建器接口以获取更多信息。

表单组件

您可以像往常一样注册salesforce类型,但您可以使用特殊的Force.com类型而不是标准symfony 2表单类型。这些类型仅需要几个强制参数,即

  • 对象类型
  • 字段名称
  • 可选的记录类型ID

其他知名选项,如“必填”、“选择”等,也均可使用,因为每个Force.com表单类型都扩展了标准symfony 2类型!

注意:要使用force_tk小部件,您必须在config.yml的twig部分中启用全局自定义表单模板

twig:
    form:
        resources:
            - 'CodemitteForceToolkitBundle:Form:fields.html.twig'

构建启用Force.com的表单类型的示例

src/AcmeBundle/Type/AccountEditType.php

<?php
namespace AcmeBundle\Type\EditAccountType;

use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;

/**
 * Contact type for rendering a registration form.
 */
class EditAccountType extends AbstractType
{
    /**
     * @param \Symfony\Component\Form\FormBuilderInterface $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' => 'Codemitte\Bundle\UserBundle\Validator\EditAccountValidator',
            'accountRecordTypeId' => null
        ));
    }
}

对于Force.com表单类型,该捆绑包包含一些内置验证器,您可以在您的验证模型中使用。例如,考虑以下账户表示

<?php
namespace Codemitte\Bundle\UserBundle\Validator;

use
    Symfony\Component\Validator\Constraints AS Assert,
    Codemitte\ForceToolkit\Validator\Constraints AS AssertForce
;

class EditAccountValidator
{
    /**
     * @var string
     * @Assert\NotBlank
     * @AssertForce\Picklist(sObjectType="Account", fieldname="AccountSource")
     */
    public $billingCountry;
    
    [...]

目前还没有关于Force.com验证器 + 表单类型的完整文档,因此请参阅验证器的源代码和/或捆绑包的services.xml(Resources/config/services.xml),在那里您将找到包括它们的别名(别名是使表单构建器中的“短地址”启用的令牌,例如“forcetk_picklist”、“forcetk_date”等等)的可用表单类型完整列表。