bytes-commerce/synology-php-api
Symfony bundle for the Synology NAS API (DSM). Quickly create an authenticated RequestManager and interact with shares and folders from your app. Requires PHP 8.2+ and Symfony 7.2+. Built on bytes-commerce/synology-php-api.
Installation:
composer require bytes-commerce/synology-php-api
No Symfony Flex? Manually register the bundle in config/bundles.php if using Symfony, or use the standalone package in Laravel.
First Use Case: Upload a file to a Synology share:
use BytesCommerce\SynologyApi\Factory\RequestManagerFactory;
use BytesCommerce\SynologyApi\Client;
$factory = new RequestManagerFactory();
$manager = $factory->createManager(
'https://your-nas.de99.quickconnect.to',
'username',
'password'
);
$client = new Client($manager);
$client->uploadFile(
'/path/to/local/file.txt',
'/path/to/remote/share/folder/'
);
Where to Look First:
src/Client.php for available methods (e.g., listFiles, deleteFile, copyMoveItem).Service Container Integration (Laravel):
Bind the RequestManagerFactory and Client to Laravel’s container in AppServiceProvider:
public function register()
{
$this->app->singleton(RequestManagerFactory::class, function ($app) {
return new RequestManagerFactory();
});
$this->app->bind(Client::class, function ($app) {
$factory = $app->make(RequestManagerFactory::class);
return new Client($factory->createManager(
config('synology.url'),
config('synology.username'),
config('synology.password')
));
});
}
Configuration Management:
Store credentials in .env:
SYNOLOGY_URL=https://your-nas.de99.quickconnect.to
SYNOLOGY_USERNAME=admin
SYNOLOGY_PASSWORD=yourpassword
Access via config('synology.*') or $_ENV.
Common Workflows:
// Upload
$client->uploadFile('local.txt', '/remote/share/');
// Download
$client->downloadFile('/remote/share/file.txt', 'downloads/');
// List files
$files = $client->listFiles('/remote/share/');
// Create folder (recursively)
$client->createFolder('/remote/share/new_folder/');
// Delete file/folder
$client->deleteFile('/remote/share/file.txt');
$client->copyMoveItem(
'/remote/share/source.txt',
'/remote/share/destination.txt',
'copy' // or 'move'
);
Error Handling: Wrap calls in try-catch blocks to handle Synology-specific errors:
try {
$client->uploadFile('file.txt', '/share/');
} catch (\BytesCommerce\SynologyApi\Exception\SynologyException $e) {
Log::error('Synology upload failed: ' . $e->getMessage());
// Retry or notify admin
}
Laravel Events:
Trigger events for Synology operations (e.g., synology.file.uploaded):
event(new SynologyFileUploaded($filePath, $remotePath));
Queued Jobs: Offload long-running operations (e.g., large file transfers) to Laravel Queues:
UploadToSynology::dispatch('large_file.zip', '/backup/')->onQueue('synology');
Caching:
Cache frequent API calls (e.g., listFiles) using Laravel Cache:
$files = Cache::remember("synology_files_{$path}", now()->addHours(1), function () use ($client, $path) {
return $client->listFiles($path);
});
Middleware: Add auth/validation middleware for Synology requests:
$manager->getClient()->getEmitter()->on('request', function ($request) {
$request->setHeader('X-Synology-Token', config('synology.token'));
});
Authentication:
*.de99.quickconnect.to) or a static IP.encryption or Hashicorp Vault).Path Handling:
rtrim() or DIRECTORY_SEPARATOR:
$path = rtrim($path, '/') . '/';
dest_folder_path parameter (introduced in 1.0.5) replaces dest_folder. Update old code:
// Old (deprecated)
$client->copyMoveItem('source', 'dest_folder', 'copy');
// New
$client->copyMoveItem('source', 'dest_folder_path/', 'copy');
File Operations:
json_encode() for paths with special chars (1.0.2):
$path = json_encode('/share/folder with spaces/');
Performance:
RequestManagerFactory (1.0.13):
$manager = $factory->createManager($url, $user, $pass, 30); // 30s timeout
$client->uploadFile('large_file.iso', '/backup/', [
'stream' => true,
'chunk_size' => 1024 * 1024, // 1MB chunks
]);
Caching:
Cache::forget("synology_files_{$path}");
Enable Logging: Configure Guzzle logging to debug API calls:
$manager->getClient()->getEmitter()->on('request', function ($request) {
Log::debug('Synology Request:', [
'url' => $request->getUri(),
'method' => $request->getMethod(),
'body' => $request->getBody(),
]);
});
Common Errors:
Testing:
Client for unit tests:
$mockClient = Mockery::mock(Client::class);
$mockClient->shouldReceive('uploadFile')->andReturn(true);
Custom Requests:
Extend the Client to add missing endpoints:
class ExtendedSynologyClient extends Client
{
public function customEndpoint($data)
{
return $this->request('POST', '/api/custom', $data);
}
}
Event Listeners: Listen for Synology events (e.g., file uploads) and trigger Laravel events:
$client->getManager()->getEmitter()->on('uploaded', function ($event) {
event(new SynologyFileUploaded($event->getFile()));
});
Retry Logic: Implement custom retry logic for transient failures:
$client->withRetry(3, function ($exception) {
return $exception instanceof \GuzzleHttp\Exception\ConnectException;
});
Async Operations: Use Laravel Queues for background processing:
class UploadToSynology implements ShouldQueue
{
public function handle()
{
$client->uploadFile($this->localPath, $this->remotePath);
}
}
How can I help you explore Laravel packages today?