PHPackages                             elliottlawson/daytona-php-sdk - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [API Development](/categories/api)
4. /
5. elliottlawson/daytona-php-sdk

ActiveLibrary[API Development](/categories/api)

elliottlawson/daytona-php-sdk
=============================

PHP SDK for Daytona API integration

v0.1.7(9mo ago)0527MITPHPPHP ^8.2CI passing

Since Jul 13Pushed 9mo agoCompare

[ Source](https://github.com/elliottlawson/daytona-php-sdk)[ Packagist](https://packagist.org/packages/elliottlawson/daytona-php-sdk)[ RSS](/packages/elliottlawson-daytona-php-sdk/feed)WikiDiscussions master Synced 1mo ago

READMEChangelog (8)Dependencies (8)Versions (11)Used By (0)

Daytona PHP SDK
===============

[](#daytona-php-sdk)

A PHP SDK for interacting with the Daytona API to manage development sandboxes.

Requirements
------------

[](#requirements)

- PHP 8.2 or higher
- Laravel 10.x, 11.x, or 12.x (optional, for Laravel integration)

Installation
------------

[](#installation)

```
composer require elliottlawson/daytona-php-sdk
```

Configuration
-------------

[](#configuration)

### Laravel Applications

[](#laravel-applications)

1. The service provider will be automatically registered via Laravel's package discovery.
2. Publish the configuration file:

```
php artisan vendor:publish --provider="ElliottLawson\Daytona\DaytonaServiceProvider" --tag="daytona-config"
```

3. Add your Daytona credentials to your `.env` file:

```
DAYTONA_API_URL=https://api.daytona.io
DAYTONA_API_KEY=your-api-key
DAYTONA_ORGANIZATION_ID=your-org-id

# Optional configuration
DAYTONA_DEFAULT_SNAPSHOT=laravel-php84
DAYTONA_DEFAULT_MEMORY=2
DAYTONA_DEFAULT_DISK=2
DAYTONA_DEFAULT_CPU=1
DAYTONA_AUTO_STOP_INTERVAL=30
```

### Configuration Options

[](#configuration-options)

The SDK requires three configuration values:

- **`apiUrl`** (string): The Daytona API endpoint (defaults to `https://api.daytona.io`)
- **`apiKey`** (string, required): Your Daytona API authentication key
- **`organizationId`** (string, required): Your organization ID

### Type-Safe Configuration

[](#type-safe-configuration)

For better type safety and IDE support, you can use the `Config` class:

```
use ElliottLawson\Daytona\DTOs\Config;

$config = new Config(
    apiUrl: 'https://api.daytona.io',
    apiKey: 'your-api-key',
    organizationId: 'your-org-id'
);
```

### Non-Laravel Applications

[](#non-laravel-applications)

You can instantiate the client directly with configuration:

```
use ElliottLawson\Daytona\DaytonaClient;

$client = new DaytonaClient([
    'api_url' => 'https://api.daytona.io',
    'api_key' => 'your-api-key',
    'organization_id' => 'your-org-id' // optional
]);
```

Usage
-----

[](#usage)

### Using the Facade (Laravel)

[](#using-the-facade-laravel)

The easiest way to use Daytona in Laravel is through the facade:

```
use Daytona;
use ElliottLawson\Daytona\DTOs\SandboxCreateParameters;

// Create a sandbox
$sandbox = Daytona::createSandbox(new SandboxCreateParameters(
    language: 'php',
    snapshot: 'laravel-php84',
));

// Execute commands
$result = Daytona::executeCommand($sandbox->getId(), 'composer install');

// Work with files
Daytona::writeFile($sandbox->getId(), '/workspace/test.txt', 'Hello World');
$content = Daytona::readFile($sandbox->getId(), '/workspace/test.txt');

// Delete sandbox
Daytona::deleteSandbox($sandbox->getId());
```

### Creating a Client

[](#creating-a-client)

#### In Laravel (Recommended)

[](#in-laravel-recommended)

```
use ElliottLawson\Daytona\DaytonaClient;
use ElliottLawson\Daytona\DTOs\Config;

// Using dependency injection
public function __construct(DaytonaClient $client)
{
    $this->daytonaClient = $client;
}

// Using the service container
$client = app(DaytonaClient::class);

// Using without parameters (pulls from .env via config)
$client = new DaytonaClient();

// Using the config from container
$config = app(Config::class);
$client = new DaytonaClient($config);
```

#### Manual Configuration

[](#manual-configuration)

```
use ElliottLawson\Daytona\DaytonaClient;
use ElliottLawson\Daytona\DTOs\Config;

// Using typed configuration (recommended for type safety)
$config = new Config(
    apiUrl: 'https://api.daytona.io',
    apiKey: 'your-api-key',
    organizationId: 'your-org-id'
);
$client = new DaytonaClient($config);
```

### Managing Sandboxes

[](#managing-sandboxes)

#### Create a Sandbox

[](#create-a-sandbox)

```
use ElliottLawson\Daytona\DTOs\SandboxCreateParameters;

// Create with minimal parameters
$sandbox = $client->createSandbox(new SandboxCreateParameters());

// Create with custom settings
$sandbox = $client->createSandbox(new SandboxCreateParameters(
    language: 'php',
    snapshot: 'laravel-php84',
    envVars: ['APP_ENV' => 'development'],
    memory: 4,
    disk: 10,
    cpu: 2,
    autoStopInterval: 30,
));

// The sandbox is automatically started and ready to use
echo $sandbox->getId(); // Sandbox ID
echo $sandbox->getState(); // 'started'
echo $sandbox->getRunnerDomain(); // Access URL

// Access sandbox data
$data = $sandbox->getData(); // Returns SandboxResponse DTO
$array = $sandbox->toArray(); // Returns array representation
```

#### Get Sandbox Information

[](#get-sandbox-information)

```
// Get a Sandbox object by ID
$sandbox = $client->getSandboxById($sandboxId);

// Access sandbox properties
echo $sandbox->getState(); // e.g., "started", "stopped"
echo $sandbox->getCreatedAt();
echo $sandbox->getSnapshot();
echo $sandbox->getCpu();
echo $sandbox->getMemory();

// Refresh data from API
$sandbox->refresh();

// Get raw SandboxResponse DTO if needed
$response = $client->getSandbox($sandboxId);
```

#### Start/Stop Sandbox

[](#startstop-sandbox)

```
// Using the Sandbox object (recommended)
$sandbox->start();
$sandbox->stop();
$sandbox->delete();

// Wait for state transitions
$sandbox->waitUntilStarted(timeout: 60); // Wait up to 60 seconds
$sandbox->waitUntilStopped(timeout: 30);

// Or using the client directly
$client->startSandbox($sandboxId);
$client->stopSandbox($sandboxId);
$client->deleteSandbox($sandboxId);
```

### Working with Files

[](#working-with-files)

#### Using the Sandbox Object (Recommended)

[](#using-the-sandbox-object-recommended)

```
// Read files
$content = $sandbox->readFile('/workspace/index.php');
echo $content;

// Write files
$sandbox->writeFile('/workspace/hello.txt', 'Hello, World!');

// List directory contents
$listing = $sandbox->listDirectory('/workspace');
foreach ($listing->files as $file) {
    echo $file->name . ' - ' . $file->type . PHP_EOL;
}

// Delete files
$sandbox->deleteFile('/workspace/temp.txt');

// Check file existence
if ($sandbox->fileExists('/workspace/config.php')) {
    echo "File exists!";
}
```

### Executing Commands

[](#executing-commands)

```
// Using the Sandbox object (recommended)
$result = $sandbox->exec('ls -la');

// Check the result
if ($result->isSuccessful()) {
    echo $result->output;
} else {
    echo "Command failed with exit code: " . $result->exitCode;
    echo "Error: " . $result->error;
}

// Quick command execution
$result = $sandbox->exec('composer install');
echo $result->output;

// Note about exit codes:
// - Exit code 0 means success
// - Exit codes 1-255 indicate various error conditions
// - Exit code -1 means the actual exit code couldn't be determined by Daytona
if (!$result->hasKnownExitCode()) {
    echo "Warning: Exit code is unknown";
}

// Execute with specific working directory
$result = $sandbox->exec('ls -la', '/workspace');

// Execute with custom environment variables
$env = ['NODE_ENV' => 'production', 'API_KEY' => 'secret123'];
$result = $sandbox->exec('npm run build', null, $env);

// Execute with timeout (in milliseconds)
$timeout = 30000; // 30 seconds
$result = $sandbox->exec('npm test', null, null, $timeout);

// Execute with cwd, env and timeout
$result = $sandbox->exec('composer install', '/app', $env, $timeout);

// Or using the client directly
$result = $client->executeCommand($sandboxId, 'npm test', '/workspace', $env, $timeout);
```

### Session Management for Long-Running Commands

[](#session-management-for-long-running-commands)

The SDK provides session support for managing long-running processes like development servers, build watchers, and background tasks.

```
// Create a session for long-running commands
$session = $sandbox->createSession('dev-server');

// Start a development server asynchronously
$serverCommand = $session->executeCommand(
    'npm run dev',
    runAsync: true,
    cwd: '/workspace/app'
);

// Get preview URL while server is running
$preview = $sandbox->getPreviewLink(3000);
echo "Access your app at: {$preview->url}\n";

// Stream server logs in real-time
$serverCommand->streamLogs(function($chunk) {
    echo $chunk;
    flush();
});

// Or use the convenience method for quick async execution
$buildCommand = $sandbox->execAsync('npm run build');
$status = $buildCommand->waitForCompletion(timeout: 300);
if ($status->exitCode === 0) {
    echo "Build successful!\n";
}

// Clean up when done
$session->delete();
```

For more details on session management, see [Session Management Documentation](docs/SESSIONS.md).

### Git Operations

[](#git-operations)

#### Using the Sandbox Object (Recommended)

[](#using-the-sandbox-object-recommended-1)

```
// Clone a repository
$sandbox->gitClone(
    'https://github.com/laravel/laravel.git',
    'main', // branch (optional)
    '/workspace', // destination path
    'username', // for private repos (optional)
    'password'  // for private repos (optional)
);

// Git status
$status = $sandbox->gitStatus('/workspace');
echo "Branch: " . $status->branch . PHP_EOL;
echo "Modified files: " . count($status->modified) . PHP_EOL;

// Git workflow with fluent interface
$sandbox->gitAdd('/workspace', ['file1.php', 'file2.php'])
    ->gitCommit('/workspace', 'Add new features', 'John Doe', 'john@example.com')
    ->gitPush('/workspace', 'username', 'password');
```

#### Using the Client Directly

[](#using-the-client-directly)

```
// List branches
$branches = $client->gitListBranches($sandboxId, '/workspace');
echo "Current branch: " . $branches->current . PHP_EOL;
foreach ($branches->branches as $branch) {
    echo "- " . $branch . PHP_EOL;
}

// Git history
$history = $client->gitHistory($sandboxId, '/workspace');
foreach ($history->commits as $commit) {
    echo $commit->hash . ' - ' . $commit->message . PHP_EOL;
}
```

### Complete Example

[](#complete-example)

#### Using the Facade

[](#using-the-facade)

```
use Daytona;
use ElliottLawson\Daytona\DTOs\SandboxCreateParameters;

// Create a sandbox
$sandbox = Daytona::createSandbox(new SandboxCreateParameters(
    language: 'php',
    snapshot: 'laravel-php84',
    envVars: ['APP_ENV' => 'testing'],
));

// Clone and setup a Laravel project
$sandbox->gitClone('https://github.com/laravel/laravel.git')
    ->exec('composer install')
    ->exec('cp .env.example .env')
    ->exec('php artisan key:generate');

// Run tests
$result = $sandbox->exec('php artisan test');
echo $result->output;

// Clean up
$sandbox->delete();
```

#### Using Dependency Injection

[](#using-dependency-injection)

```
use ElliottLawson\Daytona\DaytonaClient;
use ElliottLawson\Daytona\DTOs\SandboxCreateParameters;

class DeploymentService
{
    public function __construct(
        private DaytonaClient $daytona
    ) {}

    public function testDeployment(string $commitHash): bool
    {
        $sandbox = $this->daytona->createSandbox(new SandboxCreateParameters(
            language: 'php',
            snapshot: 'production-like',
        ));

        try {
            $sandbox->gitClone('https://github.com/mycompany/app.git')
                ->exec("git checkout {$commitHash}")
                ->exec('composer install --no-dev')
                ->exec('npm install && npm run build');

            $result = $sandbox->exec('./vendor/bin/phpunit');
            return $result->isSuccessful();
        } finally {
            $sandbox->delete();
        }
    }
}
```

### Advanced Usage

[](#advanced-usage)

#### Working with Sandbox Data

[](#working-with-sandbox-data)

```
// Get all sandbox data
$data = $sandbox->getData(); // Returns SandboxResponse DTO
$array = $sandbox->toArray(); // Returns array

// Access specific properties
echo $sandbox->getState(); // 'started', 'stopped', etc.
echo $sandbox->getRunnerDomain(); // Sandbox URL
echo $sandbox->getCpu(); // CPU cores
echo $sandbox->getMemory(); // Memory in GB
echo $sandbox->getDisk(); // Disk in GB
echo $sandbox->getCreatedAt(); // Creation timestamp

// Check sandbox state
if ($sandbox->getState() === 'started') {
    // Sandbox is ready
}

// Refresh data from API
$sandbox->refresh();
```

#### State Management

[](#state-management)

```
// Create sandbox without waiting
$sandbox = $client->createSandbox(
    new SandboxCreateParameters(snapshot: 'php-8.3'),
    waitForStart: false
);

// Manually wait for it to start
$sandbox->waitUntilStarted(timeout: 120); // Wait up to 2 minutes

// Stop and wait
$sandbox->stop()->waitUntilStopped();
```

#### Preview URLs

[](#preview-urls)

Access services running in your sandbox through preview URLs:

```
// Get preview URL for a specific port
$previewInfo = $sandbox->getPreviewLink(3000);

echo "Preview URL: " . $previewInfo->url;
echo "Access Token: " . $previewInfo->token;

// For programmatic access (e.g., curl), use the authorization token:
$response = Http::withHeaders([
    'x-daytona-preview-token' => $previewInfo->token
])->get($previewInfo->url);

// Multiple ports example
$ports = [3000, 8080, 5000];
foreach ($ports as $port) {
    $preview = $sandbox->getPreviewLink($port);
    echo "Port {$port}: {$preview->url}\n";
}
```

Preview URLs allow external access to services running in your sandbox:

- **Public sandboxes**: URLs are publicly accessible
- **Private sandboxes**: Require authentication token in `x-daytona-preview-token` header
- **URL format**: `https://{port}-{sandboxId}.{runner-domain}`

#### Error Handling

[](#error-handling)

The SDK provides specific exception types for different error scenarios:

```
use ElliottLawson\Daytona\Exceptions\ConfigurationException;
use ElliottLawson\Daytona\Exceptions\SandboxException;
use ElliottLawson\Daytona\Exceptions\FileSystemException;
use ElliottLawson\Daytona\Exceptions\CommandExecutionException;
use ElliottLawson\Daytona\Exceptions\GitException;
use ElliottLawson\Daytona\Exceptions\ApiException;

try {
    $sandbox = $client->createSandbox(new SandboxCreateParameters());
    $result = $sandbox->exec('npm test');

    if (!$result->isSuccessful()) {
        // Handle command failure
        echo "Tests failed: " . $result->error;
    }
} catch (ConfigurationException $e) {
    // Handle configuration errors (missing API key, etc.)
    echo "Configuration error: " . $e->getMessage();
} catch (SandboxException $e) {
    // Handle sandbox-specific errors
    echo "Sandbox error: " . $e->getMessage();
} catch (CommandExecutionException $e) {
    // Handle command execution errors
    echo "Command failed: " . $e->getMessage();
} catch (FileSystemException $e) {
    // Handle file operation errors
    echo "File operation failed: " . $e->getMessage();
} catch (GitException $e) {
    // Handle Git operation errors
    echo "Git operation failed: " . $e->getMessage();
} catch (ApiException $e) {
    // Handle API errors with status codes
    echo "API error ({$e->getStatusCode()}): " . $e->getMessage();
    echo "Response: " . $e->getResponseBody();
}
```

**Exception Types:**

- `ConfigurationException` - Missing API keys, invalid configuration
- `SandboxException` - Sandbox creation, state transitions, lifecycle errors
- `FileSystemException` - File read/write/delete operations
- `CommandExecutionException` - Command execution failures
- `GitException` - Git operations (clone, commit, push, etc.)
- `ApiException` - HTTP API errors with status codes and responses

All exceptions extend the base `ElliottLawson\Daytona\Exception` class. echo $commit-&gt;hash . ' - ' . $commit-&gt;message . PHP\_EOL; echo 'Author: ' . $commit-&gt;author . PHP\_EOL; echo 'Date: ' . $commit-&gt;date . PHP\_EOL; }

```

### Using the Sandbox Object

For a more object-oriented approach, you can work with the `Sandbox` object:

```php
// Get a sandbox instance
$sandbox = new \ElliottLawson\Daytona\Sandbox($sandboxId, $client);

// Execute commands
$result = $sandbox->exec('npm install');

// File operations
$content = $sandbox->readFile('/workspace/package.json');
$sandbox->writeFile('/workspace/test.js', 'console.log("Hello");');

// Directory operations
$files = $sandbox->listDirectory('/workspace');

// Lifecycle management
$sandbox->start();
$sandbox->stop();
$sandbox->delete();

```

Testing
-------

[](#testing)

```
# Run feature tests only (default)
composer test

# Run integration tests (requires Daytona server)
composer test:integration

# Run all tests
composer test:all

# Run tests with coverage
composer test-coverage
```

### Test Configuration

[](#test-configuration)

The test suite is split into two groups:

- **Feature tests**: Unit tests that don't require external services
- **Integration tests**: Tests that require a running Daytona server

By default, `composer test` or `vendor/bin/pest` only runs feature tests. This allows for quick testing during development without needing a Daytona server.

Error Handling
--------------

[](#error-handling-1)

All SDK methods throw `Exception` on errors:

```
use ElliottLawson\Daytona\Exceptions\Exception;

try {
    $sandbox = $client->createSandbox([...]);
} catch (Exception $e) {
    echo "Error: " . $e->getMessage();
}
```

License
-------

[](#license)

MIT

###  Health Score

34

—

LowBetter than 77% of packages

Maintenance56

Moderate activity, may be stable

Popularity18

Limited adoption so far

Community6

Small or concentrated contributor base

Maturity45

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~1 days

Total

8

Last Release

295d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/6254cce9312896ac7e2d54852a67745f163aef7284adc749222dbff0f06c37f2?d=identicon)[elliottlawson](/maintainers/elliottlawson)

---

Top Contributors

[![elliottlawson](https://avatars.githubusercontent.com/u/3441829?v=4)](https://github.com/elliottlawson "elliottlawson (59 commits)")

---

Tags

phpapisdksandboxesdaytonadevelopment-environments

###  Code Quality

TestsPest

Code StyleLaravel Pint

### Embed Badge

![Health badge](/badges/elliottlawson-daytona-php-sdk/health.svg)

```
[![Health](https://phpackages.com/badges/elliottlawson-daytona-php-sdk/health.svg)](https://phpackages.com/packages/elliottlawson-daytona-php-sdk)
```

###  Alternatives

[openai-php/laravel

OpenAI PHP for Laravel is a supercharged PHP API client that allows you to interact with the Open AI API

3.7k7.6M74](/packages/openai-php-laravel)[hubspot/api-client

Hubspot API client

23414.2M16](/packages/hubspot-api-client)[mailchimp/transactional

458.9M16](/packages/mailchimp-transactional)[resend/resend-php

Resend PHP library.

564.7M21](/packages/resend-resend-php)[checkout/checkout-sdk-php

Checkout.com SDK for PHP

553.3M7](/packages/checkout-checkout-sdk-php)[mozex/anthropic-laravel

Anthropic PHP for Laravel is a supercharged PHP API client that allows you to interact with the Anthropic API

71226.4k1](/packages/mozex-anthropic-laravel)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
