Skip to content

Instantly share code, notes, and snippets.

@alecs
Last active January 15, 2026 12:54
Show Gist options
  • Select an option

  • Save alecs/2f45b8812b6859b2a7d93959aadcd1b6 to your computer and use it in GitHub Desktop.

Select an option

Save alecs/2f45b8812b6859b2a7d93959aadcd1b6 to your computer and use it in GitHub Desktop.
symfony v2 s3
<?php
// s3_operations.php
// Bootstrap the Symfony environment
require_once __DIR__ . '/app/bootstrap.php.cache';
require_once __DIR__ . '/app/AppKernel.php';
use Symfony\Component\Console\Input\ArgvInput;
use Symfony\Component\Debug\Debug;
use Aws\S3\S3Client;
// Get the environment and debug mode from console arguments or use defaults
$input = new ArgvInput();
$env = $input->getParameterOption(['--env', '-e'], getenv('SYMFONY_ENV') ?: 'dev');
$debug = getenv('SYMFONY_DEBUG') !== '0' && !$input->hasParameterOption(['--no-debug', '']) && $env !== 'prod';
if ($debug) {
Debug::enable();
}
// Create the kernel and boot it
$kernel = new AppKernel($env, $debug);
$kernel->loadClassCache();
$kernel->boot();
// Get the service container
$container = $kernel->getContainer();
// Get AWS credentials from Symfony parameters
$awsKey = $container->getParameter('aws_key');
$awsSecretKey = $container->getParameter('aws_secret_key');
$awsRegion = $container->getParameter('aws_region') ?: 'us-east-1';
// Ensure we have credentials
if (empty($awsKey) || empty($awsSecretKey)) {
echo "ERROR: AWS credentials are not properly configured.\n";
exit(1);
}
// Create S3 client
$s3Client = new S3Client([
'version' => 'latest',
'region' => $awsRegion,
'credentials' => [
'key' => $awsKey,
'secret' => $awsSecretKey,
],
]);
// Parse command line arguments
$argc = $_SERVER['argc'];
$argv = $_SERVER['argv'];
if ($argc < 2) {
showUsage();
exit(1);
}
$operation = $argv[1];
// Handle different operations
switch ($operation) {
case 'cp':
if ($argc < 4) {
echo "ERROR: 'cp' requires source and destination parameters.\n";
showUsage();
exit(1);
}
$source = $argv[2];
$destination = $argv[3];
// Determine if uploading or downloading
if (strpos($source, 's3://') === 0) {
// Download from S3
$parts = parse_url($source);
$bucket = $parts['host'];
$key = ltrim($parts['path'], '/');
try {
echo "Downloading s3://$bucket/$key to $destination\n";
$s3Client->getObject([
'Bucket' => $bucket,
'Key' => $key,
'SaveAs' => $destination
]);
echo "Download completed successfully.\n";
} catch (Exception $e) {
echo "ERROR: " . $e->getMessage() . "\n";
exit(1);
}
} elseif (strpos($destination, 's3://') === 0) {
// Upload to S3
$parts = parse_url($destination);
$bucket = $parts['host'];
$key = ltrim($parts['path'], '/');
try {
echo "Uploading $source to s3://$bucket/$key\n";
$s3Client->putObject([
'Bucket' => $bucket,
'Key' => $key,
'SourceFile' => $source
]);
echo "Upload completed successfully.\n";
} catch (Exception $e) {
echo "ERROR: " . $e->getMessage() . "\n";
exit(1);
}
} else {
echo "ERROR: Either source or destination must be an S3 URL (s3://bucket/path).\n";
exit(1);
}
break;
case 'ls':
if ($argc < 3) {
echo "ERROR: 'ls' requires an S3 path.\n";
showUsage();
exit(1);
}
$s3Path = $argv[2];
if (strpos($s3Path, 's3://') !== 0) {
echo "ERROR: Path must be an S3 URL (s3://bucket/path).\n";
exit(1);
}
$parts = parse_url($s3Path);
$bucket = $parts['host'];
$prefix = '';
if (isset($parts['path']) && !empty($parts['path'])) {
$prefix = ltrim($parts['path'], '/');
}
try {
// Add trailing slash to prefix if it's not empty and doesn't have one
if (!empty($prefix) && substr($prefix, -1) !== '/') {
$prefix .= '/';
}
$params = [
'Bucket' => $bucket,
];
// Only add prefix if it's not empty to avoid listing everything in the bucket
if (!empty($prefix)) {
$params['Prefix'] = $prefix;
}
// For directory-like behavior, use delimiter
$params['Delimiter'] = '/';
$result = $s3Client->listObjectsV2($params);
// Display common prefixes (directories)
if (isset($result['CommonPrefixes']) && !empty($result['CommonPrefixes'])) {
echo "Directories:\n";
foreach ($result['CommonPrefixes'] as $commonPrefix) {
echo " " . $commonPrefix['Prefix'] . "\n";
}
}
// Display objects (files)
if (isset($result['Contents']) && !empty($result['Contents'])) {
echo "Files:\n";
foreach ($result['Contents'] as $object) {
// Skip the directory placeholder object (if prefix ends with /)
if ($object['Key'] === $prefix) {
continue;
}
$size = formatBytes($object['Size']);
$lastModified = $object['LastModified']->format('Y-m-d H:i:s');
$displayName = str_replace($prefix, '', $object['Key']);
// Skip empty display names (can happen with directories)
if (empty($displayName)) {
continue;
}
echo " {$displayName} ({$size}) - {$lastModified}\n";
}
}
if ((!isset($result['CommonPrefixes']) || empty($result['CommonPrefixes'])) &&
(!isset($result['Contents']) || empty($result['Contents']))) {
echo "No objects found.\n";
}
} catch (Exception $e) {
echo "ERROR: " . $e->getMessage() . "\n";
exit(1);
}
break;
default:
echo "Operation '$operation' not supported. Currently only 'cp' and 'ls' are supported.\n";
showUsage();
exit(1);
}
// Shutdown the kernel
$kernel->shutdown();
/**
* Display usage information
*/
function showUsage() {
echo "Usage:\n";
echo " For upload: php s3_operations.php cp /local/path s3://bucket/path\n";
echo " For download: php s3_operations.php cp s3://bucket/path /local/path\n";
echo " For listing: php s3_operations.php ls s3://bucket/path\n";
}
/**
* Format bytes to human-readable format
*
* @param int $bytes Size in bytes
* @param int $precision Precision for rounding
* @return string Formatted size
*/
function formatBytes($bytes, $precision = 2) {
$units = ['B', 'KB', 'MB', 'GB', 'TB', 'PB'];
$bytes = max($bytes, 0);
$pow = floor(($bytes ? log($bytes) : 0) / log(1024));
$pow = min($pow, count($units) - 1);
$bytes /= pow(1024, $pow);
return round($bytes, $precision) . ' ' . $units[$pow];
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment