Giter VIP home page Giter VIP logo

salesforce-rest-sdk's Introduction

Salesforce Rest SDK

This API supports the following areas of the Salesforce API:

  • Limits
  • Global Describe
  • SObject Describe
  • SObject CRUD
  • SObject Get Updated/Deleted
  • Composite API
    • Batch
    • Tree
    • SObject Collections
  • Bulk API
  • Streaming API

Installation

composer require ae/salesforce-rest-sdk

Instantiate a Rest Client

<?php

use AE\SalesforceRestSdk\Rest\Client;
use AE\SalesforceRestSdk\AuthProvider\OAuthProvider;

$client = new Client(
  new OAuthProvider(
      "SF_CLIENT_ID",
      "SF_CLIENT_SECRET",
      "https://login.salesforce.com",
      "SF_USER",
      "SF_PASS"
  ),
  "46.0", // optional version number, defaults to 44.0
  "MyAppName" // optional client app name, used when filtering out Change Data Events in the Streaming API
);

For more information about using client app names with Change Data Capture, see https://developer.salesforce.com/docs/atlas.en-us.change_data_capture.meta/change_data_capture/cdc_event_fields_header.htm

If you have an authorization code returned to your redirectUrl and wish to use it, you can do so like this:

<?php
use AE\SalesforceRestSdk\Rest\Client;
use AE\SalesforceRestSdk\AuthProvider\OAuthProvider;

$client = new Client(
  new OAuthProvider(
      "SF_CLIENT_ID",
      "SF_CLIENT_SECRET",
      "https://login.salesforce.com",
      null,
      null,
      OAuthProvider::GRANT_CODE,
      "https://your.redirect.uri",
      "THE_CODE_FROM_SALESFORCE"
  )
);

Cached Auth Providers

Cached Auth Providers provide a way to hold onto valid credentials across requests, otherwise the client will authenticate with Salesforce every time it's instantiated.

<?php
use AE\SalesforceRestSdk\Rest\Client;
use AE\SalesforceRestSdk\AuthProvider\CachedOAuthProvider;
use Symfony\Component\Cache\Adapter\FilesystemAdapter;

// Any adapter that uses Psr\Cache\CacheItemPoolInterface will work with the Cached Providers
$adapter = new FilesystemAdapter();

$client = new Client(
  new CachedOAuthProvider(
      $adapter,
      "SF_CLIENT_ID",
      "SF_CLIENT_SECRET",
      "https://login.salesforce.com",
      null,
      null,
      CachedOAuthProvider::GRANT_CODE,
      "https://your.redirect.uri",
      "THE_CODE_FROM_SALESFORCE"
  )
);

Composer autoloading without a framework

If you happen to not be using a PHP Framework that handles annotation registration for you, like Symfony, then you must do it yourself:

<?php

use AE\SalesforceRestSdk\Rest\Client;
use AE\SalesforceRestSdk\AuthProvider\OAuthProvider;
use Doctrine\Common\Annotations\AnnotationRegistry;

$loader = require_once 'vendor/autoload.php';
AnnotationRegistry::registerLoader(array($loader, "loadClass"));

