Programando Con Yii2: Usando Amazon S3
Spanish (Español) translation by Rafael Chavarría (you can also view the original English article)



Si te estás preguntando, "¿Qué es Yii?" revisa mi tutorial previo Introducción al Framework Yii, el cuál revisa los beneficios de Yii e incluye un vistazo a qué hay de nuevo en Yii 2.0, liberado en Octubre de 2014.
En esta serie de Programando Con Yii2, estoy guiando a los lectores en el uso del Framework Yii2 para PHP. En el tutorial de hoy, te guiaré a través de los básicos de navegar, subir y descargar archivos a y desde el servicio de almacenamiento basado en la nube Amazon S3. Esencialmente, he creado un modelo de almacenamiento simple y ejemplos de controlador que puedes extender para tus necesidades.
Solo un recordatorio, participo en la sección de comentarios de abajo. Estoy especialmente interesado si tienes diferentes aproximacimaciones, ideas adicionales o quieres sugerir temas para futuros tutoriales. Si tienes una pregunta o sugerencia de tema, por favor publícala abajo. También puedes contactarme directamente en Twitter @reifman.
¿Qué es Amazon S3?
Amazon S3 proporciona almacenamiento basado en la nube fácil de utilizar para objetos y archivos. Ofrece el 99.99% de disponibilidad y 99.999999999% de durabilidad de objetos.
Ofrece una variedad de características para uso simple y avanzado. Es comunmente usado como el componente de almacenamiento para el servicio CDN de Amazon CloudFront, pero estos son distintos y pueden ser usados de independientemente uno de otro.
También puedes usar S3 para migrar archivos a través del tiempo para archivar en Amazon Glacier, para ahorros adicionales de costos.
Como la mayoría de los AWS, operas S3 vía APIs, y hoy, voy a guiarte a través de navegar, subir y descargar archivos desde S3 con Yii.
Comenzando
Para ejecutar el código de demostración, necesitarás tu propia cuenta AWS y llaves de acceso. Puedes navegar tu árbol S3 desde la consola AWS mostrada abajo:



S3 consiste de cubetas que contienen numerosos directorios y archivos dentro de ellas. Desde que usé AWS como un CDNm mi árbol WordPress permanece en mi vieja cubeta. También puedes navegar tu cubeta:



Mientras atravieso el árbol de objetos, aquí hay una vista más profunda de los contenidos de mi cubeta:



Programando con S3
De nuevo, construiré en el árbol hello desde GitHub para nuestro código de demostración (mira el enlace en esta página) Está derivado de Yii2 basic.
Obteniedo Tus Llaves de Acceso
Necesitarás llaves de acceso para la API AWS S3 si no es que ya las tienes. Si no, puedes obtenerlas navegando a Credenciales de Seguridad y creando un nuevo par:



Para el código de nuestra demostración, necesitarás colocarlas en tu archivo hello.ini con otras llaves y códigos seguros:
1 |
$ more /var/secure/hello.ini |
2 |
mysql_host="localhost" |
3 |
mysql_db="hello" |
4 |
mysql_un="tom_mcfarlin" |
5 |
mysql_pwd="is-never-gonna-give-up-rick-astley" |
6 |
aws_s3_access = "AXXXXXXXXXXXXXXXXXXXXXXXXXXXA" |
7 |
aws_s3_secret = "nXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXb" |
8 |
aws_s3_region = "us-east-1" |
Instalando la extensión Yii para AWS
Para este tutorial, usaremos la extensión AWS de Federico Motta para Yii2. El es definitivamente el programador Yii más jóven del cuál he usado código para un tutorial Envato Tuts+:



