Skip to content

Customer Model ​

DB Table Name{wp_db_prefix}_fct_customers
SchemaCheck Schema
Source Filefluent-cart/app/Models/Customer.php
Name SpaceFluentCart\App\Models
ClassFluentCart\App\Models\Customer

Traits ​

TraitDescription
CanSearchProvides search(), whereLike(), whereBeginsWith(), whereEndsWith(), groupSearch() scopes for flexible query filtering
CanUpdateBatchProvides batchUpdate() scope for batch updating multiple records

Attributes ​

AttributeData TypeComment
idInteger (BIGINT UNSIGNED)Primary Key, Auto Increment
user_idInteger (BIGINT UNSIGNED)WordPress user ID (nullable)
contact_idInteger (BIGINT UNSIGNED)Contact ID (default 0)
emailString (VARCHAR 192)Customer email address
first_nameString (VARCHAR 192)Customer first name
last_nameString (VARCHAR 192)Customer last name
statusString (VARCHAR 45)Customer status (default: 'active')
purchase_valueJSONPurchase value data (stored/retrieved as JSON)
purchase_countInteger (BIGINT UNSIGNED)Number of purchases (default 0)
ltvInteger (BIGINT)Lifetime value in cents (default 0)
first_purchase_dateDate TimeFirst purchase date (nullable)
last_purchase_dateDate TimeLast purchase date (nullable)
aovDecimal (18,2)Average order value (nullable)
notesText (LONGTEXT)Customer notes
uuidString (VARCHAR 100)Unique identifier (auto-generated on creation)
countryString (VARCHAR 45)Customer country code (nullable)
cityString (VARCHAR 45)Customer city (nullable)
stateString (VARCHAR 45)Customer state (nullable)
postcodeString (VARCHAR 45)Customer postcode (nullable)
created_atDate TimeCreation timestamp
updated_atDate TimeLast update timestamp

Appended Attributes ​

These virtual attributes are appended to every serialized Customer instance via the $appends property:

AttributeAccessor MethodReturn TypeDescription
full_namegetFullNameAttribute()StringConcatenation of first_name and last_name
photogetPhotoAttribute()StringAvatar URL from Helper::getUserAvatarUrl($user_id, $email); an empty string when there is no avatar
country_namegetCountryNameAttribute()StringHuman-readable country name from country code
formatted_addressgetFormattedAddressAttribute()ArrayFormatted address data array
user_linkgetUserLinkAttribute()StringWordPress admin user-edit URL (empty if no user_id)

Searchable Fields ​

The $searchable property defines which fields are used by the searchBy scope:

  • first_name
  • last_name
  • email

Mutators ​

MutatorDirectionDescription
setPurchaseValueAttributeSetAccepts array/object (JSON-encodes) or scalar value
getPurchaseValueAttributeGetReturns decoded JSON as array, or null if empty

Boot Behavior ​

On creating, the model auto-generates the uuid attribute using md5($model->email . '_' . wp_generate_uuid4()).

Usage ​

Please check Model Basic for Common methods.

Accessing Attributes ​

php
$customer = FluentCart\App\Models\Customer::find(1);

$customer->id; // returns customer ID
$customer->email; // returns email address
$customer->first_name; // returns first name
$customer->last_name; // returns last name
$customer->status; // returns customer status
$customer->full_name; // returns "John Doe" (appended)
$customer->photo; // returns photo URL (appended)
$customer->country_name; // returns country name (appended)
$customer->formatted_address; // returns address array (appended)
$customer->user_link; // returns WP user edit URL (appended)

Methods ​

Along with Global Model methods, this model has few helper methods.

getFullNameAttribute() ​

Get customer full name by concatenating first_name and last_name.

  • Returns String - Full name (first_name + last_name), trimmed
php
$customer = FluentCart\App\Models\Customer::find(1);
$fullName = $customer->full_name; // returns "John Doe"

getPhotoAttribute() ​

Get customer photo URL. First checks for a custom photo URL stored in user meta (fc_customer_photo_url). Falls back to Gravatar (100x100) if no custom photo is set.

  • Returns String - Photo URL (custom or Gravatar)
php
$customer = FluentCart\App\Models\Customer::find(1);
$photo = $customer->photo; // returns photo URL