$client = new Client(
   // ...

Work with SObjects with the SObject Client

Reference

<?php

//...

/** @var \AE\SalesforceRestSdk\Rest\SObject\Client $sObjectClient */
$sObjectClient = $client->getSObjectClient();

// Get basic metadata and recently used records for an object
$info = $sObjectClient->info("Account");

// Get very detailed metadata about an object
$describe = $sObjectClient->describe("Account");

// Get basic metadata info about all objects in SF
$globalDescribe = $sObjectClient->describeGlobal();

// Let's CRUD it up
$account = new \AE\SalesforceRestSdk\Model\SObject();

$sObjectClient->persist("Account", $account); // returns true if success

echo $account->Id; // outputs the SFID of the account

$account->MyCustomField__c = "Some Value I want to Save";

$sObjectClient->persist("Account", $account); // returns true on success

// Let's get new info from out account, pretend it was updated in SF
$account = $sObjectClient->get("Account", $account->Id, ["Name", "AnotherCoolField__c"]);

// Kill the account
$sObjectClient->remove("Account", $account);

// Query for more stuff
$result = $sObjectClient->query("SELECT Id, Name FROM Account");

echo $result->getTotalSize(); // OUtputs the total number of records for the query

var_dump($result->getRecords()); // SObject[]

while (!$result->isDone()) {
    // There are more records to be returned!
     // Just pass in the last result set and get the next batch
     // Lather, rinse, repeat until $result->isDone() === true;
    $result = $sObjectClient->query($result);
    
    var_dump($result->getRecords()); // CompositeSObject[]
}

// Query deleted and merged records, too
$result = $sObjectClient->queryAll(
    "SELECT Id, Name FROM Account",
     1000 // optional batch size, defaults to 2000, which is the max, min is 200
     );

// Search for something
$result = $sObjectClient->search("FIND {Some Query} IN ALL FIELDS");

var_dump($result->getSearchRecords()); // CompositeSObject[]

For more information on Batch Sizes and the Sforce-Query-Options header, see https://developer.salesforce.com/docs/atlas.en-us.220.0.api_rest.meta/api_rest/headers_queryoptions.htm.

It should be noted that batch size may not be respected in Salesforce if it is not optimal for performance

Instantiate the Streaming Client

Reference

<?php
use AE\SalesforceRestSdk\Bayeux\BayeuxClient;
use AE\SalesforceRestSdk\AuthProvider\OAuthProvider;
use AE\SalesforceRestSdk\Bayeux\Transport\LongPollingTransport;

$client = new BayeuxClient(
      new LongPollingTransport(),
      new OAuthProvider(
          "SF_CLIENT_ID",
          "SF_CLIENT_SECRET",
          "https://login.salesforce.com",
          "SF_USER",
          "SF_PASS"
      ),
      "46.0" // optional version number, defaults to 44.0
 );

Subscribe to a PushTopic

You can create a new PushTopic using the Rest Client above. The topic only needs created once in a Salesforce Org. All custom objects are supported by the Streaming API, however, not all standard objects supported.

Supported Standard Objects:

  • Account
  • Campaign
  • Case
  • Contact
  • ContractLineItem
  • Entitlement
  • Lead
  • LiveChatTranscript
  • Opportunity
  • Quote
  • QuoteLineItem
  • ServiceContract
  • Task

Tasks that are created or updated using the following methods don’t appear in task object topics in the streaming API.

  • Lead conversion
  • Entity merge
  • Mass email contacts/leads
<?php
use AE\SalesforceRestSdk\Bayeux\BayeuxClient;
use AE\SalesforceRestSdk\Bayeux\Consumer;
use AE\SalesforceRestSdk\Bayeux\ChannelInterface;
use AE\SalesforceRestSdk\Bayeux\Message;
use AE\SalesforceRestSdk\Bayeux\Extension\ReplayExtension;
use AE\SalesforceRestSdk\Bayeux\Extension\CachedReplayExtension;
use Symfony\Component\Cache\Adapter\FilesystemAdapter;

/** @var BayeuxClient $client */

// Getting a channel tells the client you want to subscribe to a topic
$channel = $client->getChannel('/topic/[YOUR_PUSH_TOPIC_NAME]');

// Give some durability to the messages on this channel by adding the ReplayExtension
$channel->addExtension(new ReplayExtension(ReplayExtension::REPLAY_SAVED));

// Using the CachedReplayExtension give greater durability in that it will remember the replay Id of the last
// message received and pick up where it left off, even if the process stops and restarts. If no messages for the
// channel topic have been received, it will use the value provided in the constructor.
// Again, Any Psr\Cache\CacheItemPoolInterface will do for the adapter parameter
$channel->addExtension(new CachedReplayExtension(new FilesystemAdapter(), CachedReplayExtension::REPLAY_SAVED));

// You can also apply extensions at the Client level, rather than the channel.
// In the case of the ReplayExtension, the last replayId will be remembered for each channel,
// however, if no messages have been received on the channel, the constructor argument is used
$client->addExtension(new CachedReplayExtension(new FilesystemAdapter(), CachedReplayExtension::REPLAY_SAVED));

// Register topic consumers prior to starting the client
$channel->subscribe(
    Consumer::create(function (ChannelInterface $channel, Message $message) {
        // This will be fired when the client receives a topic notification
        
        $payload = $message->getData();
        
        // The payload has information about the event that occurred
        $event = $payload->getEvent();
        
        echo $event->getType(); // "created", "updated", "undeleted", "deleted"
        echo $event->getCreatedDate()->format(\DATE_ISO8601); // outputs the datetime the event was created
        echo $event->getReplayId(); // This ia n ID used by the replay extension so it can pick up the feed where it left off
        
        $sobject = $payload->getSobject();
        
        echo $sobject->Id; // Get the Id
        echo $sobject->getFields(); // this outputs all the fields and their values that were in the create or update request
    })
);

// Start the client to begin receiving notifications;
$client->start();

The $client->start(); is a blocking call and no code after it will execute until an error occurs in the client, causing it to disconnect.

For instance, the client must reconnect to the streaming server within 40 seconds after each notification is received. If it fails to do so, it will attempt to re-handshake to create a new connection. If that fails, then the client will disconnect, which will allow the rest of the script to execute.

It's recommended that the streaming client be run in it's own thread

Dispatching Generic Events

Create a Streaming Channel

Before you can dispatch a Generic Event, you must create a Streaming Channel. That can be done in a number of ways:

  1. Via the Salesforce Classic UI as documented here
  2. By enabling Enable Dynamic Streaming Channel Creation under Setup > User Interface and then subscribing to a Streaming Channel using the Streaming Client as documented above
  3. Streaming Channels are a regular ole SObject and can be created like one:
<?php
use Symfony\Component\Cache\Adapter\FilesystemAdapter;
use AE\SalesforceRestSdk\Rest\Client;
use AE\SalesforceRestSdk\AuthProvider\CachedOAuthProvider;
use AE\SalesforceRestSdk\Model\SObject;

// Use the SObject Client to create a Streaming Channel

// Any adapter that uses Psr\Cache\CacheItemPoolInterface will work with the Cached Providers
$adapter = new FilesystemAdapter();

$client = new Client(
  new CachedOAuthProvider(
      $adapter,
      "SF_CLIENT_ID",
      "SF_CLIENT_SECRET",
      "https://login.salesforce.com",
      "SF_USERNAME",
      "SF_PASSWORD"
  )
);

$streamingChannel = new SObject([
    'name' => '/u/MY_AWESOME_TOPIC'
]);

$client->getSObjectClient()->persist('StreamingChannel', $streamingChannel);

Send Generic Events to the Streaming Channel

Once the StreamingChannel is created, events can now be sent to it using the GenericEventClient, which piggybacks on the SObject client. Let's pretend we're continuing the code from above in this next example:

<?php
use Symfony\Component\Cache\Adapter\FilesystemAdapter;
use AE\SalesforceRestSdk\Rest\Client;
use AE\SalesforceRestSdk\AuthProvider\CachedOAuthProvider;
use AE\SalesforceRestSdk\Model\SObject;
use AE\SalesforceRestSdk\Rest\GenericEventClient;
use AE\SalesforceRestSdk\Model\Rest\GenericEvent;
use AE\SalesforceRestSdk\Model\Rest\GenericEvents;

// ... Client and everything is defined as above

// Generic Event Client also takes a cache adapter which it uses to keep track of Ids for StreamingChannels. You can
// resuse the adapter given to the client if you wish. The keys won't conflict.
$geClient = new GenericEventClient($adapter, $client->getSObjectClient());

// Next we'll create a Generic Event to dispatch
$event = new GenericEvent();
$event->setPayload("This is the payload of the event. It has to be a string. But it could be XML or JSON data");

// You can also set which clients subscribing to the channel you want to receive your message,
// if you didn't want all of them getting it. Use the GenericEventClient to see which users are subscribed to the channel
$users = $geClient->getChannelSubscribers('/u/MY_AWESOME_TOPIC');
$event->setUserIds($users);

// Send the event to the Streaming Channel
$geClient->sendEvent('/u/MY_AWESOME_TOPIC', $event);

// Multiple events can also be sent at once
$events = GenericEvents::create([
    GenericEvent::create("Event payload magic here"),
    GenericEvent::create("More event payload magic here"),
]);

// Send the events to the Streaming Channel
$geClient->sendEvents('/u/MY_AWESOME_TOPIC', $events);

Future Additions

  • Tooling API
  • Metadata API

salesforce-rest-sdk's People

Contributors

bluedot74 avatar curiosity26 avatar nickalafrance avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

salesforce-rest-sdk's Issues

Library license

Hi, really cool lib thanks! But as I see in composer.json it is under proprietary license. Are you going to make it MIT or similar free to use? Because, otherwise, It doesn't make sense to contribute to this lib.

Topic-level Extensions for the Streaming API

Per PR #34, a difference in how the Java/Javascript clients connect with CometD and make use of Extensions is different than how this SDK handles extensions.

Currently, this SDK applies Extensions to the Streaming Client and all topic subscriptions share the extensions, which may not always be the best solution.

The suggestion is to modify the ChannelInterface and Channel to allow for extensions to subscribe to them and pass the ChannelInterface object into the Extension as a parameter for the extension to make use of in determining if the extension needs to modify the message, also provided.

How to use replayId from Streaming API

Hello,

I wish to use replayId from streaming API to get missing messages while listener was down. I found the following code
$replayExtension = new \AE\SalesforceRestSdk\Bayeux\Extension\ReplayExtension({replayId here});
$streamingClient->addExtension($replayExtension);
But I can't get how to tie this to $channel->subsribe code. Could you point me to some piece of code which uses replayId to get messages that was not processed during listener shutdown?

Thanks

trouble with streaming client

when i try the demo code on my test environment,it throw:

In AnnotationException.php line 54:

  [Semantical Error] The annotation "@JMS\Serializer\Annotation\PreSerialize"
   in method AE\SalesforceRestSdk\Bayeux\Message::preSerialize() does not exi
  st, or could not be auto-loaded.

having trouble autoloading JMS package

Doctrine\Common\Annotations\AnnotationException::semanticalError("The annotation "@jms\Serializer\Annotation\ExclusionPolicy" in class AE\SalesforceRestSdk\Bayeux\Message does not exist, or could not be auto-loaded.")

This is the problem im facing while using this package. Im trying to implement in laraval. im trying to do pushTopic streaming from salesforce but for some reason it is not supporting.

Possible to return SF response when Persisting object?

If I persist a new SObject (e.g Contact) on SF using the persist() method of the Client, the default response is true on success. But what if SF is returning JSON (crm_id) on successful persist. Is it possible to retrieve this data in the response?

Getting strange errors for all calls I make

Authentication works well, but as soon as I issue pretty much any command, I get below error.
For example:
$result = $sObjectClient->query("SELECT Id, Name FROM Account");

PHP Fatal error: Uncaught Doctrine\Common\Annotations\AnnotationException: [Semantical Error] The annotation "@jms\Serializer\Annotation\Type" in property AE\SalesforceRestSdk\Model\Rest\QueryResult::$done does not exist, or could not be auto-loaded. in C:\Users\ilana\vendor\doctrine\annotations\lib\Doctrine\Common\Annotations\AnnotationException.php:54
Stack trace:
#0 C:\Users\ilana\vendor\doctrine\annotations\lib\Doctrine\Common\Annotations\DocParser.php(734): Doctrine\Common\Annotations\AnnotationException::semanticalError('The annotation ...')
#1 C:\Users\ilana\vendor\doctrine\annotations\lib\Doctrine\Common\Annotations\DocParser.php(663): Doctrine\Common\Annotations\DocParser->Annotation()
#2 C:\Users\ilana\vendor\doctrine\annotations\lib\Doctrine\Common\Annotations\DocParser.php(354): Doctrine\Common\Annotations\DocParser->Annotations()
#3 C:\Users\ilana\vendor\doctrine\annotations\lib\Doctrine\Common\Annotations\AnnotationReader.php(254): Doctrine\Common\Annotations\DocParser->parse('/**\n * @var...', 'property AE\ in C:\Users\ilana\vendor\doctrine\annotations\lib\Doctrine\Common\Annotations\AnnotationException.php on line 54

Symfony 5 support

Hey there! Any chance that there could be support for "symfony/cache" and "symfony/expression-language" versions that are used in symfony 5? Or do you know of a way to allow composer to install the required versions in this package?

I currently get:

Restricting packages listed in "symfony/symfony" to "5.0.*"
Your requirements could not be resolved to an installable set of packages.

Problem 1
    - ae/salesforce-rest-sdk v1.3.8 requires symfony/cache ~3.4|~4.0 -> no matching package found.
    - ae/salesforce-rest-sdk v1.3.7 requires symfony/cache ~3.4|~4.0 -> no matching package found.
    - ae/salesforce-rest-sdk v1.3.6 requires symfony/cache ~3.4|~4.0 -> no matching package found.
    - ae/salesforce-rest-sdk v1.3.5 requires symfony/cache ~3.4|~4.0 -> no matching package found.
    - ae/salesforce-rest-sdk v1.3.4 requires symfony/cache ~3.4|~4.0 -> no matching package found.
    - ae/salesforce-rest-sdk v1.3.3 requires symfony/cache ~3.4|~4.0 -> no matching package found.
    - ae/salesforce-rest-sdk v1.3.2 requires symfony/cache ~3.4|~4.0 -> no matching package found.
    - ae/salesforce-rest-sdk v1.3.1 requires symfony/cache ~3.4|~4.0 -> no matching package found.
    - ae/salesforce-rest-sdk v1.3.0 requires symfony/cache ~3.4|~4.0 -> no matching package found.
    - Installation request for ae/salesforce-rest-sdk ^1.3 -> satisfiable by ae/salesforce-rest-sdk[v1.3.0, v1.3.1, v1.3.2, v1.3.3, v1.3.4, v1.3.5, v1.3.6, v1.3.7, v1.3.8].

Thanks for your time!

PHP 8 support

Composer gives this error

- ae/salesforce-rest-sdk[2.0.0, v2.0.1] require php ^7.2 -> your php version (8.0.2) does not satisfy that requirement.

Runtime exception with Streaming API

Getting this weird runtime exception error after about 60 seconds ....

PHP Fatal error:  Uncaught RuntimeException: Error creating resource: [message] fopen(https://nettix--uat.my.salesforce.com/cometd/48.0/meta/connect): failed to open stream: HTTP request failed!
[file] /home/kiran/web/my-vehicles/php/vendor/guzzlehttp/guzzle/src/Handler/StreamHandler.php
[line] 323 in /home/kiran/web/my-vehicles/php/vendor/guzzlehttp/guzzle/src/Handler/StreamHandler.php:252
Stack trace:
#0 /home/kiran/web/my-vehicles/php/vendor/guzzlehttp/guzzle/src/Handler/StreamHandler.php(334): GuzzleHttp\Handler\StreamHandler->createResource(Object(Closure))
#1 /home/kiran/web/my-vehicles/php/vendor/guzzlehttp/guzzle/src/Handler/StreamHandler.php(51): GuzzleHttp\Handler\StreamHandler->createStream(Object(GuzzleHttp\Psr7\Request), Array)
#2 /home/kiran/web/my-vehicles/php/vendor/guzzlehttp/guzzle/src/PrepareBodyMiddleware.php(66): GuzzleHttp\Handler\StreamHandler->__invoke(Object(GuzzleHttp\Psr7\Request), Array)
#3 /home/kiran/web/my-vehicles/php/vendor/guzzlehttp/guzzle/src/Middleware.php(36): GuzzleHttp\PrepareBodyMiddlew in /home/kiran/web/my-vehicles/php/vendor/guzzlehttp/guzzle/src/Exception/RequestException.php on line 52

Can't unsubscribe after subscribe.

How can I unsubscribe after subscribe.
The flow I want to implement is
I start subscribing of Salesforce Streaming API by cron job in morning.
And I want to stop subscribing of Salesforce Streaming API in evening.

But I can't unsubsubscribe if no events is receiving during that time.

Is there anyways for unsubscribing the channel?

Issue regarding topic subscribing

Hi All,
I am using your "ae/salesforce-rest-sdk" library. Its awesome. Thanks for it.

However i am trying to do Streaming api using this. But i am getting error.

  1. I created a push topic in my org , called "InvoiceStatementUpdates".
  2. I followed the instructions given on readme
  3. When i run the code, it started listing
  4. Then i opened my salesforce org and push a event on this topic by creating one contact
  5. As soon as i created a contact my php page stopped and given below error.

( ! ) Fatal error: Uncaught TypeError: Argument 1 passed to {closure}() must implement interface AE\SalesforceRestSdk\Bayeux\ConsumerInterface, instance of AE\SalesforceRestSdk\Bayeux\Channel given in D:\wamp64\www\salesforce-rest\client.php on line 47
( ! ) TypeError: Argument 1 passed to {closure}() must implement interface AE\SalesforceRestSdk\Bayeux\ConsumerInterface, instance of AE\SalesforceRestSdk\Bayeux\Channel given in D:\wamp64\www\salesforce-rest\client.php on line 47

Please help me to solve this. I have attached my code as well as error screen.

<?php
use AE\SalesforceRestSdk\Bayeux\BayeuxClient;
use AE\SalesforceRestSdk\AuthProvider\OAuthProvider;
use AE\SalesforceRestSdk\Bayeux\Transport\LongPollingTransport;
use Doctrine\Common\Annotations\AnnotationRegistry;
use AE\SalesforceRestSdk\Bayeux\Consumer;
use AE\SalesforceRestSdk\Bayeux\ConsumerInterface;
use AE\SalesforceRestSdk\Bayeux\Message;
use AE\SalesforceRestSdk\Bayeux\Extension\ReplayExtension;
use AE\SalesforceRestSdk\Bayeux\Extension\CachedReplayExtension;
use Symfony\Component\Cache\Adapter\FilesystemAdapter;

$loader = require_once 'vendor/autoload.php';
AnnotationRegistry::registerLoader(array($loader, "loadClass"));


$client = new BayeuxClient(
      new LongPollingTransport(),
      new OAuthProvider(
     "xxxxxx",
      "yyyyyyy",
      "https://login.salesforce.com",
      "ttttt",
      "zzzzz"
  )
 );



/** @var BayeuxClient $client */

// Getting a channel tells the client you want to subscribe to a topic
$channel = $client->getChannel('/topic/InvoiceStatementUpdates');

// Give some durability to the messages on this channel by adding the ReplayExtension
$channel->addExtension(new ReplayExtension(ReplayExtension::REPLAY_SAVED));

// Using the CachedReplayExtension give greater durability in that it will remember the replay Id of the last
// message received and pick up where it left off, even if the process stops and restarts. If no messages for the
// channel topic have been received, it will use the value provided in the constructor.
// Again, Any Psr\Cache\CacheItemPoolInterface will do for the adapter parameter
$channel->addExtension(new CachedReplayExtension(new FilesystemAdapter(), CachedReplayExtension::REPLAY_SAVED));


// Register topic consumers prior to starting the client
$channel->subscribe(
    Consumer::create(function (ConsumerInterface $consumer, Message $message) {
        // This will be fired when the client receives a topic notification
        
        $payload = $message->getData();
        
        // The payload has information about the event that occurred
        $event = $payload->getEvent();
        
        echo $event->getType(); // "created", "updated", "undeleted", "deleted"
        echo $event->getCreatedDate()->format(\DATE_ISO8601); // outputs the datetime the event was created
        echo $event->getReplayId(); // This ia n ID used by the replay extension so it can pick up the feed where it left off
        
        $sobject = $payload->getSobject();
        
        echo $sobject->Id; // Get the Id
        echo $sobject->getFields(); // this outputs all the fields and their values that were in the create or update request
    })
);

// Start the client to begin receiving notifications;
$client->start();

?>

By the way, one more thing, i wanted to subscibe "Platform Events" as well. Will this is also same as subscribing "Topic" ?

curl SSL certificate error

I have faced problem getting curl SSL certificate error CachedOAuthProvider and OAuthProvider when running from shell.
We should add options parameter for CachedOAuthProvider and OAuthProvider construct function.

Error: [GuzzleHttp\Exception\RequestException] cURL error 60: SSL certificate problem: unable to get local issuer certificate (see https://curl.haxx.se/libcurl/c/libcurl-errors.html) in \vendor\guzzlehttp\guzzle\src\Handler\CurlFactory.php on line 201
#1 \vendor\guzzlehttp\guzzle\src\Handler\CurlFactory.php(105): GuzzleHttp\Handler\CurlFactory::finishError()

Stack Trace:
#0 \vendor\guzzlehttp\guzzle\src\Handler\CurlFactory.php(155): GuzzleHttp\Handler\CurlFactory::createRejection()
#1 \vendor\guzzlehttp\guzzle\src\Handler\CurlFactory.php(105): GuzzleHttp\Handler\CurlFactory::finishError()
#2 \vendor\guzzlehttp\guzzle\src\Handler\CurlHandler.php(43): GuzzleHttp\Handler\CurlFactory::finish()
#3 \vendor\guzzlehttp\guzzle\src\Handler\Proxy.php(28): GuzzleHttp\Handler\CurlHandler->__invoke()
#4 \vendor\guzzlehttp\guzzle\src\Handler\Proxy.php(51): GuzzleHttp\Handler\Proxy::GuzzleHttp\Handler{closure}()
#5 \vendor\guzzlehttp\guzzle\src\PrepareBodyMiddleware.php(66): GuzzleHttp\Handler\Proxy::GuzzleHttp\Handler{closure}()
#6 \vendor\guzzlehttp\guzzle\src\Middleware.php(29): GuzzleHttp\PrepareBodyMiddleware->__invoke()
#7 \vendor\guzzlehttp\guzzle\src\RedirectMiddleware.php(70): GuzzleHttp\Middleware::GuzzleHttp{closure}()
#8 \vendor\guzzlehttp\guzzle\src\Middleware.php(59): GuzzleHttp\RedirectMiddleware->__invoke()
#9 \vendor\guzzlehttp\guzzle\src\HandlerStack.php(71): GuzzleHttp\Middleware::GuzzleHttp{closure}()
#10 \vendor\guzzlehttp\guzzle\src\Client.php(351): GuzzleHttp\HandlerStack->__invoke()
#11 \vendor\guzzlehttp\guzzle\src\Client.php(162): GuzzleHttp\Client->transfer()
#12 \vendor\guzzlehttp\guzzle\src\Client.php(182): GuzzleHttp\Client->requestAsync()
#13 \vendor\guzzlehttp\guzzle\src\Client.php(95): GuzzleHttp\Client->request()
#14 \vendor\ae\salesforce-rest-sdk\src\AuthProvider\OAuthProvider.php(148): GuzzleHttp\Client->__call()
#15 \vendor\ae\salesforce-rest-sdk\src\Rest\Client.php(214): AE\SalesforceRestSdk\AuthProvider\OAuthProvider->authorize()
#16 \vendor\ae\salesforce-rest-sdk\src\Rest\Client.php(55): AE\SalesforceRestSdk\Rest\Client->createHttpClient()

Trouble with Replay Extension

For some reason ReplayExtension doesn't work at all for me on the channel. I can set it up at the client level and I properly receive all past events when I subscribe to the PushTopic but it doesn't work on the channel object.

I've used the hasExtension method before and after the addExtension on the channel and it seems ok, it's false before and true after.

Any idea of what I'm missing ?

By the way I also encounter the #74 issue.

For information I'm using laravel 7 and SF API V44.0.

Annotation error with Streaming API

It's giving this weird error with streaming api client. I have already included doctrine-autoload-annotation package which is mentioned in one of the issue

PHP Fatal error:  Uncaught Doctrine\Common\Annotations\AnnotationException: [Semantical Error] The annotation "@JMS\Serializer\Annotation\PreSerialize" in method AE\SalesforceRestSdk\Bayeux\Message::preSerialize() does not exist, or could not be auto-loaded. in /home/kiran/web/my-vehicles/php/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/AnnotationException.php:54
Stack trace:
#0 /home/kiran/web/my-vehicles/php/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/DocParser.php(739): Doctrine\Common\Annotations\AnnotationException::semanticalError('The annotation ...')
#1 /home/kiran/web/my-vehicles/php/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/DocParser.php(661): Doctrine\Common\Annotations\DocParser->Annotation()
#2 /home/kiran/web/my-vehicles/php/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/DocParser.php(354): Doctrine\Common\Annotations\DocParser->Annotations()
#3 /home/kiran/web/my-vehicles/php/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/AnnotationReader in /home/kiran/web/my-vehicles/php/vendor/doctrine/annotations/lib/Doctrine/Common/Annotations/AnnotationException.php on line 54

I am using slim framework and composer auto-loading is already there. May I require to use manually register loaders as shown in readme?
AnnotationRegistry::registerLoader(array($loader, "loadClass"));

registerLoader method is deprecated and will be removed in new versions, so a good solution is required.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.