Properties & Model Features
Property Definitions
HubSpot properties have type definitions that control serialization and deserialization of values (e.g. dates become Carbon instances, enumerations become arrays).
Loading Definitions
use Rollogi\LaravelHubspot\Crm\Contact;
// Get all property definitions for a model
$definitions = Contact::query()->definitions()->get();
// Get a single property definition
$emailDefinition = Contact::query()->definitions()->get('email');
// Access via model instance
$contact = Contact::findOrFail('123');
$definitions = $contact->definitions;Caching
Property definitions are cached for the duration configured in hubspot.definitions.cache (default: 30 days). You can force a refresh:
use Rollogi\LaravelHubspot\Crm\Contact;
Contact::query()->definitions()->refresh();Set definitions.cache to false in the config to disable caching entirely.
Creating Custom Properties
use Rollogi\LaravelHubspot\Crm\Contact;
$property = Contact::query()->definitions()->create([
'name' => 'custom_score',
'label' => 'Custom Score',
'type' => 'number',
'fieldType' => 'number',
'groupName' => 'contactinformation',
]);Value Serialization
Property values are automatically serialized/deserialized based on their definition type:
| Property Type | PHP Type | Behavior |
|---|---|---|
date | Carbon\Carbon | Parsed to/from ISO 8601 |
datetime | Carbon\Carbon | Parsed to/from Y-m-d |
number | int|float | Cast to numeric |
enumeration | array | Split/joined by ; |
Model Features
Magic Property Access
Models support dynamic property access through __get and __set:
use Rollogi\LaravelHubspot\Crm\Contact;
$contact = Contact::findOrFail('123');
// Read properties
echo $contact->firstname;
echo $contact->email;
echo $contact->id; // From payload
echo $contact->createdAt; // Cast to Carbon
// Write properties
$contact->firstname = 'Jane';
$contact->save();Dirty Tracking
Only changed properties are sent when calling save():
use Rollogi\LaravelHubspot\Crm\Contact;
$contact = Contact::findOrFail('123');
$contact->firstname = 'Updated';
$contact->getDirty(); // ['firstname' => 'Updated']
$contact->save(); // Only sends firstnamePayload Casting
The model $schema defines automatic type casting for payload-level fields:
| Field | Cast Type |
|---|---|
id | int |
createdAt | datetime (Carbon) |
updatedAt | datetime (Carbon) |
archived | bool |
archivedAt | datetime (Carbon) |
properties | array |
associations | array |
Scopes
Define reusable query constraints as scope methods on your models:
use Rollogi\LaravelHubspot\Api\Builder;
use Rollogi\LaravelHubspot\Crm\Contact;
// In a custom model extending Contact
public function scopeActive(Builder $builder): Builder
{
return $builder->where('lifecyclestage', 'customer');
}
// Usage
$customers = Contact::query()->active()->get();Macros
Models use the Macroable trait, allowing you to add methods at runtime:
use Rollogi\LaravelHubspot\Crm\Contact;
Contact::macro('findByEmail', function (string $email): ?Contact {
return Contact::query()->where('email', $email)->first();
});
$contact = Contact::findByEmail('john@example.com');Expand
Re-fetch a model with all properties:
use Rollogi\LaravelHubspot\Crm\Contact;
$contact = Contact::find('123');
$contact->expand(); // Re-fetches with full() properties