Skip to content
Guide

Use the PHP SDK

Use the PHP SDK

Use the PHP SDK

Start from generated code

A generated resource includes a model, Controller, Policy, and Resource Module. Add fields and business rules to these files instead of rebuilding the whole flow.

TaskEdit
Add stored fieldsMigration and model
Validate, save, and return dataController
Allow reads, creation, or updatesPolicy
Declare resource names, navigation, and permissionsResource Module

See Create a resource and Add fields for examples.

Identify the current actor

For an authenticated Laravel request, use $request->user()->getAuthIdentifier(). In a Policy or service receiving Nexia\Identity\Contracts\Actor, use $actor->key(). Keep the generated authentication middleware on protected routes.

Do not assume that the user is a Core Eloquent model or call its getKey(), model relationships, or Core-specific methods. App-owned Eloquent records can still use getKey(). This contract preserves actor identity across the App execution boundary.

Use $actor->publicId() for the public user identifier and $actor->partyKey() for the linked Party key. The Party key can be null; treat an unlinked user as having no self-service workforce record. Do not read $actor->party_id or other host model attributes, including inside Resource Reference resolvers.

Read platform-managed settings

Use the public interface from the App backend:

Code example
PHP
use Nexia\Settings\Contracts\AppSettings;

$setting = app(AppSettings::class)->get('tenant', 'my-app.integration.api_key');
if (! $setting->configured) {
    // Handle the missing configuration in your App.
}

Use a key declared by your App. app reads an App-wide value; tenant reads the current tenant's value. Consume the value inside its use() callback and never return or log secrets. Follow Settings and secrets to declare and configure values.

Rules to retain

  • Preserve generated permission and tenant handling. Hiding a button does not enforce access.
  • Do not query another App's tables or Core internal models directly.
  • Confirm public SDK support before relying on a platform capability.
  • After local checks, verify allowed and denied users and actual persistence in the sandbox.

Verify the backend behavior

Test the operation with permitted and denied users. For settings, test both configured and missing values and confirm that API responses and logs contain no secret. For writes, reopen the saved record and verify tenant isolation.

For relationships to Core tables, see Reference Core identities from App tables for the allowed targets and checks before saving.

Receive external database writes

Use the external-writer contracts to issue bounded INSERT credentials and register source IPs. See Receive external database writes for provisioning, asynchronous readiness, one-time reveal, rotation and connection tests.

Current person status and company access

A resource owner may expose ResourceDescriptor.searchSchema.person_status_filter.options (value/translation-key label pairs). The host discovers a single authorized provider; without one, approval history omits the current drafter-status filter. The host calls paged resource-reference search with purpose core.person-status-filter, the selected legal entity, current asOf, and filters.person_status. Return only authorized matching people, with fields.person_party_public_id. The owner defines current employment semantics. Core matches that Party to the historical drafter without rewriting documents. An explicitly selected filter fails closed if its provider disappears. Account activation is not employment status.

Nexia\Identity\Contracts\PersonLegalEntityAccess::end(actor, personPartyPublicId, legalEntityKey, sourceReference) ends company participation and company-scoped grants, retaining the user identity, history, and other-company access. The actor requires legal_entity.member.remove and authorization.legal_entity_grant.update in that company. The runtime also enforces Party visibility and an owner-prefixed source reference. Results are completed, unlinked, or review_required; tenant-wide authority requires explicit review and is not automatically changed. The owning App must check other current employment before calling, persist successful handoffs, and retry failures independently of the already-effective employment change. The consuming App must not report completion while access handoff is unresolved.

Company-access termination requires PHP SDK 0.10.13, Core 0.8.159 and Manager 0.1.0-alpha.83 or later with the matching App runtime. Adopt all three before enabling the App integration; changing App source alone does not update the runtime. No user-account deletion or global account-disable operation is implied.

Optional custom read declarations

Standard Resource list/read routes are discovered automatically. With a PHP SDK and managed runtime release that supports Nexia\AppRuntime\BatchableRead, a custom read-only JSON GET controller method can opt into host-managed grouping:

Code example
PHP
#[\Nexia\AppRuntime\BatchableRead]
public function index(Request $request): JsonResponse
{
    // Preserve the existing authorization and organization checks.
}

Declare only finite, read-only JSON responses. Do not annotate mutations, downloads or streams. The runtime discovers actual registered routes; no client API change or manual route list is needed. Update the App's PHP SDK dependency to a release containing the attribute before using it, then refresh the App through its normal development update or build/deployment flow. This requires PHP SDK 0.10.14, Core 0.8.161 and Manager 0.1.0-alpha.85 or later with the matching App runtime.

Verify the refreshed screen in browser Network: compatible concurrent reads may use read-batch; dependent or differently scoped reads can remain separate. The host splits groups larger than eight automatically, keeps authorization for every member, and supports individual fallback when grouping is unavailable. A batch does not guarantee faster screen completion.

Development hints tagged [NEXIA_READ_BATCH_INFO] appear in the browser console and connected CLI with matching host/CLI support. These are information, not a build, submission or deployment gate. nexia check cannot determine runtime route registration. Existing Apps without the attribute continue to use individual custom reads.

Authorized profile history

PHP SDK 0.10.15 adds the optional final ?ResourceRef $authorizationResource = null argument to PersonProfileHistory::pageForAuthorizedHr(actor, partyKey, legalEntityKey, cursor, limit, authorizationResource). Apps implementing this interface must add the optional argument. Existing calls that omit it still need directory authority. Core 0.8.173 supports this contract with the corresponding App runtime.

A ResourceRef identifies the owner record; it grants no access itself. The owner's descriptor declares fieldSchema.person_profile_history.read_permission as an active App-owned Legal Entity permission, and its resolver returns fields.person_profile_history containing party_key and legal_entity_key. Core resolves the reference with purpose {app}.person-profile-history and verifies the exact record, actor, company and population. Do not accept a browser-supplied reference as permission or widen scope to make a query pass.

See the profile-history contract, company-access contract and read declaration limits. Verify allowed/denied owner records and calls without an owner before enabling an integration.

Source of truth: docs/developers/content/en/app-sdk/sdk-contracts.md