getCountryNameAttribute() ​

Get country name from country code using Helper::getCountryName().

  • Returns String - Country name
php
$customer = FluentCart\App\Models\Customer::find(1);
$countryName = $customer->country_name; // returns country name

getFormattedAddressAttribute() ​

Get formatted address as an associative array with resolved country and state names.

  • Returns Array - Formatted address data with keys: country, state, city, postcode, first_name, last_name, full_name
php
$customer = FluentCart\App\Models\Customer::find(1);
$address = $customer->formatted_address;
// [
//     'country'    => 'United States',
//     'state'      => 'California',
//     'city'       => 'San Francisco',
//     'postcode'   => '94102',
//     'first_name' => 'John',
//     'last_name'  => 'Doe',
//     'full_name'  => 'John Doe'
// ]

getUserLinkAttribute() ​

Get WordPress user edit link. Returns empty string if the customer has no associated user_id.

  • Returns String - User edit URL (e.g., /wp-admin/user-edit.php?user_id=5) or empty string
php
$customer = FluentCart\App\Models\Customer::find(1);
$userLink = $customer->user_link; // returns user edit URL

recountStats() ​

Recount customer order statistics. Sets total_order_count (count of all orders) and total_order_value (sum of total_amount across all orders) and saves the model.

  • Returns FluentCart\App\Models\Customer - Updated customer instance
php
$customer = FluentCart\App\Models\Customer::find(1);
$customer->recountStats();

recountStat() ​

Recount detailed customer purchase statistics from successful payment orders only.

Totals are grouped per currency and only added together after each order's amount is converted at the rate frozen on that order, so a multi-currency customer's lifetime value is not a sum of mixed units:

  • purchase_value — net paid minus refunds, kept per currency
  • ltv — the same figure converted to the store's base currency
  • aov — ltv divided by the count of orders with a trusted exchange rate, not by all orders
  • purchase_count, first_purchase_date, last_purchase_date

Saves the model.

  • Returns FluentCart\App\Models\Customer - Updated customer instance
php
$customer = FluentCart\App\Models\Customer::find(1);
$customer->recountStat();

updateCustomerStatus($newStatus) ​

Update customer status and fire action hooks. If the new status is the same as the current status, returns early without saving or firing hooks.

Fires the following WordPress action hooks:

  • fluent_cart/customer_status_to_{$newStatus} - Status-specific hook
  • fluent_cart/customer_status_updated - General status change hook

Both hooks receive an array with keys: customer, old_status, new_status.

  • Parameters: $newStatus (String) - New status value
  • Returns FluentCart\App\Models\Customer - Updated customer instance
php
$customer = FluentCart\App\Models\Customer::find(1);
$customer->updateCustomerStatus('active');

getWpUserId($recheck = false) ​

Returns the stored user_id. The $recheck parameter is accepted for backward compatibility and has no effect — the method performs no email lookup and never rewrites user_id.

  • Parameters: $recheck (Boolean) - accepted and ignored
  • Returns Integer|null - the stored WordPress user ID
php
$customer = FluentCart\App\Models\Customer::find(1);
$wpUserId = $customer->getWpUserId();

getWpUser() ​

Get the WordPress user by the stored user_id. Returns false when the customer has no user_id, i.e. when the account is unclaimed.

  • Returns WP_User|false - WordPress user object, or false when unlinked
php
$customer = FluentCart\App\Models\Customer::find(1);
$wpUser = $customer->getWpUser();

getMeta($metaKey, $default = null) ​

Get customer meta value from the fct_customer_meta table.

  • Parameters: $metaKey (String) - Meta key, $default (Mixed) - Default value if not found (default: null)
  • Returns Mixed - Meta value or default
php
$customer = FluentCart\App\Models\Customer::find(1);
$metaValue = $customer->getMeta('custom_field', 'default');

updateMeta($metaKey, $metaValue) ​

Create or update customer meta value in the fct_customer_meta table.

  • Parameters: $metaKey (String) - Meta key, $metaValue (Mixed) - Meta value
  • Returns FluentCart\App\Models\CustomerMeta - Meta instance (created or updated)
php
$customer = FluentCart\App\Models\Customer::find(1);
$meta = $customer->updateMeta('custom_field', 'new_value');

