Introducción a Composer

logo-composer-transparent

Composer es una herramienta para la gestión de dependencias en PHP. Nos permite definir, de una manera muy simple, las librerías (paquetes a partir de ahora) que necesita nuestra aplicación y las descarga por nosotros. Sin duda, ha sido una de las mejores noticias de los últimos años en el mundo PHP, ya que ha cambiado radicalmente la forma en la que construimos los proyectos. Es posible encontrar paquetes de calidad para casi cualquier funcionalidad en Packagist.

En este tutorial mostraremos como instalarlo y empezar a utilizarlo.

Instalación

Windows

La forma más sencilla de instalar Composer en Windows es descargar y ejecutar su instalador. También se encargará de actualizar la variable %PATH% para que pueda ser llamado desde cualquier directorio en línea de comandos.

*nix

En sistemas Unix como Linux o Mac OS, la instalación se realiza descargando el instalador con cURL, que no es más que un script PHP que debe ejecutarse. Éste se asegurará que Composer puede ser usado en el sistema. Después, descargará automáticamente el fichero composer.phar, que es el ejecutable de Composer. La instrucción para realizar la instalación sería la siguiente:

$ curl -sS https://getcomposer.org/installer | php

Para instalar Composer de forma global en el sistema y poder usarlo como cualquier otro comando, es tan sencillo como copiar el archivo composer.phar en alguno de los directorios incluidos en la variable de entorno PATH, por ejemplo en /usr/local/bin:

$ mv composer.phar /usr/local/bin/composer

Como funciona

Composer es un gestor de dependencias por proyecto, por lo que los paquetes necesarios para nuestra aplicación no se instalarán globalmente como ocurre con PEAR, sino en un directorio especial llamado vendor. Después, simplemente añadiendo un require_once del archivo de autoload que genera Composer tendremos acceso a todas nuestras dependencias.

Las dependencias se definen en un archivo llamado composer.json. Un ejemplo simple sería el siguiente:

    "require": {
        "fabpot/goutte": "v1.0.5"
    }

En el ejemplo anterior definimos una única dependencia, el paquete “fabpot/goutte”, que sirve para hacer screen scrapping y web crawling en PHP.

Cuando ejecutamos “composer install”, Composer comprueba las dependencias que hemos definido y descarga los paquetes necesarios para satisfacerlas:

$ composer install
Loading composer repositories with package information
Installing dependencies (including require-dev)
  - Installing symfony/event-dispatcher (v2.4.2)
    Downloading: 100%
  - Installing guzzle/common (v3.8.1)
    Downloading: 100%
  ...
  - Installing symfony/browser-kit (v2.4.2)
    Downloading: 100%
  - Installing fabpot/goutte (v1.0.5)
    Downloading: 100%

symfony/event-dispatcher suggests installing symfony/dependency-injection ()
symfony/event-dispatcher suggests installing symfony/http-kernel ()
Writing lock file
Generating autoload files

Como puedes comprobar, Composer no solo ha descargado “fabpot/goutte”, también algunos paquetes adicionales. Esto se debe a que el paquete “fabpot/goutte” define a su vez otras dependencias – se pueden comprobar en su archivo composer.json -, pero no nos tenemos que preocupar de esto, Composer se encarga automáticamente de calcular el grafo de dependencias. Este es un proceso bastante costoso si el número de dependencias crece, por lo que Composer intenta minimizar el problema creando el archivo composer.lock, que contiene las versiones exactas de todos los paquetes a instalar. Así, la próxima vez que ejecutemos “composer install”, Composer simplemente leerá el archivo composer.lock y descargará los paquetes. Si modificamos el archivo composer.json, necesitamos ejecutar “composer update” para que el archivo composer.lock se calcule de nuevo.

“composer update” es el nuevo “compilando…” :)

Una vez que los paquetes se han descargado, Composer genera un archivo php que debemos incluir en el proyecto para poder utilizar las dependencias. Éste archivo registra un autoloader PSR-0/PSR-4, lo que facilita hacer uso de las dependencias:

<?php

require_once __DIR__.'/vendor/autoload.php';

use Goutte\Client;

$client = new Client();
$crawler = $client->request('GET', 'http://www.servergrove.com');
$title = $crawler->filter('head > title')->text();
echo $title;

En el ejemplo anterior, incluímos el archivo autogenerado autoload.php, y a continuación creamos un objeto de la clase Goutte\Client, que forma parte del paquete “fabpot/goutte”. Por último, utilizamos el objeto para extraer el contenido de la etiqueta title de la página web de ServerGrove.