¿No es asombroso lo rápido que los chicos están entrando a la programación estos días?
Aquí está el proceso de instalación usando composer:
1 |
$ composer require fedemotta/yii2-aws-sdk
|
2 |
Using version ^2.0 for fedemotta/yii2-aws-sdk
|
3 |
./composer.json has been updated |
4 |
Loading composer repositories with package information |
5 |
Updating dependencies (including require-dev) |
6 |
... |
7 |
|
8 |
- Installing aws/aws-sdk-php (3.18.27) |
9 |
Downloading: 100% |
10 |
|
11 |
- Installing fedemotta/yii2-aws-sdk (v2.0) |
12 |
Loading from cache |
13 |
|
14 |
aws/aws-sdk-php suggests installing aws/aws-php-sns-message-validator (To validate incoming SNS notifications) |
15 |
aws/aws-sdk-php suggests installing doctrine/cache (To use the DoctrineCacheAdapter) |
16 |
Writing lock file |
17 |
Generating autoload files |
Posteriormente, también instalé las dos librerías que sugiere, pero no instalé todas las sugerencias de siguiente nivel para mi máquina de desarrollo local:
1 |
$ composer require aws/aws-php-sns-message-validator |
2 |
Using version ^1.1 for aws/aws-php-sns-message-validator |
3 |
./composer.json has been updated |
4 |
Loading composer repositories with package information |
5 |
Updating dependencies (including require-dev) |
6 |
- Installing aws/aws-php-sns-message-validator (1.1.0) |
7 |
Loading from cache |
8 |
|
9 |
Writing lock file |
10 |
Generating autoload files |
11 |
|
12 |
$ composer require cache/doctrine-adapter |
13 |
Using version ^0.5.0 for cache/doctrine-adapter |
14 |
./composer.json has been updated |
15 |
Loading composer repositories with package information |
16 |
Updating dependencies (including require-dev) |
17 |
- Installing doctrine/cache (v1.6.0) |
18 |
Loading from cache |
19 |
|
20 |
- Installing psr/cache (1.0.0) |
21 |
Loading from cache |
22 |
|
23 |
- Installing cache/taggable-cache (0.4.0) |
24 |
Loading from cache |
25 |
|
26 |
- Installing psr/log (1.0.0) |
27 |
Loading from cache |
28 |
|
29 |
- Installing cache/adapter-common (0.3.2) |
30 |
Loading from cache |
31 |
|
32 |
- Installing cache/doctrine-adapter (0.5.0) |
33 |
Loading from cache |
34 |
|
35 |
cache/doctrine-adapter suggests installing ext-apc (Allows for caching with Apc) |
36 |
cache/doctrine-adapter suggests installing ext-memcache (Allows for caching with Memcache) |
37 |
cache/doctrine-adapter suggests installing ext-memcached (Allows for caching with Memcached) |
38 |
cache/doctrine-adapter suggests installing ext-redis (Allows for caching with Redis) |
39 |
Writing lock file |
40 |
Generating autoload files |
También registré el componente awssdk dentro de hello/config/web.php:
1 |
'components' => [ |
2 |
'awssdk' => [ |
3 |
'class' => 'fedemotta\awssdk\AwsSdk', |
4 |
'credentials' => [ |
5 |
//you can use a different method to grant access
|
6 |
'key' => $config['aws_s3_access'], |
7 |
'secret' => $config['aws_s3_secret'], |
8 |
],
|
9 |
'region' => $config['aws_s3_region'], //i.e.: 'us-east-1' |
10 |
'version' => 'latest', //i.e.: 'latest' |
11 |
],
|
12 |
Navegando Mis Directorios S3
Para la demostración de hoy, creé un hello/controllers/StorageController.php con métodos de acción para ejecutar cada muestra, tal como http://localhost:8888/hello/storage/browse para navegar directorios.
Estos métodos llaman en turno al modelo Storage.php que creé con sus propios métodos.
Aquí está el código del controlador:
1 |
public function actionBrowse() |
2 |
{
|
3 |
$s = new Storage(); |
4 |
$s->browse('jeff-reifman-wp',"manual"); |
5 |
}
|
Este requiere que el modelo Storage alcance las nubes en el "S3ky" y navegar el directorio manual.
Cada vez que el modelo Storage.php es instanciado, este carga la extensión AWS SDK y crea una instancia S3:
1 |
<?php
|
2 |
namespace app\models; |
3 |
use Yii; |
4 |
use yii\base\Model; |
5 |
|
6 |
class Storage extends Model |
7 |
{
|
8 |
|
9 |
private $aws; |
10 |
private $s3; |
11 |
|
12 |
function __construct() { |
13 |
$this->aws = Yii::$app->awssdk->getAwsSdk(); |
14 |
$this->s3 = $this->aws->createS3(); |
15 |
}
|
En mi ejemplo de navegación, solo estoy haciendo echo de directorios y archivos, pero siéntete libre de personalizar este código como necesites:
1 |
public function browse($bucket='',$prefix='') { |
2 |
$result = $this->s3->listObjects(['Bucket' => $bucket,"Prefix" => $prefix])->toArray(); |
3 |
foreach ($result as $r) { |
4 |
if (is_array($r)) { |
5 |
if (array_key_exists('statusCode',$r)) { |
6 |
echo 'Effective URL: '.$r['effectiveUri'].'<br />'; |
7 |
} else { |
8 |
foreach ($r as $item) { |
9 |
echo $item['Key'].'<br />'; |
10 |
}
|
11 |
}
|
12 |
} else { |
13 |
echo $r.'<br />'; |
14 |
}
|
15 |
}
|
16 |
}
|
Aquí están los resultados cuando navego a http://localhost:8888/hello/storage/browse:



Subiendo Archivos
Para subir un archivo, necesitas especificar la ruta local y la llave de destino remoto. Aquí está el código del controlador para la carga:
1 |
public function actionUpload() { |
2 |
$bucket = 'jeff-reifman-wp'; |
3 |
$keyname = '/manual/upload.txt'; |
4 |
$filepath ='/Users/Jeff/Sites/hello/upload.txt'; |
5 |
$s = new Storage(); |
6 |
$result = $s->upload($bucket,$keyname,$filepath); |
7 |
echo $result['ObjectURL']; |
8 |
}
|
Y aquí está el método del modelo Storage:
1 |
public function upload($bucket,$keyname,$filepath) { |
2 |
$result = $this->s3->putObject(array( |
3 |
'Bucket' => $bucket, |
4 |
'Key' => $keyname, |
5 |
'SourceFile' => $filepath, |
6 |
'ContentType' => 'text/plain', |
7 |
'ACL' => 'public-read', |
8 |
'StorageClass' => 'REDUCED_REDUNDANCY', |
9 |
'Metadata' => array( |
10 |
'param1' => 'value 1', |
11 |
'param2' => 'value 2' |
12 |
)
|
13 |
));
|
14 |
return $result; |
Navegando a http://localhost:8888/hello/storage/upload muestra la URL de regreso desde la cuál puedo ver el archivo subido, porque especifiqué public-read en mi código de arriba:



En turno, navegar a la dirección S3 de arriba muestra los contenidos del archivo subido:
1 |
This is a test to upload to S3 |
Descargando Archivos
Aquí está el código del controlador para descargar un archivo:
1 |
public function actionDownload() { |
2 |
$s = new Storage(); |
3 |
$f = $s->download('jeff-reifman-wp','files/2013/01/i103-wedding-cover.jpg'); |
4 |
//download the file
|
5 |
header('Content-Type: ' . $f['ContentType']); |
6 |
echo $f['Body']; |
7 |
}
|
Ya que el navegador responde al content-type, debería mostrar la imagen apropiada, la cuál estoy pidiendo aquí.
Nota: Estoy descargando una imagen de portada de mi experiencia casándose con una corporación llamada Corporate Person a una mujer (sí, en realidad pasó). El matrimonio no funcionó a largo plazo.
Aquí está el código del modelo Storage para descargar:
1 |
public function download($bucket='',$key ='') { |
2 |
//get the last object from s3
|
3 |
//$object = end($result['Contents']);
|
4 |
// $key = $object['Key'];
|
5 |
$file = $this->s3->getObject([ |
6 |
'Bucket' => $bucket, |
7 |
'Key' => $key, |
8 |
]);
|
9 |
return $file; |
10 |
// save it to disk
|
11 |
}
|
Aquí esá lo que ves cuando el archivo es transmitido al navegador--esa es la novia celebrando el matrimonio con Corporate Person (estoy sonriendo en el fondo, misión cumplida).



Ciertamente, podrías solo almacenar los resultados en tu servidor en un archivo. Depende de ti. Te aliento a que juegues con el código y lo personalizes según necesites.
¿Qué Sigue?
Espero que esto te ayude con los básicos de usar AWS S3 desde tu aplicación Yii.
Si te gusta el concepto de objeto y almacenamiento basado en la nube pero quieres encontrar otros proveedores , revisa Alternativas a Amazon AWS. Me he estado alejando gradualmente de AWS por un número de razones mencionadas en el artículo. Una de mis siguientes tareas es migrar mis objetos S3 que aún están parcialmente en uso en mi propio servidor, el cuál puedo espejear con KeyCDN.
Espera tutoriales por venir en nuestra serie Programando Con Yii2 mientras continuamos sumergiéndonos en diferentes aspectos del framework. También querrás revisar nuestra serie Construyendo Tu Startup Con PHP el cuál está usando la plantilla avanzada de Yii2 mientras construimos una aplicación del mundo real. La aplicación Planificador de Reuniones en la serie startup está ahora lista para usar, y está toda construida en Yii.
Si te gustaría saber cuando llega el siguiente tutorial Yii2, sígueme en @reifman en Twitter o revisa mi página de instructor.