Relations ​

This model has the following relationships that you can use

orders ​

Access the customer orders.

  • Relation type: HasMany
  • Returns collection of FluentCart\App\Models\Order
  • Foreign key: customer_id
php
$customer = FluentCart\App\Models\Customer::find(1);
$orders = $customer->orders;

success_order_items ​

Access the successful order items (items from orders with successful payment statuses).

  • Relation type: HasManyThrough (through FluentCart\App\Models\Order)
  • Returns collection of FluentCart\App\Models\OrderItem
  • Filters orders by successful payment statuses via Status::getOrderPaymentSuccessStatuses()
php
$customer = FluentCart\App\Models\Customer::find(1);
$orderItems = $customer->success_order_items;

subscriptions ​

Access the customer subscriptions.

  • Relation type: HasMany
  • Returns collection of FluentCart\App\Models\Subscription
  • Foreign key: customer_id
php
$customer = FluentCart\App\Models\Customer::find(1);
$subscriptions = $customer->subscriptions;

shipping_address ​

Access the shipping addresses (filtered by type = 'shipping').

  • Relation type: HasMany
  • Returns collection of FluentCart\App\Models\CustomerAddresses
  • Foreign key: customer_id
php
$customer = FluentCart\App\Models\Customer::find(1);
$addresses = $customer->shipping_address;

billing_address ​

Access the billing addresses (filtered by type = 'billing').

  • Relation type: HasMany
  • Returns collection of FluentCart\App\Models\CustomerAddresses
  • Foreign key: customer_id
php
$customer = FluentCart\App\Models\Customer::find(1);
$addresses = $customer->billing_address;

primary_shipping_address ​

Access the primary shipping address (filtered by type = 'shipping' and is_primary = 1).

  • Relation type: HasOne
  • Returns FluentCart\App\Models\CustomerAddresses|null
php
$customer = FluentCart\App\Models\Customer::find(1);
$address = $customer->primary_shipping_address;

primary_billing_address ​

Access the primary billing address (filtered by type = 'billing' and is_primary = 1).

  • Relation type: HasOne
  • Returns FluentCart\App\Models\CustomerAddresses|null
php
$customer = FluentCart\App\Models\Customer::find(1);
$address = $customer->primary_billing_address;

labels ​

Access the customer labels (polymorphic relationship).

  • Relation type: MorphMany
  • Returns collection of FluentCart\App\Models\LabelRelationship
php
$customer = FluentCart\App\Models\Customer::find(1);
$labels = $customer->labels;

wpUser ​

Access the associated WordPress user.

  • Relation type: BelongsTo
  • Returns FluentCart\App\Models\User|null
  • Foreign key: user_id
php
$customer = FluentCart\App\Models\Customer::find(1);
$user = $customer->wpUser;

Scopes ​

unclaimed() ​

Customers with no linked WordPress user — user_id is NULL or 0. These are guest purchases that nobody has claimed by registering with the same email.

php
$guests = FluentCart\App\Models\Customer::unclaimed()->get();

This model has the following scopes that you can use

ofActive() ​

Get only active customers (where status = 'active').

php
$customers = FluentCart\App\Models\Customer::ofActive()->get();

ofArchived() ​

Get only archived customers (where status = 'archived').

php
$customers = FluentCart\App\Models\Customer::ofArchived()->get();

Search customers by query string. Supports multiple search modes:

  • Operator-based search: column_name > value, column_name = value, etc. (supports =, !=, >, <)
  • Column-specific LIKE search: column_name:value (searches with LIKE %value%)
  • Column-specific exact search: column_name=value
  • General search: Searches across $searchable fields (first_name, last_name, email) with LIKE matching. Also handles multi-word queries by splitting into first_name/last_name search.
  • Parameters: $search (String) - Search query
php
// General search across searchable fields
$customers = FluentCart\App\Models\Customer::searchBy('john')->get();

// Operator-based search
$customers = FluentCart\App\Models\Customer::searchBy('purchase_count > 5')->get();

// Column-specific LIKE search
$customers = FluentCart\App\Models\Customer::searchBy('email:example.com')->get();

// Full name search (splits "John Doe" into first_name + last_name)
$customers = FluentCart\App\Models\Customer::searchBy('John Doe')->get();

