Laravel Forge SDK
repository·4.x·Indexed 20 days ago
https://github.com/laravel/forge-sdkAn expressive PHP interface for interacting with the Laravel Forge API v2. It enables programmatic management of servers, organizations, sites, domains, certificates, deployments, databases, and PHP settings. The SDK includes support for cursor pagination, asynchronous operation timeouts, and resource-specific classes for managing entities like BackupConfiguration, Domain, Recipe, and ScheduledJob.
What's inside laravel-forge-sdk
- The Laravel Forge SDK is an expressive PHP interface designed for interacting with the Laravel Forge API v2. It allows developers to programmatically manage Laravel Forge servers, organizations, sites, domains, certificates, and deployments.
How pagination works with CursorPaginator
4.xIn v4.0+, all list methods return a
CursorPaginatorinstead of a plain array. While it remains iterable and countable (supportingforeachandcount()), you must use specific methods for advanced pagination tasks.Accessing current page items
- Use
foreachto iterate. - Use
count($paginator)for the item count on the current page. - Use
$paginator[0]for index access. - Use
$paginator->items()to retrieve the underlying plain array.
Navigating pages
- Next Page: Use
$paginator->nextPage()to get the nextCursorPaginatorinstance. - Check for more: Use
$paginator->hasMorePages()to check if subsequent pages exist. - Resuming via Cursor: Use
$paginator->nextCursor()to get a string cursor. You can resume pagination later by passing this cursor in the query array:['cursor' => $cursor].
Iterating all items
- Lazy Iteration: Use
->lazy()to automatically fetch and iterate through all pages. - Page-by-Page: Use
->lazyPages()to iterate through eachCursorPaginatorinstance.
// Iterating all items across all pages automatically foreach ($forge->servers($organizationSlug)->lazy() as $server) { // ... } // Resuming pagination from a stored cursor $cursor = Cache::get('forge_cursor'); $page = $forge->servers($organizationSlug, ['cursor' => $cursor]); // Controlling page size $servers = $forge->servers($organizationSlug, ['page' => ['size' => 50]]);- Use
Handling mutation methods that return `void` in v4.0
4.xIn v4.0, mutation endpoints that return
202 Acceptedwith no body now returnvoidin the SDK. Because these actions are asynchronous, you cannot rely on the return value to confirm the change. To inspect the resulting state, you must issue a follow-upGETrequest once the action is expected to have completed.Affected methods include:
updateSite,installPhpVersion,createRecipeRun,createBackup,createBackupConfiguration,updateBackupConfiguration,updateBackgroundProcess,updateDatabaseUser,updateComposerCredential,updateNpmCredential, and others.// Perform the mutation $forge->updateSite($organizationSlug, $serverId, $siteId, ['aliases' => ['foo.com']]); // Fetch the resource to verify the change $site = $forge->site($organizationSlug, $serverId, $siteId);How CursorPaginator works in v4.0
4.xIn v4.0, all list methods that previously returned arrays now return a
CursorPaginatorinstance.While
CursorPaginatorimplementsCountable,ArrayAccess, andIteratorAggregate(meaningforeach,count(), and$result[0]still work), it is not a plain array. Functions likearray_map()orarray_filter()will fail when used directly on the paginator.To use the underlying array, call
$paginator->items(). Alternatively, you can iterate over pages using$paginator->lazy()or$paginator->lazyPages().// v3.x $servers = $forge->servers(); // returns array // v4.0 $servers = $forge->servers($organizationSlug); // returns CursorPaginator // To get the array back: $serverArray = $servers->items(); // To iterate: foreach ($servers as $server) { ... }Handle paginated results with CursorPaginator
4.xCollection methods like
servers(),sites(), andrecipes()return aLaravel\Forge\CursorPaginator. You can interact with these results in three ways:- Direct Iteration: Use
foreachto iterate the current page (note that this hides pagination details). - Lazy Iteration: Use the
->lazy()method to walk every page across the entire collection, fetching the next cursor on demand. - Array Snapshot: Use
->toArray()to convert the current page into a plain array.
// Iterate the current page foreach ($forge->servers($organizationSlug) as $server) { echo $server->name; } // Lazily iterate across all pages foreach ($forge->servers($organizationSlug)->lazy() as $server) { echo $server->name; } // Snapshot the current page as a plain array $page = $forge->servers($organizationSlug)->toArray();- Direct Iteration: Use
Accessing undeclared properties via `$attributes` in v4.0
4.xThe
Resourcebase class in v4.0 no longer uses#[\\[AllowDynamicProperties]. This means you can no longer access fields from the API response as dynamic properties if they are not explicitly declared in the class. To access undeclared fields, use the$attributesarray.// v3.x — dynamic property access worked $server->someUndeclaredField; // v4.0 — use the attributes array $server->attributes['some_undeclared_field'];Organization-scoped endpoints in v4.0
4.xMost resource endpoints in v4.0 now require an
organizationSlugas the first parameter. This change applies to almost all endpoints except for global or user-specific ones.Endpoints requiring
$organizationSlug:servers(),server(),createServer()sites(),site(),createSite()(Note:$forge->sites()is a global method for all sites across organizations)backgroundProcesses(),scheduledJobs(), etc.
Endpoints that DO NOT require
$organizationSlug:$forge->user()/$forge->me()$forge->organizations()$forge->sites()(Global access)$forge->providers()/$forge->providerSizes()/$forge->providerRegions()$forge->permissions()/$forge->predefinedRoles()$forge->forgeRecipes()
// v3.x $forge->servers(); $forge->server($serverId); // v4.0 $forge->servers($organizationSlug); $forge->server($organizationSlug, $serverId);Install the Laravel Forge SDK
4.xTo install the SDK in your project, use Composer to require the package.
composer require laravel/forge-sdkMigrate from v3.x to v4.0
4.xUpgrading to v4.0 involves several breaking changes. Follow this checklist to ensure a successful migration:
- Update PHP: Ensure your environment is running PHP 8.2 or higher.
- Retrieve Organization Slug: Most methods now require an
$organizationSlug. You can retrieve your slugs via$forge->organizations(). - Inject Organization Slug: Add the
$organizationSlugas the first argument to all resource methods (e.g.,$forge->servers($organizationSlug, ...)). - Handle Pagination Changes: List methods no longer return arrays. If you use array functions like
array_map()orarray_filter(), call->items()on the result first. - Update Renamed Methods:
daemons()$\rightarrow$backgroundProcesses()jobs()$\rightarrow$scheduledJobs()allSites()$\rightarrow$sites()siteNginxConfig()$\rightarrow$siteNginx()updateSiteNginxConfig()$\rightarrow$updateSiteNginx()
- Verify Resource Properties: Properties are now strictly typed and camelCased. Unknown API fields are moved to the
$attributesarray and are no longer accessible via dynamic properties.
// Before (v3.x) $names = array_map(fn($s) => $s->name, $forge->servers()); // After (v4.x) $names = array_map(fn($s) => $s->name, $forge->servers($org)->items());Manage asynchronous operations and timeouts
4.xSome methods (like
createSite) wait for the action to complete on Forge by periodically checking the resource status. By default, this waits up to 30 seconds.- Disable waiting: Pass
falseas the final argument to the method. - Customize timeout: Use the
setTimeout(int $seconds)method on the Forge instance before calling the action. - Error handling: If the operation exceeds the timeout, a
Laravel\Forge\Exceptions\TimeoutExceptionis thrown.
// This will wait until the site is fully installed (max 30 seconds) $site = $forge->createSite($organizationSlug, $serverId, [ 'domain' => 'example.com', 'type' => 'php', ]); // Don't wait $site = $forge->createSite($organizationSlug, $serverId, $data, false); // Wait up to 2 minutes $site = $forge->setTimeout(120)->createSite($organizationSlug, $serverId, $data);- Disable waiting: Pass
Use consistent service action patterns in v4.0
4.xIn v4.0, service actions (like restarting Nginx, MySQL, etc.) follow a unified pattern using
perform[Service]Actionmethods.$forge->performNginxAction($organizationSlug, $serverId, ['action' => 'restart']); $forge->performMySQLAction($organizationSlug, $serverId, ['action' => 'restart']); $forge->performPostgresAction($organizationSlug, $serverId, ['action' => 'restart']); $forge->performRedisAction($organizationSlug, $serverId, ['action' => 'restart']); $forge->performPHPAction($organizationSlug, $serverId, ['action' => 'restart']); $forge->performSupervisorAction($organizationSlug, $serverId, ['action' => 'restart']);Upgrade from v2.x to v3.0
4.xWhen upgrading from version 2.x to 3.0, you must perform the following steps to ensure compatibility:
- Update Package Name: Change the dependency in your
composer.jsonfrom the old package name tolaravel/forge-sdk. - Update Namespaces: Replace all instances of the
ThemSaid\namespace withLaravel\. - Verify PHP Version: Ensure your environment is running at least PHP 7.2.
- Refactor Method Calls: Update deprecated or removed methods as specified in the breaking changes section.
- Update Package Name: Change the dependency in your