20steps/highrise-bundle
Laravel bundle for integrating with Highrise CRM. Provides configuration, service bindings, and convenient helpers to connect, authenticate, and interact with Highrise resources from your application.
Installation
Add the bundle to your composer.json:
composer require 20steps/highrise-bundle
Enable the bundle in config/bundles.php:
return [
// ...
HighriseBundle\HighriseBundle::class => ['all' => true],
];
Configuration
Publish the default config and update config/packages/highrise.yaml:
highrise:
api_key: '%env(HIGHRISE_API_KEY)%'
subdomain: 'your_subdomain' # e.g., 'yourcompany' for yourcompany.highrisehq.com
version: 'v1' # or 'v2' if using Highrise v2 API
First Use Case Fetch a list of contacts:
use HighriseBundle\Highrise\HighriseClient;
class SomeService
{
public function __construct(private HighriseClient $highrise)
{
}
public function getContacts()
{
return $this->highrise->get('contacts');
}
}
CRUD Operations Use the client methods for standard API calls:
// Create
$contact = $this->highrise->post('contacts', ['first_name' => 'John']);
// Read
$contact = $this->highrise->get('contacts/123');
// Update
$this->highrise->put('contacts/123', ['last_name' => 'Doe']);
// Delete
$this->highrise->delete('contacts/123');
Querying with Filters Pass query parameters for filtering:
$contacts = $this->highrise->get('contacts', [
'query' => 'John Doe',
'page' => 2,
'per_page' => 50,
]);
Handling Responses
The client returns Symfony\Component\HttpFoundation\Response objects. Use:
$response = $this->highrise->get('contacts');
$data = json_decode($response->getContent(), true);
Dependency Injection
Inject HighriseClient into services or controllers:
public function __construct(
private HighriseClient $highrise,
private EntityManagerInterface $em
) {}
Batch Operations
Use the post method with collections:
$this->highrise->post('contacts/batch', [
'contacts' => [
['first_name' => 'Alice', 'email' => 'alice@example.com'],
['first_name' => 'Bob', 'email' => 'bob@example.com'],
],
]);
Symfony Forms
Bind Highrise data to forms using DataTransformer or PropertyAccess:
use Symfony\Component\Form\DataTransformerInterface;
class HighriseContactTransformer implements DataTransformerInterface
{
public function __construct(private HighriseClient $highrise) {}
public function transform($contact): ?array
{
return $contact ? ['id' => $contact['id']] : null;
}
public function reverseTransform($data): ?array
{
return $this->highrise->get("contacts/{$data['id']}");
}
}
Event Listeners
Sync Highrise data with your app on events (e.g., UserCreatedEvent):
public function onUserCreated(UserCreatedEvent $event)
{
$this->highrise->post('contacts', [
'first_name' => $event->getUser()->getFirstName(),
'email' => $event->getUser()->getEmail(),
]);
}
Doctrine Entities Map Highrise resources to Doctrine entities:
#[ORM\Entity]
class Contact
{
#[ORM\Id]
private ?int $highriseId;
#[ORM\Column]
private string $firstName;
// Getters/setters...
}
Command Bus
Use Symfony’s CommandBus for async operations:
$this->commandBus->dispatch(new SyncHighriseContactsCommand());
API Versioning
v1. If using Highrise v2, explicitly set version: 'v2' in config.page[number] instead of page).Rate Limiting
$cache = $this->cache->get('highrise_contacts', function () {
return $this->highrise->get('contacts');
}, 300); // Cache for 5 minutes
Authentication Failures
401 Unauthorized occurs, verify:
api_key is correct in highrise.yaml.subdomain matches your Highrise account URL.Data Mismatches
$mappedContact = $this->highriseMapper->mapToEntity($highriseContact);
Deprecated Endpoints
/people) may be deprecated in v2. Check Highrise API docs for updates.Enable Debug Mode
Set debug: true in highrise.yaml to log requests/responses:
highrise:
debug: true
Logs appear in var/log/dev.log.
Manual API Testing
Use curl to test endpoints directly:
curl -X GET \
-H "Authorization: Basic YOUR_API_KEY" \
"https://your_subdomain.highrisehq.com/api/v1/contacts.json"
Error Handling Wrap API calls in try-catch:
try {
$this->highrise->get('contacts/999');
} catch (\HighriseBundle\Exception\HighriseException $e) {
$this->logger->error('Highrise error: ' . $e->getMessage());
// Fallback logic
}
Custom HTTP Client
Override the default Guzzle client by binding your own:
# config/services.yaml
services:
HighriseBundle\Highrise\HighriseClient:
arguments:
$client: '@your_custom_http_client'
Response Transformers
Extend HighriseClient to auto-transform responses:
class CustomHighriseClient extends HighriseClient
{
protected function transformResponse(Response $response): array
{
$data = parent::transformResponse($response);
return $this->customMapper->map($data);
}
}
Webhook Handling
Use Symfony’s EventDispatcher to process Highrise webhooks:
// src/EventListener/HighriseWebhookListener.php
public function onKernelRequest(GetResponseEvent $event)
{
if ($event->isMasterRequest() && $this->isHighriseWebhook()) {
$this->dispatcher->dispatch(new HighriseWebhookEvent($this->request));
}
}
Testing
Mock HighriseClient in PHPUnit:
$mockClient = $this->createMock(HighriseClient::class);
$mockClient->method('get')->willReturn(new Response(json_encode(['id' => 1])));
$service = new YourService($mockClient);
How can I help you explore Laravel packages today?