applyCustomFilters($filters) ​

Apply custom filters using an associative array. Each filter key must be a fillable attribute. Supports operators: includes (LIKE), not_includes (NOT LIKE), gt (>), lt (<), and standard SQL operators.

  • Parameters: $filters (Array) - Associative array of filter key => ['value' => ..., 'operator' => ...]
php
$customers = FluentCart\App\Models\Customer::applyCustomFilters([
    'status' => ['value' => 'active', 'operator' => '='],
    'email'  => ['value' => 'example.com', 'operator' => 'includes'],
    'ltv'    => ['value' => '1000', 'operator' => 'gt']
])->get();

searchByFullName($data) ​

Search by concatenated full name (CONCAT(first_name, ' ', last_name)). Supports multiple matching operators.

  • Parameters: $data (Array) - Search data with keys:
    • value (String) - The search term
    • operator (String) - One of starts_with, ends_with, not_like, or default (contains/like_all)
php
$customers = FluentCart\App\Models\Customer::searchByFullName([
    'value' => 'John',
    'operator' => 'starts_with'
])->get();

$customers = FluentCart\App\Models\Customer::searchByFullName([
    'value' => 'Doe',
    'operator' => 'ends_with'
])->get();

$customers = FluentCart\App\Models\Customer::searchByFullName([
    'value' => 'Test User',
    'operator' => 'not_like'
])->get();

Inherited Scopes from CanSearch Trait ​

These scopes are available via the CanSearch trait:

search($params) ​

Flexible search with multiple operators per column.

php
$customers = FluentCart\App\Models\Customer::search([
    'email' => ['column' => 'email', 'operator' => 'like_all', 'value' => 'example.com'],
    'status' => ['column' => 'status', 'operator' => '=', 'value' => 'active']
])->get();

whereLike($column, $value) ​

WHERE column LIKE %value% query.

php
$customers = FluentCart\App\Models\Customer::whereLike('email', 'example.com')->get();

whereBeginsWith($column, $value) ​

WHERE column LIKE value% query.

php
$customers = FluentCart\App\Models\Customer::whereBeginsWith('first_name', 'Jo')->get();

whereEndsWith($column, $value) ​

WHERE column LIKE %value query.

php
$customers = FluentCart\App\Models\Customer::whereEndsWith('email', '.com')->get();

groupSearch($groups) ​

Search across related models using dot notation.

php
$customers = FluentCart\App\Models\Customer::groupSearch([
    'fct_customers.email' => ['column' => 'email', 'operator' => 'like_all', 'value' => 'test'],
])->get();

Inherited Scope from CanUpdateBatch Trait ​

batchUpdate($values, $index = null) ​

Batch update multiple records at once.

php
FluentCart\App\Models\Customer::batchUpdate([
    ['id' => 1, 'status' => 'active'],
    ['id' => 2, 'status' => 'archived'],
]);

Usage Examples ​

Creating a Customer ​

php
use FluentCart\App\Models\Customer;

// uuid is auto-generated on creation
$customer = Customer::create([
    'email' => '[email protected]',
    'first_name' => 'John',
    'last_name' => 'Doe',
    'status' => 'active'
]);

Retrieving Customers ​

php
// Get all active customers
$customers = Customer::ofActive()->get();

// Get customer by email
$customer = Customer::where('email', '[email protected]')->first();

// Get customer with orders
$customer = Customer::with('orders')->find(1);

// Search customers
$customers = Customer::searchBy('john doe')->get();

// Get customers with custom filters
$customers = Customer::applyCustomFilters([
    'country' => ['value' => 'US', 'operator' => '=']
])->get();

Updating a Customer ​

php
$customer = Customer::find(1);
$customer->first_name = 'Jane';
$customer->save();

// Update status with hooks
$customer->updateCustomerStatus('archived');

// Recount purchase statistics
$customer->recountStat();

Working with Meta ​

php
$customer = Customer::find(1);

// Get meta
$value = $customer->getMeta('preferred_language', 'en');

// Set/update meta
$customer->updateMeta('preferred_language', 'fr');

Deleting a Customer ​

php
$customer = Customer::find(1);
$customer->delete();

FluentCart developer documentation