El comando composer

Ya hemos hablado de los comandos “install” y “update”, pero Composer dispone de algunos comandos adicionales. “composer list” muestra una lista de todos los comandos disponibles:

$ composer list
   ______
  / ____/___  ____ ___  ____  ____  ________  _____
 / /   / __ \/ __ `__ \/ __ \/ __ \/ ___/ _ \/ ___/
/ /___/ /_/ / / / / / / /_/ / /_/ (__  )  __/ /
\____/\____/_/ /_/ /_/ .___/\____/____/\___/_/
                    /_/

Available commands:
  about            Short information about Composer
  archive          Create an archive of this composer package
  config           Set config options
  create-project   Create new project from a package into given directory.
  depends          Shows which packages depend on the given package
  diagnose         Diagnoses the system to identify common errors.
  dump-autoload    Dumps the autoloader
  dumpautoload     Dumps the autoloader
  global           Allows running commands in the global composer dir ($COMPOSER_HOME).
  help             Displays help for a command
  init             Creates a basic composer.json file in current directory.
  install          Installs the project dependencies from the composer.lock file if present, or falls back on the composer.json.
  licenses         Show information about licenses of dependencies
  list             Lists commands
  require          Adds required packages to your composer.json and installs them
  run-script       Run the scripts defined in composer.json.
  search           Search for packages
  self-update      Updates composer.phar to the latest version.
  selfupdate       Updates composer.phar to the latest version.
  show             Show information about packages
  status           Show a list of locally modified packages
  update           Updates your dependencies to the latest version according to composer.json, and updates the composer.lock file.
  validate         Validates a composer.json

Algunos comandos interesantes:

  • init: Crea un archivo composer.json de forma interactiva.
  • validate: Comprueba si el archivo composer.json es válido.
  • selfupdate: Actualiza Composer a la última versión disponible. Si la versión de Composer es demasiado antigua – 30 días o más -, se muestra un mensaje de alerta cuando se ejecuta cualquier comando.
  • search: Busca paquetes en Packagist – por ejemplo, “composer search yaml” -.
  • show: Muestra información sobre los paquetes. Por ejemplo, “composer show –installed” muestra un listado de los paquetes instalados.
  • create-project: Crea un nuevo proyecto a partir de un paquete. Es bastante útil para frameworks – por ejemplo, para crear un nuevo proyecto Symfony2: “php composer.phar create-project symfony/framework-standard-edition path/ 2.4.2”.

Versiones de los paquetes

Hay varias formas de definir qué versión o versiones aceptamos en nuestro proyecto:

  • Versión exacta: “1.4.2”, “v1.4.2”.
  • Rangos: “>=1.0,<2.0", ">=1.0,<1.1 | >=1.2″.
  • Comodines: “1.0.*”, “1.*”.
  • Next Significant Release: “~1.2” es equivalente a “>=1.2,<2.0".

Estabilidad

Cada una de las versiones de los paquetes dispone de un stability flag, que indica si la versión es “final” o si en cambio se trata de una versión previa (p.ej. beta). Por defecto, solo se tienen en cuenta las versiones finales, por lo que si necesitamos alguna versión no stable, debemos cambiar el parámetro minimum-stability. Los valores disponibles son “dev”, “alpha”, “beta”, “RC” y “stable”. También es posible definir el minimum stability por dependencia, añadiendo “@flag” a la versión del paquete – por ejemplo “”fabpot/goutte”: “1.0.*@dev””.

El directorio “vendor”

Composer crea automáticamente el directorio vendor, que debemos ignorar en el sistema de control de versiones (VCS) – por ejemplo, añadiéndolo al .gitignore en GIT-. Es recomendable incluir el archivo composer.lock en el VCS para que todo el equipo de desarrollo utilice exactamente las mismas versiones de los paquetes. Se acabó la excusa de “funciona en mi ordenador…”!

Más información

Éste artículo es solamente una introducción a Composer y como empezar a utilizarlo en nuestros proyectos para gestionar sus dependencias. Si deseas profundizar más, Composer dispone de una excelente documentación, tanto para creadores de paquetes como para los consumidores.

marzo 19 / 2014
Author Raul Fraile
Category PHP
Comments No Comments

Upcoming Conferences

WeCamp

PHP New Zealand

PHP Summer Camp Croatia

PHPNE

MadisonPHP

brnoPHP

SymfonyLiveLondon

ZgPHP

PHPSouthAfrica

PHPNWUK

SymfonyLiveNYC

PHPForumParis

PHPARG

PHPWorld

TechMeetupUY

SymfonyConMadrid

Nuevas características de PHP 5.5

php55
PHP 5.5 se lanzó el pasado 20 de junio, y pronto anunciamos su soporte en los VPS de ServerGrove. Desde entonces, muchos usuarios han actualizado sus servidores virtuales a PHP 5.5 para aprovechar las mejoras de rendimiento y algunas de sus nuevas características. Aquí hablamos de algunas de las mejoras más significativas:

Generadores

Los generadores, básicamente, simplifican el proceso de implementar iteradores. Cualquier funcion que contenga la palabra clave yield se convierte automáticamente en una función generadora.

Imagina que quieres recorrer una lista de millones de números. Sin iteradores, tendrías que crear un array enorme primero y recorrerlo después, con el correspondiente consumo de memoria. Esto se puede evitar usando iteradores, ya que los números son producidos en cada iteración. Los generadores permiten crear los iteradores sin todo el código extra necesario para crear iteradores.

<?php
function getList($number) {
    for ($i=0;$i<$number;$i++) {
        yield $i;
    }
}

foreach (getList(10000000) as $number) {
    echo "$number ";
}

La salida sería:

0 1 2 3 4 5 6 ...

He creado un benchmark sencillo para comparar la memoria usada para 10.000 números, suficiente para ver la diferencia de consumo:

Creating array: 26.60 Mb
Generator: 12.60 Mb

Try-catch… y ¡finally!

Los bloques try-catch tienen ahora un nuevo amigo: finally. El código del bloque finally debe ejecutarse tanto si la excepción se ha lanzado o no. Esto asegura también que el bloque finally se ejecutará incluso si se lanza una excepción no contemplada.

<?php
try {
    $db = new PDO('mysql:host=localhost;dbname=test', 'username', 'password');
}
catch (Exception $e) {
    echo 'catch' . "\n";
}
finally {
    echo 'finally';
}

En caso de que la conexión a la base de datos falle, los bloques catch y finally se ejecutarán. Y si la conexión es correcta, solo el bloque finally:

// database connection fail
catch
finally

// database connection ok
finally

empty() acepta ahora expresiones

Seguro que más de una vez has intentado hacer algo como empty($user->getName())… ¿verdad? Es abstante molesto tener que crear una nueva variable con el resultado de la función solo para poder pasarla a empty(). En PHP 5.5, esto ya no es necesario, ya que acepta expresiones:

<?php
echo (int) empty(0) . "\n";
echo (int) empty(1) . "\n";
echo (int) empty("") . "\n";
echo (int) empty("hello") . "\n";
echo (int) empty(empty(empty(0)));

The output:

1
0
1
0
1

Si te estás preguntando por qué la última línea devuelve 1/true, recuerda que empty() considera como vacío “”, 0, 0.0, “0”, NULL, FALSE y array(). Por lo tanto, empty(0) es true, empty(true) false y por último empty(false) es true.

Como curiosidad, el RFC original incluía también a isset(), pero fue finalmente desechada para evitar confusiones.

Array/string deferencing

Se puede acceder directamente a literales y arrays estáticos para acceder a elementos o caracteres individuales.

<?php
echo [1, 2, 3][0] . "\n";
echo array(1, 2, 3)[1] . "\n";
echo "hello"[0];

La salida sería:

1
2
h

FQN de clases usando ::class

Antes de PHP 5.5, si queríamos obtener el FQN de una clase teníamos que usar Reflection o instanciar la clase para pasarla a la función get_class(). Era común definir constantes para superar esta limitación (p.ej. ClassName::CLASS_NAME). Ahora, es posible usar ClassName::class para obtener el FQN de la clase ClassName.

<?php
namespace Foo;
class Bar {}

echo Bar::class;

La salida sería:

Foo\Bar

Es importante destacar que ::class es una palabra clave, no una constante ni un método mágico.

foreach acepta list() y claves complejas

Se ha mejorado la estructura foreach con dos nuevas características: extraer arrays anidados con list() y claves complejas (no escalares).

Con list(), los arrays anidados pueden ser extraídos en variables, lo que mejora su legibilidad:

<?php
$values = [[1, 2], [3, 4]];
foreach ($values as list($a, $b)) {
    echo $a . '-' . $b . "\n";
}

La salida:

1-2
3-4

Para claves de tipos no escalares, debe utilizarse un Iterator, ya que no es posible usarlas en arrays nativos todavía.

Extensión OPcache

Zend Optimiser+ se ha añadido a PHP como la nueva extensión OPcache. OPcache mejora el rendimiento de PHP almacenando los bytecodes precompilados en la memoria compartida. Por lo tanto, elimina la necesidad de tener que leer y parsear los scripts en cada petición. La extensión está integrada en PHP 5.5.0 y posteriores, aunque también está disponible en PECL para versiones más antiguas (5.2, 5.3 y 5.4).

Password hashing API

PHP incluye una nueva API de hashing, que nos facilita la gestión de passwords. Proporciona funciones para generar un hash de un string, obtener información de ese hash, verificarlo y comprobar si necesita ser hasheado de nuevo.

<?php
$hash = password_hash('servergrove', PASSWORD_BCRYPT); // create hash
echo $hash . "\n";
var_dump(password_get_info($hash)); // get hash info (algorithm and options)
var_dump(password_needs_rehash($hash, PASSWORD_BCRYPT)); // check if hash implements the algorithm and options provided
var_dump(password_verify('servergrove', $hash)); // check hash matches the password
$2y$10$XmxdWDeAGR7eyQOiDmRC2.RMQXko3..ELuWwpL1Qyni1gVOlAWUk2
array(3) {
  ["algo"]=>
  int(1)
  ["algoName"]=>
  string(6) "bcrypt"
  ["options"]=>
  array(1) {
    ["cost"]=>
    int(10)
  }
}
bool(false)
bool(true)

El objetivo de esta nueva API es que sea fácil de utilizar, segura y compatible con futuras versiones de algoritmos de hashing. Anthony Ferrara, el PHP core developer que propuso esta nueva API escribió un artículo realmente interesante sobre el diseño de la API. En el RFC también se puede encontrar buen contenido sobre la API y criptografía en general.

GD

Se han añadido algunas mejoras en la extensión de GD. Especialmente importante es el soporte para el formato WebP, que proporciona compresión con y sin pérdida para imágenes destinadas para web.

agosto 26 / 2013
Author Raul Fraile
Category PHP
Comments No Comments

Upcoming Conferences

WeCamp

PHP New Zealand

PHP Summer Camp Croatia

PHPNE

MadisonPHP

brnoPHP

SymfonyLiveLondon

ZgPHP

PHPSouthAfrica

PHPNWUK

SymfonyLiveNYC

PHPForumParis

PHPARG

PHPWorld

TechMeetupUY

SymfonyConMadrid

Resumen de deSymfony 2013, la mayor conferencia del año sobre Symfony

logoDeSymfony

La semana pasada tuvimos el placer de participar un año más en la que en pocos años se ha convertido en la conferencia de Symfony con mayor número de asistentes del mundo: deSymfony. Durante los días 20, 21 y 22 de julio disfrutamos junto a los 400 asistentes de 23 charlas de excelente calidad divididas en 2 tracks, un taller y una unconference.

Un poco de historia

La primera edición de deSymfony se realizó en el año 2010, y desde entonces no ha parado de crecer. De los 92 asistentes de la primera edición se ha pasado a los 400 de la última. Todo un éxito, y más teniendo en cuenta que la conferencia está enfocada en un framework.

Esta última edición se ha celebrado en Madrid, a diferencia de años anteriores, que se había realizado en Castellón. El lugar elegido fue la Escuela Universitaria de Informática de la Universidad Politécnica de Madrid.

Nuestra aportación

ServerGrove ha vuelto a ser un año más patrocinador del evento. Como siempre, es un placer apoyar este tipo de iniciativas, y más en el caso de deSymfony, a cuyos organizadores consideramos ya buenos amigos. Además, dos de las charlas fueron impartidas por miembros del equipo: “Creando aplicaciones web desde otro ángulo con Symfony y AngularJS”, por Pablo Godel, y “Refactorización de aplicaciones PHP/Symfony2”, que la impartí yo.

Pablo hizo una introducción a AngularJS, el framework de JavaScript que utilizamos en ServerGrove para nuestro panel de control. También dio algunos consejos para integrarlo con Symfony2 y Twig. Por otro lado, el objetivo de mi charla fue motivar para que el refactoring sea un proceso contínuo en el ciclo de trabajo, buscando siempre la perfección y asentándose en buenas prácticas. Puedes encontrar todas las diapositivas aquí. Y según nos comentan desde la organización, los vídeos estarán disponibles en unas semanas.

Mi opinión

La mayoría de las charlas a las que asistí fueron interesantes y me enseñaron algo, razón más que suficiente para salir contento. Mis tres favoritas fueron las siguientes:

  • “Escalabilidad y alto rendimiento con Symfony2” – Ricard Clau
    Sencillamente espectacular. Ricard es una de esas personas a las que hay que escuchar cuando está hablando, ya que siempre tiene algo interesante que contar. Me gustó especialmente que entrara en el terreno pantanoso de los benchmarks, con cuya opinión coincido al 100%. Si te interesa más el tema, su artículo “APC vs Zend Optimizer+ Benchmarks with Symfony2” es de lectura obligada.
  • “Silex al límite” – Javier Eguiluz
    Javier es un valor seguro, no te equivocas cuando eliges asistir a su charla. Me gustó especialmente la primera parte de la charla, donde se habló de rendimiento, tanto de Silex como de PHP, y como exprimirlo al máximo. Si me sigues por twitter, ya he “confesado” alguna vez que me encantan las micro-optimizaciones. Sí, se que la ganancia no es importante a pequeña escala, pero sí cuando tu software es utilizado por miles de personas cada día, además de ser una forma muy divertida de conocer más tu código y las particularidades del lenguaje.
  • “Testing aplicado en Symfony2” – Marcos Quesada
    Muy buena charla. Marcos hizo una introducción muy completa al mundo del testing. Como el ritmo fue bastante intenso os recomiendo revisar sus diapositivas, son oro puro. Una de las cosas que me gustó es que Marcos tiene los pies en el suelo y sabe que en la vida real no siempre es posible tener una cobertura de tests perfecta o que testear métodos privados con reflection “is not a big deal…”.

Keynote

La keynote del evento corrió a cargo de Fabien Potencier, todo un lujo escucharle un año más en deSymfony. Pese a que gran parte de la charla fue sobre SensioLabs Insight (un nuevo producto de SensioLabs para medir la calidad del código de tus proyectos y avisarte de posibles problemas), Fabien contó cosas muy interesantes sobre el estado actual de las herramientas de análisis de código actuales y tuvo momentos muy divertidos:

“Todas las herramientas de análisis de calidad de código que hay en PHP han sido creadas por alemanes. Vamos a darle un toque francés.” – Fabien Potencier

El futuro

deSymfony ya se ha convertido en una referencia tanto en España como en países de latinoamérica, donde se sigue también con mucho interés. Evidentemente, organizar un evento con 400 personas conlleva un gran esfuerzo y debemos agradecer a todos los organizadores por lo que han conseguido. ¡Nos vemos en 2014!

junio 27 / 2013
Author Raul Fraile
Category PHP
Comments No Comments

Upcoming Conferences

WeCamp

PHP New Zealand

PHP Summer Camp Croatia

PHPNE

MadisonPHP

brnoPHP

SymfonyLiveLondon

ZgPHP

PHPSouthAfrica

PHPNWUK

SymfonyLiveNYC

PHPForumParis

PHPARG

PHPWorld

TechMeetupUY

SymfonyConMadrid

Porque ser parte de la comunidad de PHP está genial!

Cuando decidimos empezar a apoyar y patrocinar conferencias en la comunidad de PHP, lo hicimos porque pensamos que era lo correcto. Teníamos asignado un presupuesto para marketing y queríamos hacer algo significativo con él, no sólo promocionar nuestros servicios y nuestra empresa, era nuestra forma de decir gracias, de contribuir, porque al final, sin la comunidad de PHP, ServerGrove no sería lo que es hoy.

Sin notarlo, nos convertimos en parte de esta increíble comunidad. Todavía nos impresiona cuando vamos a una conferencia y nuestro logo está ahí con el resto de los sponsors apoyando el evento, colaborando para que ocurra. O cuando nuestro nombre es mencionado durante una charla o un Symfony Jeopardy.

Es un orgullo cuando nos presentamos y la gente reconoce nuestro nombre, o cuando conocemos a un cliente y este nos agradece infinítamente por nuestro servicio y soporte, por algo en lo que ponemos mucho orgullo y esfuerzo.

Hemos hecho grandes y duraderas amistades, y ha sido muy gratificante conocer a tantas personas talentosas, dispuestas a compartir sus conocimientos y experiencias, de forma tan desinteresada.

Pero aquí hay algo que no ha sido para nada esperado. Hace unas semanas, creamos un repositorio en Github para alojar nuestros archivos de traducciones de nuestro Panel de Control, para que alguien con ganas de contribuir con correcciones, pudiera hacerlo sin mucho esfuerzo. Lo que pasó después realmente nos impresionó.

Unas pocas horas después de publicar los archivos, Pascal Borreli comenzó a enviar correcciones para los diccionarios en Inglés, Francés e incluso lenguajes que él no habla.

Unos pocos días después, Joshua Thijssen se contactó con nosotros para ver si estabamos trabajando en las traducciones para el idioma Holandés, e incluso le pidió a sus colegas que colaboraran.

Hace unos días, recibimos el PR con la contribución de las traducciones en Holandés y lo publicamos!

No podemos estar más felices y orgullosos de ser parte de tan asombroso grupo de personas y estamos inmensamente agradecidos!

Así que si todavía te estás preguntando que puedes obtener al participar en conferencias, o contribuir con ese framework o proyecto que usas todos los días, por favor tómate un momento y piensa en que puedes hacer, de qué conferencia participar. Invierte en tu futuro y colabora en hacer un mundo mejor. Y sin notarlo, serás parte de la comunidad PHP. ¡Estarás en muy buena compañía!

noviembre 06 / 2012
Author Kim
Category Conferencias, PHP
Comments No Comments
Tags

Upcoming Conferences

WeCamp

PHP New Zealand

PHP Summer Camp Croatia

PHPNE

MadisonPHP

brnoPHP

SymfonyLiveLondon

ZgPHP

PHPSouthAfrica

PHPNWUK

SymfonyLiveNYC

PHPForumParis

PHPARG

PHPWorld

TechMeetupUY

SymfonyConMadrid

Anunciando ServerGrove Europa

¡Así es, finalmente ha sucedido! Aprovechando nuestra presencia en Europa durante las conferencias Symfony Live y deSymfony, estamos sumamente contentos de anunciar servergrove.eu y la disponibilidad de servidores en Europa. Luego de una larga búsqueda para el lugar correcto, hemos decidido instalar nuestros servidores en el datacenter de  Telecity en Dublin, Irlanda. Aaron Stephens estará a cargo de las operaciones europeas, por lo que si te encuentras en Symfony Live no dudes en saludarlo.

La conectividad es un tema sumamente importante, estas son algunas estadísticas:

Amsterdam 8 hops
Berlin 7 hops
Bruges 5 hops
Copenhagen 6 hops
Frankfurt 7 hops
Helsinki 8 hops
Lisbon 6 hops
Milan 3 hops
Paris 5 hops
Valencia 5 hops
Warsaw 5 hops
Zurich 11 hops

Para comenzar ofreceremos en Europa servicios de VPS y MongoDB, y pronto incluiremos hosting compartido. Europa dispone de una comunidad de PHP increíble, que nos ha apoyado permanentemente. Queremos agradecer el apoyo y la paciencia para que esto suceda.

Promoción lanzamiento: 
Tenemos una promoción con el código “Europa” para 10% de descuento en cualquier VPS. Vence el 1ro de noviembre de 2012.

También lanzamos una promoción con $100 de descuento para nuevos clientes que compren un plan con pago anual, más información aquí.

Además ofrecemos $25  de comisión. Si tienes un amigo que tiene un hosting deficiente este es el momento de recomendarnos. Puedes obtener el enlace de recomendación desde el area del cliente, o envíanos un email diciendo: he recomendado a “___________”.

¿Cómo muevo mi VPS en USA a Europa?

Si eres un cliente existente con un VPS en USA, simplemente abre un ticket de soporte solicitando la transferencia. Con previa coordinación moveremos tu VPS y le asignaremos una nueva dirección IP.

junio 07 / 2012
Author Kim
Category PHP
Comments No Comments

Upcoming Conferences

WeCamp

PHP New Zealand

PHP Summer Camp Croatia

PHPNE

MadisonPHP

brnoPHP

SymfonyLiveLondon

ZgPHP

PHPSouthAfrica

PHPNWUK

SymfonyLiveNYC

PHPForumParis

PHPARG

PHPWorld

TechMeetupUY

SymfonyConMadrid